Posted on Leave a comment

4 Steps to create WiFi Controlled RGB LED Strip using ESP8266

I have always wanted to have an internet controlled LED light. So after researching a few different combination, I manage to find the one that is suitable. Using the RGB LED strip, and connecting this to the ESP8266 as the IoT device. I happened to have a spare RGB LED strip that is lying around from last Christmas. It is powered by 12 V, but no fear we are doing some serious current sinking using the MOSFET transistor.

We are designing the control using the same layout as the Remote Control. My RGB LED strip comes with remote control that looks like the following picture:

Since the ESP8266 can function as a webserver as well, we are utilising this capabilities to create the Remote layout. So the idea is we are using the ESP8266 to serve the website which function as the remote control, and the output will be used to drive the MOSFET which act as a switch to turn each of the LEDs (RED, GREEN or BLUE). With the different combination we can achieve different variety of colours.

Step 1. Gather all the components required

We will need the following components:

  • 1 x ESP8266
  • 3 x MOSFET IRF510
  • RGB LED Strip
  • Prototype board
  • Connector wire
  • 12V Power supply for LED Strip
  • 5V Power supply for the ESP8266

Now that we have gathered all the components, we can start connecting the Circuit.

Step 2. Connected the circuit

Connect the circuit as per the connection diagram shown below:

One thing important to note is to make sure the GND of 12 V power supply is connected to the GND of the 5V power supply if they are sourced from a different power source. You could also use the same 12 V power and down convert to 5V using the Regulator LM7805, but in this writeup, I am assuming we are using 2 different power source.

Step 3. Upload the Code

Now that everything is wired up, it is time to do the smoke test, and turn on the 12 V power supply, and if you don’t see any smoke then hopefully everything is wired correctly. Now the fun part begins. You can upload the following source code.

Step 4. Code Walkthrough

The source code consist of 4 files:

  • ESP8266LEDStripWifi.ino: This is the main file where the heavy lifting is done
  • Color.cpp and Color.h : is the header files and the Color library to make the code more object oriented so that you can make necessary adjustment to RGB value easily
  • mainPage.h: this is the html code which is served by ESP8266 as shown in the first picture above.

The code uses the an OTA library as well to make sure faster upload if there is any adjustment required for the source code. Here are some of the important things to note during initialisation:

/* Network settings */
const char* ssid = "yourWIFISSID"; // SSID - your WiFi's name 
const char* password = "yourwifipassword"; // Password 
const char* device_name = "led"; // you can access controller by http://led.local/
IPAddress ip(192,168,1,111);  // static IP adress of device 
IPAddress gateway(192,168,1,1); // Gateway
IPAddress subnet(255,255,255,0); // Network mask

const int redLED = 0;  // D3 GPIO0
const int greenLED = 2;  // D2 GPIO2
const int blueLED = 4;  // D4 GPIO4

You will need to change the ssid and password to allow the device to connect to your WiFi router. We are also assigning the static ip address of 192.168.1.111 for the ESP8266, if you have a different subnet, please feel free to change this along with the Gateway and the network mask.

Connection to the MOSFET is done from D2, D3 and D4 pin on the ESP8266, if you are connecting this to different pin, please make sure you make the appropriate adjustment.

Setup Section ()

Here are some snippets of the code in the setup () section:

void setup(void) {
 delay(1000);
 /* Begin some (un)important things */
   Serial.begin(115200);
   WiFi.begin(ssid, password);
   WiFi.config(ip, gateway, subnet);
   Serial.println("");
   // OTA code
   ArduinoOTA.setHostname("LEDStrip");
   ArduinoOTA.setPassword((const char *)"ledstripOTApassword");
   ArduinoOTA.begin();
...
/* Show website (in browser), than send RGB code */
   server.on("/", []() {
     server.send(200, "text/html", webPage);
     Serial.println("Loaded main page");
     Serial.print("Pressed: ");
     Serial.println("on");
   });

...
server.on("/red", []() {
     server.send(200, "text/html", webPage);
     createColor.red();
     Serial.print("Pressed: ");
     Serial.println("red");
     delay(1000);
   });

...

}

You will notice that in this section, the OTA password is being defined, this is to make sure we always have security in mind and not allowing unauthorised update. The code is quite repetitive for each section to handle the main website, and when each button press according the the colour.

For example when the RED button on the website is being pressed, we are calling the following code:

server.on("/red", []() {
     server.send(200, "text/html", webPage);
     createColor.red();
     Serial.print("Pressed: ");
     Serial.println("red");
     delay(1000);
   });

