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

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.

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

Publish MQTT using Javascript

Continuation to the previous post about the Automatic IoT Gate control, once we have connected the ESP8266 gate Opener to listen to the message broker, we will need a mechanism to be able to publish the message to the node it was listening to.

In the previous post, the ESP8266 was listening to the “/homeautomation/gate” topic. So in this post we are trying to create a simple website to publish “ON” and “OFF”message to this topic. This can be achieved with the following Javascript code:

<script src="https://assets.shiftr.io/js/mqtt-2.9.0.js"></script>
<script>
// Note: This line is only required when running in node.js 
var client = mqtt.connect('mqtt://try:try@broker.shiftr.io', {
    clientId: 'ESP8266' 
}); 
client.on('connect', function(){
       console.log('client has connected!');   
});
</script>
<script language="javascript">
function colorchange(id){
     var xmlhttp;
     xmlhttp=new XMLHttpRequest();
     if(document.getElementById(id).name == 'OFF' ){
         client.publish('/homeautomation/gate', 'ON');
         document.getElementById(id).name = 'ON';
         xmlhttp.open("GET","a.htm?ON",true);
         xmlhttp.send();
 } else { 
    client.publish('/homeautomation/gate', 'OFF'); 
    document.getElementById(id).name= 'OFF'; 
    xmlhttp.open("GET","a.htm?OFF",true);
    xmlhttp.send(); 
}
}
</script>

In the code above, we are using the broker.shiftr.io as the MQTT broker, and I am using their public try:try account, so please change this to your own account and password to ensure security.

The html code is crafted in such a way using the css to make it looks like an ON/OFF button, this is shown below, full credit to the author that made such and outstanding button.

The code that publish the “ON” message is executed from the “colorchange” function as below:

client.publish('/homeautomation/gate', 'ON');

and the code that publish the “OFF” message is executed from the same function as below:

client.publish('/homeautomation/gate', 'OFF');

If all is well you should see the “ON” and “OFF:” message being published to /homeautomation/gate topic, as shown in the below screen shot.

The full source code for the html page can be found in the following link. Please let me know if you like this post and subscribe for more projects related to IoT. Feel free to share this also.

Posted on Leave a comment

Connecting the IoT Remote Gate Opener to MQTT

Now that we have a reasonable understanding about MQTT, we can connect our IoT Gate Remote from the previous post to the MQTT broker.

The idea is to have our Remote Gate opener listen to the message in the MQTT broker. Looking at our previous example, we have setup 2 topics in the message broker, “/homeautomation” and “/hello”, we can expand the “/homeautomation” into

/homeautomation/gate

When a message is send to “/homeautomation/gate” topic, our ESP8266 will get the message and we can act on it, which mean we can open or close the gate.

So we need to modify the code so that we can subscribe to this topic. This can be done with the following:

MQTTClient client; 
// MQTT info
 const char* thehostname = "broker.shiftr.io";
 const char* user = "tokenusername";
 const char* user_password = "tokenpassword";
 const char* id = "ESP8266";

Serial.print("\nconnecting…");
   while (!client.connect(id, user, user_password)) {
     Serial.print(".");
     delay(1000);
   }
Serial.println("\nconnected!");
client.subscribe("/homeautomation/gate");

Once this you had subscribe to the topic, we need to modify the code to perform the action when we received the message. In this example let us assume the message that we are going to receive is “OPEN”. Assuming we have the following code in the Setup() section:

void setup() {  
...
  client.begin(thehostname, net);
  client.onMessage(messageReceived);
...
}

And to act on the message, we need to process the message in the messageReceived() function as below:

void messageReceived(String &topic, String &payload) {
   Serial.println("incoming: " + topic + " - " + payload);
if (payload == "OPEN"){
// open the door
digitalWrite(LEDpin,LOW); //LED ON
} else if (payload == "CLOSE") {
// close the door
digitalWrite(LEDpin,HIGH);
}
}

Now you should be able to control the Remove Gate from the internet. We can test this by posting the “OPEN” and “CLOSE” message to the topic.

I hope you enjoy this post, if you have any questions please don’t hesitate to ask and subscribe to my blog to get more frequent update on projects that I am currently working on.

Posted on Leave a comment

IoT Remote Gate Opener

I am helping my brother to make a remote Gate opener. He have a remote that can open the gate, but being in this day and age, we would like to connect everything to the Internet. So the concept can be seen in the following picture:

IoT Remote Gate Opener circuit
Remote Gate Opener

