Projects

WiFi Temperature Sensor with Scrolling Display

Peter Stewart

Issue 60, July 2022

This article includes additional downloadable resources.
Please log in to access.

Log in

This ESP8266-based project shows the current temperature on a scrolling LED display.

It is human nature to want to know what the temperature is. Whether it is outside, another town, in the pool, in the fridge or many other locations. I myself monitor the temperature in my pool, on my patio, in my fridge, in my freezer, in my garage and in my garage roof storage area. I display all these temperatures via my Home Automations System (HAS).

The home page of my HAS as seen on my Desktop computer is shown here. (See also the “Temperature Graphs” shown enlarged.) I can also access my HAS on my iPhone with similar displays.

You might think I am a little obsessed with knowing the temperature in many areas of my property. There are good reasons for this. Knowing the temperature inside my Fridge and Freezer lets me know that all the food my wife stores in them is safe and at the right temperature. In my garage roof, I store many items which I value.
The temperature in my garage roof can exceed 50°C in summer. My HAS examines the temperature and when it exceeds 30°C, my HAS turns on the fan I have in the roof to remove some of the heat.

Now, all these Temperature Sensors use WiFi to send data via my WiFi router using the Message Queueing Telemetry Transport (MQTT) protocol. Now, you might be a bit suspicious on how all these sensors in many different locations around my house including inside my fridge and freezer can actually communicate through metal containers and walls to my WiFi Router.

I did cheat a little. I installed a WiFi Extender in my garage which picks up many of my sensors, then links to my main router in my study. Even using this setup, I was amazed that the Temperature Sensors inside my fridge and freezer still managed to connect via WiFi.

Now, not everyone has a HAS. So I decided to look at different ways to display the data. I have previously played with LED Dot Matrix displays, which scroll messages across the display. I used a 32 by 8 LED Dot Matrix display. I know most households have a WiFi Router, but I thought it might be useful to have a display that worked independently of the WiFi Router.

I still need to use some form of Radio communications, especially for Temperature Sensors inside things like fridges or freezers. I did think of using the Nordic Semiconductor nRF24L01 transceivers, but have not had a lot of success with these trying to transmit data through walls. I was having success with ESP8266 transmitting WiFi through walls. After a little research, I found that the designers of the ESP8266 had incorporated a WiFi mode called ESPNow.

It is a simple protocol that is ideal for low bandwidth data transmission, ie small packets of data (250 bytes maximum). ESPNow supports point to point transmission and also mesh networks. What I wanted was a many (lots of sensors) to a one (hub – display) network. ESPNow supports this. While this is a proprietary protocol, it is supported by the ubiquitous ESP8266 and ESP32.

Now, those of you who recognise my name from the December 2021 edition of DIYODE, will know that I am a retired engineer. So, the first thing I do after investigating the issues is to come up with a set of requirements. Let’s first look at the Display Module.

I came up with the following requirements:

  1. Use a scrolling type display, 32x8 LED Dot matrix (I have one to reuse);
  2. Use an ESP8266 or ESP32 to take advantage of the ESPNow protocol;
  3. Run from a DC supply, eg a Plug Pack (battery operation is not required as the display will most likely be located near a mains socket);
  4. Accept data from a Temperature Sensor and display it;
  5. Be accommodated in a small to medium size enclosure;
  6. Be capable of blanking the display at night when no one will be looking at the display; and
  7. Be programmable via either the Arduino IDE or PlatformIO.

The Temperature Sensor requirements are as follows:

  1. Also use an ESP8266 or ESP32 to take advantage of the ESPNow protocol and be compatible with the Display Module;
  2. Be powered from a battery, preferably rechargeable;
  3. Use a readily available Temperature Sensor, either internal or external;
  4. Be accommodated in a small sized enclosure so that it can be located in many situations, (inside a fridge, freezer, fish tank, in a pool, in outside environments);
  5. Be able to give the Temperature Sensor a name during setup (not fixed in the program);
  6. Also be able to set the update time (in seconds) also during setup (not fixed in the program); and
  7. Be programmable via either the Arduino IDE or PlatformIO.

THE DESIGN

THE DISPLAY MODULE