This will send back the website refresh and then call the createColor.red() method which will drive the LED colour of the LED, then followed by showing the Pressed: red message in the Serial output window for debugging purposes.

Please note that not all buttons have been program, especially the special effects button.

Loop () section

Loop () section of the code is quite simple as shown below:

void loop(void) {
   server.handleClient();
   ArduinoOTA.handle();
 }

It only serve the webserver and handle the OTA update.

If all goes well, you should have the WiFi controlled LED strip that you can control from anywhere in your home or office. You should see the following results:

Please drop me a line if you like this project, and let me know if you find any issue, feel free to share it with your friends, and stay tune for more IoT projects.

Posted on Leave a comment

ESP8266 Internet Weather Station

In this writeup, I am utilising the previous magic 8 ball circuit. You can expand the use of the same circuit to be Internet Weather Station. The code use in this is taken from the Example code of “WeatherStationDemo” that comes with the ESP8266 Weather station library.

Step 1. Downloading the Weather Station Library

From the Ardunio IDE, click on Tools->Manage Library, you should be prompted with the following Library Manager window:

You can then search for “ESP8266 Weather” and install the ESP8266 Weather Station library.

Step 2: Preparation

Once the library have been downloaded, you can restart the Arduino IDE, and then select File->Examples-> ESP8266 Weather Station->WeatherStationDemo. Then follow the following preparation step to configure the code.

  • I am in Melbourne, Australia so I made the adjustment to GMT + 10, you will need to make adjustment to the time where you live.
  • SSD1306 LED Display: SDA is connected to GPIO 4 (pin D2) and SDC is connected to GPIO 2 (pin D4)
  • We are using the OpenWeatherMap, to use this you will need to sign up to get and API key, you can use the following link. Then populate the key into the code below.
  • Locate your location for the weather using the link https://openweathermap.org/find?q, using the location found, enter that into the following code below to replace the OPEN_WEATHER_MAP_LOCATION_ID

This is shown in the following code:

#define TZ              10       // (utc+) TZ in hours
#define DST_MN          0      // use 60mn for daylight savings
...
const int SDA_PIN = 4; //D2 (GPIO 4);
const int SDC_PIN = 2; //D4 (GPIO 2);
...
String OPEN_WEATHER_MAP_APP_ID = "yourOpenWeatherMapAPIKey";
String OPEN_WEATHER_MAP_LOCATION_ID = "7932632";

Step 2: Upload the code and Test

Once you have setup the code above you can now upload the code to the ESP8266 and if all goes well you should have a working Internet Weather station.

If all goes well you now should have an internet weather station as shown in the following video.

If you like this post, please share and drop me a line. Don’t forget to subscribe if you haven’t already to get more IoT related post.

Posted on Leave a comment

3 Steps to perform ESP8266 Secure OTA Update

As the previous follow up to the Magic 8 Ball with ESP8266, I am extending this to add the code for OTA (On The Air) update. This will ensure that we can update the code without having to plug the ESP8266 to the USB, but this is done through “On The Air” update. The OTA update seems to be a lot faster than the USB connection for some reason.

For Security purposes we don’t want random people who have access to our network being able to perform the update over the air, therefore we added an extra layer of security so that we need to enter the password before the OTA update can be done. Here are the steps how this can be achieved.

Step 1. Include the Arduino OTA Library

You can include the arduino OTA library as per the below code:

#include <ESP8266mDNS.h>
#include <ArduinoOTA.h>

Step 2. Setup() Section

Add the following code to the setup() section:

void setup (){
...
// OTA code
   ArduinoOTA.setHostname("MAGIC8Ball");
   ArduinoOTA.setPassword((const char *)"setyourpassword");
   ArduinoOTA.begin();
   ArduinoOTA.onStart([]() {
     display.clear();
     display.setFont(ArialMT_Plain_10);
     display.setTextAlignment(TEXT_ALIGN_CENTER_BOTH);
     display.drawString(DISPLAY_WIDTH/2, DISPLAY_HEIGHT/2 - 10, "OTA Update");
     display.display();
   });
   ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
     display.drawProgressBar(4, 32, 120, 8, progress / (total / 100) );
     display.display();
   });
   ArduinoOTA.onEnd([]() {
     display.clear();
     display.setFont(ArialMT_Plain_10);
     display.setTextAlignment(TEXT_ALIGN_CENTER_BOTH);
     display.drawString(DISPLAY_WIDTH/2, DISPLAY_HEIGHT/2, "Restart");
     display.display();
   });  
...
}

The setHostname function allows you to set the name of the ESP8266 so that it is much easier to tell especially when you have a few devices in your network that support OTA.

