Building a Wireless Temperature Sensor battery-powered
Wireless temperature sensor which used ESP-NOW and Deep Sleep to save power and transmit data.
Components and supplies
1
DHT11 Temperature & Humidity Sensor (4 pins)
1
Arduino® Nano ESP32
Tools and machines
1
Soldering Iron Tip, Drag Hoof
Apps and platforms
1
Arduino IDE
1
altium designer
Project description
Code
Humidity Sensor Code
cpp
Humidity Sensor Code with ESP-NOW
1/** 2 ESPNOW - Basic communication - Master 3 Date: 26th September 2017 4 Author: Arvind Ravulavaru <https://github.com/arvindr21> 5 Purpose: ESPNow Communication between a Master ESP32 and a Slave ESP32 6 Description: This sketch consists of the code for the Master module. 7 Resources: (A bit outdated) 8 a. https://espressif.com/sites/default/files/documentation/esp-now_user_guide_en.pdf 9 b. http://www.esploradores.com/practica-6-conexion-esp-now/ 10 11 << This Device Master >> 12 13 Flow: Master 14 Step 1 : ESPNow Init on Master and set it in STA mode 15 Step 2 : Start scanning for Slave ESP32 (we have added a prefix of `slave` to the SSID of slave for an easy setup) 16 Step 3 : Once found, add Slave as peer 17 Step 4 : Register for send callback 18 Step 5 : Start Transmitting data from Master to Slave 19 20 Flow: Slave 21 Step 1 : ESPNow Init on Slave 22 Step 2 : Update the SSID of Slave with a prefix of `slave` 23 Step 3 : Set Slave in AP mode 24 Step 4 : Register for receive callback and wait for data 25 Step 5 : Once data arrives, print it in the serial monitor 26 27 Note: Master and Slave have been defined to easily understand the setup. 28 Based on the ESPNOW API, there is no concept of Master and Slave. 29 Any devices can act as master or salve. 30*/ 31 32// this code is written by RoboCircuits 33// follow us on YouTube 34 35#include <esp_now.h> 36#include <WiFi.h> 37#include <esp_wifi.h> // only for esp_wifi_set_channel() 38#include <Adafruit_Sensor.h> 39#include <DHT.h> 40#include <DHT_U.h> 41 42#define uS_TO_S_FACTOR 1000000ULL /* Conversion factor for micro seconds to seconds */ 43#define TIME_TO_SLEEP 10 /* Time ESP32 will go to sleep (in seconds) */ 44 45 46#define DHTPIN 6 47 48// Global copy of slave 49esp_now_peer_info_t slave; 50#define CHANNEL 1 51#define PRINTSCANRESULTS 0 52#define DELETEBEFOREPAIR 0 53 54#define DHTTYPE DHT11 // DHT 11 55 56DHT_Unified dht(DHTPIN, DHTTYPE); 57 58 59// Init ESP Now with fallback 60void InitESPNow() { 61 WiFi.disconnect(); 62 if (esp_now_init() == ESP_OK) { 63 Serial.println("ESPNow Init Success"); 64 } else { 65 Serial.println("ESPNow Init Failed"); 66 // Retry InitESPNow, add a counte and then restart? 67 // InitESPNow(); 68 // or Simply Restart 69 ESP.restart(); 70 } 71} 72 73// Scan for slaves in AP mode 74void ScanForSlave() { 75 int16_t scanResults = WiFi.scanNetworks(false, false, false, 300, CHANNEL); // Scan only on one channel 76 // reset on each scan 77 bool slaveFound = 0; 78 memset(&slave, 0, sizeof(slave)); 79 80 Serial.println(""); 81 if (scanResults == 0) { 82 Serial.println("No WiFi devices in AP Mode found"); 83 } else { 84 Serial.print("Found "); 85 Serial.print(scanResults); 86 Serial.println(" devices "); 87 for (int i = 0; i < scanResults; ++i) { 88 // Print SSID and RSSI for each device found 89 String SSID = WiFi.SSID(i); 90 int32_t RSSI = WiFi.RSSI(i); 91 String BSSIDstr = WiFi.BSSIDstr(i); 92 93 if (PRINTSCANRESULTS) { 94 Serial.print(i + 1); 95 Serial.print(": "); 96 Serial.print(SSID); 97 Serial.print(" ("); 98 Serial.print(RSSI); 99 Serial.print(")"); 100 Serial.println(""); 101 } 102 delay(10); 103 // Check if the current device starts with `Slave` 104 if (SSID.indexOf("Slave") == 0) { 105 // SSID of interest 106 Serial.println("Found a Slave."); 107 Serial.print(i + 1); 108 Serial.print(": "); 109 Serial.print(SSID); 110 Serial.print(" ["); 111 Serial.print(BSSIDstr); 112 Serial.print("]"); 113 Serial.print(" ("); 114 Serial.print(RSSI); 115 Serial.print(")"); 116 Serial.println(""); 117 // Get BSSID => Mac Address of the Slave 118 int mac[6]; 119 if (6 == sscanf(BSSIDstr.c_str(), "%x:%x:%x:%x:%x:%x", &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5])) { 120 for (int ii = 0; ii < 6; ++ii) { 121 slave.peer_addr[ii] = (uint8_t)mac[ii]; 122 } 123 } 124 125 slave.channel = CHANNEL; // pick a channel 126 slave.encrypt = 0; // no encryption 127 128 slaveFound = 1; 129 // we are planning to have only one slave in this example; 130 // Hence, break after we find one, to be a bit efficient 131 break; 132 } 133 } 134 } 135 136 if (slaveFound) { 137 Serial.println("Slave Found, processing.."); 138 } else { 139 Serial.println("Slave Not Found, trying again."); 140 } 141 142 // clean up ram 143 WiFi.scanDelete(); 144} 145 146// Check if the slave is already paired with the master. 147// If not, pair the slave with master 148bool manageSlave() { 149 if (slave.channel == CHANNEL) { 150 if (DELETEBEFOREPAIR) { 151 deletePeer(); 152 } 153 154 Serial.print("Slave Status: "); 155 // check if the peer exists 156 bool exists = esp_now_is_peer_exist(slave.peer_addr); 157 if (exists) { 158 // Slave already paired. 159 Serial.println("Already Paired"); 160 return true; 161 } else { 162 // Slave not paired, attempt pair 163 esp_err_t addStatus = esp_now_add_peer(&slave); 164 if (addStatus == ESP_OK) { 165 // Pair success 166 Serial.println("Pair success"); 167 return true; 168 } else if (addStatus == ESP_ERR_ESPNOW_NOT_INIT) { 169 // How did we get so far!! 170 Serial.println("ESPNOW Not Init"); 171 return false; 172 } else if (addStatus == ESP_ERR_ESPNOW_ARG) { 173 Serial.println("Invalid Argument"); 174 return false; 175 } else if (addStatus == ESP_ERR_ESPNOW_FULL) { 176 Serial.println("Peer list full"); 177 return false; 178 } else if (addStatus == ESP_ERR_ESPNOW_NO_MEM) { 179 Serial.println("Out of memory"); 180 return false; 181 } else if (addStatus == ESP_ERR_ESPNOW_EXIST) { 182 Serial.println("Peer Exists"); 183 return true; 184 } else { 185 Serial.println("Not sure what happened"); 186 return false; 187 } 188 } 189 } else { 190 // No slave found to process 191 Serial.println("No Slave found to process"); 192 return false; 193 } 194} 195 196void deletePeer() { 197 esp_err_t delStatus = esp_now_del_peer(slave.peer_addr); 198 Serial.print("Slave Delete Status: "); 199 if (delStatus == ESP_OK) { 200 // Delete success 201 Serial.println("Success"); 202 } else if (delStatus == ESP_ERR_ESPNOW_NOT_INIT) { 203 // How did we get so far!! 204 Serial.println("ESPNOW Not Init"); 205 } else if (delStatus == ESP_ERR_ESPNOW_ARG) { 206 Serial.println("Invalid Argument"); 207 } else if (delStatus == ESP_ERR_ESPNOW_NOT_FOUND) { 208 Serial.println("Peer not found."); 209 } else { 210 Serial.println("Not sure what happened"); 211 } 212} 213 214uint8_t data = 255; 215// send data 216void sendData() { 217 218 pinMode(5, OUTPUT); 219 digitalWrite(5, HIGH); 220 221 sensors_event_t event; 222 while (data == 255) { 223 dht.temperature().getEvent(&event); 224 if (isnan(event.temperature)) { 225 Serial.println(F("Error reading temperature!")); 226 } else { 227 Serial.print(F("Temperature: ")); 228 Serial.print(event.temperature); 229 Serial.println(F("°C")); 230 } 231 data = (uint8_t)(event.temperature); 232 delay(100); 233 } 234 // Get humidity event and print its value. 235 dht.humidity().getEvent(&event); 236 if (isnan(event.relative_humidity)) { 237 Serial.println(F("Error reading humidity!")); 238 } else { 239 Serial.print(F("Humidity: ")); 240 Serial.print(event.relative_humidity); 241 Serial.println(F("%")); 242 } 243 244 // Serial.print(data); 245 const uint8_t *peer_addr = slave.peer_addr; 246 247 Serial.print("Sending: "); 248 Serial.println(data); 249 esp_err_t result = esp_now_send(peer_addr, &data, sizeof(data)); 250 Serial.print("Send Status: "); 251 if (result == ESP_OK) { 252 Serial.println("Success"); 253 } else if (result == ESP_ERR_ESPNOW_NOT_INIT) { 254 // How did we get so far!! 255 Serial.println("ESPNOW not Init."); 256 } else if (result == ESP_ERR_ESPNOW_ARG) { 257 Serial.println("Invalid Argument"); 258 } else if (result == ESP_ERR_ESPNOW_INTERNAL) { 259 Serial.println("Internal Error"); 260 } else if (result == ESP_ERR_ESPNOW_NO_MEM) { 261 Serial.println("ESP_ERR_ESPNOW_NO_MEM"); 262 } else if (result == ESP_ERR_ESPNOW_NOT_FOUND) { 263 Serial.println("Peer not found."); 264 } else { 265 Serial.println("Not sure what happened"); 266 } 267} 268 269// callback when data is sent from Master to Slave 270void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) { 271 char macStr[18]; 272 snprintf(macStr, sizeof(macStr), "%02x:%02x:%02x:%02x:%02x:%02x", 273 mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]); 274 Serial.print("Last Packet Sent to: "); 275 Serial.println(macStr); 276 Serial.print("Last Packet Send Status: "); 277 Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success" : "Delivery Fail"); 278} 279 280void setup() { 281 Serial.begin(115200); 282 dht.begin(); 283 284 pinMode(7,OUTPUT); 285 digitalWrite(7,HIGH); 286 287 //Set device in STA mode to begin with 288 WiFi.mode(WIFI_STA); 289 esp_wifi_set_channel(CHANNEL, WIFI_SECOND_CHAN_NONE); 290 Serial.println("ESPNow/Basic/Master Example"); 291 // This is the mac address of the Master in Station Mode 292 Serial.print("STA MAC: "); 293 Serial.println(WiFi.macAddress()); 294 Serial.print("STA CHANNEL "); 295 Serial.println(WiFi.channel()); 296 // Init ESPNow with a fallback logic 297 InitESPNow(); 298 // Once ESPNow is successfully Init, we will register for Send CB to 299 // get the status of Trasnmitted packet 300 esp_now_register_send_cb(OnDataSent); 301 302 sensor_t sensor; 303 dht.temperature().getSensor(&sensor); 304 Serial.println(F("------------------------------------")); 305 Serial.println(F("Temperature Sensor")); 306 Serial.print(F("Sensor Type: ")); 307 Serial.println(sensor.name); 308 Serial.print(F("Driver Ver: ")); 309 Serial.println(sensor.version); 310 Serial.print(F("Unique ID: ")); 311 Serial.println(sensor.sensor_id); 312 Serial.print(F("Max Value: ")); 313 Serial.print(sensor.max_value); 314 Serial.println(F("°C")); 315 Serial.print(F("Min Value: ")); 316 Serial.print(sensor.min_value); 317 Serial.println(F("°C")); 318 Serial.print(F("Resolution: ")); 319 Serial.print(sensor.resolution); 320 Serial.println(F("°C")); 321 Serial.println(F("------------------------------------")); 322 // Print humidity sensor details. 323 dht.humidity().getSensor(&sensor); 324 Serial.println(F("Humidity Sensor")); 325 Serial.print(F("Sensor Type: ")); 326 Serial.println(sensor.name); 327 Serial.print(F("Driver Ver: ")); 328 Serial.println(sensor.version); 329 Serial.print(F("Unique ID: ")); 330 Serial.println(sensor.sensor_id); 331 Serial.print(F("Max Value: ")); 332 Serial.print(sensor.max_value); 333 Serial.println(F("%")); 334 Serial.print(F("Min Value: ")); 335 Serial.print(sensor.min_value); 336 Serial.println(F("%")); 337 Serial.print(F("Resolution: ")); 338 Serial.print(sensor.resolution); 339 Serial.println(F("%")); 340 Serial.println(F("------------------------------------")); 341 342 esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR); 343 Serial.println("Setup ESP32 to sleep for every " + String(TIME_TO_SLEEP) + " Seconds"); 344} 345 346void loop() { 347 // In the loop we scan for slave 348 ScanForSlave(); 349 // If Slave is found, it would be populate in `slave` variable 350 // We will check if `slave` is defined and then we proceed further 351 if (slave.channel == CHANNEL) { // check if slave channel is defined 352 // `slave` is defined 353 // Add slave as peer if it has not been added already 354 bool isPaired = manageSlave(); 355 if (isPaired) { 356 // pair success or already paired 357 // Send data to device 358 sendData(); 359 } else { 360 // slave pair failed 361 Serial.println("Slave pair failed!"); 362 } 363 } else { 364 // No slave found to process 365 } 366 367 // wait for 3seconds to run the logic again 368 369 digitalWrite(7,LOW); 370 371 Serial.println("Going to sleep now"); 372 Serial.flush(); 373 esp_deep_sleep_start(); 374}
ESP-NOW Slave Code
cpp
ESP-NOW Slave Code
1/** 2 ESPNOW - Basic communication - Slave 3 Date: 26th September 2017 4 Author: Arvind Ravulavaru <https://github.com/arvindr21> 5 Purpose: ESPNow Communication between a Master ESP32 and a Slave ESP32 6 Description: This sketch consists of the code for the Slave module. 7 Resources: (A bit outdated) 8 a. https://espressif.com/sites/default/files/documentation/esp-now_user_guide_en.pdf 9 b. http://www.esploradores.com/practica-6-conexion-esp-now/ 10 11 << This Device Slave >> 12 13 Flow: Master 14 Step 1 : ESPNow Init on Master and set it in STA mode 15 Step 2 : Start scanning for Slave ESP32 (we have added a prefix of `slave` to the SSID of slave for an easy setup) 16 Step 3 : Once found, add Slave as peer 17 Step 4 : Register for send callback 18 Step 5 : Start Transmitting data from Master to Slave 19 20 Flow: Slave 21 Step 1 : ESPNow Init on Slave 22 Step 2 : Update the SSID of Slave with a prefix of `slave` 23 Step 3 : Set Slave in AP mode 24 Step 4 : Register for receive callback and wait for data 25 Step 5 : Once data arrives, print it in the serial monitor 26 27 Note: Master and Slave have been defined to easily understand the setup. 28 Based on the ESPNOW API, there is no concept of Master and Slave. 29 Any devices can act as master or salve. 30*/ 31#include <Wire.h> // Only needed for Arduino 1.6.5 and earlier 32#include "SSD1306Wire.h" // legacy: #include "SSD1306.h" 33// OR #include "SH1106Wire.h" // legacy: #include "SH1106.h" 34 35#include "pins_arduino.h" 36 37#include <esp_now.h> 38#include <WiFi.h> 39 40#define CHANNEL 1 41 42SSD1306Wire display(0x3c, SDA_OLED, SCL_OLED); // ADDRESS, SDA, SCL - SDA_OLED and SCL_OLED are the pins from pins_arduino.h where the Heltec connects the OLED display 43 44#define DEMO_DURATION 3000 45typedef void (*Demo)(void); 46 47int demoMode = 0; 48int counter = 1; 49 50void VextON(void) { 51 pinMode(Vext, OUTPUT); 52 digitalWrite(Vext, LOW); 53} 54 55// Init ESP Now with fallback 56void InitESPNow() { 57 WiFi.disconnect(); 58 if (esp_now_init() == ESP_OK) { 59 Serial.println("ESPNow Init Success"); 60 } else { 61 Serial.println("ESPNow Init Failed"); 62 // Retry InitESPNow, add a counte and then restart? 63 // InitESPNow(); 64 // or Simply Restart 65 ESP.restart(); 66 } 67} 68 69// config AP SSID 70void configDeviceAP() { 71 const char *SSID = "Slave_1"; 72 bool result = WiFi.softAP(SSID, "Slave_1_Password", CHANNEL, 0); 73 if (!result) { 74 Serial.println("AP Config failed."); 75 } else { 76 Serial.println("AP Config Success. Broadcasting with AP: " + String(SSID)); 77 Serial.print("AP CHANNEL "); 78 Serial.println(WiFi.channel()); 79 } 80} 81 82void displayReset(void) { 83 // Send a reset 84 pinMode(RST_OLED, OUTPUT); 85 digitalWrite(RST_OLED, HIGH); 86 delay(1); 87 digitalWrite(RST_OLED, LOW); 88 delay(1); 89 digitalWrite(RST_OLED, HIGH); 90 delay(1); 91} 92 93void OnDataRecv(const esp_now_recv_info_t * info, const uint8_t *data, int data_len) { 94 char macStr[18]; 95 snprintf(macStr, sizeof(macStr), "%02x:%02x:%02x:%02x:%02x:%02x", 96 info->src_addr[0], info->src_addr[1], info->src_addr[2], info->src_addr[3], info->src_addr[4], info->src_addr[5]); 97 Serial.print("Last Packet Recv from: "); Serial.println(macStr); 98 Serial.print("Last Packet Recv Data: "); 99 Serial.println(*data); 100 Serial.println(""); 101 102 char message[20]; 103 sprintf(message, "Temperature = %d", *data); 104 display.setFont(ArialMT_Plain_16); 105 display.setTextAlignment(TEXT_ALIGN_LEFT); 106 display.drawStringMaxWidth(0, 0, 128, message); 107 108 display.setFont(ArialMT_Plain_10); 109 display.setTextAlignment(TEXT_ALIGN_RIGHT); 110 // display.drawString(128, 54, String(millis())); 111 // write the buffer to the display 112 display.display(); 113 display.clear(); 114} 115 116void setup() { 117 Serial.begin(115200); 118 Serial.println("ESPNow/Basic/Slave Example"); 119 120 // This turns on and resets the OLED on the Heltec boards 121 VextON(); 122 displayReset(); 123 124 // Initialising the UI will init the display too. 125 display.init(); 126 127 display.flipScreenVertically(); 128 display.setFont(ArialMT_Plain_10); 129 130 //Set device in AP mode to begin with 131 WiFi.mode(WIFI_AP); 132 // configure device AP mode 133 configDeviceAP(); 134 // This is the mac address of the Slave in AP Mode 135 Serial.print("AP MAC: "); 136 Serial.println(WiFi.softAPmacAddress()); 137 // Init ESPNow with a fallback logic 138 InitESPNow(); 139 // Once ESPNow is successfully Init, we will register for recv CB to 140 // get recv packer info. 141 esp_now_register_recv_cb(OnDataRecv); 142} 143 144// callback when data is recv from Master 145 146 147void loop() { 148 // Chill 149}
Downloadable files
Gerber File for PCB
Gerber File for PCB
Altium_humidity sensor wifi_2024-08-02.zip
Documentation
More Details
More Details
https://robocircuits.com
Comments
Only logged in users can leave comments