Remote temperature sensor for thermometers with ESP8266

This post complements the previous post. He describes a temperature sensor with ESP8266 that sends the current temperature to the thermometer presented in the last article every five minutes. During the break between two measurements, the ESP8266 is placed in deep sleep mode, in which it consumes hardly any energy. The ESP Now protocol is used to send the data, which sends the data directly to the MAC address of the thermometer without the need to establish a connection.

We use the ESP8266-E12 Module with Adapter, as this, unlike the ESP8266-01 module, has led out the Wake Pin GPIO-16 and does not have a permanently luminous LED on the supply voltage. We need the Wake Pin to wake up from deep sleep and the power LED only consumes energy unnecessarily.

Circuit:

The orange wire connects the Wake Pin to the reset input and ensures that the module is restarted at the end of the sleep break. The sensor is connected to the GPIO2 (white wire).

To upload the program we need an FDTI adapter to program the ESP8266 via the serial interface.

We connect the FDTI adapter to the GND connector and TX to RX and RX to TX. In addition, the Flash Pin GPIO 0 must be connected to ground (green wire) so that the ESP8266 goes into programming mode.

After programming, the green wire must be removed again. If DEBUG was set to true in the Sketch, you can follow the messages of the module via the serial interface.

Attention: A supply of the ESP8266 by the FDTI board causes crashes when the scanNetwork function is called, because the power consumption is then too high.

Sketch:

To compile the board on

Set!!

 

/*
 Wi-Fi temperature sensor
 ESP Now with the thermometer
 If no MAC address has yet been determined
 the sensor is looking for a WLAN with SSID thermometer
 When he finds the AP, he remembers the MAC address 
 as long as the power supply has not been interrupted
 The ESP Now protocol is very fast so only very short time (us)
 higher current flows. The sensor sends temperature data and then goes into the 
 deep sleep so that very little energy is consumed and the
 sensor can therefore be operated with batteries. 
*/

Library for WiFi
#include <ESP8266WiFi.H>
Libraries for temperature sensor DS18B20
#include <OneWire.H>

Library for ESP Now
#include <DallasTemperature.H>
External "C" {   #include <espnow.H>
}

Debug flag if false all debug messages are suppressed
to save additional power
#define Debug True

Constants for WiFi
#define WIFI_CHANNEL 1
#define SEND_TIMEOUT 2450  245 milliseconds timeout 

Pins for temperature sensor
Const Byte Bus = 2;pin GPIO2

Data structure for data exchange
Struct DATEN_STRUKTUR {     Float Temp = 0;
};

Data structure for the Rtc Memory with checksum around the validity
to check this the MAC address is saved
Struct MEMORYDATA {   uint32_t crc32;   uint8_t Mac[6];
};

Global data
volatile Bool callbackCalled;

MEMORYDATA statinfo;

OneWire oneWire(Bus);

DallasTemperature Sensors(&oneWire);

Array to store sensor addresses
DeviceAddress Addresses;

Subprogram for calculating the checksum
uint32_t calculateCRC32(Const uint8_t *Data, Size_t length)
{   uint32_t Crc = 0xffffffff;   while (length--) {     uint8_t C = *Data++;     for (uint32_t  = 0x80;  > 0;  >>= 1) {       Bool Bit = Crc & 0x80000000;       If (C & ) {         Bit = !Bit;       }       Crc <<= 1;       If (Bit) {         Crc ^= 0x04c11db7;       }     }   }   Return Crc;
}

Writes the data structure statinfo with correct checksum to the RTC memory
Void UpdateRtcMemory() {     uint32_t crcOfData = calculateCRC32(((uint8_t*) &statinfo) + 4, Sizeof(statinfo) - 4);     statinfo.crc32 = crcOfData;     Esp.rtcUserMemoryWrite(0,(uint32_t*) &statinfo, Sizeof(statinfo));
}