The setPassword function allows you to password protect the OTA. The system will prompt you the second time you are trying to perform the OTA. This is shown in the following picture:

ESP8266 OTA Password

The onStart function will get called when the OTA process started. In this example of the Magic 8 ball with OLED screen we are showing the “OTA update” text on the OLED display when the OTA starts.

The onProgress function will get called in the middle of the OTA update, so this is the perfect location to put the OTA status indicator. In this example we are displaying the update progress in the OLED screen of the magic 8 ball.

The onEnd function will get called when the OTA update is completed. In this example we are showing the “Restart” text when the OTA process finished just before the ESP8266 restarted.

Step 3. Loop() function

In order the ensure that the ESP8266 always listen to the OTA we need to insert the following code in the loop function.

void loop(){
...
ArduinoOTA.handle();
...
}

That’s all and once you have modified the magic 8 ball code, and uploaded it to the device, you should have a working Magic 8 ball that supports OTA update. If you like to download the code that I have used for this tutorial, you can downloaded it here.

Other considerations

There are some requirements that needs to be fulfil for the OTA to works, first of all the Flash chip size needs to be big enough to hold the old code (the one that is currently running) and the new code (OTA) at the same time, so you will need to plan this to ensure that there is enough memory space to hold both. The other consideration is that the module that will be updated needs to be in the same network as the computer with Arduino IDE that will perform the OTA update. The disadvantage is then you are not able to use serial port to perform the code debugging if there is anything wrong with your code.

Hopefully you are finding this post useful and please drop me a line and don’t forget to subscribe for more regular update on other IoT circuits.

Posted on Leave a comment

ESP8266 Magic 8 Ball

Do you have the urge to have Magic 8 Ball, but never get around to get one? Well I do. So what can I do in this case? I make one using ESP8266. This is the document on what I have done and what can be further improved.

Step 1. Gather all the Materials

  • ESP8266
  • OLED Display
  • Battery recycled from old mobile phone
  • TP4056 Battery Charger Module Charging Board
  • LED
  • Shake sensor
  • Clear plastic ball
  • Some cables
  • Prototype board (optional)

Step 2. The Circuit

The idea is to have a circuit that is activated when it is shaken. So we achieve this by using the shake sensor connected to pin D5 and GND. When the circuit is shaken it will get activated and we randomly answer the questions and display the results in the Display. At the same time we activated the LED to show that we are processing the input.

Step 3. Putting it together (connecting the charge module to the battery)

I soldered the charging module directly to the battery and then connected to the rest of the circuit using the prototype board as shown in the following picture.

Step 4. Combine the rest of the circuit

Connect the rest of the circuit by wiring up the shake sensor to D5 and GND, connect the LED to pin D6 and VCC and last but not the least, the OLED display SCL to pin D4 and SDA to pin D2. Once this is done connect the circuit to the battery via the VIN pin and GND.

Step 5. Load the Code and testing

Once you have the complete circuit, it is time to load the code and test the circuit. The code is using the SSD1306 library, OneButton library as describe in the previous post to detect the double click action when the ball is being shaken.

The code will detect the double click from the Onebutton library, and it will execute the following function:

// this function will be called when the button was pressed 2 times in a short timeframe.
 void myDoubleClickFunction(){
     started = false;
     digitalWrite(LEDpin, LOW);
      int answer = random(8);
     Serial.print("Double click:");
     Serial.println(answer);
     display.clear();
     display.setTextAlignment(TEXT_ALIGN_LEFT);
     display.drawString(0, 10, "Thinking …..");
     display.display();
     delay(1000);
     display.clear();
     display.drawString(0, 24, answers);
     display.display();
     delay(2000);
   started = !started;
   display.clear();
   display.display();
   digitalWrite(LEDpin, HIGH);
 }

As you can see the code above will turn on the LED by pulling it low. Then generate a random number between 0 – 7 and it will write the word “Thinking ….” for 1 second before displaying the answer for another 2 seconds. It will then clear the display and turn the LED off.

The full source code can be found in the following link. If all goes well you should be able to see the result like the following video.

Step 6. After thoughts

Now that you have an internet connected Magic 8 ball, you can expand it using your imagination. Here are a few examples:

  • Expand it to post the answers via MQTT
  • Trigger the magic 8 ball from the internet (this will freak your friend out)
  • Expand to have more than 8 answers
  • The possibility is only limited by your imagination.

I hope you liked this post, please let me know what is the expansion idea that you like to see and why. Please don’t forget to share and subscribe if you haven’t already. Stay tune for the next episode.

Posted on Leave a comment

