'3x Arduino + ESP32 with ESP-NOW

The configuration on "machine" looks like this: Computer with custom app WPF C#, have connected ESP32-sender. On other side of room there is ESP32 as recaiver that have connected to it 3 arduino due, that controls a lot of stepper motors.

My problem is, that if I send a single command all works great. Directly on other side it executes. The problem starts when there is a lot of commands to send. ESP32 starts to makes Delivery fail status and after that moment all further commands are lost.

That's the code of Master-ESP connected to PC. Which arduino to send is decide by one of the symbols on begin of message "!,@,#"

#include <esp_now.h>
#include <WiFi.h>
#include <Wire.h>
uint8_t broadcastAddress[] = {0x94, 0xB9, 0x7E, 0xD0, 0x93, 0x64};
String inMess;
typedef struct Message {
    char a[100];
} Message;
// Variable to store if sending data was successful
String success;
Message message;
Message send_message;

esp_now_peer_info_t peerInfo;
char incoming;
String full = "";
bool text_done = false;
bool sended = false;
// Callback when data is sent
void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
  //Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success*" : "Delivery Fail*");
  if (status ==0){
    success = "Delivery Success :)";
    text_done = false;
    full = "";
    sended = false;
  }
  else{
    success = "Delivery Fail :(";
    delay(10);
    sended = false;
    Serial.println(success);
  }
}
// Callback when data is received
void OnDataRecv(const uint8_t * mac, const uint8_t *incomingData, int len) {
  memcpy(&message, incomingData, sizeof(message));
  Serial.println(message.a);

}
 
void setup() {
  // Init Serial Monitor
  Serial.begin(115200);

  // Set device as a Wi-Fi Station
  WiFi.mode(WIFI_STA);
  Serial.println(WiFi.macAddress());
  // Init ESP-NOW
  if (esp_now_init() != ESP_OK) {
    Serial.println("Error initializing ESP-NOW");
    return;
  }
  esp_now_register_send_cb(OnDataSent);
  
  // Register peer
  memcpy(peerInfo.peer_addr, broadcastAddress, 6);
  peerInfo.channel = 0;  
  peerInfo.encrypt = false;
  
  // Add peer        
  if (esp_now_add_peer(&peerInfo) != ESP_OK){
    Serial.println("Failed to add peer");
    return;
  }
  esp_now_register_recv_cb(OnDataRecv);
}
 
void loop() {

  if(Serial.available() > 0 && !text_done){
    incoming = Serial.read();
    if(incoming == '\n'){
      text_done = true;
      full.trim();
      full.toUpperCase();
    }
    if(text_done == false){
      full += incoming;
    }
  }
  if(text_done){
    if(full[0] != '!' && full[0] != '@' && full[0] != '#'){ //check if text is worth sending to other esp
      text_done = false;
      full = "";
    }
  }
  if(text_done){
    if(!sended){
     full.toCharArray(send_message.a,sizeof(send_message));
  esp_err_t result = esp_now_send(broadcastAddress, (uint8_t *) &send_message, sizeof(send_message));
   
  if (result == ESP_OK) {
    //Serial.println("Sent success*");
    sended = true;
  }
  else {
    Serial.println("Error sending*");
    delay(10);
  }
  }
  }
  
}

That's the code of recaiver ESP

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

SoftwareSerial worker;
SoftwareSerial tool;
//Serial2 is Table, software serials are others

uint8_t broadcastAddress[] = {0x7C, 0x9E, 0xBD, 0x4B, 0x47, 0xA4};

String outMess;
String outMessTable;
String outMessTool;
String inMess;

typedef struct Message {
    char a[100];
} Message;
String success;
Message message;
Message send_message;
bool sended = true;
String again_message = "";
esp_now_peer_info_t peerInfo;

void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
  //Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success" : "Delivery Fail");
  if (status == 0) {
    success = "Delivery Success :)";
    sended = true;
    again_message = "";
  }
  else {
    success = "Delivery Fail :(";
    sended = false;
    delay(5);
  }
}

void OnDataRecv(const uint8_t * mac, const uint8_t *incomingData, int len) {
  memcpy(&message, incomingData, sizeof(message));

  Serial.println(message.a);
  sendTo((String)message.a);
}