The Display Module consists of the following main components:

  1. The LED Dot Matrix Display;
  2. The ESP8266 Processor Module;
  3. The BH1750FVI Light Sensor Module; and
  4. 5V Plug Pack.

The LED Dot Matrix Display

I chose a LED Dot Matrix Display based on the MAX7219 driver chip, as I have used it before and there are some very good Arduino libraries to allow simple programming. I used a module that contained four 8x8 Red LED Dot Matrix displays, which is available from several suppliers in Australia. Just Google MAX7219 Display Modules. You can also buy individual 8x8 LED Dot Matrix display modules and stack them side by side. The Arduino MAX7219 Library can accommodate displays of many 8x8 modules stacked side by side. The limit is determined by the amount of memory your processor has.

I found four modules a good compromise as 32x8 modules are commonly available. The four module unit also fitted nicely into a UB1 Jiffy Box and can be read from several metres away.

MAX7219 Display Modules are interfaced by a Serial Peripheral Interface (SPI) which is native to the ESP8266.

ESP8266 Processor

I chose the ESP8266 processor over the ESP32 processor. The main reason is that the readily available WeMos/Lolin D1 Mini, which contains an ESP8266, comes in a small form factor and is supported by the Arduino IDE and PlatformIO. I have used this ESP8266 Module in both the Display Module and the Temperature Sensor Module. The D1 Mini provides 4 MBytes External Flash memory, 64KBytes Instruction RAM and 96kBytes Data RAM.

Light Sensor

To blank the display at night (it is quite bright in a dark room), I added a BH1750FVI Light Sensor to measure the ambient light. If the light level is below a level set in the program, the display is blanked. The BH1750FVI is a very cheap and readily available light sensor. Just Google BH1750FVI. It is sometimes also known as a GY30 Module. The BH1750FVI has an I2C interface for which the ESP8266 has a native interface. There is also a BH1750FVI Library provided through the Arduino IDE which again makes programming easy. The ESP8266 uses different pins for the I2C interface and the SPI interface. Therefore the ESP8266 can support I2C and SPI concurrently.

5V Plug Pack

To power the Display Module, I decided to use a 5VDC Plug Pack. These are in common use and available from many sources. I decided to install a 5.5mmx2.1mm DC Socket in the Display Module case. This allows the Plug Pack to be easily connected and many normally have the 5.5 mmx2.1mm DC Plug attached. Also, for those who might want some portability, the Display Module could also be powered by a Power Bank with the appropriate cable.

THE TEMPERATURE SENSOR

The Temperature Sensor consists of the following main components:

  1. The ESP8266 Processor Module;
  2. A Dallas Semiconductor DS18B20 Temperature Sensor;
  3. A single Li-ion Battery with a TP4056 Battery Charger Module; and
  4. A small Case.

ESP8266 PROCESSOR

As indicated in the Display Module description, the Temperature Sensor will contain a WeMos/Lolin D1 Mini also. Aside from supporting the ESPNow protocol, the ESP8266 has a Deep Sleep mode. This allows the processor to be put in a very low power consumption mode and awoken via an internal programmable Real Time Clock (RTC) module.

The RTC module also contains RAM which is maintained while the ESP8266 is in Deep Sleep mode. This RTC RAM can be used for storage of variables. Note normal RAM loses its content during Deep Sleep. Also note, on power down, the RTC RAM also loses its content.

Temperature Sensor

For this design, I have selected the Dallas Semiconductor DS18B20 Temperature Sensor.

The DS18B20 comes in two forms, a transistor style (TO-92) package and a waterproof package which can be purchased with various length cables (see photo).

The DS18B20 uses a single wire interface (the other two connections are for power). Again, the Arduino IDE provides a Library to support simple programming.

Other temperature sensors could also be used. I have also included support for the DHT11, a very common Temperature/Humidity sensor. The downside of the DHT11 is that it only operates over the temperature range of 0 to 50°C, which may be adequate for most applications.

The DS18B20 operates over the -55 to +125°C temperature range. (Great for use in fridges and freezers!)

Power Circuit

As the Temperature Sensor is to be a portable device, battery operation is essential. To give the longest time between battery replacements, I decided to use a 3000mAh Li-ion battery.