3 Steps to Test TV remote using ESP8266

I have a dilema of trying to test the TV remove, but not having the TV. I have tried to point the remote to the Iphone camera but this didn’t produce anything. I remember having an infrared detector circuit but haven’t get around to make it, so here are what I have done to test and fix my broken TV remote.

Step 1. Gather the components

You will need the following components:

  • ESP8266
  • IR receiver TL1838
  • Prototype board

Step 2. Connecting the Circuit

You can connect the IR receiver to the ESP8266. The IR receiver have 3 pins, the first pin is the output which we connect to the D4 of ESP8266, the second (middle) pin is GND and the right pin is VCC, which we connect to the 3.3V of ESP8266. This is shown in the following diagram.

ESP8266 IR Receiver

The following diagram shows the pin out of the IR receiver TL1838

When the IR Receiver received any IR signal it will be transmitted to pin D4 of ESP8266 to be decoded. The remote that I have have some intermittent problem with the power ON/OFF switch, so you can imagine how annoying that is.

Step 3. Load the Sketch to ESP8266

Once you have connected the circuit, it is time to load the following sketch to the ESP8266.

/*
 IRremoteESP8266: IRrecvDump - dump details of IR codes with IRrecv
 An IR detector/demodulator must be connected to the input RECV_PIN.
 Version 0.1 Sept, 2015
 Based on Ken Shirriff's IrsendDemo Version 0.1 July, 2009,
 Copyright 2009 Ken Shirriff, http://arcfn.com
 JVC and Panasonic protocol added by Kristian Lauszus
 (Thanks to zenwheel and other people at the original blog post)
 LG added by Darryl Smith (based on the JVC protocol)
 */ 
 #ifndef UNIT_TEST
 #include <Arduino.h> 
 #endif
 #include <IRremoteESP8266.h>
 #include <IRrecv.h>
 #include <IRutils.h> 
 // an IR detector/demodulator is connected to GPIO pin 2 (D4)
 uint16_t RECV_PIN = 2;
 IRrecv irrecv(RECV_PIN);
 decode_results results;

 void setup() {
   Serial.begin(115200);
   irrecv.enableIRIn();  // Start the receiver
 }
 void dump(decode_results *results) {
   // Dumps out the decode_results structure.
   // Call this after IRrecv::decode()
   uint16_t count = results->rawlen;
   if (results->decode_type == UNKNOWN) {
     Serial.print("Unknown encoding: ");
   } else if (results->decode_type == NEC) {
     Serial.print("Decoded NEC: ");
   } else if (results->decode_type == SONY) {
     Serial.print("Decoded SONY: ");
   } else if (results->decode_type == RC5) {
     Serial.print("Decoded RC5: ");
   } else if (results->decode_type == RC5X) {
     Serial.print("Decoded RC5X: ");
   } else if (results->decode_type == RC6) {
     Serial.print("Decoded RC6: ");
   } else if (results->decode_type == RCMM) {
     Serial.print("Decoded RCMM: ");
   } else if (results->decode_type == PANASONIC) {
     Serial.print("Decoded PANASONIC - Address: ");
     Serial.print(results->address, HEX);
     Serial.print(" Value: ");
   } else if (results->decode_type == LG) {
     Serial.print("Decoded LG: ");
   } else if (results->decode_type == JVC) {
     Serial.print("Decoded JVC: ");
   } else if (results->decode_type == AIWA_RC_T501) {
     Serial.print("Decoded AIWA RC T501: ");
   } else if (results->decode_type == WHYNTER) {
     Serial.print("Decoded Whynter: ");
   }
   serialPrintUint64(results->value, 16);
   Serial.print(" (");
   Serial.print(results->bits, DEC);
   Serial.println(" bits)");
   Serial.print("Raw (");
   Serial.print(count, DEC);
   Serial.print("): ");
 for (uint16_t i = 1; i < count; i++) {     if (i % 100 == 0)       yield();  // Preemptive yield every 100th entry to feed the WDT.     if (i & 1) {       Serial.print(results->rawbuf[i] * RAWTICK, DEC);
     } else {
       Serial.write('-');
       Serial.print((uint32_t) results->rawbuf[i] * RAWTICK, DEC);
     }
     Serial.print(" ");
   }
   Serial.println();
 }

 void loop() {
   if (irrecv.decode(&results)) {
     serialPrintUint64(results.value, 16);
     dump(&results);
     irrecv.resume();  // Receive the next value
   }
 }