The brain consist of ESP8266, which is connected to relay that will trigger the remote. The original idea is to have some sort of sensor (magnetic) that can be detected using Hall Effect sensor to detect when the gate had been closed or opened. Then to be able to access this remotely from anywhere in the world, we can connect this to Node-RED and subsequently able to access this via Apple Homekit.

To start off as the proof of concept and to reduce the complexity, we revert back to the basics, by just connecting the ESP8266 to a relay that will activate the remote to open and close the Gate door. To start off follow the following steps:

Step 1. Gather the components

Components for ESP8266 with Relay

We will need ESP8266, Relay module, and PCB to connect the two together. You can connect the two module together by soldering it on to the PCB. Connect the 3.3 Volt pin from ESP8266 to VCC of the Relay module, and GND from the ESP8266 to the GND of the Relay module, and finally for this example, I am connecting the pin D5 to the IN pin of the Relay module. Note that the Relay IN is active LOW, this means that the relay will be activated (Green LED on Relay board turn ON) when IN is LOW. The fully assembled board looks like the following picture.

Fully assembled ESP8266 with Relay module

Step 2. Modify the Remote

Remote Modification
Remote Wiring

In the image above, we solder 2 wire across the button that can activate the Gate. This two wire will be connected by the Relay module later on.

Step 3. Uploading the Arduino Code

The idea is to use ESP8266 as a webserver. This will allow us to show a setting page to connect the ESP8266 to the WiFi without having to hardcode the WiFi access points in the code. The website will also serve as the command to turn the Relay ON and OFF. Thanks for the handy work of Martyn Currey on how to create JavaScipt and AJAX within the ESP8266, and also some AJAX code to update ESP8266 from Circuits4you, I was able to massage the AJAX code into my previous Arduino code for the Temperature sensor. The final result looks like the following picture.

ESP8266 Webserver
ESP8266 Webserver

Once the ESP8266 is connected to the WiFi, only then the “Switch” button will appear in the webserver interface. When the ESP8266 is not connected to the WiFi, by default it will revert to be an Access Point, this will allow you to connect and configure the WiFi settings.

When you click on the “Switch” it will turn the relay ON, and thus simulating the press of the remote button to open the gate. Because we don’t have any feedback from the Gate in this solution, we will need to turn the “Switch” off manually, otherwise the button on the gate remote will be pressed and the battery will drain.

In the next section we will dive in a bit deeper into the Arduino code. If you are not interested in the code, you can skip this section and just upload the code straight away into the ESP8266. When the ESP8266 load up the first time you will be able to see the AP as coded in “settings.h” file. The AP name is “ESP-Gate” with the default password defined in the file. You can change this to make sure it is much more secure.

define CLOCK_NAME "ESP-Gate"
define WIFI_AP_NAME CLOCK_NAME
define WIFI_APPSK "DefaultAPPassword" // default AP password

Step 4. Arduino Code deep dive

The Arduino code comes in 5 files, and here are the list of the files:

  1. ESP8266GateSwitchV2: This is the main file where the magic happens. Pay special attention to the following sections (void setup(), void handleLED(), void handleRoot(), void loop()).
  2. Clock.h: This file is the header file for the CLOCK
  3. mainPage.h: This file is the webserver html file which get served when you connect to the ESP8266 web server
  4. ntp: This file consist of the function to connect to the ntp server to synchronise the clock
  5. settings.h: This file contain most of the settings for the project.

Void setup() section

#include <ESP8266WebServer.h>
// Create an instance of the server
// specify the port to listen on as an argument
ESP8266WebServer server(80);

void setup() {
DebugStart();
timer = 200;
pinMode(LED_BUILTIN, OUTPUT);
pinMode(LEDpin, OUTPUT); // setup LED
digitalWrite(LEDpin, HIGH); // Relay Active LOW
setupWiFi(1); // SetupAP mode
setupTime();
server.on("/", handleRoot);
server.on("/form", handleForm);
server.on("/setLED", handleLED);
server.begin();
}

This section will initialise the LEDpin, which is the trigger connected to the IN input of the Relay module. We will need to set the LEDpin to HIGH, because the relay module is active LOW. Initially setupWiFi will be called to try to connect to the WiFi, if this fail the program will defaulted to AP mode. SetupTime() will attempt to setup the time by synchonising the time with ntp server. The next couple of line define what function will be called when the webserver is being invoked. For example, handleRoot function will be called when the root of the webserver is being accessed. The handleForm function will be callled when the “/form” is being called, this is called when we setting up the Wifi parameter as well a a few other settings of the clock, daylight savings, etc. Finally “/setLED” will be called when we “button” is being pressed to activate the Relay.