Also, sometimes you don’t want to replace the battery, especially if it means unscrewing the case to get access to the battery. Also, disconnecting the battery could mean having to set up the configuration again (this is the case in my design). So I decided to add a Li-ion battery charger module, a TP4056 module.

The TP4056 module is a simple and cheap module allowing charging of a single Li-ion battery via the micro USB connector or via a 5VDC source connected to the two pads as shown on the left of the photograph.

The Build:

The design of the hardware has mostly been examined. Now it is time to put the Display Module and Temperature Sensor Module together.

The Display Module

Parts Required:JaycarAltronicsPakronics
1 x WeMos/Lolin D1 MiniXC3802Z6441-
1 x MAX7219 Display Module (32x8)XC4499eBay-
1 x BH1750FVI Light Sensor-eBayADA4681^
1 x UB1 Jiffy CaseHB6011H0201-
1 x DC SocketPS0522P0622-
1 x 5V PlugpackMP3144M8903A-
1 x Red Acetate Sheet-eBay or craft store-
1 x Pack of Dupont Cables 5-wire Female to FemaleWC6026P1023ADA1950
2 x 5-pin Male headers*HM3211P5430ADA3009
1 x 5-pin right angle Male header*-P5440DF-FIT0100
2 x 8-pin Female headers*HM3230P5375DF-FIT0165
1 x Veroboard*HP9540H0714-

Parts Required:

* Quantity shown, may be sold in packs. ^Similar product, may need wiring and code change to operate. Some mounting hardware is also required - see text.

The Schematic of the Display Module is shown adjacent. It is a very simple design with the WeMos D1 Mini located on a small Veroboard with connectors for connecting via cables to the MAX7219 Display Module and the BH1750FVI Light Sensor Module. Note the on the Veroboard, the copper strips run horizontally and “X” indicates where the tracks are cut. The 5VDC connector is located in the side of the case.

From the photo of the assembled Display Module, you will notice a clamping arrangement around the MAX7219 Display Module. Unfortunately, the MAX7219 Display Module does not have any mounting holes. I made two aluminium strips drilling four 3mm holes in each and used nylon spacers to clamp the display to the Jiffy Box lid.

I also inserted a cut red acetate sheet between the MAX7219 Display Module and the Jiffy Box lid. This makes for a better appearance as you cannot see the LEDs which are not illuminated. For the MAX7219 Display Module, I cut a rectangular hole 31mm x 127mm in the Jiffy Box lid.

Note the hole is set to one side of the lid as the connector for the Display is located at one end and space needs to be allowed for the cable to connect. Four 3mm holes were drilled, each approximately 5mm from the rectangular hole for the clamping arrangement.

This, of course, can be varied depending on the clamping arrangement you use.

Three holes are drilled for the BH1750FVI Light Sensor below the centre of the display. Two 3mm holes are for mounting the BH1750FVI Light Sensor Module and the third 6mm hole is for light to illuminate the light sensor on the BH1750 Light Sensor Module. Note 2mm spacers are required between the lid and the BH1750 Light Sensor Module to keep the Module flat. Also, when soldering the 5-pin header to the BH1750FVI, use a right angle header.

The connectors on the Display Module Veroboard for the MAX7219 Display Module and the BH1750FVI are standard 2.54mm 5-pin male headers. I use the 40-pin breakable strips and break off a five pin strip. I used 2.54mm 8-pin Female headers for mounting the WeMos D1 Mini.

The cables for connecting the MAX7219 Display Module and the BH1750FVI Light Sensor Module can be made from Dupont cables with female ends. They come in a bunch of 40 wires. Tear off five wires (only four required for BH1750FVI) and connect them between the Veroboard, display and sensors, making sure the right pins are connected.

The cable interconnections I used is shown adjacent.

The Temperature Sensor Module

Parts Required:JaycarAltronics
WeMos/Lolin D1 MiniXC3802Z6441
HT7333 Voltage RegulatoreBay-
MCP1700-33021296588-
DS18B20 Temperature Sensor (TO-92)2515605eBay
DS18B20 Temperature Sensor (WaterProof)2816441eBay
100kΩ ResistorRR0620R7606
4.7kΩ ResistorRR0588R7574
10μF Capacitors (2)RZ6655R2628A
Cable Gland (PG7) (3)HP0720H4304A
TP4056eBay-
Li-Ion BatterySB2308S4737
UB3 Jiffy CaseHB6013H0203
DC SocketPS0522P0622
Tactile Pushbutton Switch 6x6 mmS11204511189
8-pin Female headers (2)P5375-
VeroboardHP9540H0714