Once you have uploaded the code above, the ESP8266 should be ready to receive the IR signal, and it will dump the result to the Serial output. In my case, the remote it SONY TV, and I was able to fix it by inserting an aluminium foil between the button and the PCB. This fixes the intermittent ON/OFF button problem. For some reason this type of remote ON/OFF button is problematic. I have the second SONY remote that also have the same problem.

I hope this post is useful and you can use it for further expansion, now that you can decode the IR remote, you can automate some sequence for your TV. Because ESP8266 can be connected to WiFi, all of a sudden you can control your TV from the internet. Stay tune for more of this. Please drop me a line if you have any questions and don’t forget to subscribe for more IoT related projects.

Posted on Leave a comment

ESP8266 Modem Sleep with MQTT

Just to finished up with the final post in regards to ESP8266 sleep mode. In the process of learning all the different sleep modes, I stumble across a good post to share the measurements on the different sleep modes, you can check it out here.

To continue the journey from previous post about ESP8266 Deep sleep and ESP8266 Light sleep, the last one is about the Modem sleep. The Modem Sleep is useful when you want to safe some battery, this is done by powering off WiFi only. The code to switch the Wifi OFF and ON the is as below:

WiFi.forceSleepBegin(); // Wifi off 
WiFi.forceSleepWake(); // Wifi on

Hopefully this can be useful to reduce the power consumption when constant Wifi connection is not required. So with slight modification our previous code used to perform the light sleep can be repurposed for this.

Setup() section

The Setup () section only consist of the serial port initialisation as shown in the following code:

void setup() {
   Serial.begin(115200);
   Serial.println();
 }

Loop() section

The loop section is responsible to do the work, this can be shown in the following code:

 void loop() {
   data();
   delay(200);
   Serial.println("Going to sleep now");
   WiFi.forceSleepBegin();  // Wifi Off
   delay(1000*10); // sleep for 10 seconds
   WiFi.forceSleepWake();  // Wifi On
   Serial.println("Wake up");
 }

As you can see the Data() function is responsible to get the temperature sensor reading and posting the result to the MQTT broker. This is explained in details in the next section. We are forcing the Wifi to go to sleep for 10 seconds and then bring it back to life.

Data() function

The data function as explained previously is responsible to read the temperature sensor value. When this is done, because it just woke up from Modem sleep we need to re-initialise the Wifi, this is achieve by calling the initiWifi() function. Then once the Wifi connection is established we are trying to connect to the MQTT broker, this is done by calling the connectMQTT() function. Once we are connected then we publish the temperature to the “/homeautomation/temperature” topic. The code of data() function is shown below:

void data() {
   int value = analogRead(A0);
   float volts=(value * 3.03) / 1024;      //conversion to volts
   tempC = volts*100.0;             //conversion to temp Celsius
   Serial.print("Temperature C: ");
   Serial.println(tempC);
   initWifi();   // init Wifi
   connectMQTT(); // connect to MQTT broker and publish
   if (client.connected()) {
     Serial.println("MQTT client connected");
     client.publish("/homeautomation/temperature", String(tempC));
     delay(1000);
   } else {
     Serial.println("MQTT client not connected");
   }
 }

If you would like the full source code of the above, you can download it from the following location. If you like this post, please drop me a line or let me know if you have any questions.

Posted on Leave a comment

3 Steps to prune Mongo DB in Unifi Controller

You will need two session of terminal to repair, the first session to run the mongo daemon and the second session to prune the database. You will need the mongo_prune_js.js.

Step 1. Login to the first session of the Unifi Controller

Once you login successfully, Stop the unifi service using the following command

service unifi stop

make sure there is no Mongodb session using the following command

ps -aux | grep mongo

Run the mongodb using the following command

sudo mongod --port 27117 -dbpath /usr/lib/unifi/data/db -smallfiles -logpath /usr/lib/unifi/logs/server.log -journal

you should see something similar to the following window:

start mongo db

Step 2. Login to the second session of the Unifi Controller

Download the pruning script, if you don’t have it already. Edit the file using the following command

vi mongo_prune_js.js

and make sure the following line is there

var days=0;
var dryrun=true;

Then execute the pruning script as below:

sudo /usr/bin/mongo --port 27117 < mongo_prune_js.js

You should see something like the following when it finished pruning

Mongo db pruning

Once it is success you need to run it again but this time edit the mongo_prune_js.js with the following

var days=0;
var dryrun=false;

When it is running completely you should see something similar to the following:

Step 3. run the unifi service

Jump back to the first session, and stop the running mongo db using Ctrl + C. You should be back to your command prompt now.

Start the unify server using the following:

service unifi start

If all goes well you should see the following message

Unifi start service

Double check the log files to ensure that the unifi service started successfully using the following command

