Hello, I am working on a weather station wibe project. It utilezes ESP-NOW that transmits data to the "server" (esp32) from sender (esp8266), then it displays on basic server interface that I can open in my browser.
Here are the specifikations
- I am using the dht11 on both boards
- for esp8266 I picked the modul ESP8266 + NodeMCU V3 Arduino WIFI link to the shop
- for esp32 I picked ESP32, ESP32S nodemcu link to the shop (sorry its in czech)
So the problem basicly is that the dht-11 sensor failes almost all the time and when it finaly works it displays humidity of like 140? Also on my web server it displays the board number one (esp32), but not the esp8266, which doesnt make any sense becouse for the function to be executed there must be incoming mesage from esp8266. The dht-11 sensor works just fine I tried changing them, but the problem lasts.
here is my esp32 (server) code
/*
Rui Santos & Sara Santos - Random Nerd Tutorials
Complete project details at https://RandomNerdTutorials.com/esp-now-auto-pairing-esp32-esp8266/
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files.
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
Based on JC Servaye example: https://github.com/Servayejc/esp_now_web_server/
*/
#include <esp_now.h>
#include <WiFi.h>
#include <esp_wifi.h>
#include "ESPAsyncWebServer.h"
#include "AsyncTCP.h"
#include <ArduinoJson.h>
#include <Adafruit_Sensor.h>
#include <DHT.h>
#define DHTPIN 27 // Digital pin connected to the DHT sensor
// Uncomment the type of sensor in use:
#define DHTTYPE DHT11 // DHT 11
DHT dht(DHTPIN, DHTTYPE);
// Replace with your network credentials (STATION)
const char* ssid = "thanks";
const char* password = "for helping";
esp_now_peer_info_t slave;
int chan;
enum MessageType {PAIRING, DATA,};
MessageType messageType;
int counter = 0;
uint8_t clientMacAddress[6];
// Structure example to receive data
// Must match the sender structure
typedef struct struct_message {
uint8_t msgType;
uint8_t id;
float temp;
float hum;
unsigned int readingId;
} struct_message;
typedef struct struct_pairing { // new structure for pairing
uint8_t msgType;
uint8_t id;
uint8_t macAddr[6];
uint8_t channel;
} struct_pairing;
struct_message incomingReadings;
struct_message outgoingSetpoints;
struct_pairing pairingData;
AsyncWebServer server(80);
AsyncEventSource events("/events");
const char index_html[] PROGMEM = R"rawliteral(
<!DOCTYPE HTML><html>
<head>
<title>ESP-NOW DASHBOARD</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.2/css/all.css" integrity="sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr" crossorigin="anonymous">
<link rel="icon" href="data:,">
<style>
html {font-family: Arial; display: inline-block; text-align: center;}
p { font-size: 1.2rem;}
body { margin: 0;}
.topnav { overflow: hidden; background-color: #2f4468; color: white; font-size: 1.7rem; }
.content { padding: 20px; }
.card { background-color: white; box-shadow: 2px 2px 12px 1px rgba(140,140,140,.5); }
.cards { max-width: 700px; margin: 0 auto; display: grid; grid-gap: 2rem; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); }
.reading { font-size: 2.8rem; }
.packet { color: #bebebe; }
.card.temperature { color: #fd7e14; }
.card.humidity { color: #1b78e2; }
</style>
</head>
<body>
<div class="topnav">
<h3>ESP-NOW DASHBOARD</h3>
</div>
<div class="content">
<div class="cards">
<div class="card temperature">
<h4><i class="fas fa-thermometer-half"></i> BOARD #1 - TEMPERATURE</h4><p><span class="reading"><span id="t1"></span> °C</span></p><p class="packet">Reading ID: <span id="rt1"></span></p>
</div>
<div class="card humidity">
<h4><i class="fas fa-tint"></i> BOARD #1 - HUMIDITY</h4><p><span class="reading"><span id="h1"></span> %</span></p><p class="packet">Reading ID: <span id="rh1"></span></p>
</div>
<div class="card temperature">
<h4><i class="fas fa-thermometer-half"></i> BOARD #2 - TEMPERATURE</h4><p><span class="reading"><span id="t2"></span> °C</span></p><p class="packet">Reading ID: <span id="rt2"></span></p>
</div>
<div class="card humidity">
<h4><i class="fas fa-tint"></i> BOARD #2 - HUMIDITY</h4><p><span class="reading"><span id="h2"></span> %</span></p><p class="packet">Reading ID: <span id="rh2"></span></p>
</div>
</div>
</div>
<script>
if (!!window.EventSource) {
var source = new EventSource('/events');
source.addEventListener('open', function(e) {
console.log("Events Connected");
}, false);
source.addEventListener('error', function(e) {
if (e.target.readyState != EventSource.OPEN) {
console.log("Events Disconnected");
}
}, false);
source.addEventListener('message', function(e) {
console.log("message", e.data);
}, false);
source.addEventListener('new_readings', function(e) {
console.log("new_readings", e.data);
var obj = JSON.parse(e.data);
document.getElementById("t"+obj.id).innerHTML = obj.temperature.toFixed(2);
document.getElementById("h"+obj.id).innerHTML = obj.humidity.toFixed(2);
document.getElementById("rt"+obj.id).innerHTML = obj.readingId;
document.getElementById("rh"+obj.id).innerHTML = obj.readingId;
}, false);
}
</script>
</body>
</html>)rawliteral";
void readMacAddress(){
uint8_t baseMac[6];
esp_err_t ret = esp_wifi_get_mac(WIFI_IF_STA, baseMac);
if (ret == ESP_OK) {
Serial.printf("%02x:%02x:%02x:%02x:%02x:%02x\n",
baseMac[0], baseMac[1], baseMac[2],
baseMac[3], baseMac[4], baseMac[5]);
} else {
Serial.println("Failed to read MAC address");
}
}
void readDataToSend() {
outgoingSetpoints.msgType = DATA;
outgoingSetpoints.id = 0;
outgoingSetpoints.temp = random(0, 40);
outgoingSetpoints.hum = random(0, 100);
outgoingSetpoints.readingId = counter++;
}
// ---------------------------- esp_ now -------------------------
void printMAC(const uint8_t * mac_addr){
char macStr[18];
snprintf(macStr, sizeof(macStr), "%02x:%02x:%02x:%02x:%02x:%02x",
mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
Serial.print(macStr);
}
bool addPeer(const uint8_t *peer_addr) { // add pairing
memset(&slave, 0, sizeof(slave));
const esp_now_peer_info_t *peer = &slave;
memcpy(slave.peer_addr, peer_addr, 6);
slave.channel = chan; // pick a channel
slave.encrypt = 0; // no encryption
// check if the peer exists
bool exists = esp_now_is_peer_exist(slave.peer_addr);
if (exists) {
// Slave already paired.
Serial.println("Already Paired");
return true;
}
else {
esp_err_t addStatus = esp_now_add_peer(peer);
if (addStatus == ESP_OK) {
// Pair success
Serial.println("Pair success");
return true;
}
else
{
Serial.println("Pair failed");
return false;
}
}
}
// callback when data is sent
void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
Serial.print("Last Packet Send Status: ");
Serial.print(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success to " : "Delivery Fail to ");
printMAC(mac_addr);
Serial.println();
}
void OnDataRecv(const uint8_t * mac_addr, const uint8_t *incomingData, int len) {
Serial.print(len);
Serial.println(" bytes of new data received.");
StaticJsonDocument<1000> root;
String payload;
uint8_t type = incomingData[0]; // first message byte is the type of message
switch (type) {
case DATA : // the message is data type
memcpy(&incomingReadings, incomingData, sizeof(incomingReadings));
// create a JSON document with received data and send it by event to the web page
root["id"] = incomingReadings.id;
root["temperature"] = incomingReadings.temp;
root["humidity"] = incomingReadings.hum;
root["readingId"] = String(incomingReadings.readingId);
serializeJson(root, payload);
Serial.print("event send :");
serializeJson(root, Serial);
events.send(payload.c_str(), "new_readings", millis());
Serial.println(incomingReadings.temp);
delay(1000);
root["id"] = 1;
root["temperature"] = dht.readTemperature();
root["humidity"] = dht.readHumidity();
root["readingId"] = String(incomingReadings.readingId);
serializeJson(root, payload);
Serial.print("event send :");
serializeJson(root, Serial);
events.send(payload.c_str(), "new_readings", millis());
break;
case PAIRING: // the message is a pairing request
memcpy(&pairingData, incomingData, sizeof(pairingData));
Serial.println(pairingData.msgType);
Serial.println(pairingData.id);
Serial.print("Pairing request from MAC Address: ");
printMAC(pairingData.macAddr);
Serial.print(" on channel ");
Serial.println(pairingData.channel);
clientMacAddress[0] = pairingData.macAddr[0];
clientMacAddress[1] = pairingData.macAddr[1];
clientMacAddress[2] = pairingData.macAddr[2];
clientMacAddress[3] = pairingData.macAddr[3];
clientMacAddress[4] = pairingData.macAddr[4];
clientMacAddress[5] = pairingData.macAddr[5];
if (pairingData.id > 0) { // do not replay to server itself
if (pairingData.msgType == PAIRING) {
pairingData.id = 0; // 0 is server
// Server is in AP_STA mode: peers need to send data to server soft AP MAC address
WiFi.softAPmacAddress(pairingData.macAddr);
Serial.print("Pairing MAC Address: ");
printMAC(clientMacAddress);
pairingData.channel = chan;
Serial.println(" send response");
esp_err_t result = esp_now_send(clientMacAddress, (uint8_t *) &pairingData, sizeof(pairingData));
addPeer(clientMacAddress);
}
}
break;
}
}
void initESP_NOW(){
// Init ESP-NOW
if (esp_now_init() != ESP_OK) {
Serial.println("Error initializing ESP-NOW");
return;
}
esp_now_register_send_cb(OnDataSent);
esp_now_register_recv_cb(esp_now_recv_cb_t(OnDataRecv));
}
void setup() {
// Initialize Serial Monitor
Serial.begin(115200);
WiFi.mode(WIFI_STA);
WiFi.STA.begin();
Serial.print("Server MAC Address: ");
readMacAddress();
delay(100);
WiFi.mode(WIFI_AP_STA);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Setting as a Wi-Fi Station..");
}
Serial.print("Server SOFT AP MAC Address: ");
Serial.println(WiFi.softAPmacAddress());
chan = WiFi.channel();
Serial.print("Station IP Address: ");
Serial.println(WiFi.localIP());
Serial.print("Wi-Fi Channel: ");
Serial.println(WiFi.channel());
initESP_NOW();
// Start Web server
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, "text/html", index_html);
});
// Events
events.onConnect([](AsyncEventSourceClient *client){
if(client->lastId()){
Serial.printf("Client reconnected! Last message ID that it got is: %u\n", client->lastId());
}
// send event with message "hello!", id current millis
// and set reconnect delay to 1 second
client->send("hello!", NULL, millis(), 10000);
});
server.addHandler(&events);
// start server
server.begin();
}
void loop() {
static unsigned long lastEventTime = millis();
static const unsigned long EVENT_INTERVAL_MS = 5000;
if ((millis() - lastEventTime) > EVENT_INTERVAL_MS) {
events.send("ping", NULL, millis());
lastEventTime = millis();
readDataToSend();
esp_now_send(NULL, (uint8_t *) &outgoingSetpoints, sizeof(outgoingSetpoints));
}
}
here is my esp8266(sender) code
/*
Rui Santos & Sara Santos - Random Nerd Tutorials
Complete project details at https://RandomNerdTutorials.com/esp-now-auto-pairing-esp32-esp8266/
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files.
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
Based on JC Servaye example: https://https://github.com/Servayejc/esp8266_espnow
*/
#include <ESP8266WiFi.h>
#include <espnow.h>
#include <Adafruit_Sensor.h>
#include <DHT.h>
//-------dht11
#define DHTPIN 5 // Digital pin connected to the DHT sensor
// Uncomment the type of sensor in use:
#define DHTTYPE DHT11 // DHT 11
//#define DHTTYPE DHT22 // DHT 22 (AM2302)
//#define DHTTYPE DHT21 // DHT 21 (AM2301)
DHT dht(DHTPIN, DHTTYPE);
uint8_t channel = 1;
int readingId = 0;
int id = 2;
#define MAX_CHANNEL 13 // 11 in North America or 13 in Europe
unsigned long currentMillis = millis();
unsigned long lastTime = 0;
unsigned long timerDelay = 2000; // send readings timer
uint8_t broadcastAddressX[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
uint8_t clientMacAddress[6];
enum PairingStatus {PAIR_REQUEST, PAIR_REQUESTED, PAIR_PAIRED, };
PairingStatus pairingStatus = PAIR_REQUEST;
enum MessageType {PAIRING, DATA,};
MessageType messageType;
// Define variables to store DHT readings to be sent
float temperature;
float humidity;
// Define variables to store incoming readings
float incomingTemp;
float incomingHum;
int incomingReadingsId;
// Updates DHT readings every 10 seconds
//const long interval = 10000;
unsigned long previousMillis = 0; // will store last time DHT was updated
//Structure example to send data
//Must match the receiver structure
typedef struct struct_message {
uint8_t msgType;
uint8_t id;
float temp;
float hum;
unsigned int readingId;
} struct_message;
typedef struct struct_pairing { // new structure for pairing
uint8_t msgType;
uint8_t id;
uint8_t macAddr[6];
uint8_t channel;
} struct_pairing;
// Create a struct_message called myData
struct_message myData;
struct_message incomingReadings;
struct_pairing pairingData;
#define BOARD_ID 2
unsigned long start;
float readDHTTemperature() {
float t = dht.readTemperature();
if (isnan(t)) {
Serial.println("Failed to read from DHT sensor!");
return 0;
}
else {
Serial.println(t);
return t;
}
}
float readDHTHumidity() {
float h = dht.readHumidity();
if (isnan(h)) {
Serial.println("Failed to read from DHT sensor!");
return 0;
}
else {
Serial.println(h);
return h;
}
}
// Callback when data is sent
void OnDataSent(uint8_t *mac_addr, uint8_t sendStatus) {
Serial.print("Last Packet Send Status: ");
if (sendStatus == 0){
Serial.println("Delivery success");
}
else{
Serial.println("Delivery fail");
}
}
void printMAC(const uint8_t * mac_addr){
char macStr[18];
snprintf(macStr, sizeof(macStr), "%02x:%02x:%02x:%02x:%02x:%02x",
mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
Serial.print(macStr);
}
void printIncomingReadings(){
// Display Readings in Serial Monitor
Serial.println("INCOMING READINGS");
Serial.print("Temperature: ");
Serial.print(incomingTemp);
Serial.println(" ºC");
Serial.print("Humidity: ");
Serial.print(incomingHum);
Serial.println(" %");
Serial.print("Led: ");
Serial.print(incomingReadingsId);
}
// Callback when data is received
void OnDataRecv(uint8_t * mac, uint8_t *incomingData, uint8_t len) {
Serial.print("Size of message : ");
Serial.print(len);
Serial.print(" from ");
printMAC(mac);
Serial.println();
uint8_t type = incomingData[0];
switch (type) {
case DATA :
memcpy(&incomingReadings, incomingData, sizeof(incomingReadings));
Serial.print(len);
Serial.print(" Data bytes received from: ");
printMAC(mac);
Serial.println();
incomingTemp = incomingReadings.temp;
incomingHum = incomingReadings.hum;
printIncomingReadings();
if (incomingReadings.readingId % 2 == 1){
digitalWrite(LED_BUILTIN, LOW);
} else {
digitalWrite(LED_BUILTIN, HIGH);
}
break;
case PAIRING:
memcpy(&pairingData, incomingData, sizeof(pairingData));
if (pairingData.id == 0) { // the message comes from server
Serial.print("Pairing done for ");
printMAC(pairingData.macAddr);
Serial.print(" on channel " );
Serial.print(pairingData.channel); // channel used by the server
Serial.print(" in ");
Serial.print(millis()-start);
Serial.println("ms");
//esp_now_del_peer(pairingData.macAddr);
//esp_now_del_peer(mac);
esp_now_add_peer(pairingData.macAddr, ESP_NOW_ROLE_COMBO, pairingData.channel, NULL, 0); // add the server to the peer list
pairingStatus = PAIR_PAIRED ; // set the pairing status
}
break;
}
}
void getReadings(){
// Read Temperature
temperature = readDHTTemperature();
humidity = readDHTHumidity();
}
void readGetMacAddress(){
String val = WiFi.macAddress();
Serial.println(val);
char* endPtr;
clientMacAddress[0] = strtol(val.c_str(), &endPtr, 16); // read the first starting at the beginning of the buffer. this initializes endPtr as a pointer to the ':' after the first number
for (int i = 1; (*endPtr) && (i < 6); i++) {
clientMacAddress[i] = strtol(endPtr + 1, &endPtr, 16); // using +1 for the pointer as we want to skip the ':'
}
for (int i = 0; i < 6; i++) {
Serial.print(clientMacAddress[i], HEX);
if (i != 5) Serial.print(F(":"));
}
}
PairingStatus autoPairing(){
switch(pairingStatus) {
case PAIR_REQUEST:
Serial.print("Pairing request on channel " );
Serial.println(channel);
// clean esp now
esp_now_deinit();
WiFi.mode(WIFI_STA);
// set WiFi channel
wifi_promiscuous_enable(1);
wifi_set_channel(channel);
wifi_promiscuous_enable(0);
//WiFi.printDiag(Serial);
WiFi.disconnect();
// Init ESP-NOW
if (esp_now_init() != 0) {
Serial.println("Error initializing ESP-NOW");
}
esp_now_set_self_role(ESP_NOW_ROLE_COMBO);
// set callback routines
esp_now_register_send_cb(OnDataSent);
esp_now_register_recv_cb(OnDataRecv);
// set pairing data to send to the server
pairingData.id = BOARD_ID;
pairingData.channel = channel;
pairingData.macAddr[0] = clientMacAddress[0];
pairingData.macAddr[1] = clientMacAddress[1];
pairingData.macAddr[2] = clientMacAddress[2];
pairingData.macAddr[3] = clientMacAddress[3];
pairingData.macAddr[4] = clientMacAddress[4];
pairingData.macAddr[5] = clientMacAddress[5];
previousMillis = millis();
// add peer and send request
Serial.println(esp_now_send(broadcastAddressX, (uint8_t *) &pairingData, sizeof(pairingData)));
pairingStatus = PAIR_REQUESTED;
break;
case PAIR_REQUESTED:
// time out to allow receiving response from server
currentMillis = millis();
if(currentMillis - previousMillis > 1000) {
previousMillis = currentMillis;
// time out expired, try next channel
channel ++;
if (channel > MAX_CHANNEL) {
channel = 0;
}
pairingStatus = PAIR_REQUEST;
}
break;
case PAIR_PAIRED:
//Serial.println("Paired!");
break;
}
return pairingStatus;
}
void setup() {
// Init Serial Monitor
Serial.begin(74880);
pinMode(LED_BUILTIN, OUTPUT);
// Init DHT sensor
// Set device as a Wi-Fi Station
WiFi.mode(WIFI_STA);
readGetMacAddress();
//Serial.println(WiFi.macAddress());
WiFi.disconnect();
// Init ESP-NOW
if (esp_now_init() != 0) {
Serial.println("Error initializing ESP-NOW");
return;
}
// Set ESP-NOW Role
esp_now_set_self_role(ESP_NOW_ROLE_COMBO);
// Register for a callback function that will be called when data is received
esp_now_register_recv_cb(OnDataRecv);
esp_now_register_send_cb(OnDataSent);
pairingData.id = 2;
}
void loop() {
if (autoPairing() == PAIR_PAIRED) {
static unsigned long lastEventTime = millis();
static const unsigned long EVENT_INTERVAL_MS = 10000;
if ((millis() - lastEventTime) > EVENT_INTERVAL_MS) {
Serial.print(".");
getReadings();
//Set values to send
myData.msgType = DATA;
myData.id = 2;
myData.temp = temperature;
myData.hum = humidity;
myData.readingId = readingId ++;
// Send message via ESP-NOW to all peers
esp_now_send(pairingData.macAddr, (uint8_t *) &myData, sizeof(myData));
lastEventTime = millis();
}
}
}
As you can see the code is from Random nerd tutorials so the code should be fine, I just slightly changed it.
here is the screenshot of the web server
thanks everyone for reading this, also I apologise for my grammar (I am czech).