void handleLED() section

void handleLED() {
String ledState = "OFF";
String t_state = server.arg("LEDstate"); //Refer xhttp.open("GET", "setLED?LEDstate="+led, true);
Serial.println(t_state);
if(t_state == "1"){
digitalWrite(LEDpin,LOW); //LED ON
ledState = "ON"; //Feedback parameter
}
else {
digitalWrite(LEDpin,HIGH); //LED OFF
ledState = "OFF"; //Feedback parameter
}
server.send(200, "text/plane", ledState); //Send web page
}

If we look at the handleLED function above, this is where the Relay is being activated. When the AJAX code post the LEDstate parameters back to the webserver, this section will check whether the LEDState parameter value is equal to 1 or 0, if it is 1, the code will write LEDpin output to LOW, and activate the Relay, and if the parameter value is 0, the code will write LEDpin output to HIGH, and deactivated the Relay. The ledState feedback parameter is just to make our life easier when debugging the code, this will show on the website whether the ledState is ON or OFF via AJAX return code.

void loop() section

void loop() {
server.handleClient();
if (timeStatus() != timeNotSet){
time_t t = now();
}
}

This section of the code is very simple, all it needs to do is to make sure the server.handleClient() function is called, to ensure that ESP8266 will allow client to connect to it’s webserver.

void handleRoot() section

void handleRoot() {
DebugLn("handleRoot");
String s = MAIN_page;
if (WiFi.status() == WL_CONNECTED) {
s += ButtonControl;
// check led state
boolean pinStatus = digitalRead(LEDpin);
if (pinStatus==LOW) {
s.replace("@@NA@@", "ON");
s.replace("@@SW@@", "ON");
s.replace("@@Checked@@", "checked");
}
else {
s.replace("@@NA@@", "OFF");
s.replace("@@SW@@", "OFF");
s.replace("@@Checked@@", "");
}
}
s+= WifiSetting;
time_t t = now();
s.replace("@@SSID@@", settings.ssid);
s.replace("@@PSK@@", settings.psk);
s.replace("@@TZ@@", String(settings.timezone));
s.replace("@@USDST@@", settings.usdst?"checked":"");
s.replace("@@HOUR@@", String(adjustedHour(t)));
s.replace("@@MIN@@", String(minute(t)));
s.replace("@@NTPSRV@@", settings.timeserver);
s.replace("@@NTPINT@@", String(settings.interval));
s.replace("@@SYNCSTATUS@@", timeStatus() == timeSet ? "OK" : "Overdue");
s.replace("@@CLOCKNAME@@", settings.name);
s.replace("@@UPDATERESPONSE@@", httpUpdateResponse);
httpUpdateResponse = "";
server.send(200, "text/html", s);
}

This section deals on how the root of the webserver should look like. It will first get the MAIN_page content from mainPage.h file, and then substitute the checkbox status based on the reading of the LEDpin. If the currently the LEDpin is LOW, that means the switch is active, so it will need to show the “switch” as on. And if the reading is HIGH, this means that the switch is not active, so it will need to show the “switch” as off. Then the rest of the code is to display the WiFi SSID, time zone, ntp server, update interval, device name.

I hope you like this post, and please subscribe if you haven’t done so. And let me know if you have any questions.

Posted on Leave a comment

Connecting ESP8266 to MQTT broker

So what is MQTT, according to mqtt.org, it is a connectivity protocol used to connect machine to machine, used for Internet of Things (IoT). It was designed as an extremely light weight publish/subscribe messaging transport. In short it is the messaging designed for Internet of Things devices to allow robust connectivity when faced with challenged bandwidth limitation, and power consumption. It stands for Message Queuing Telemetry Transport.

MQTT how it works

The concept of MQTT is a Publish/Subscribe system. This means that there is at least one system that publish a message on a topic and there is at least one system that subscribe to the “topic” to receive “messages”. The “Messages” are information that are being exchange between the devices. “Topic” are series of strings separated by a forward slash (/), each topic is separated by the forward slash.

MQTT Broker

MQTT Broker is responsible for receiving messages and forwarding the messages to the devices that are interested (Subscribed) to the topic. There are a few MQTT Broker that you can use. In this example we will use the one called https://shiftr.io/try.

You can also installed your own message broker (Mosquitto broker) into Raspberry Pi to relay all the messages for your home automation projects.

Getting Started with MQTT Broker

Start by getting a free account with shiftr.io, then follow the documentation to create the Namespace and Token. The Token is username and password pair that will be used to authenticate the client, the one that will publish or subscribe to the messages. The token will be used in the following section of the code:

const char* user = "tokenusername";
const char* user_password = "tokenpassword";

You will need to download the MQTT library to send the message to the MQTT broker. The initialisation is done using the following code:

#include <MQTT.h>
MQTTClient client;

During the setup you will need to connect the onMessage event to the function that be executed when the message is received, this is done with the following code:

void setup() {  
...
client.begin(thehostname, net);
client.onMessage(messageReceived);
...
}

In the loop section of the code, you will need to execute the client.loop() function and the following code will try to connect to the message broker and at the same it will publish “Alive” message to the “/hello” topic.

void loop() {
client.loop();
if (!client.connected()) {
connect();
}
// publish a message roughly every second.
if (millis() - lastMillis > 1000) {
lastMillis = millis();
client.publish("/hello", "Alive");
}

}

Here are the connect() function, which will attempt to connect to the WiFi and upon connection will subscribe to the “/hello” topic.

void connect() {
Serial.print("checking wifi…");
while (WiFi.status() != WL_CONNECTED) {
Serial.print(".");
delay(1000);
}
Serial.print("\nconnecting…");
while (!client.connect(id, user, user_password)) {
Serial.print(".");
delay(1000);
}
Serial.println("\nconnected!");
client.subscribe("/hello");
// client.unsubscribe("/hello");
}

Here are the full source code from the example above:

// MQTT Test client
//
// 128x64 OLED pinout:
// GND goes to ground
// Vin goes to 3.3V
// Data to I2C SDA (GPIO 4)
// Clk to I2C SCL (GPIO 2)
// Add MQTT
#include <TimeLib.h>
#include <ArduinoJson.h>
#include <ESP8266WiFi.h>
#include <SSD1306.h>
#include <SSD1306Wire.h>
#include <MQTT.h>

char ssid[] = "ssidname"; // your network SSID (name)
char pass[] = "ssidpassword"; // your network password (use for WPA, or use as key for WEP)
int keyIndex = 0; // your network key Index number (needed only for WEP)
int status = WL_IDLE_STATUS;
WiFiClient net;
MQTTClient client;
unsigned long lastMillis = 0;
// MQTT info
const char* thehostname = "broker.shiftr.io";
const char* user = "tokenusername";
const char* user_password = "tokenpassword";
const char* id = "ESP8266";
SSD1306 display(0x3c, 4, 2); //0x3d for the Adafruit 1.3" OLED, 0x3C being the usual address of the OLED
void connect() {
Serial.print("checking wifi…");
while (WiFi.status() != WL_CONNECTED) {
Serial.print(".");
delay(1000);
}
Serial.print("\nconnecting…");
while (!client.connect(id, user, user_password)) {
Serial.print(".");
delay(1000);
}
Serial.println("\nconnected!");
client.subscribe("/hello");
// client.unsubscribe("/hello");
}
void messageReceived(String &topic, String &payload) {
Serial.println("incoming: " + topic + " - " + payload);
}
void setup() {
//Initialize serial and wait for port to open:
Serial.begin(115200);
//Setup Rest Client
WiFi.begin(ssid, pass);
Wire.pins(4, 2); // Start the OLED with GPIO 4 and 2 on ESP-01
Wire.begin(4, 2); // 4=sda, 2=scl
display.init();
display.flipScreenVertically();
display.drawString(0, 24, "Connected.");
display.display();
client.begin(thehostname, net);
client.onMessage(messageReceived);
connect();
delay(1000);
}
int timer =0;
void loop() {
client.loop();
if (!client.connected()) {
connect();
}
// publish a message roughly every second.
if (millis() - lastMillis > 1000) {
lastMillis = millis();
client.publish("/hello", "Alive");
}
//delay(1000);
}

If everything goes well, you should be able to see the message being published to the topic that you are monitoring. In the example above the message will go from the ESP8266 device to the /hello topic.

The message being published is “Alive” message, as shown at the top left hand corner. This will keep being published every seconds.

That’s all for now, I hope this post is useful as an introduction to the MQTT. Please share this if you like, or provide some comments. The next step from here is to modify the Temperature sensor to use the MQTT, stay tune if you would like to know about this.