tail -f /usr/lib/unifi/logs/mongod.log
tail -f /usr/lib/unifi/logs/server.log

You can also check that your Unifi web interface have started successfully using the following

https://yourunifiipaddress:8443

If you encounter problem pruning because you are running out of space, you can find the files that are big using the following command

find / -type f -size +20M -exec ls -lh {} \; | awk '{ print $NF ": " $5 }'

I hope this post have saved you time and frustration.

Posted on Leave a comment

ESP8266 Light Sleep with MQTT

This is the continuation of the ESP8266 Light Sleep mode. In this post, I will show the practical example of using the Light Sleep mode combined with MQTT. For this to work you will need the following components:

  • ESP8266
  • MQTT broker account (I am using shiftr.io)
  • Temperature Sensor LM35

We are reusing the same temperature sensor in the previous post on ESP8266 Deep Sleep mode. The connection diagram can be seen below:

The idea is to have the ESP8266 in deep sleep most of the time to save the battery power and then only wakes up when the button is pressed. When it wakes up it will connect to the WiFi, take the measurement of the temperature via the temperature sensor and then post it to the MQTT broker. So let’s get started:

Step 1. Defining the MQTT broker connection

The following code defines the MQTT broker, because I am using the shiftr.io service for this example, I am using their test account. For your security you should create your own account and make sure to use your own username and password to post to the “topic”.

// MQTT info
 const char* thehostname = "broker.shiftr.io";
 int port = 10031;
 const char* user = "try";
 const char* user_password = "try";
 const char* id = "ESP8266";

Step 2. Setting up section

Similar to the previous post, we are initialising the serial connection for debugging purposes and initialisation of the GPIO pins. Additionally we need to define the connection to the MQTT broker. This is shown in the following code:

void setup() {
   Serial.begin(115200);
   Serial.println();
   gpio_init(); // Initilise GPIO pins
     // Connect to MQTT
   client.begin(thehostname, net);
   client.onMessage(messageReceived);  
 }

Step 3. Loop() section of code

Different from the Deep Sleep mode, the loop section is where the light sleep mode will wake up and perform the temperature reading and posting the results to the MQTT broker. This is shown in the below code:

void loop() {
   initWifi();
   data();
   delay(200);
   Serial.println("Going to sleep now");
   light_sleep();
   doDelays();
   Serial.println("Wake up");
 }

It is necessary to call initWifi() function first, as this will make sure that when ESP8266 wakes up, the first thing it will do is to connect to the WiFi. Then the data() is where we get the temperature reading (this is explained in step 5), and posting it to MQTT broker at the same time. It is necessary to set a delay after this processing, as the light_sleep() function takes a while to take affect and this is to ensure that the code will not loop back when the ESP8266 is still trying to sleep.

Step 4. InitWifi() function

InitiWifi() function is very similar to the InitWifi() function used in the previous post. The sole purpose of this is to attemp connection to the WiFi and also connecting to the MQTT broker. The code can be seen below:

void initWifi() {
   WiFi.mode(WIFI_STA);
   WiFi.begin(ssid, password);  
 Serial.print("Attempting to connect: ");
   //try to connect for 10 seconds
   int i = 10;
   while(WiFi.status() != WL_CONNECTED && i >=0) {
     delay(1000);
     Serial.print(i);
     Serial.print(", ");
     i--;
   }
   Serial.println("");
   if(WiFi.status() == WL_CONNECTED){
     Serial.print("WiFi connected, IP address: "); Serial.println(WiFi.localIP());
     Serial.print("\nconnecting to MQTT…");
       while (!client.connect(id, user, user_password)) {
         Serial.print(".");
         delay(1000);
       }
       //client.subscribe("/homeautomation/temperature");
   }
     else {
       Serial.println("Connection failed - check your credentials or connection");
   }  
 }

Step 5. Data() function

This section performs the heavy listing by starting to read the LM35 via analog pin A0, then converting this to the temperature value and then posting the value to the MQTT broker in the “/homeautomation/temperature” topic, if the MQTT broker is connected. This is shown in the following code:

void data() {
   int value = analogRead(A0);
   float volts=(value * 3.03) / 1024;      //conversion to volts
   tempC = volts*100.0;             //conversion to temp Celsius
   Serial.print("Temperature C: ");
   Serial.println(tempC);
 if (client.connected()) {
     Serial.println("MQTT client connected");
     client.publish("/homeautomation/temperature", String(tempC));
     delay(1000);
   } else {
     Serial.println("MQTT client not connected");
   }
 }

Step 6. Light_sleep() function

