[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();

Leave a comment

Your email address will not be published.


*