ESP8266 отправляет данные GPS через ESP сейчас
У меня есть проект, включающий два модуля ESP8266 и один GPS-модуль NEO-6M. Я хочу отправить данные GPS на другой микроконтроллер через ESP-NOW, но он не отправляет данные, хотя и отображает координаты. Я просто хочу понять, как отправить данные через ESP-NOW. Я пробовал размещать два микроконтроллера рядом друг с другом, но статус всё ещё отображается как «Fail». Код отправителя:
#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");
}
}
В то время как код приемника для другого микроконтроллера показан ниже
#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() {
}
@mizuto0, 👍0
Обсуждение2 ответа
Лучший ответ:
Есть несколько моментов, связанных с неправильной настройкой ESP-Now.
- Для приемника ESP-Now он должен находиться в режиме точки доступа с помощью
WiFi.mode(WIFI_AP)и убедиться, что он не подключается к WiFi с помощьюWiFi.disconnect(). - Для передатчика ESP-Now он должен находиться в режиме STA (это сделано правильно) и он НЕ ДОЛЖЕН подключаться к WiFi, поэтому добавьте
WiFi.disconnect()сразу послеWiFi.mode(WIFI_STA). - Вам не нужно регистрировать обратный вызов повторно в цикле, строку
esp_now_register_send_cb(OnDataSent);следует перенести вsetup(). 4. Для sendData() удалите операторuint8_t result =иif, состояние sendData предоставляется в функции обратного вызова. - Чтобы адрес
receiveMAC[]в передатчике совпадал либо с фактическим MAC-адресом приёмника ESP8266, либо с локально управляемым MAC-адресом. Преимущество использования локально управляемого MAC-адреса заключается в следующем: а) вам не нужно писать скетч для определения MAC-адреса, как показано в другом ответе; б) если в будущем вы замените приёмник ESP8266 на другой, вам не нужно будет перепрошивать передатчик для изменения MAC-адреса.
Ниже приведен пример кода (без кода GPS) для передатчика ESP8266 ESP-Now и приемника ESP-Now с примером использования локально администрируемого MAC-адреса.
Передатчик ESP-Now
#include <ESP8266WiFi.h>
#include <espnow.h>
typedef struct gps_message_s {
float latitude;
float longitude;
float altitude;
} gps_t;
// *** следующие переменные должны соответствовать настройкам приемника ***
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); // отключить постоянный Wi-Fi
WiFi.mode(WIFI_STA); // Передатчик ESP-Now должен быть в режиме STA
WiFi.disconnect(); // Не подключаться к 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() {
// фиктивные данные для структуры myData, заменяем их фактическими данными
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); // отправить снова через 1 секунду
}
Приёмник ESP-Now
#include <ESP8266WiFi.h>
#include <espnow.h>
typedef struct struct_message {
float latitude;
float longitude;
float altitude;
} struct_message;
// *** следующие 3 настройки должны соответствовать настройкам передатчика ***
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); // отключить постоянный Wi-Fi
WiFi.mode(WIFI_AP); // Приемник ESP-Now должен быть в режиме точки доступа
WiFi.disconnect(); // Не подключаться к WiFi
wifi_set_macaddr(SOFTAP_IF, mac); // если используется локально администрируемый 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() {
}
Вот две мои записи в блоге о проекте дверного звонка ESP-Now и тесте дальности и времени отклика
Ваш receiverMAC в настоящее время равен {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}. Это недопустимый MAC-адрес. Получите правильный MAC-адрес принимающего ESP8266, выполнив следующий код:
void setup() {
Serial.begin(115200);
WiFi.mode(WIFI_STA);
Serial.print("ESP8266 MAC: ");
Serial.println(WiFi.macAddress());}
void loop() {}
Более подробную информацию можно найти в этом руководстве: https://randomnerdtutorials.com/get-change-esp32-esp8266-mac-address-arduino/. Определите правильный MAC-адрес и обновите его в коде. Если вы хотите изготовить печатные платы для своего проекта, здесь вы найдете информацию о стоимости. https://www.allpcb.com/blog/pcb-ordering/pcb-cost-per-unit.html
- Загрузка кода Arduino, OTA, через подключенный ESP8266-12E с запущенным Esp-Link
- Невозможно подключить ESP8266 к сети WPA2+Enterprise
- Как постоянно отправлять данные от нескольких клиентов на сервер с помощью NodeMCU?
- Подключите ESP8266 к Thingspeak
- Самая низкая задержка при запуске нескольких Arduino с использованием NRF24L01+
- Ошибка при загрузке кода в ESP8266 через Arduino Mega 2560
- Как отправлять твиты с датчиком пламени и ESP8266?
- Отправка нескольких сообщений через последовательный монитор в nodeMCU
1) Для приемника ESP-Now он должен находиться в режиме точки доступа с помощью
WiFi.mode(WIFI_AP);,WiFi.disconnect();. 2) Для передатчика ESP-Now не нужно повторно регистрировать обратный вызов в цикле, строкуesp_now_register_send_cb(OnDataSent);следует перенести в setup(). 3) Для sendData() удалитеuint8_t result =и оператор if, состояние sendData предоставляется в функции обратного вызова., @hcheungИзвините за поздний ответ и спасибо за ответ. Я попробовал выполнить ваши рекомендации, однако функция OnDataSent всё ещё выдаёт ошибку. Я не знаю, почему это происходит., @mizuto0
1) Добавьте
WiFi.disconnect();в код передатчика, чтобы убедиться, что он не подключен к WiFi. 2) Сопоставляете ли выreceiverMAC[]с фактическим MAC-адресом вашей платы приемника? 3) Вам не обязательно использовать фактический аппаратный MAC-адрес платы приемника, вы также можете назначить приемнику [локально управляемый MAC-адрес](https://serverfault.com/a/40720) и убедиться, что вы используете его как на передатчике, так и на приемнике, как показано в моем [примере кода](https://www.e-tinkers.com/2024/10/fix-a-wireless-doorbell-with-esp-now/)., @hcheungСпасибо за предложение, я попробовал применить ваши рекомендации, и, похоже, всё заработало, поскольку данные отправляются на приёмник ESP8266. Однако отправка данных занимает некоторое время., @mizuto0
Определение «некоторое время» основано не на моём [опыте] (https://www.e-tinkers.com/2020/05/esp-01-range-test-with-esp-now-protocol/), где обычно требуется 500 мкс на полный оборот, а на дальних дистанциях оно варьируется от 2000 мкс до иногда 20 000 мкс. Поскольку в вашем наброске есть GPS, «некоторое время» связано с приёмом GPS или с работой ESP-NOW?, @hcheung
Успешная отправка данных заняла около двух секунд; за это время уже были получены данные GPS. Следовательно, соединение, вероятно, было установлено благодаря ESP-NOW. У меня нет количественной оценки доли успешных попыток (в микросекундах), но, возможно, стоит добавить это значение для проверки., @mizuto0
Данные NMEA GPS публикуются с частотой 1 Гц (то есть каждую секунду), поэтому интервал составляет не менее 1 секунды. Что касается передачи и приёма ESP-Now, проблема решена, поэтому я собрал всю предоставленную мной информацию и добавил её в качестве ответа, а также код для измерения времени прохождения сигнала туда и обратно. Буду благодарен, если вы примете это как ответ на благо будущих читателей., @hcheung