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 Deep sleep mode

I always wanted to learn about the deep sleep mode in ESP8266. So I stumble across a few post in the internet, and comparing various post, there are several ways the ESP8266 can perform the deep sleep. They are:

  1. Deep-sleep
  2. Light-sleep
  3. Modem-sleep

Each mode can be described in the following tables:

As you can see in the table above, the point to have Deep-sleep is to conserve as much current as possible. In all mode above the Wi-Fi will be off. This will ensure that maximum power saving is achieved. In Deep-sleep the only things that awake is the RTC, so the typical application for this would be for a sensor reading that will happened periodically to take up every few minutes for non mission critical and update the reading. A good example for this would be a temperature sensor that wakes up every few seconds or even minutes to read the temperature and update this reading, this can be through MQTT, Thingspeak or IFTTT.

According to ESP8266 SDK, you can only sleep for 4,294,967,295 µs which is about 71 minutes.

Wake up Trigger

When ESP8266 is in Deep-sleep, it will need a mechanism to wake-up, given that everything, including CPU is OFF. The only thing that is still on is RTC. To wake up that means we have 2 options, first one is to set the time to wake up, and the second one is to press the reset button on the ESP8266 to wake it up. The first one can be done using the following code:

ESP.deepSleep(15e6);  // deep sleep for 15 seconds

To allow this to happen you will need to connect the WAKE up pin GPIO 16 (D0) to the RST pin. This can be shown in the following diagram:

Please note that when the RST is connected to D0, this will not allow the code to be uploaded to the ESP8266. The suggestion is to have a jumper or switch to allow the control of the connection between RST and D0 pin.

So with a practical example to allow reading of temperature sensor every 15 seconds we can modify the circuit above by adding the LM35 temperature sensor and a switch to allow connection and disconnection between RST and D0. This is shown in the following diagram:

The normal setup() function will need to contain the code to connect to WiFi and the posting of the reading of the temperature. This can be done using the following code:

void setup() {
   Serial.begin(115200);
   Serial.println("device is in Wake up mode");
   while (!Serial) { }
   connectToWifi();                // connect to WiFi
   int value = analogRead(A0);
   float volts=(value * 3.03) /1024;      //conversion to volts   
   tempC = volts*100;             //conversion to temp Celsius
   Serial.print("Temperature C: ");
   Serial.println(tempC);
   data();                       // post data else where
   Serial.println("deep sleep for 15 seconds");
   ESP.deepSleep(15e6); 
 }

In the code above once the ESP8266 wake up, the first thing it will do is to connect the the WiFi via the connectToWifi() function. Then it will read the sensor reading from A0, and convert this reading to celsius and posted the data and go back to sleep. The connectToWifi() function is shown below:

void connectToWifi() {
   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
   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());
   }
   else {
     Serial.println("Connection failed - check your credentials or connection");
   }
 }

Thus, the loop() function will not contain any code, as this will never get executed at all. This is shown below:

void loop() {
   //if deep sleep is working, this code will never run.
   Serial.println("This shouldn't get printed");
 }

This conclude my learning on ESP8266 Deep sleep, please let me know if it is useful and don’t forget to subscribe for more and don’t hesitate to let me know if you have any questions.

Posted on Leave a comment

Connecting IoT Sensors data to Node-RED

This is the continuation of the Temperature sensor project in the previous post. The concept is to allow the data from sensors (temperature, motion) can be displayed in Apple Homekit, so that the user can interact with the information and control the IoT connected devices (Lights, Fan, etc). It is best described in the following picture.

The following instruction shows how to install Node-RED on a linux computer running Debian OS.

sudo npm install -g --unsafe-perm node-red

You will also need to install the mosquitto MQTT message broker, here are the command required

sudo apt-key add mosquitto-repo.gpg.key
sudo wget http://repo.mosquitto.org/debian/mosquitto-jessie.list
sudo apt-get update
sudo apt-get install mosquitto

You will also need the latest Python library, so grab them using the following instruction

sudo apt-get install python-dev

