План уроку
- Передавання та прийом даних між ESP32 за допомогою ESP-NOW (Доопрацювання СК)
- Обробка прийнятих значень та вивід кутів на сервоприводи
Матеріали
- Електроніка СК
- ESP32 – 10 шт
- MG90 Servomotors – 20 шт
- Провідники 4-х кольорів, 26AWG, по 10 м.
- Паяльники
- Припій. Флюс/каніфоль
Результат уроку
Результатом мають бути два модулі:
- Електроніка СК:
- ESP32
- MPU6050
- Електроніка Роборуки:
- ESP32
- 2x MG90 Servomotors
Між двома модулями має бути організовано передачу даних. На електроніці СК розраховуємо кути орієнтації, передаємо на електроніку Роборуки, обробляємо та змінюємо кути положення валів сервомоторів.
Урок
ESP-NOW
ESP-NOW — це протокол бездротового зв’язку для ефективного передавання між пристроями з низькою затримкою, здатний надсилати до 250 байт. Працює як одноранговий (P2P) протокол, забезпечуючи прямий зв’язок між двома пристроями ESP8266 або ESP32 без необхідності центрального сервера або точки доступу(наприклад маршрутизатор Wi-Fi). Кожен пристрій ESP має унікальну MAC-адресу, яка використовується для ідентифікації плати.
Основні переваги ESP-NOW:
- Низька затримка: Оскільки дані передаються напряму між пристроями, затримка передачі даних значно менша в порівнянні з класичними мережами Wi-Fi.
- Низьке енергоспоживання: ESP-NOW працює без постійного підключення до точки доступу або маршрутизатора, що значно економить енергію, особливо для батарейних пристроїв.
- Мультикаст підтримка: Один пристрій може відправляти повідомлення кільком пристроям одночасно, що робить ESP-NOW ефективним для сценаріїв з широкомовною передачею даних (наприклад, керування освітленням чи іншими IoT пристроями).
- Надійність: Завдяки тому, що зв’язок відбувається напряму між пристроями, зменшується ризик втрати даних через точки доступу або інші мережеві вузли.
Обмеження:
- Мала довжина повідомлень: Максимальний розмір повідомлення становить 250 байт, що обмежує використання ESP-NOW для великих обсягів даних.
- Обмежена кількість пірів: Як вже зазначалось, ESP8266 підтримує до 20 пірів, тоді як ESP32 за замовчуванням підтримує 10 пірів, проте цей параметр можна збільшити.
- Невелика дальність: Хоча ESP-NOW використовує Wi-Fi частоту (2.4 GHz), дальність зв’язку зазвичай обмежена кількома десятками метрів у порівнянні з класичними Wi-Fi мережами.
Типи зв’язку
Односторонній зв’язок
У режимі одностороннього зв’язку один пристрій (відправник) може надсилати дані іншому пристрою (одержувачу), не очікуючи відповіді. Цей режим часто використовується для сценаріїв, коли один пристрій передає дані або команди іншому пристрою, наприклад показники віддаленого давача або команди керування.
Двосторонній зв’язок
У режимі двостороннього зв’язку обидва пристрої можуть обмінюватися даними в двох напрямках. Цей режим дає змогу обмінюватися інформацією між пристроями, забезпечуючи більш інтерактивне спілкування. Він підходить для ситуацій, де пристроям потрібно надсилати й отримувати дані один від одного, наприклад системи дистанційного керування або інтерактивні пристрої Інтернету речей.
Приклад коду роборуки
1. Ініціалізація Wi-Fi у режимі “станція” (WIFI_STA):
- Вмикаємо режим станції. Це дозволяє використовувати ESP-NOW для передачі даних між пристроями, без підключення до маршрутизатора чи точки доступу.
Також одразу виводимо собі mac адресу пристрою (в майбутньому знадобиться для налаштування передавача).
WiFi.mode(WIFI_STA); Serial.println(WiFi.macAddress());
2. Ініціалізація ESP-NOW:
- Після налаштування Wi-Fi, ініціалізуємо ESP-NOW. Якщо виникає помилка під час ініціалізації, у послідовний порт виводимо повідомлення про помилку.
if (esp_now_init() != ESP_OK) {
Serial.println("Error initializing ESP-NOW");
return;
}
3. Підготовка структури для отриманих даних
Для того аби зручно і впорядковано зберігати отримані дані, можна створити структуру
typedef struct {
int y;
int x;
} ;
RxData_t RxData;
4. Реєстрація колбек-функції для прийому даних:
- Основною частиною коду є функція
onDataReceive(), яка викликається автоматично, коли пристрій отримує нові дані через ESP-NOW. Вона приймає три аргументи:mac: MAC-адреса відправника (не використовується в цьому прикладі, але може бути корисна для ідентифікації пристрою-передавача).rxData: вказівник на отримані дані.len: довжина отриманих даних.
- У цій функції копіюємо дані у структуру
RxData
void onDataReceive(const uint8_t *mac, const uint8_t *rxData, int len) {
memcpy(&RxData, rxData, sizeof(RxData));
}
5. Основний цикл програми:
- В основному циклі
loop()ми оновлюємо кути сервомоторів з отриманих даних.
void loop() {
servoX.write(RxData.x);
servoY.write(180 - RxData.y);
}
Приклад коду передавача
1. Налаштування Wi-Fi в режимі станції:
- Вмикаємо режим станції. Це дозволяє використовувати ESP-NOW для передачі даних між пристроями, без підключення до маршрутизатора чи точки доступу
WiFi.mode(WIFI_STA);
2. Ініціалізація ESP-NOW:
- Після того, як Wi-Fi перейшов у режим станції, ініціалізуємо ESP-NOW.
if (esp_now_init() != ESP_OK) {
Serial.println("Error initializing ESP-NOW");
return;
}
3. Реєстрація пірів:
- Для передачі даних необхідно вказати MAC-адресу приймача(якраз ту, що ми на початку передавали у послідовний порт приймача). У цьому прикладі вона встановлюється у змінній
receiverMac:
const uint8_t receiverMac[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
- Інформацію про пір додаємо до ESP-NOW, вказуючи MAC-адресу, канал зв’язку (0 за замовчуванням), і вимикаючи шифрування (<стаття про шифрування>):
esp_now_peer_info_t peerInfo;
memcpy(peerInfo.peer_addr, receiverMac, 6);
peerInfo.channel = 0;
peerInfo.encrypt = false;
if (esp_now_add_peer(&peerInfo) != ESP_OK) {
Serial.println("Failed to add peer");
return;
}
4. Підготовка та відправка повідомлення:
- В основному циклі програми
loop()готуємо повідомлення, яке складається з тексту та послідовного номера:
- Повідомлення передаємо за допомогою функції
esp_now_send(), де вказується MAC-адреса приймача та вказівник на повідомлення:
esp_now_send(peerInfo.peer_addr, (uint8_t *) &txMessage, sizeof(txMessage));
- Зворотний зв’язок про статус відправки:
- Якщо відправка не була успішною, виводимо повідомлення “Error sending the message”:
if (result != ESP_OK) {
Serial.println("Error sending the message");
}
Основні моменти:
- Не забудьте змінити MAC-адресу приймача на реальну адресу пристрою, який прийматиме повідомлення.
- Враховуйте розмір і типи даних для надсилання. Якщо вам потрібно передавати динамічні типи даних, то в варто робити “обгортки” для пакетів даних(хедер, тип, розмір пакету)