searches for a suitable AccessPoint
Void ScanForSlave() {   Bool slaveFound = 0;      int8_t scanResults = Wifi.scanNetworks();   reset on each scan   If (Debug) Serial.println("Scan done");   If (scanResults == 0) {     If (Debug) Serial.println("No WiFi devices found in AP Mode");   } else {     If (Debug) Serial.Print("Found");      If (Debug) Serial.Print(scanResults);      If (Debug) Serial.println(" devices ");     for (Int  = 0;  < scanResults; ++) {       Print SSID and RSSI for each device found       String Ssid = Wifi.Ssid();       int32_t Rssi = Wifi.Rssi();       String BSSIDstr = Wifi.BSSIDstr();       If (Debug) {         Serial.Print( + 1);         Serial.Print(": ");         Serial.Print(Ssid);         Serial.Print(" (");         Serial.Print(Rssi);         Serial.Print(")");         Serial.println("");       }       Delay(10);       Check if the current device starts with 'Thermometer'       If (Ssid.Indexof("Thermometer") == 0) {         SSID of interest         If (Debug) {           Serial.println("Found a Slave.");           Serial.Print( + 1); Serial.Print(": "); Serial.Print(Ssid); Serial.Print(" ["); Serial.Print(BSSIDstr); Serial.Print("]"); Serial.Print(" ("); Serial.Print(Rssi); Serial.Print(")"); Serial.println("");         }         Int Mac[6];         we determine the MAC address and store it in the RTC memory         If ( 6 == sscanf(BSSIDstr.c_str(), "%x:%x:%x:%x:%x:%x%c",  &Mac[0], &Mac[1], &Mac[2], &Mac[3], &Mac[4], &Mac[5] ) ) {           for (Int  = 0;  < 6; ++ ) {             statinfo.Mac[] = (uint8_t) Mac[];           }           UpdateRtcMemory();         }         slaveFound = 1;         After the AP is found, we can cancel         Break;       }     }   }         If (Debug) {     If (slaveFound) {       Serial.println("Slave Found, processing.".);     } else {       Serial.println("Slave Not Found, try again.");     }   }   Share RAM   Wifi.scanDelete();
}
function to print a sensor address
Void printAddress(DeviceAddress Addresses)
{   for (uint8_t  = 0;  < 8; ++)   {     If (Addresses[] < 16) Serial.Print("0");     Serial.Print(Addresses[], Hex);   }
}

