ESP-Now

From RevSpace
Jump to navigation Jump to search

In the beginning, revspace was strung together using a mix of genuine and cloned nRF42 modules. This has made a lot of people very angry and been widely regarded as a bad move.

Project ESP-Now
ESP-WROOM-32.jpeg
ESP-Now netwerk op de space
Status Completed
Contact Kartoffel,bertrik
Last Update 2022-12-03

Tegenwoordig zijn de meeste sensors en frutsels zelf via WiFi direct met MQTT verbonden. Het is in sommige gevallen fijn om een simpeler, meer low-power radioprotocol te hebben waarmee we berichtjes naar MQTT kunnen slingeren.

Dit is per december 2022 vervangen door een simpeler broadcast esp-now systeem op kanaal 9. Hiermee is geen pairing via het revspace-espnow SSID meer nodig.

Werking

Aan de ledspace Raspberry Pi hangt een ESP32 die alle espnow broadcasts op WiFi kanaal 9 opvangt. Als de berichten met #R of #U beginnen worden ze naar de seriële poort doorgestuurd en door pyserial-mqtt op MQTT gepubliceerd.

De verzendende ESP8266 en ESP32's sturen een esp-now bericht naar het broadcast adres (0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF) op kanaal 9, met data:

  • #Rtopic payload voor een retained MQTT topic
  • #Utopic payload voor een unretained MQTT topic

That's it!

Projecten

Voorbeeldcode

Dit zou portable moeten zijn voor zowel ESP8266 als ESP32 modules binnen de Arduino omgeving. De esp8266 heeft wat extra trickery nodig om daadwerkelijk op kanaal 9 uit te zenden.

#include "Arduino.h"

#if defined(ESP8266)
  #include <espnow.h>
  #include "ESP8266WiFi.h"
#else
  #include <esp_now.h>
  #include <esp_wifi.h>
  #include <WiFi.h>
#endif

// Custom protocol for MQTT over ESP-NOW
// Always start with #, then R for retained or U for unretained
#define MQTT_TOPIC  "#Urevspace/button/test"
#define MQTT_MSG    "hallo"

#define ESP_NOW_CHANNEL 9
#if defined(ESP32)
  esp_now_peer_info_t peerInfo;
#endif
uint8_t broadcastAddress[] = {0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF};

void setup(void) {
  // Welcome
  Serial.begin(115200);
  Serial.printf("\nStart\n");

#if defined(ESP32)
  WiFi.mode(WIFI_STA);
  ESP_ERROR_CHECK(esp_wifi_start());
  ESP_ERROR_CHECK(esp_wifi_set_promiscuous(true));

  if (esp_wifi_set_channel(ESP_NOW_CHANNEL, WIFI_SECOND_CHAN_NONE) != ESP_OK) {
    Serial.println("Failed to set WiFi channel!");
    return;
  }

  if (esp_now_init() != ESP_OK) {
    Serial.println("Error initializing ESP-NOW");
    return;
  }
    
  // register peer
  memcpy(peerInfo.peer_addr, broadcastAddress, 6);
  peerInfo.channel = ESP_NOW_CHANNEL;  
  peerInfo.encrypt = false;
          
  if (esp_now_add_peer(&peerInfo) != ESP_OK){
    Serial.println("Failed to add peer");
    return;
  }
#else
  WiFi.forceSleepWake();
  WiFi.persistent(false);
  WiFi.mode(WIFI_STA);
  WiFi.begin("aapnoot", "miesmies", ESP_NOW_CHANNEL, NULL, false);
  WiFi.disconnect();
  wifi_set_channel(ESP_NOW_CHANNEL);

  if (esp_now_init() != 0) {
    Serial.println("Error initializing ESP-NOW");
  }
  
  esp_now_set_self_role(ESP_NOW_ROLE_CONTROLLER);
  esp_now_add_peer(broadcastAddress, ESP_NOW_ROLE_SLAVE, ESP_NOW_CHANNEL, NULL, 0);
#endif

}

bool send_topic_text(const char *topic, const char *text) {
  uint8_t *mac = broadcastAddress;
  char buf[250];
  int n = snprintf(buf, sizeof(buf), "%s %s", topic, text);
  return esp_now_send(mac, (uint8_t *)buf, n) == 0;
}

void loop(void) {

  send_topic_text(MQTT_TOPIC, MQTT_MSG);

  delay(10);

  // Sleep forever
#if defined(ESP32)
  esp_deep_sleep_start();
#else
  ESP.deepSleep(0);
#endif
}