I have a project that involves twoESP8266 and aNEO-6M GPS module. I want to send the GPS data to the other microcontroller using ESP-NOW, however it fails to send the data although it displays the coordinates. I just want to figure out how can I send the data through ESP-NOW. I have tried putting the two microcontrollers near each other, however, the status still displays as fail. The sender code is
#include <TinyGPS++.h>#include <ESP8266WiFi.h>#include <espnow.h>#include <SoftwareSerial.h>SoftwareSerial ss(5, 4); TinyGPSPlus gps;int baud = 9600;uint8_t receiverMAC[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};typedef struct struct_message { float latitude; float longitude; float altitude;} struct_message;struct_message myData;void setup() { Serial.begin(baud); ss.begin(baud); WiFi.mode(WIFI_STA); delay(100); if (esp_now_init() != 0) { Serial.println("ESP-NOW initialization failed!"); while (true); } esp_now_set_self_role(ESP_NOW_ROLE_CONTROLLER); if (esp_now_add_peer(receiverMAC, ESP_NOW_ROLE_SLAVE, 1, NULL, 0) != 0) { Serial.println("Failed to add peer"); return; }}void loop() { while (ss.available() > 0) { if (gps.encode(ss.read())) { if (gps.location.isValid()) { myData.latitude = gps.location.lat(); myData.longitude = gps.location.lng(); myData.altitude = gps.altitude.meters(); displayInfo(); sendData(); } } } esp_now_register_send_cb(OnDataSent);}void OnDataSent(uint8_t * mac_addr, uint8_t sendStatus) { Serial.print("ESP-NOW Send Status: "); if (sendStatus == 0) { Serial.println("Delivery success"); } else { Serial.println("Delivery fail"); }}void displayInfo() { Serial.print("Latitude: "); Serial.println(myData.latitude, 6); Serial.print("Longitude: "); Serial.println(myData.longitude, 6); Serial.print("Altitude: "); Serial.println(myData.altitude, 2);}void sendData() { delay(100); uint8_t result = esp_now_send(receiverMAC, (uint8_t *) &myData, sizeof(myData)); if (result != 0) { Serial.println("Error sending data"); }}While the receiver code for the other microcontroller is shown below
#include <ESP8266WiFi.h>#include <espnow.h>typedef struct struct_message { float latitude; float longitude; float altitude;} struct_message;struct_message myData;void OnDataRecv(uint8_t * mac, uint8_t *incomingData, uint8_t len) { Serial.println("Data received!"); memcpy(&myData, incomingData, sizeof(myData)); Serial.print("Latitude: "); Serial.println(myData.latitude, 6); Serial.print("Longitude: "); Serial.println(myData.longitude, 6); Serial.print("Altitude: "); Serial.println(myData.altitude, 2);}void setup() { Serial.begin(9600); WiFi.mode(WIFI_STA); if (esp_now_init() != 0) { Serial.println("Error initializing ESP-NOW"); return; } esp_now_set_self_role(ESP_NOW_ROLE_SLAVE); esp_now_register_recv_cb(OnDataRecv);}void loop() {}- 11) For ESP-Now Receiver, it needs to be in AP mode with
WiFi.mode(WIFI_AP);,WiFi.disconnect();. 2) For ESP-Now Transmitter, you don't need to register the callback repeatedly in the loop, the lineesp_now_register_send_cb(OnDataSent);should be moved to setup(). 3) for the sendData(), remove theuint8_t result =and the if statement, the sendData status is provided in the callback function.hcheung– hcheung2025-03-02 11:06:25 +00:00CommentedMar 2 at 11:06 - Sorry for the late response, and thank you for replying. I have tried doing your suggestions, however, the OnDataSent function still displays fail. I do not know why this is happening.mizuto0– mizuto02025-03-08 01:56:51 +00:00CommentedMar 8 at 1:56
- 1) Add
WiFi.disconnect();to the transmitter code to make sure it does not connected to WiFi. 2)Are you matching thereceiverMAC[]with the actual mac address of your receiver board mac address. 3) You don't have to use the actual hardware mac address of the receiver board, you could also assigned aLocally Administered mac address to the receiver and make sure you use it on both the transmitter and the receiver as shown in myexample code.hcheung– hcheung2025-03-08 02:09:20 +00:00CommentedMar 8 at 2:09 - Thanks for the suggestion, I have tried adding your suggestions and it looks like it worked since the data is sending to the receiver esp8266. However, it takes some time for it to send data.mizuto0– mizuto02025-03-09 12:26:16 +00:00CommentedMar 9 at 12:26
- Define "some time", not based on myexperience where it generally toke 500uS for round trip, at the range stretch, it varies between 2000uS to occasionally up to 20000uS. Since your sketch included GPS, is the "some time" caused by GPS acquisition or by ESP-NOW?hcheung– hcheung2025-03-09 13:11:03 +00:00CommentedMar 9 at 13:11
2 Answers2
There are several things regarding ESP-Now is not setup correctly.
- For ESP-Now Receiver, it needs to be in AP mode with
WiFi.mode(WIFI_AP), and make sure it doesn't connect to WiFi withWiFi.disconnect(). - For ESP-Now Transmitter, it needs to be in STA mode (this is done correctly) and itMUST NOT connect to WiFi, so add
WiFi.disconnect()right afterWiFi.mode(WIFI_STA). - You don't need to register the callback repeatedly in the loop, the line
esp_now_register_send_cb(OnDataSent);should be moved tosetup(). 4. For the sendData(), remove theuint8_t result =and theifstatement, the sendData status is provided in the callback function. - For the
receiveMAC[]address in the transmitter need to either match the actual MAC address of the receiver ESP8266 or theLocally Administrated MAC Address, the advantage of using the locally administrated MAC address is that a) you don't need to write a sketch to find out the MAC address as shown in the other answer; b) when you change swap ESP8266 receiver with another new one in future, you don't need to re-flash your transmitter to change the MAC address.
The following is the example code (without the GPS code) for the ESP8266 ESP-Now transmitter and ESP-Now receiver, with the example of using a locally administrated MAC address.
ESP-Now Transmitter
#include <ESP8266WiFi.h>#include <espnow.h>typedef struct gps_message_s { float latitude; float longitude; float altitude;} gps_t;// *** the following variables need to match the receiver settings ***uint8_t receiverMAC[] = {{0x82, 0x88, 0x88, 0x88, 0x88, 0x88};gps_t myData;const unit8_t channel = 1;// **************************************************************unsigned long sendStartTime;void OnDataSent(uint8_t * mac, uint8_t sendStatus) { unsigned long sentEndTime = micros(); Serial.printf("< Device: %02x:%02x:%02x:%02x:%02x:%02x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); Serial.printf("< Status: %s\n", (sendStatus == 0 ? "Success" : "Failed"));' Serial.printf("Round-trip in uS: %4lu, ", sentEndTime - sentStartTime);}void setup() { Serial.begin(115200); WiFi.persistent(false); // turn off wifi persistent WiFi.mode(WIFI_STA); // ESP-Now transmitter must be in STA mode WiFi.disconnect(); // Do not connect to WiFi if (esp_now_init() != 0) { Serial.println("ESP-NOW initialization failed!"); while (true); } esp_now_set_self_role(ESP_NOW_ROLE_CONTROLLER); esp_now_add_peer(receiverMAC, ESP_NOW_ROLE_SLAVE, channel, NULL, 0); esp_now_register_send_cb(onDataSent);}void loop() { // dummy data for the myData struct, replace it with actual data myData.latitude = 1.72; myData.longitude = 1.03; myData.altitude = 13.0; Serial.printf("Sending Lat=%.2f, Long=%.2f; Alt=%.2f\n", myData.latitude, myData.longitude, myData.altitude); sentStartTime = micros(); esp_now_send(receiverMAC, (uint8_t *) &myData, sizeof(myData)); delay(1000); // send again in 1 second}ESP-Now Receiver
#include <ESP8266WiFi.h>#include <espnow.h>typedef struct struct_message { float latitude; float longitude; float altitude;} struct_message;// *** following 3 settings must match transmitter's settings ***uint8_t mac[] = {0x82, 0x88, 0x88, 0x88, 0x88, 0x88};const uint8_t channel = 1;struct_message myData;// **************************************************************void OnDataRecv(uint8_t * tmac, uint8_t *incomingData, uint8_t len) { Serial.println("Data received!"); memcpy(&myData, incomingData, len); Serial.printf("From: %02x:%02x:%02x:%02x:%02x:%02x, ", tmac[0], tmac[1], tmac[2], tmac[3], tmac[4], tmac[5]); Serial.print("Latitude: "); Serial.println(myData.latitude, 6); Serial.print("Longitude: "); Serial.println(myData.longitude, 6); Serial.print("Altitude: "); Serial.println(myData.altitude, 2);}void setup() { Serial.begin(115200); WiFi.persistent(false); // turn off wifi persistent WiFi.mode(WIFI_AP); // ESP-Now receiver must be in AP mode WiFi.disconnect(); // Do not connect to WiFi wifi_set_macaddr(SOFTAP_IF, mac); // if using Locally Administrated MAC if (esp_now_init() != 0) { Serial.println("Error initializing ESP-NOW"); return; } esp_now_set_self_role(ESP_NOW_ROLE_SLAVE); esp_now_register_recv_cb(OnDataRecv);}void loop() {}Here are two of my blogs for myESP-Now doorbell project andRange and Response time test
YourreceiverMAC is currently {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}. This is not a valid MAC address. Get the correct MAC address of the receiving ESP8266, by writing the following code:
void setup() { Serial.begin(115200); WiFi.mode(WIFI_STA); Serial.print("ESP8266 MAC: "); Serial.println(WiFi.macAddress());} void loop() {}You can get more info from this tutorial.https://randomnerdtutorials.com/get-change-esp32-esp8266-mac-address-arduino/. Please figure out the correct MAC address and update it in your code. If you want to make print PCBs for your project, here you will get some idea about the cost.https://www.allpcb.com/blog/pcb-ordering/pcb-cost-per-unit.html
Explore related questions
See similar questions with these tags.