Parts Required:

* Quantity shown, may be sold in packs. ^Similar product, may need wiring and code change to operate. Some mounting hardware is also required - see text.

The Schematic of the Temperature Sensor Module is shown above. The design of the Temperature Sensor Module has some similarities with the Display Module. An ESP8266 WeMos D1 Mini module is used again. The difference here is that the Sensor can be contained on the Veroboard, unless you use the waterproof DS18B20 Temperature Sensor. In which case, one end of the cable is soldered to the Veroboard and the Sensor can dangle somewhere. Also, the power is provided by a Li-ion battery via the TP4056 Battery Charger Module. The Li-ion battery can be charged via the TP4056 by connecting a 5V source, eg plupack or powerbank, to the DC connector.

Power is fed to the Veroboard Module from the output of the TP4056. The Li-ion battery voltage can vary up to 4.2V when fully charged and down to 3.0V when considered discharged. The battery voltage is regulated to 3.3V to power the WeMOsD1 Mini and the DS18B20 using either a MCP1700-3302 or a HT7333. My favourite is a HT7333 as it has a wide input voltage range, which is not required here.

If the Battery Voltage falls below 3.365V, the HT7333 Voltage regulator will drop out, although it will still pass the battery voltage through to the WeMos D1 Mini. The WeMos D1 Mini can operate at voltages lower than 3.3V, but reliability in operation below 3.0V cannot be guaranteed. To monitor the Battery voltage, a 100kΩ Resistor (R1) is connected to the TP4056 output and the A0 input of the WeMos D1 Mini. The A0 input of the WeMos D1 Mini is connected internally to a voltage divider consisting of a 220kΩ and a 100kΩ resistor such that if 3.3V was directly applied to the A0 input, 1V would be applied to the ESP8266, which is the maximum voltage that can be applied. So adding the extra 100kΩ resistor externally allows measuring the battery voltage up to 4.2V without damaging the ESP8266. You will also notice a 4.7kΩ resistor (R2) connected between 3.3 Volts (VCC) and the signal pin of the DS18B20. This is required as per the Data Sheet. Without it the DS18B20 does not function. However, if you replace the DS18B20 with a three-pin DHT11 module, R2 is not required.

With the Temperature Sensor Module being battery powered, current consumption is very important. So I did a couple of checks on current consumption using the WeMos D1 Mini. The first measurement I made was powering the Module via the Micro USB port. In Deep Sleep mode, where it was expected the Module would spend most of its time, the current consumption was 3.3 mA.

It would jump briefly to 80 mA when it woke up from Deep Sleep. So assuming for now we ignore the non-Deep Sleep consumption, as it is in this mode for a fraction of time, a 3000mAh battery would last a maximum of 909 hours or just under 38 days. This is a best case and is dependent on how long the ESP8266 is put into Deep Sleep. For example, if the Deep Sleep time is only 60 seconds, the battery may only last for a few days. For some, this might be acceptable as I have included the option to charge the battery. Now, this current measurement was via the USB port which is not how the design works.

I have connected the battery to a 3.3V Voltage Regulator which in turn is connected to the 3.3V connection on the WeMos D1 Mini. Normally, the 3.3V connection is an output, but can be used as an input. It just means that the internal Voltage Regulator is bypassed. In this configuration, I measured a current of 1.25 mA during Deep Sleep. This equates to 2400 hours or 100 days maximum. This is acceptable, except for me. I have designed a breakout board for the ESP12E/F (contains the ESP8266) modules where Deep Sleep current is less than 100μA. The reason for the lower consumption is that there is no USB chip (CH340 or CP2102). More details of my breakout board will be part of the associated resources as is the software.

On the previous page are two photographs. The first shows the version of the Temperature Sensor Module with the DS18B20 (TO-92) Temperature Sensor soldered to the Veroboard. The second photo shows the waterproof DS18B20 Temperature in position but not connected. All that is required is for the TO-92 version of the DS18B20 to be de-soldered and the three wires of the waterproof DS18B20 to be soldered in its place. (Black wire to GND, Red wire to VCC and the Yellow wire to SIG).

