Sunday, December 18, 2022

ESP NOW sender and receiver basic project

ESP Now seems to be a link layer protocol for the ESP 32 and ESP 8266.  It is easy to use for a simple project passing data between an ESP 8266 with a sensor attached, to an ESP 32 with an actuator.

randomnerdtutorials.com has example ESP NOW code for the ESP8266 and ESP32, which form the basis for this project.

The addressing of ESP NOW uses MAC addresses.  In this project, the ESP 8266 is sending data to the ESP 32.  So, the MAC address of the ESP 32 is needed.  There is a code snippet in the link above that can be loaded into the ESP 32, and the MAC address retrieved from Arduino Serial Monitor.  In my case this address was 58:BF:25:31:9D:E0


This was put into the example code from the link above, for the ESP 8266:
/*
  Original Code by Rui Santos, edited for illustration of sensor data forwarding via ESP NOW on ESP 8266
  Complete project details at https://RandomNerdTutorials.com/esp-now-esp8266-nodemcu-arduino-ide/
  
  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.
*/

#include <ESP8266WiFi.h>
#include <espnow.h>

// REPLACE WITH RECEIVER MAC Address
uint8_t broadcastAddress[] = {0x58, 0xBF, 0x25, 0x31, 0x9D, 0xE0};

// Structure example to send data
// Must match the receiver structure
typedef struct struct_message {
  char a[32];
  int b;
  float c;
  String d;
  bool e;
} struct_message;

// Create a struct_message called myData
struct_message myData;

unsigned long lastTime = 0;  
unsigned long timerDelay = 250;  // send readings timer

// 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 setup() {
  // Init Serial Monitor
  Serial.begin(115200);
 
  // Set device as a Wi-Fi Station
  WiFi.mode(WIFI_STA);

  // Init ESP-NOW
  if (esp_now_init() != 0) {
    Serial.println("Error initializing ESP-NOW");
    return;
  }

  // Once ESPNow is successfully Init, we will register for Send CB to
  // get the status of Trasnmitted packet
  esp_now_set_self_role(ESP_NOW_ROLE_CONTROLLER);
  esp_now_register_send_cb(OnDataSent);
  
  // Register peer
  esp_now_add_peer(broadcastAddress, ESP_NOW_ROLE_SLAVE, 1, NULL, 0);
}
 
void loop() {
  if ((millis() - lastTime) > timerDelay) {
    // Set values to send
    strcpy(myData.a, "THIS IS A CHAR");
    myData.b = analogRead(A0);
    myData.c = 1.2;
    myData.d = "Hello";
    myData.e = false;

    // Send message via ESP-NOW
    esp_now_send(broadcastAddress, (uint8_t *) &myData, sizeof(myData));

    lastTime = millis();
  }
}
The only changes made to the original code are inputting the MAC address of the ESP 32, changing the value of the 'timerDelay' variable, and changing assignment to mydata.b from 'random(1,20);' to 'analogRead(A0);'.  The wiring is as follows:
  • ESP8266 3.3 V Pin to Potentiometer High
  • ESP8266 Gnd Pin to Potentiometer Low
  • ESP8266 A0 Pin to Potentiometer wiper
Once flashed, the ESP8266 is powered by a 5V lithium battery, intended for use as a cellphone battery charger.

The ESP 32 code from the link above also has minor changes:
/*
  Original code by Rui Santos, minor additions made to actuate an LED upon receipt of ESP
  NOW data exceeding an arbitrary threshold.
  Complete project details at https://RandomNerdTutorials.com/esp-now-esp32-arduino-ide/
  
  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.
*/

#include <esp_now.h>
#include <WiFi.h>

// Structure example to receive data
// Must match the sender structure
typedef struct struct_message {
    char a[32];
    int b;
    float c;
    bool d;
} struct_message;

// Create a struct_message called myData
struct_message myData;

// callback function that will be executed when data is received
void OnDataRecv(const uint8_t * mac, const uint8_t *incomingData, int len) {
  memcpy(&myData, incomingData, sizeof(myData));
  Serial.print("Bytes received: ");
  Serial.println(len);
  Serial.print("Char: ");
  Serial.println(myData.a);
  Serial.print("Int: ");
  Serial.println(myData.b);
  Serial.print("Float: ");
  Serial.println(myData.c);
  Serial.print("Bool: ");
  Serial.println(myData.d);
  Serial.println();
}
 
void setup() {
  // Initialize Serial Monitor
  Serial.begin(115200);
  pinMode(4, OUTPUT);
    digitalWrite(4, HIGH);
    
  // Set device as a Wi-Fi Station
  WiFi.mode(WIFI_STA);

  // Init ESP-NOW
  if (esp_now_init() != ESP_OK) {
    Serial.println("Error initializing ESP-NOW");
    return;
  }
  
  // Once ESPNow is successfully Init, we will register for recv CB to
  // get recv packer info
  esp_now_register_recv_cb(OnDataRecv);
}
 
void loop() {
if(myData.b>512)
{
  digitalWrite(4, HIGH);
  }
  
  else
  {
    digitalWrite(4, LOW);
    }
}
The only changes made to the original code is addition of the 'if' and 'else' statements within the loop, and 'pinMode(4,OUTPUT);' and 'digitalWrite(4,HIGH);' in setup to make pin 4 ready to actuate an LED. The wiring is as follows:
  • ESP32 Pin 4 to LED Anode
  • LED Cathode to 150 Ohm resistor
  • 150 Ohm Resistor to ESP32 Gnd Pin
Once flashed, the ESP 32 is powered by my PC USB port.  I can monitor the data received on Arduino Serial monitor, and confirm that the LED illuminates when the potentiometer wiper passes the 512 position.


Note "Int: 770", the wiper is past the threshold, the LED is on: 



Now the wiper is below the threshold ('Int: 390') and the LED is off:


Paring down the data structure to only send data that is necessary to function is an exercise left to the reader.

No comments:

Post a Comment