The light_sleep() function similar to the previous post is to force the ESP8266 to go into light sleep for indefinite period of time until the pin GPIO2 (D4) is connected to the GND. The code is shown below:

void light_sleep(){
   wifi_station_disconnect();
   wifi_set_opmode_current(NULL_MODE);
   wifi_fpm_set_sleep_type(LIGHT_SLEEP_T); // set sleep type, the above posters wifi_set_sleep_type() didnt seem to work for me although it did let me compile and upload with no errors 
   wifi_fpm_open(); // Enables force sleep
   gpio_pin_wakeup_enable(GPIO_ID_PIN(2), GPIO_PIN_INTR_LOLEVEL); // GPIO_ID_PIN(2) corresponds to GPIO2 on ESP8266-01 , GPIO_PIN_INTR_LOLEVEL for a logic low, can also do other interrupts, see gpio.h above
   wifi_fpm_do_sleep(0xFFFFFFF); // Sleep for longest possible time
 }

You can access the full source code here.

Once you have uploaded the code to the ESP8266 and wired the connection as per diagram above, you should be able to test the posting. The following image shows my log files when the button is pressed.

I hope you can put this into a good use. Please drop me a line if you like this post and don’t hesitate to let me know if you have any further questions related to this topic. If you like you can subscribe to the blog to receive regular update on IoT related topic.

Posted on Leave a comment

ESP8266 Light Sleep Mode

This is the continuation from the previous blog about ESP8266 Deep Sleep Mode, I am trying to use the other sleep mode. So I embark on the journey to find out how to make use of the Light Sleep Mode. Several codes that I have find causes my ESP8266 to crash miserably.

The concept is to let ESP8266 to Light Sleep indefinitely, only to be waken up when there is a level changes (HIGH to LOW) or (LOW to HIGH) on one of the GPIO pin. This is also called Forced Light Sleep.

After pulling my hair for several days trying to get the Light Sleep Mode to work, I finally figured out how to do this. So here I am sharing my findings. I hope this will be useful for people trying to implement the Light Sleep Mode.

Step 1. Setup() section

Unlike the deep sleep, where most of the working code is in the Setup() section, for Light Sleep, the code will be in the Loop() section, the Setup() section will be used as per normal to initialise the serial connection and initialisation of GPIO pins. This is shown below:

void setup() {
   Serial.begin(115200);
   Serial.println();
   gpio_init(); // Initilise GPIO pins
 }

Step 2. Loop() section

The loop section contains the code where we initialise the WiFi, this is because when during the Light Sleep the WiFi will be off (shown in the above diagram), upon waking up we will need to initialise the WiFi again. The Loop() section code is shown below:

void loop() {
    initWifi();
    // insert working code here e.g.: post Temperature value
    delay(200);
       Serial.println("Going to sleep now");
   light_sleep();
   delay(200);
   Serial.println("Wake up");
 }

As you can see in the code above we start with Initialising WiFi, and then followed by 200 ms delay and we are going to sleep. The sleep code is performed by light_sleep() function. It will only wake up when the GPIO pin is triggered, this will be explained in the next section. When ESP8266 wakes up, it will have 200 ms delay before printing the “Wake up” string in the Serial console, then it will perform the initialisation of WiFi again. Ideally the working code will be inserted after initWifi() function.

Step 3. Light_sleep() function

The Light_sleep() function is used to disconnect the WiFi and then forced the ESP to go to sleep, and defining the GPIO pin that will makes it wake up. This is shown in the code below:

void light_sleep(){
   wifi_station_disconnect();
   wifi_set_opmode_current(NULL_MODE);
   wifi_fpm_set_sleep_type(LIGHT_SLEEP_T); // set sleep type, the above    posters wifi_set_sleep_type() didnt seem to work for me although it did let me compile and upload with no errors 
   wifi_fpm_open(); // Enables force sleep
   gpio_pin_wakeup_enable(GPIO_ID_PIN(2), GPIO_PIN_INTR_LOLEVEL); // GPIO_ID_PIN(2) corresponds to GPIO2 on ESP8266-01 , GPIO_PIN_INTR_LOLEVEL for a logic low, can also do other interrupts, see gpio.h above
   wifi_fpm_do_sleep(0xFFFFFFF); // Sleep for longest possible time
 }

As you can see in the code above, we are using GPIO pin 2, (D4) to wake up the ESP8266 from the Light sleep. It will wake up when D4 is changing transition from HIGH to LOW as per the code above.

To be able to use this we need to include the gpio.h in the definition. This is done in the code below:

extern "C" {
   #include "gpio.h"
 }