A cable gland has also been used to hold the waterproof DS18B20 in place and also provides protection against water ingress. I have used the waterproof version in my pool and a more waterproof case with the case mounted on top of a polystyrene block to allow it to float on top of my pool. The case is not submerged in the pool as it would eventually leak.

Lastly, you will see a small Tactile Pushbutton Switch labelled “Boot” to the right side of the WeMos D1 Mini. This is used after pushing the Reset Button (located on the side next to the USB connector on the WeMos D1 Mini) and releasing it, then immediately pressing the “Boot” button will indicate to the ESP8266 that a setup is to be performed again. This happens automatically on power up.

CONCEPT OF OPERATION

The main idea behind the Display and Temperature Sensor Modules is simple. The Temperature Sensor Module measures the temperature, at where it is located, and sends it to the Display Module to be displayed on its LED Dot Matrix Display. To pass the data between the Temperature Sensor Module and the Display Module, both modules employ the ESPNow protocol. The ESPNow protocol relies on the Temperature Sensor Module knowing the Media Access Control (MAC) address of the Display Module. The data to be sent (up to 250 Bytes) is combined with the MAC Address of the Display Module and also the MAC Address of the Temperature Sensor Module and sent over a 2.4 GHz wireless transmission. It is similar to that often used with a wireless mouse. This can work well when there are multiple Sensors. As long as all the Sensors know the MAC Address of the Display Module, the Display Module will receive data from all the Sensors.

Now, how to you know the MAC Address of the Display Module. You can run the code below on the Display Module via the Arduino IDE and use the MAC Address displayed.

#include <ESP8266WiFi.h> </p>
void setup(){
  Serial.begin(115200);
  Serial.println();
  Serial.print("ESP Board MAC Address: ");
  Serial.println(WiFi.macAddress());
}
void loop(){ 
}

