All Collections
IoT Projects Tutorials
DIY Smart fan to beat the heat using Ubidots and Electric imp
DIY Smart fan to beat the heat using Ubidots and Electric imp

Log the temperature data from your Imp to Ubidots and trigger an event to turn the fan ON/OFF

David Sepúlveda avatar
Written by David Sepúlveda
Updated over a week ago

In our last Electric Imp tutorial we learned how to measure temperature, humidity and overall thermal comfort with Ubidots. This time we are going to make a simple on-off fan control. We will log the temperature to Ubidots and trigger an event when it is over 30ºC, so that the Electric Imp turns on a fan, and then a trigger to turn it off when temperature is below 27ºC.

It really works like a charm, so here we go:

1. Materials

  • Three female to female wires

  • 10k resistor

  • DHT11 humidity and temperature sensor

  • A fan

3. Wiring

Connect components as follows:

 

...and just one more thing: plug in your fan!

4. Coding

  • Login to the Electric Imp IDE and take note of the url of your Imp:

Copy the next two codes. In the Agent code we will use a function to handle http requests to Ubidots, don't forget to put your Ubidots' token and variables id  .

  • Agent Code:

device.on("temp", function(value) {    //server.log("Trying to post to Ubi the value:");    //server.log(value);    local headers = { "Content-Type": "application/json", "X-Auth-Token": "NBbF3PWPxWc2IaO40aXOKnhIu8tOv92rYN3ibiEc7Jh6GV3KZUUCHtXuNz7Y" }; // Replace the token with yours    local url = "http://things.ubidots.com/api/v1.6/variables/53d2beb37625424630223dac/values"; // Replace the Variable ID with yours    local string = {"value": value};    local request = http.post(url, headers, http.jsonencode(string));    local response = request.sendsync();});device.on("hum", function(value) {    //server.log("Trying to post to Ubi the value:hola");    //server.log(value);    local headers = { "Content-Type": "application/json", "X-Auth-Token": "NBbF3PWPxWc2IaO40aXOKnhIu8tOv92rYN3ibiEc7Jh6GV3KZUUCHtXuNz7Y" }; // Replace the token with yours    local url = "http://things.ubidots.com/api/v1.6/variables/53e541e57625422c7d900a1d/values"; // Replace the Variable ID with yours    local string = {"value": value};    local request = http.post(url, headers, http.jsonencode(string));    local response = request.sendsync();});function requestHandler(request, response) {  try {    // check if the user sent led as a query parameter    if ("relay" in request.query) {      server.log("entre");      // if they did, and led=1.. set our variable to 1      if (request.query.relay == "1" || request.query.relay == "0") {        // convert the led query parameter to an integer        local relayState = request.query.relay.tointeger();        // send "led" message to device, and send ledState as the data        device.send("relay", relayState);       }    }    // send a response back saying everything was OK.    response.send(200, "OK");  } catch (ex) {    response.send(500, "Internal Server Error: " + ex);  }} // register the HTTP handlerhttp.onrequest(requestHandler);
  • Device Code:

Note the last part of the code where there's a function to turn on/off the fan with the Powerswitch tail.

const SPICLK = 937.5;// Class to read the DHT11 temperature/humidity sensor// 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 sensorclass DHT11 {    static STARTTIME_LOW     = 0.001000;    // 1 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) {        this.spi = _spi;        this.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);    }        // 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);    }}relay <- hardware.pin8;spi  <- hardware.spi257;rele.configure(DIGITAL_OUT);function setRelay(relayState){    server.log("relayState:" + relayState );    relay.write(relayState);}  agent.on("relay", setRelay);function mainLoop(){imp.wakeup(1.0, mainLoop);clkspeed <- spi.configure(MSB_FIRST, SPICLK);dht11 <- DHT11(spi, clkspeed);data <- dht11.read();server.log(format("Relative Humidity: %0.1f",data.rh)+" %");server.log(format("Temperature: %0.1f C",data.temp));agent.send("temp",data.temp);agent.send("hum",data.rh);}mainLoop();

5. Set up Ubidots Events

  • In your Ubidots account, create one data source with two variables: Temperature and Humidity

  • Click on the "Events" section and add one:

  • Choose Electric imp as source and temperature (temp) as variable.

  • Put a condition when temp is over 30ºC.

  • Choose Request URL " and type your Imp URL plus "?relay=1"

  • Add another event with this conditional.

  • Choose "Request URL"  and type your Imp URL plus "?relay=0"

5. Wrapping up

In this project we were able to control an electric fan from internet with Electric Imp. Just as we controlled a fan using temperature data, you could also log any other data and take actions based on it. For example, you could open your garage door whenever your cat approaches a motion sensor (meaning it wants to go out!).

Don't forget to check out some of our latest posts:

If you're new to Ubidots, click below to get started!

Originally Published in Ubidots Blog August 26, 2014

Did this answer your question?