ESP-Now through put

Greetings,
I have an issue with sending multiple ESP-Now packets back to back.

Trying to send send current state of a collection of switches. Send a single packet for the change of a switch works great. I want to send a complete update of all the switches every 10 seconds or so. This is done in broadcast mode.

When it runs through the loop for 5 packets the transmitting board says "Sending confirmed" for each. The receiving board shows 2 or 3 packets received. I thought it was receiving packets faster than it could process them. So, I implemented a ring buffer.

After the ring buffer was added I discovered it was receiving all five packets, but the missing packets were actually empty.

Back to the transmitting board. Apparently the loop is putting the data into the "esp_now_send" function too fast. I fixed it by putting a delay of 1ms after sending.

This is, in my opinion, inefficient. Is there a way to check if the transmit function is clear before sending the next packet vice waiting a predetermined time?

Switch are sent with a float value and text string identifying the switch function because it is sent to another program that requires this format.

void sendESPNow(String key, float value) {
  // Debug start
  Serial.print(key);
  Serial.print(" - ");
  Serial.println(value);
  //Debug end

  char datarefKeyBuffer[datarefKey_length];  // datarefKey_length = 200
  ESPNowDataOut.origin[0] = 0x2D; // ASCII code for - (minus sign)
  ESPNowDataOut.sysID = systemID;

  key.toCharArray(datarefKeyBuffer, key.length() + 1);
  strcpy(ESPNowDataOut.datarefKey, datarefKeyBuffer);

  ESPNowDataOut.datarefValue = value;
  
  // Send message via ESP-NOW
  esp_err_t result = esp_now_send(broadcastAddress, (uint8_t*)&ESPNowDataOut, sizeof(ESPNowDataOut));

  if (result == ESP_OK) {
    Serial.println("Sending confirmed");
  } else {
    Serial.println("Sending error");
  }
  delay(1); // Delay to prevent buffer over run
}

Why not cut the traffic and just send a packet that gets acknowledged when a switch changes. You can also have the slave request status when starting up to sync everything. This will be more robust and less prone to errors.

gilshultz,
It does send when a switch is changed. The receiving program does not send an acknowledgement.
It is in case a packet gets lost. I want to ensure that the program, a flight simulator, receives all the correct switch settings as indicated on a custom instrument panel. For example, I don't want someone to turn on the switch for carburetor de-icing and not have it get through. They would be flying along and all of a sudden the engines shut off due to ice build up even though they had flip the switch.
The program above works, but I was looking for a more efficient way to send the data rather than after a predetermined time. Plus I would like to know if there is a clear to send or buffer empty function.

Thanks for not saying "Go to Espressif's forum" like is often said here. :slight_smile:
Been all over it and most of the internet, but can't find what I'm looking for or I don't know how to ask it in the correct terms.

Thanks!
Randy

The automotive does that in real time all over the world. There primary communication is CAN (Controller Area Network). Check it out, it is extremely reliable, robust, and inexpensive to implement. Yes it is also used in airplanes.

CAN does the error checking etc for you, prioritizes the messages, It will try again if a message does not make it. This is done in the hardware without your processor doing the work.

It is good up to a few thousand feet distance and is multi master. This allows each switch etc to tell the world when it has changed etc and the world can ask it if it wants to. There is no arbitrator to determine when to send. Arbitration is done on a hardware basis and is based on the modules ID.

gilshultz,
I've seen CAN when doing automobile forensics. Something I want to dig into more some where down the road.
Can CAN be done wirelessly? All I've seen so far is two wire, high and low, transmission.

Randy

I tried using a binary semaphore: the sender will block to take it in the loop(), and the esp_now_register_send_cb callback will give it back. give it once at the end of start(). Tracking the amount of time waiting to take, just by comparing millis() before and after, with a 12-byte payload containing an incrementing counter

  • two thirds of the time it took 1ms
  • 14% took "zero" ms
  • 7% took 2ms
  • and ballpark 2/3 of the previous percentage for each ms after that
  • occasionally it would take 20 or 30 ms or more

A hard-coded 1ms delay is both sometimes too long, and occasionally not long enough.

Broadcasts averaged 550 to 650 sends per second. On the receiving end, I got runs of contiguous payloads, but also gaps. It's likely more reliable to transmit directly to a (or each) peer; and likely slower too to get confirmation.

kenb,
I don't know enough C++ to go real time. I program via Google searches :slight_smile:

Your observation matches what I'm experiencing. I can live with it as is, but really wish there was some indicator to let you know if it was OK to push the next packet through.

I've put the entire project on github:
https://github.com/CannonFodderSE/X-Plane-Instruments-via-ESP-Now/tree/main