This is what I initially did, when developing my prototypes. However, I had a failure of my WeMos D1 Mini in the Display Module, which meant I had to find out the Mac address of my replacement WeMos D1 Mini. This seemed a bit inefficient. Then I found you can set the MAC Address in the ESP8266 (and ESP32) to whatever you want. However, I did not want to use MAC Addresses that are already in use. So I followed the rules for “Locally Administered Unicast” addresses. (See Wiki link https://en.wikipedia.org/wiki/MAC_address). I created a MAC address for the Display Module and used this in my Temperature Sensor Module.

Now, I thought a little more about this Concept of Operation where I could have multiple Temperature Sensors and the Display Module would display each temperature that each sensor sent. However, how would you know which sensor was being displayed. If I knew the MAC Address of each sensor, I would know which sensor temperature I was displaying. This all seems a bit complicated. I decided the easiest way is for the Display Module to be relatively dumb and put some intelligence into the Temperature Sensor. So I decided to include a Webserver in the Temperature Sensor which would allow me to set the “Name” of the sensor and also the “Time” in seconds between updates, ie for how long the Temperature Sensor would be in deep sleep. Now the Temperature Sensor would compile a string of characters and send that to the Display Module for example:

"Aquarium Temperature is 21.0°C"

This also meant I could have other sensors doing the same. For example, Moisture Sensors, Door Open Sensors, etc. They would send a complete message and the Display Module would display each message in total. The Display Module, as it receives each message stores them and then displays them in sequence. As the ESP8266 does not have infinite memory, I decided to allow up to ten different sensors to be displayed (I couldn’t see me having more than ten sensors around the house!) This of course can be changed in the software. Now as the MAC address of the Sensor is also received by the Display Module, the Display Module when it receives updates can replace the data that it previously received. This makes sure that one sensor, that may be updating more often than the others does not use up all ten buffers. But if Sensor eleven fires up, then I replace the oldest buffer. So they all sensors get a fair go!

SOFTWARE

I have developed both the Display and Temperature Sensor Modules software using the Arduino IDE. I could have used PlatformIO, but the software is relatively simple, so the Arduino IDE, which in my opinion is simpler to use, was employed. The screen capture below shows the settings used in the Arduino IDE for both the Display and Temperature Sensor Modules software.

The complete software code can be found at the resource link at the end of this article.

Display Module Software

Looking at the Display Module software first – “MAX7219_ESPNow_Temp_Display_V1”, as usual all the libraries used for this program are included at the beginning. The first three libraries are for the LED Dot Matrix Display. The last two are for ESPNow protocol. I have also included some compile time macros for print statements to debug the software.

#include <MD_Parola.h> 
#include <MD_MAX72xx.h> 
#include <SPI.h> 
#include <BH1750FVI.h> 
// For Light Sensor on top of case 
#include <ESP8266WiFi.h> 
#include <espnow.h> 
// Comment out if DEBUGG messages are not to be 
// displayed on Serial monitor 
//#define DEBUGG 1 
#ifdef DEBUGG 
#define DEBUGG_PRINT(str) Serial.print(str) 
#define DEBUGG_PRINTLN(str) Serial.println(str) 
#else 
#define DEBUGG_PRINT(str) 
#define DEBUGG_PRINTLN(str) 
#endif 

This is followed by definitions for the BH1750FVI Light Sensor and the MAX7219 LED Display as well as all the buffers associated with storing messages received from the various sensors. One important definition is that of the MAC address to be set in the code for the Display Module.

// If you want to set the Mac Address for this 
// ESP8266, modify the following for a different 
// MAC Address 
uint8_t ThisMacAddress[] = 
{0x3A, 0x4A, 0x5A, 0x00, 0x00, 0x01};

The first part of the program that is always executed is the “Setup” function.

void setup() 

Serial.begin(115200); 
delay(500); 
// Initialise all buffers, 
// except the first to not used 
BuffValid[0] = true; 
for(int k=1; k<NUM_BUFFS; k++) 

BuffValid[k] = false; 

DEBUGG_PRINT("nMax7219 Scrolling Displayn"); 
// Initialise MAX7219 Display 
P.begin(); 
P.displayText(curMessage, scrollAlign, scrollSpeed, ...

The flags for the message buffers are all set to unused, except for the first buffer which contains the startup message “Hello, this is the MAX7219 Scrolling Sensor Display”. The LED Dot Matrix Display is then initialised, noting all the parameters were declared earlier (See full code in Resources link at the end of this article) and can be changed. For example, the “scrollSpeed” you may find to be too fast, so you can decrease the speed. Or “scrollEffect” is set to scroll left “PA_SCROLL_LEFT”. You may want to scroll right, so change the setting of “scrollEffect” to “PA_SCROLL_RIGHT”.

After initialising the BH1750FVI Light Sensor, the MAC Address is setup for the Display Module. It is important to make sure the ESP8266 is in Station Mode when this is done. Once the ESPNow function is initialised a callback is setup for when messages are received. “Disp_counter” is initialised to zero. This is to display the startup message. “Disp_counter” is incremented to display subsequent messages as they are received. “Display_Timer” is also initialised to the current time.

Once “Setup” is complete, the “Loop” function is continually executed. Firstly, the current time is checked. If the “DISPLAY_TIMEOUT” (currently set to 10 seconds) has been exceeded, the BH1750FVI Light Sensor is read to determine if the light level is low, ie night time, in which case the LED Dot Matrix display is turned off. I used a ten second sampling time as I thought this a quick enough response time to turning the display off or on.

void loop() 

if(millis() > (Display_Timer + DISPLAY_TIMEOUT)) 

Light_Read = L_SENS.readLightLevel(); 
DEBUGG_PRINT("Light Level is "); 
DEBUGG_PRINT(Light_Read); 
DEBUGG_PRINTLN(" Lx"); 
if(Light_Read <LIGHT_MIN) 

P.displayShutdown(true); 
DEBUGG_PRINTLN("Display Shutdown"); 

else 

P.displayShutdown(false); 
DEBUGG_PRINTLN("Display Reset"); 
...

A check is then made to see if a message was currently being scrolled across the display. If not, a new message is taken from the buffer holding messages received and placed into the buffer for display (“curMessage”). A check is then made to see if the message to be displayed was received more than the allowed time without an update being received (“MAX_MESS_TO” currently set to 12 minutes).

If no messages have been received from that particular sensor for “MAX_MESS_TO”, the message and the associated MAC Address are deleted. The “Disp_counter” pointer is incremented but set to zero if the count exceeds the Number of Buffers (“NUM_BUFFS” currently set to 10). If the “Disp_counter” pointer points to an empty buffer, the pointer is set back to the last valid buffer.

Now a lot of the magic happens in the callback function “onRecv”. So it is worth examining this briefly.

The callback function is automatically called whenever a message is received from a sensor.

// Function to process received messages from 
// Sensors 
void onRecv(uint8_t *mac_addr, uint8_t *data, 
uint8_t data_len) { 
int j; // general counter 
for(j=0; j<NUM_BUFFS; j++) 

if(mac_cmp(mac_addr, MacAddr[j])) break; // Mac Address already received 

// if Mac Address not found, ie. j = NUM_BUFFS, 
// save Mac Address and message in new buffer 
// if all buffers used, save in the oldest used 
// buffer 
if(j==NUM_BUFFS) 

memcpy(&MacAddr[Last_Ptr], mac_addr, MAC_SIZE); 
...

First a check is made to see if the message received has come from a sensor that has previously sent a message. If a message has not previously been received from the particular sensor, a new buffer is allocated and a message timeout is set. If all buffers are in use, the oldest buffer is used. Otherwise the new message is put into the message buffer from the previously received sensor and the message timeout is reset.

Temperature Sensor Module Software

The “ESPNow_Temperature_Sensor_ESP8266_V1” software is slightly different in that a Library is declared as “extern”. This is because the functions are contained within “user_interface.h” which are called within my program. This is all to do with knowing what caused a reset of the ESP8266 processor as can be seen in the “#define” declarations.

extern "C" { 
#include <user_interface.h> 
// Required for ESP Reset Cause SDK calls 

rst_info *reset_info; 
// Structure to hold Reset Information (cause, etc.) 
#define PWR_UP_RESET 0 
// Reset reason due to Power Up 
#define DEEP_SLEEP_WAKEUP 5 
// Reset reason due to wake up from Deep Sleep 
#define EXT_RESET 6 
// Reset reason is Reset Button pressed 

The code has been written to allow the use of either a DS18B20 or DHT11 Temperature Sensor. You will see the following snippets in the program. Only the snippets associated with the selected Temperature Sensor are compiled.

// Comment out the following #define if using a 
// DHT11 Temp Sensor, 
// else it is assumed a DS18B20 Temp Sensor is 
// being used. 
#define DS18B20_INST 1 


#ifdef DS18B20_INST 
//DS18B20 definitions 
#include <OneWire.h> 
#include <DallasTemperature.h> 
#define ONE_WIRE_BUS 13 //Pin to which is attached a // temperature sensor 
OneWire oneWire(ONE_WIRE_BUS); 
DallasTemperature DS18B20(&oneWire); 
#else 
//DHT11 definitions 
#include "DHT.h" 
#define DHTPIN 13 // connected to GPIO13 
#define DHTTYPE DHT11 // DHT 11 
DHT dht(DHTPIN, DHTTYPE); // Initialize DHT sensor. 
#endif 
...

Most of the code that is executed is in the “Setup()” function. The “Loop()” function is only used when setting up the Sensor Name and Sensor Update time value through the Webserver. The first thing looked at in the “Setup()” function is to find out what the reset reason is.

// Get the Reset cause first up 
reset_info = ESP.getResetInfoPtr(); 
Start_Time = millis(); 
// Setup Boot pin 
pinMode(Boot_Pin, INPUT); 
Serial.begin(115200); 
Serial.println(""); 
ESP.rtcUserMemoryRead(TS_ADDR, (uint32_t*) 
&TS_Data, sizeof(TS_Data)); 
switch ((*reset_info).reason) 

case PWR_UP_RESET: // Power up Reset, battery has ...

There are three main reasons for a reset occurring. They are Power up, the Reset Button is pushed or wakeup from Deep Sleep. However, if the Reset Button is pushed during Deep Sleep, this is counted as wakeup from Deep Sleep. This is actually useful when testing a program which has gone into a long Deep Sleep and you want to test your code but in a much shorter time.

Looking at the reset cause is done for two reasons. The first reason is to go into setup via the Webserver. Via the Webserver, the “name” of the Sensor is set and the time between updates is set. This normally occurs when first powered up and when the Reset Button is pressed followed by the Boot Button. The other reason is to measure the temperature and send it to the Display Module. This is normally associated with waking up from Deep Sleep.

Once it has been determined that setup via the Webserver is required. This is found in the last section of the “Setup()” function and the “Loop()” function. Initially, an Access Point is setup. Once this has been done, you connect to the Temperature Sensor via your Mobile phone or WiFi enabled notebook computer. The Access Point name is “Temp_Sensor” and the password is “12345678”. You can then use a Web Browser on your mobile phone or notebook computer and display the setup webpage by using the address “192.168.5.1”.

// If not previously initialised, set up as an 
// access point 
// to set the Temperature Sensor Deep Sleep time 
// and to set the Sensor Name 
// First, setup AP (Access Point) 
// reset networking 
WiFi.softAPdisconnect(true); 
WiFi.disconnect(); 
delay(1000); 
DEBUGG_PRINTLN("Starting Soft AP"); 
WiFi.mode(WIFI_AP); 
WiFi.softAPConfig(local_ip, gateway, subnet); 
WiFi.softAP(ssid, password); 
delay(100); // All Access Point time to setup 
DEBUGG_PRINTLN("Setting up Webserver"); 
server.on("/", handle_OnConnect); 
server.on("/UpdNum", handle_UpdNum); 
// input Moisture Sensor Number 
server.on("/FinishCal", handle_FinishCal); 
// Setup Finish Button has been pressed 
server.onNotFound(handle_NotFound); 
...

The Web page you will see is shown below. You input the “Sensor Update Rate” (Deep Sleep time) and input the Sensor Name. The Name can be anything up to 32 characters (see the “SendHTML1()” function in the program. Click on the “Save” button and then the “FINISH” button. An initialisation code “INITCODE” (currently set to “12345”) is then stored in the RTC Memory for reading back on a reset to determine the initialisation state. The Temperature Sensor is then put into a short Deep Sleep (1 second). On waking from Deep Sleep, Data will be sent to the Display Module. The Temperature Sensor is then put back into Deep Sleep as per the setting from the Web Setup page.

After waking up from Deep Sleep and determining that data is to be sent to the Display Module, ie INITCODE read from RTC Memory, the temperature is read as well as the battery voltage. The function that gets the battery voltage “Get_Bat_Val()” actually reads the battery voltage 101 times.

The first value is thrown away as it can be erroneous. The other hundred readings are averaged to get a relatively accurate value. Noise can be generated during the reading of the Analog In pin (A0). If the battery reading falls below “BATMIN”, currently set to 330 (3.3 Volts), a message is sent to the display module indicating the battery needs replacing. For example, if the Temperature Sensor name is “Fish Tank”, the message “Fish Tank Temperature Sensor Battery needs Replacing” will be sent. If the battery voltage is okay, then, for example, this message is sent “Fish Tank Temp is 20°C”.

Because there could be multiple Sensors sending data to the Display Module, if on the initial Data Send, the Temperature Sensor does not receive an acknowledgement of data being received, the Temperature Sensor will try again after a random delay. It will continue to try and send until the “MAX_SEND” timeout (currently set to 5 seconds) occurs. The Temperature Sensor then goes into Deep Sleep for the time set via the Web page Setup and the whole sequence repeats again.

It is well worth looking at the “ESPNow_Temperature_Sensor_ESP8266_V1.ino” file via the resources link below.It is more comprehensive than the Display Module code, but should be relatively easy to understand. The area that may cause some angst, is in the “SendHTML()” function as a lot of HTML is created. I used a book “HTML & CSS –design and build websites” by Jon Duckett as my bible in understanding HTML. There are also many resources on the internet which are very helpful.

The hardware for this project is relatively simple. Most of the complexity is in the software, although this is still has a low degree of complexity. Using my Temperature Sensor as a starting point, many different types of sensors can be created with their data being displayed on my Display Module.

Now, for those who want to get their current consumption down, I attach a couple of circuit diagrams. The Veroboard layouts are available via the Resource link. The first circuit uses a prototype board pictured which is available on eBay. The second circuit uses a prototype board developed by myself for use in my future projects.

Peter Stewart

Peter Stewart

Retired Engineer