We also need to include user_interface.h to allow us to the the LIGHT_SLEEP_T delay mode as shown in the following code:

// Required for LIGHT_SLEEP_T delay mode
 extern "C" {
   #include "user_interface.h"
 }

Finally, last but not the least, for completeness, I have also included the initWifi() function as below to connect to WiFi:

void initWifi() {
   WiFi.mode(WIFI_STA);
   WiFi.begin(ssid, password);
   while ((WiFi.status() != WL_CONNECTED)) {
      delay(500);
      Serial.print(".");
   }
   Serial.println("");
   Serial.print("WiFi connected, IP address: "); Serial.println(WiFi.localIP());
 }

You can see it in action, on the following video:

That’s all for now, I hope you are able to use the Light sleep function without too much trouble. Please let me know if you have any questions, and don’t forget to subscribe to get more tips on IoT projects.

Posted on Leave a comment

ESP8266 Deep sleep with MQTT

This is the continuation of the previous post regarding ESP8266 Deep sleep. In that post we discussed about how to utilise the deep sleep mode to save the power and wake up only to read temperature and post the result. In this post we will utilise the same mechanism, the ESP8266 will perform the deep sleep and only wake up every 2 minute to read the temperature and post the result to MQTT broker.

Defining the connection

The MQTT broker we use for this example is shiftr.io, you can get a free account with them if things are starting to get serious. In this example we are only using the default try account, so the definition is done as below:

// MQTT info
 const char* thehostname = "broker.shiftr.io";
 int port = 10031;
 const char* user = "try";
 const char* user_password = "try";
 const char* id = "ESP8266";

Setting up

When the ESP8266 wake up, it will need to first initialising the WiFi, initialising the connection to the MQTT host, in this case the “broker.shiftr.io”. Then the connectToWifi() function will be called, this is the procedure that actually trying to connect to the wifi, and when success it will connect to the MQTT broker. Once this is all done, the program will then read the analog temperature sensor connected to A0,and post the data using data(), and goes back to sleep for another 2 minutes. The setup() function looks like the following:

void setup() {
   Serial.begin(115200);
   Serial.println("device is in Wake up mode");
   while (!Serial) { }
     Serial.print("Connecting to: SSID NAME"); //uncomment next line to show SSID name
   //Serial.print(ssid); 
   WiFi.begin(ssid, password);  
   Serial.println(" ");// print an empty line
   // Connect to MQTT
   client.begin(thehostname, net);
   client.onMessage(messageReceived);  
   connectToWifi();
   int value = analogRead(A0);
   float volts=(value * 3.03) / 1024;      //conversion to volts
   tempC = volts*100.0;             //conversion to temp Celsius
   Serial.print("Temperature C: ");
   Serial.println(tempC);
   data();
   Serial.println("deep sleep for 120 seconds");
   ESP.deepSleep(120e6); 
 }

Connecting to Wifi and MQTT

The connectToWifi() function is attempting to connect with a second delay until 10 tries, when it is successful, it will then attempt to connect to the MQTT broker with a second delay in between tries. Upon successful connection it will subscribe to “/homeautomation/temperature” node. The code is described as below:

void connectToWifi() {
 Serial.print("Attempting to connect: ");
   //try to connect for 10 seconds
   int i = 10;
   while(WiFi.status() != WL_CONNECTED && i >=0) {
     delay(1000);
     Serial.print(i);
     Serial.print(", ");
     i--;
   }
   Serial.println(" ");// print an empty line
   //print connection result
   if(WiFi.status() == WL_CONNECTED){
     Serial.print("Connected."); 
     Serial.println(" ");// print an empty line
     Serial.print("NodeMCU ip address: "); 
     Serial.println(WiFi.localIP());
     Serial.print("\nconnecting to MQTT…");
     while (!client.connect(id, user, user_password)) {
       Serial.print(".");
     delay(1000);
   }
     client.subscribe("/homeautomation/temperature");
   // client.unsubscribe("/hello");
   }
   else {
     Serial.println("Connection failed - check your credentials or connection");
   }  
 }

Posting the temperature to MQTT broker

The function data() will post the temperature data to MQTT broker, this is shown below:

void data() {
   if (client.connected()) {
     Serial.println("MQTT client connected");
     client.publish("/homeautomation/temperature", String(tempC));
     delay(1000);
   } else {
     Serial.println("MQTT client not connected");
   }
 }

If all is well you will see the temperature is posted in the shiftr.io broker as shown in the following picture

If you would like to get the full source code, it can be found in the following link. That would be all for today, I hope you like this post, and don’t forget to subscribe for more similar post related to Arduino and IoT.