[Electric Imp 物聯網小惡魔]以網頁模式觀看溫濕度感應器

Electric IMP小惡魔,除了可以在ElectricIMP的網頁上進行coding與上傳資料,我們還能在agent code pane(代理人程式碼區),撰寫程式碼,將我們感測到的溫度數字上傳到一般網頁中。

如果想深入了解IMP小惡魔可以看下列幾篇文章

認識 Electric Imp 線上開發環境環境建置與 BlinkUp app溫濕度感應計

imp01

在執行程式之後,在agent code pane(代理人程式碼區),點選這個device(裝置)專用的網址,我們不僅可以將IMP的數值顯示在開發網頁中,IMP也可以將數值呈現在一個獨立的頁面

imp02

IMP的程式是以C語言、JAVESCRIPT與HTML的語法為基礎做撰寫,要達成下列效果,必須下列使用IMP專屬的函式,將agent code pane(代理人程式碼區)、device code pane(裝置程式碼區)之間做連結,進行資料傳遞。

1、agent.on(string, function)

2、agent.send(string, object)

3、device.on(string, function)

 

我們在device code pane(裝置程式碼區)使用agent.on(string, function)agent.send(string, object)這兩個函式,裝置接險與程式碼可以參考這篇溫濕度感應計,文章最下方有附device code pane的完整程式碼,主要傳遞訊息的部分在176-213行,讓我們先直接看這個部分。

1、我們使用agent.on(“pong”, returnFromImp)等待從agent code pane(代理人程式碼區)傳來的識別資訊”pong”,並將資訊的數值傳送到副函式returnFromImp之中。

2、將溫度感應器的溫度數值藉由agent.send(“ping”, data_temp)函式,將一個識別資訊”ping”,以及想要傳送的溫度資訊data_temp,傳送至agent code pane(代理人程式碼區)

function loop() {
imp.wakeup(INTERVAL, loop);
local data = dht11.read();
local data_hum,data_temp;
server.log("Running "+imp.getsoftwareversion()+", Free Memory: "+imp.getmemoryfree());
data_hum= data.rh;
server.log(format("Relative Humidity: %0.1f",data_hum)+" %");
//server.log(format("Relative Humidity: %0.1f",data.rh)+" %");
data_temp= data.temp;
server.log(format("Temperature: %0.1f C",data_temp));
//server.log(format("Temperature: %0.1f C",data.temp));
ping(data_temp);
}

spi <- hardware.spi257;
clkspeed <- spi.configure(MSB_FIRST, SPICLK);

dht11 <- DHT11(spi, clkspeed);
////////////////////////////////////////////////////////////////////////////////////
function ping(data_temp)
{
// Send a 'ping' message to the server with the current millis counter

agent.send("ping", data_temp);
}

function returnFromImp(startMillis)
{
}

agent.on("pong", returnFromImp);

// Start the ping-pong

//ping();

//////////////////////////////////////////////////////////////////////////////
loop();

 

 

接著在agent code pane(代理人程式碼區)使用device.on(string, function)http.onrequest(function)這兩個函式,

1、使用device.on(“ping”, startTime)函式等待從device code pane(裝置程式碼區)傳來的識別資訊”ping”並將溫度資訊data_temp傳送至副函式startTime

2、副函式startTime會先在網頁下方的 log pane(記錄區)顯示一次接收到的溫度數值

3、http.onrequest(requestHandler)會更新這個裝置專屬網頁的內容,每當我們對網頁進行重新整理,http.onrequest(requestHandler),便會到副函式requestHandler抓取最新數值response.send(200, format(“Temperature: %0.1f C”,global_data_temp));

 

agent code pane(代理人程式碼區)的完整程式碼

global_data_temp <- 45.5;
global_data_hum <- 45.5;

function startTime(data_temp)
{
server.log(format("agent Temperature: %0.1f C",data_temp));
server.log(data_temp);

global_data_temp = data_temp;
// Send the device a 'pong' message immediately
//device.send("pong", time);
}


function requestHandler(request, response) {
// send a response back to whoever made the request
server.log("http refresh");
response.send(200, format("Temperature: %0.1f C",global_data_temp));
//response.send(200, "LED OK ");
}
http.onrequest(requestHandler);


device.on("ping", startTime);

 

device code pane(裝置程式碼區)的完整程式碼


// Copyright (c) 2014 Electric Imp
// This file is licensed under the MIT License
// http://opensource.org/licenses/MIT
// Class for DHT11/RHT03 Temp/Humidity Sensor

const SPICLK = 937.5;
const INTERVAL = 5; // time between readings in seconds