Test the installation. In this example I was using Linux Debian, so typing the command node if you get the following in the command prompt, that means the installation is successful. So then you can exit node by typing .exit command in the prompt >.

If all goes well, you can run the node-red command in the command prompt. You should get the following message. This shows that the node-red is now running at http://127.0.0.1:1880.

Node-RED Settings

Node-RED setting file called settings.js, on Linux it is located in the /usr/lib/node-modules/node-red folder. You will have another settings.js file in the .node-red folder in your home folder. This setting will be loaded by default.

Creating the flow in Node-RED

Now that you have a running Node-RED, it is time to create the flow. In this example we will create a simple flow to read temperature posted by our ESP8266. Let’s start by firing up your favourite browser and point to the following URL: http://127.0.0.1:1880/

You will be presented with a blank screen similar to the following picture. Now to start creating a flow, drop an “Inject” node from input section. We will use this as a trigger to get the temperature reading. Once you dropped it in, double click to set the property. We call the node “timestamp” and we set the interval to repeat every 4 minutes.

The next step is to connect this with an “http” node, so drop an “http” node and configure this as http GET to call a server side script in the webserver. What the script needs to return is the temperature in JSON format as below:

{"CurrentTemperature":25}

So my data_store2.php script does exactly that, as shown in the following code:

 /* readtemperature file from temp.txt file    return the value back in JSON format for HomeKit  */ 
$theparam = $_GET;
$file = './temp.txt';
$temperature = file_get_contents($file);
echo '{"CurrentTemperature":'.$temperature.'}';

Now the final step is to connect to the “Homekit” node from the Advance nodes menu. Once you drop the “Homekit” node, you can double click to configure the property as below.

Once all had been connected, it is time to deploy the node. You can do this by clicking on the “Deploy” button at the top of the Node-RED window. You will need to click the “Deploy” button whenever you make any changes to the node. Sometime the deployment might stop the Node-RED server, so you just have to run the node-red command again in the command prompt.

If all goes well, you can now test this node by clicking on the button next to “timestamp” node, the temperature should be read from the webserver and displayed in Homekit, similar to the following picture.

That conclude this session on how to configure the Node-RED to work with our temperature sensor data from ESP8266. Please let me know if you have any questions related to this and don’t forget to subscribe for update on the similar projects. The next session we are going to connect this to the Apple homekit in IPhone or IPad.

Posted on Leave a comment

Connecting Touch sensor to Bluetooth Amplifier

TTP223 Touch sensor

First of all, I would like to wish everyone a Happy New year of 2019, this will be my first post of 2019. I hope you had a great start of the year.

I had discovered a capacitive touch sensor TTP223 which simulate a switch function by “touch”, it is using the capacitive of your hand or any other organic matter to allow the switch function. It can be configured to as “Toggle” or “On/Off”.

I recently post a review about various Bluetooth Amplifier that I had been testing. And the CSR8635 Dual 5W Bluetooth Amplifier had a particular interesting feature where you can “Skip” tracks, “Vol+” Vol-“, “Play/Pause” which also double up as “Pick up” call function. The problem with this is the Switch needs to connect each function to the “common” connection. So I am trying to experiment whether this will work using the touch sensor above.

Touch Sensor and Bluetooth Amplifier

The picture on the left shows how the functionality of the touch sensor. When the touch area is being touch, it will connect the I/O pin to the Vcc. While the Bluetooth Amplifier switch needs to connect the “Next” pin to the “common” pin. After some research the common pin is connected to Vcc. So I wonder whether I can connect the I/O pin straight away to the “Next” pin. So I had experimented using the circuit below, and it seems to work ok.

Connecting the Touch Sensor to Bluetooth Amplifier control pins

So I had connected a 10K ohm resistor to limit the current that flow from Vcc of the touch sensor to the Bluetooth amplifier. It seems to be working ok at this stage. I had connected 2 pin, the “Next” pin and “Play/pause” pin. Both seems to work ok.

You can see the final connection in the following picture.

Touch sensors connected to Bluetooth Amplifier controls

If you like this, please let me know or subscribe to the blog to receive frequent tips on simple circuits.