Void Setup() {   If (Debug) {     Serial.Begin(115200);      Serial.println("Start");   }   pinMode(Bus,INPUT_PULLUP);   We determine the anzah of the sensors on the single-wire bus   Sensors.Begin();   If (Debug) {     Serial.Print(Sensors.getDeviceCount(), DEC);     Serial.println(" Sensors found.");   }   Now we check if one of the sensors on the bus is a temperature sensor   If (!Sensors.getAddress(Addresses,0)) {     If (Debug) Serial.println("No temperature sensor available!");   }   View addresses   If (Debug) {     Serial.Print("Address: ");     printAddress(Addresses);     Serial.println();   }   Now we set the desired resolution (9, 10, 11 or 12 bit)   Sensors.setResolution(Addresses,10);   For control, we read the value again   If (Debug) {     Serial.Print("Resolution = ");     Serial.Print(Sensors.getResolution(Addresses), DEC);     Serial.println();   }   Sensors.requestTemperatures(); Commando to read the temperatures   We read from the RTC Memory   Esp.rtcUserMemoryRead(0, (uint32_t*) &statinfo, Sizeof(statinfo));   If (Debug) Serial.println("RTC Done");   uint32_t crcOfData = calculateCRC32(((uint8_t*) &statinfo) + 4, Sizeof(statinfo) - 4);   Wifi.Fashion(WIFI_STA); Station mode for esp-now sensor node   If (Debug) Serial.println("WifiMode");   If (statinfo.crc32 != crcOfData) { we do not have a valid MAC address     If (Debug) Serial.println("Scan before Slave");     ScanForSlave();     If (Debug) {       Serial.Printf("This mac: %s, ", Wifi.macAddress().c_str());        Serial.Printf("target mac: %02x%02x%02x%02x%02x%02x%02x", statinfo.Mac[0], statinfo.Mac[1], statinfo.Mac[2], statinfo.Mac[3], statinfo.Mac[4], statinfo.Mac[5]);        Serial.Printf(", channel: %i'n", WIFI_CHANNEL);      }   }   If (esp_now_init() != 0) {     If (Debug) Serial.println("*** ESP_Now init failed");     Esp.restart();   }   ESP Now Controller   esp_now_set_self_role(ESP_NOW_ROLE_CONTROLLER);   Initialize peer data   esp_now_add_peer(statinfo.Mac, ESP_NOW_ROLE_SLAVE, WIFI_CHANNEL, Null, 0);   we register the function to be called after sending   esp_now_register_send_cb([](uint8_t* Mac, uint8_t sendStatus) {     If (Debug) {       Serial.Print("send_cb, status = "); Serial.Print(sendStatus);        Serial.Print(", to mac: ");        Char macString[50] = {0};       Sprintf(macString,"%02X:%02X:%02x:%02X:%02X:%02X", statinfo.Mac[0], statinfo.Mac[1], statinfo.Mac[2], statinfo.Mac[3], statinfo.Mac[4], statinfo.Mac[5]);       Serial.println(macString);     }     callbackCalled = True;   });      Set flag to false   callbackCalled = False;   Start temperature measurement   Sensors.requestTemperatures();      Delay(750); 750 ms wait until the measurement is ready   Fetch the temperature value and save it in satellite structure for sending   DATEN_STRUKTUR Data;   Data.Temp = Sensors.getTempC(Addresses);   uint8_t Bs[Sizeof(Data)];   Copy data structure to send buffer   Memcpy(Bs, &Data, Sizeof(Data));   Send data to thermometer   esp_now_send(Null, Bs, Sizeof(Data)); NULL means send to all peers   If (Debug) {     Serial.Print("Temperature: "); Serial.Print(Data.Temp); Serial.println("°C");   }
}

Void Loop() {   wait until data is sent   If (callbackCalled || (millis() > SEND_TIMEOUT)) {     If (Debug) Serial.println("Sleep");     Delay(100);     Into deep sleep mode for 300 seconds     then a reset takes place and the ESP8266 is restarted     Data in the RTC memory is not deleted during the reset.     Esp.deepSleep(300E6);   }
}




Test:

After the module has been powered, it does not yet know a valid MAC address of the thermometer. It tries to find an open network with the SSID "Thermometer". Since the thermometer hides its SSID about five minutes after startup, we need to trigger a restart of the thermometer. Now the sensor module should find the thermometer and transmit the current temperature value every five minutes. The thermometer should alternately display the local temperature (house symbol) and the temperature of the sensor module (tree symbol).

Esp-8266Projects for advancedSensors

4 comments

Peter

Peter

Wie weit können die Module denn voneinander entfernt sein?

Peter

Peter

Tolles Projekt! Ist es möglich mehrere entfernte Module zu betreiben?
Viele Grüße Peter

Carsten Jürges

Carsten Jürges

Wenn kein “Thermometer” gefunden wird, landet irgendeine MAC-Adresse in statinfo und das war’s dann erstmal. Daher habe ich Funktion DeleteRtcMemory spendiert, den CRC-Wert “zerstört”. Diese Funktionen wird aufgerufen, wenn das Senden nicht erfolgreich (sendStatus) war …
Dann gibt es beim nächsten Start einen neuen Verbindungsversuch …

Jörg

Jörg

Super, genau so etwas habe ich gesucht.
Vielen Dank für die interessanten Projektvorstellungen.

Leave a comment

All comments are moderated before being published

Recommended blog posts

  1. Install ESP32 now from the board manager
  2. Lüftersteuerung Raspberry Pi
  3. Arduino IDE - Programmieren für Einsteiger - Teil 1
  4. ESP32 - das Multitalent
  5. OTA - Over the Air - ESP programming via WLAN