// Class to read the DHT11/DHT22 family of temperature/humidity sensors
// See http://akizukidenshi.com/download/ds/aosong/DHT11.pdf
// These sensors us a proprietary one-wire protocol. The imp
// emulates this protocol with SPI.
// To use:
// - tie MOSI to MISO with a 10k resistor
// - tie MISO to the data line on the sensor
class DHT11 {
static STARTTIME_LOW = 0.020000; // 20 ms low time for start
static STARTTIME_HIGH = 0.000020; // 20 us min high time for start
static STARTTIME_SENSOR = 0.000080; // 80 us low / 80 us high "ACK" from sensor on START
static MARKTIME = 0.000050; // 50 us low pulse between 0 or 1 marks
static ZERO = 0.000026; // 26 us high for "0"
static ONE = 0.000075; // 70 us high for "1"

_spi = null;
_clkspeed = null;
_bittime = null;
_bytetime = null;
_start_low_bits = null;
_start_low_bytes = null;
_start_high_bits = null;
_start_high_bytes = null;
_start_ack_bits = null;
_start_ack_bytes = null;
_mark_bits = null;
_mark_bytes = null;
_zero_bits = null;
_zero_bytes = null;
_one_bits = null;
_one_bytes = null;

// class constructor
// Input:
// _spi: a pre-configured SPI peripheral (e.g. spi257)
// _clkspeed: the speed the SPI has been configured to run at
// Return: (None)
constructor(spi, clkspeed) {
_spi = spi;
_clkspeed = clkspeed;

_bittime = 1.0 / (_clkspeed * 1000);
_bytetime = 8.0 * _bittime;

_start_low_bits = STARTTIME_LOW / _bittime;
_start_low_bytes = (_start_low_bits / 8);
_start_high_bits = STARTTIME_HIGH / _bittime;
_start_high_bytes = (_start_high_bits / 8);
_start_ack_bits = STARTTIME_SENSOR / _bittime;
_start_ack_bytes = (_start_ack_bits / 8);
_mark_bits = MARKTIME / _bittime;
_mark_bytes = (_mark_bits / 8);
_zero_bits = ZERO / _bittime;
_zero_bytes = (_zero_bits / 8);
_one_bits = ONE / _bittime;
_one_bytes = (_one_bits / 8);

// // Pull the signal line up
_spi.writeread("\xff");
imp.sleep(STARTTIME_LOW);
}

// helper function
// given a long blob, find times between transitions and parse to
// temp and humidity values. Assumes 40-bit return value (16 humidity / 16 temp / 8 checksum)
// Input:
// hexblob (blob of arbitrary length)
// Return:
// table containing:
// "rh": relative humidity (float)
// "temp": temperature in celsius (float)
// if read fails, rh and temp will return 0
function parse(hexblob) {
local laststate = 0;
local lastbitidx = 0;

local gotack = false;
local rawidx = 0;
local result = blob(5); // 2-byte humidity, 2-byte temp, 1-byte checksum

local humid = 0;
local temp = 0;

// iterate through each bit of each byte of the returned signal
for (local byte = 0; byte < hexblob.len(); byte++) {
for (local bit = 7; bit >= 0; bit--) {

local thisbit = (hexblob[byte] & (0x01 << bit)) ? 1:0;

if (thisbit != laststate) {
if (thisbit) {
// low-to-high transition; watch to see how long it is high
laststate = 1;
lastbitidx = (8 * byte) + (7 - bit);
} else {
// high-to-low transition;
laststate = 0;
local idx = (8 * byte) + (7 - bit);
local hightime = (idx - lastbitidx) * _bittime;

// we now have one valid bit of info. Figure out what symbol it is.
local resultbyte = (rawidx / 8);
local resultbit = 7 - (rawidx % 8);
//server.log(format("bit %d of byte %d",resultbit, resultbyte));
if (hightime < ZERO) {
// this is a zero
if (gotack) {
// don't record any data before the ACK is seen
result[resultbyte] = result[resultbyte] & ~(0x01 << resultbit);
rawidx++;
}
} else if (hightime < ONE) {
// this is a one
if (gotack) {
result[resultbyte] = result[resultbyte] | (0x01 << resultbit);
rawidx++;
}
} else {
// this is a START ACK
gotack = true;
}
}
}
}
}

//server.log(format("parsed: 0x %02x%02x %02x%02x %02x",result[0],result[1],result[2],result[3],result[4]));
humid = (result[0] * 1.0) + (result[1] / 1000.0);
if (result[2] & 0x80) {
// negative temperature
result[2] = ((~result[2]) + 1) & 0xff;
}
temp = (result[2] * 1.0) + (result[3] / 1000.0);
if (((result[0] + result[1] + result[2] + result[3]) & 0xff) != result[4]) {
return {"rh":0,"temp":0};
} else {
return {"rh":humid,"temp":temp};
}
}

// read the sensor
// Input: (none)
// Return:
// table containing:
// "rh": relative humidity (float)
// "temp": temperature in celsius (float)
// if read fails, rh and temp will return 0
function read() {
local bloblen = _start_low_bytes + _start_high_bytes + (40 * (_mark_bytes + _one_bytes));
local startblob = blob(bloblen);
for (local i = 0; i < _start_low_bytes; i++) {
startblob.writen(0x00,'b');
}
for (local j = _start_low_bytes; j < bloblen; j++) {
startblob.writen(0xff,'b');
}

//server.log(format("Sending %d bytes", startblob.len()));
local result = _spi.writeread(startblob);
return parse(result);
}
}



function loop() {
imp.wakeup(INTERVAL, loop);
local data = dht11.read();
local data_hum,data_temp;
server.log("Running "+imp.getsoftwareversion()+", Free Memory: "+imp.getmemoryfree());
data_hum= data.rh;
server.log(format("Relative Humidity: %0.1f",data_hum)+" %");
//server.log(format("Relative Humidity: %0.1f",data.rh)+" %");
data_temp= data.temp;
server.log(format("Temperature: %0.1f C",data_temp));
//server.log(format("Temperature: %0.1f C",data.temp));
ping(data_temp);
}

spi <- hardware.spi257;
clkspeed <- spi.configure(MSB_FIRST, SPICLK);

dht11 <- DHT11(spi, clkspeed);
////////////////////////////////////////////////////////////////////////////////////
function ping(data_temp)
{
// Send a 'ping' message to the server with the current millis counter

agent.send("ping", data_temp);
}

function returnFromImp(startMillis)
{
}

agent.on("pong", returnFromImp);

// Start the ping-pong

//ping();

//////////////////////////////////////////////////////////////////////////////
loop();

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *