Light Sensor for MQTT broker

Video Coming Soon – Spoilers!

Construction zone ahead.

SUMMARY:

The idea of this project is to create a Light Sensor that can measure the light level and then report this back to a MQTT broker, which can then publish this reading to other devices, for example a relay connected to a light that can then turn on or off depending on the light level.

PLAN:

As we need to connect to the home network to transmit the light level readings back to the MQTT broker at least once a minute, to do this we will use an ESP8266 that can connect to the wifi and talk directly to our broker. For measuring the light we will use a LDR (Light Dependent Resistor) connected to A0 (Analog Input) on our ESP8266, this will allow us to use the inbuilt analog to digital converter to get a scaled light reading. Also a bias resistor will be required.

PARTS:

  • 1x WiMos (ESP8266)
  • 1x LDR
  • 1x 1K resistor
  • 1x mini breadboard

BUILD:

The build is pretty simple as it only involves a few parts. If using a bread board you can connect the circuit like this:

How does it work?

The LDR acts like a resistor, however as light shines on the resistor it changes it’s resistance allowing more or less current to flow proportional to the light shining on it. The darker the LDR the higher the resistance reducing current flow through R1 and lowering the voltage across R1. This voltage across R1 is fed into our ESP8266 (WeMos) on the A0 pin. A0 pin is the inbuilt 10 bit analog to digital converter. In the opposite direction as more light shines onto the LDR the resistance drops on the LDR allowing more current to flow through R1 and a higher voltage to be presented at A0 of the WeMos.

A0 is connected internally to a 10 bit analog to digital converter, which gives us 1024 steps between 0v and 3v3. So if we take the maximum of 3.3 volts and divide it by 1024 we get 3.22mV per step, which for our use gives us plenty of resolution.

The program will connect to the wifi first, then connect to the MQTT broker. Here is where the program begins looping endlessly. When entering the start of the loop we first need to check if we have a connection to the wifi, and next if we have a connection to the broker. If all is going good we then read in a light reading from the LDR, compose this reading into a message the broker can understand and send it to the broker.

The flow of the program is as follows

DEFINITIONS/INCLUDES

We start by including 2 required libraries, first the ESP8266WiFi.h used to connect to the WiFi and secondly PubSubClient.h used to publish and subscribe to the MQTT messages.

#include <ESP8266WiFi.h>
#include <PubSubClient.h>

Define the wifi settings in ssid and password and create a WiFiClient object

 const char* ssid = "<Enter SSID>";
 const char* password =  "<Enter Wifi Password>";
 WiFiClient espClient;

Followed by some constants to contain the MQTT server details and MQTT topic to post to

 const char* mqttServer = "<Enter MQTT broker IP/address>";
 const int mqttPort = 1883;
 const char* mqttUser = "<Enter MQTT broker username>";
 const char* mqttPassword = "<Enter MQTT broker password>";
 #define MQTTtopic "ldr/value"

Next we define a couple of variables for the input output pins we will use. In out case “A0” is the analog input and “2” is the inbuilt blue LED pin

 define ldrPin A0
 define espLEDpin 2

SETUP routine

As we know the setup routine will only run once at the start of the program so any code that need to run once to start and setup is put here. In our code we set the GPIO pin directions, start the Wifi and connect to our Wifi access point, flashing the onboard blue LED while the wifi is attempting to connect. and finally we set our MQTT broker’s server address and port.

void setup() {
   //Setup the onboard ESP blue led as an output so we can turn it on and off
   pinMode(espLEDpin, OUTPUT);
   pinMode(ldrPin, INPUT);
 //Wifi Start connecting 
   WiFi.begin(ssid, password);
 //Loop until Wifi connects
   while (WiFi.status() != WL_CONNECTED) {
     delay(1000);
     // Toggle onboard ESP blue led
     digitalWrite(espLEDpin, !digitalRead(espLEDpin));
   }
 // Turn off onboard ESP blue led (inverted so High = off)
       digitalWrite(espLEDpin, HIGH);
 //define the MQTT broker
   client.setServer(mqttServer, mqttPort);
 }

LOOP routine

As we know the LOOP routine will run the code between the first “{” and the last “}” looping around endlessly.

Our loop first does a digitalWrite to the espLEDpin to turn on our little blue LED before checking whether the WiFi is still connected or not. If our WiFi has dropped out then delay 60000 mS (60 Seconds) then force a restart with the ESP.restart() command. Otherwise continue on and go and attempt to connect to the MQTT broker. If a connection is not made the the “while / else” causes our code to endlessly reattempt reconnecting after a 2 second delay until a connection is made.

Now we have established a connection to the broker we take a reading from the LDR sensor using “analogRead”. As we will be publishing a String to the broker we need to convert the digital 10bit value (0 to 1024) to a String. The “itoa” function takes in 3 variables, 1. the value to convert, 2. a variable to output the String into and 3. finally the base used, for normal decimals a base 10 is used. This handy little code can also be used with other bases like binary or hexadecimal.

Tle second last step before looping around is to publish our LDR light reading to the MQTT broker using the “client.publish” function. We are using 3 variables with the publish function 1. the topic to post to, 2. the variable containing the String to post, and finally “true” or “false” sets whether the broker retains (true) the message or not (false). We will use the “true” so it will retain the message, meaning the message will remain permanently till it is updated again, allowing multiple devices to access the last reading at any time convenient to them.

void loop() {
  //Turn on onboard LED
  digitalWrite(espLEDpin, LOW);
  // check if wifi is still conected 
  //otherwise wait 1 minute and reboot ESP
   if (WiFi.status() != WL_CONNECTED) {
     delay(60000);
     ESP.restart();
   }
//Attempt to connect to the MQTT broker 
//if connection closed and loop untill conected
 while (!client.connected()) {
 if (client.connect("ESP8266Client", mqttUser, mqttPassword )) {   //Turn off onboard LED   
digitalWrite(espLEDpin, HIGH);   
delay(100); 
} else {   
delay(2000); 
}
 }
 // input Ax value
 //Take a LDR reading and turn the RGB leds back on
   int ldrValue = analogRead(ldrPin);
 //Convert the reading to a string and publish it to the MQTT broker
   char cstr[4];
   itoa(ldrValue,cstr,10); 
 //Publish the LDR reading to the MQTT broker
   client.publish(MQTTtopic, cstr,true);
 //Wait X mS before looping to the beginning of the LOOP function
   delay(10000);    

READING ANALOG VALUES:

Just a little more info on the reading of the analog values into our ESP device. The code our ESP8266 uses to read the A0 pin’s analog value is very similar to that on an Arduino. First in the setup routine we define the A0 as an input by using the pinMode command

pinMode(A0, INPUT);

To actually read in a value to a variable ldrValue we will use the analogRead command

ldrValue = analogRead(A0);

In order to see the value in a serial monitor you can use the Serial.println command, to send the value to the serial monitor using

Serial.println(ldrValue);

But dont forget if you plan to use the serial monitor you need to have first started the serial console int he setup routine with the command

Serial.begin(115200);

Hope you find this project helpful

Leave a Reply

Your email address will not be published. Required fields are marked *