void setup() {
  // Init Serial Monitor
  Serial.begin(115200);
  Serial2.begin(115200, SERIAL_8N1, 16, 17);
  //rx tx
  worker.begin(57600, SWSERIAL_8N1, 25, 26, false);
  if (!worker) { 
    Serial.println("Invalid SoftwareSerial pin configuration, check config");
    while (1) {
      delay (1000);
    }
  }
  //rx tx
  tool.begin(57600, SWSERIAL_8N1, 32, 33, false);
  if (!tool) {
    Serial.println("Invalid SoftwareSerial pin configuration, check config");
    while (1) {
      delay (1000);
    }
  }
  // Set device as a Wi-Fi Station
  WiFi.mode(WIFI_STA);
  Serial.println(WiFi.macAddress());
  // 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 Send CB to
  // get the status of Trasnmitted packet
  esp_now_register_send_cb(OnDataSent);

  // Register peer
  memcpy(peerInfo.peer_addr, broadcastAddress, 6);
  peerInfo.channel = 0;
  peerInfo.encrypt = false;

  // Add peer
  if (esp_now_add_peer(&peerInfo) != ESP_OK) {
    Serial.println("Failed to add peer");
    return;
  }
  // Register for a callback function that will be called when data is received
  esp_now_register_recv_cb(OnDataRecv);
}

void loop() {
  // Set values to send

  if(sended){
  if (worker.available() > 0) {//!
    char t = worker.read();
    if(t == '\n'){
      outMess.trim();
      sendToEsp(outMess,"!");
      outMess = "";
    }
    else{
      outMess += t;
    }
  }
  }else{
     if(again_message.length()>0){
       delay(10);
     sendToEsp(again_message.substring(1),again_message.substring(0,1));
     }else{
       sended = true;
     }
   }
   if(sended){
  if (tool.available() > 0) {//#
    char t = tool.read();
    if(t == '\n'){
      outMessTool.trim();
      sendToEsp(outMessTool,"#");
      outMessTool = "";
    }
    else{
      outMessTool += t;
    }

  }
  }else{
     if(again_message.length()>0){
       delay(10);
     sendToEsp(again_message.substring(1),again_message.substring(0,1));
     }else{
       sended = true;
     }
   }
   if(sended){
  if (Serial2.available() > 0) { //@
    char t = Serial2.read();
    if(t == '\n'){
      outMessTable.trim();
      sendToEsp(outMessTable,"@");
      outMessTable = "";
    }else{
      outMessTable += t;
    }
  }
  }else{
     if(again_message.length()>0){
       delay(10);
     sendToEsp(again_message.substring(1),again_message.substring(0,1));
     }else{
       sended = true;
     }
   }

  if(Serial.available() > 0){
    outMess = Serial.readStringUntil('\n'); //read command from pc
    outMess.trim(); // remove uneccesery spaces
    sendTo(outMess); 
  }
   
}
void sendToEsp(String text, String which){
  String mess = which + text;
  again_message = mess;
  mess.toCharArray(send_message.a,sizeof(send_message));
  esp_err_t result = esp_now_send(broadcastAddress, (uint8_t *) &send_message, sizeof(send_message));
  if (result == ESP_OK) {
   // Serial.println("Sent with success");
  }
  else {
    Serial.println("Error sending the data");
    sended = true;
    again_message = "";
  }
}
void sendTo(String outMess){
  Serial.print("=");
  Serial.print(outMess);
    if(outMess[0] == '!'){ //worker
      worker.enableTx(true);
      worker.println(outMess.substring(1));
      worker.enableTx(false);
      Serial.println("send to worker");
    }
    if(outMess[0] == '@') {//table
      Serial2.println(outMess.substring(1));
       Serial.println("send to table");
    }
    if(outMess[0] == '#'){ //tool
    tool.enableTx(true);
      tool.println(outMess.substring(1));
      tool.enableTx(false);
       Serial.println("send to tool");
    }
}

If I send one message with a delay of writing next one by hand it works great. If the message is sended via c# very fast, esp32 is handling first few of them then losing on sending or recaiving, sometimes both of esp32 sometimes only one.

How could I prevent that to make stable connection ?



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source