How to read a struct with a for loop

Hello

I need to read the data from my struct. At the moment, I have a laughable amount of print statements (which worked fine for testing)

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("Arch 1: ");
  Serial.println(myData.arch1);
  Serial.print("Arch 2: ");
  Serial.println(myData.arch2);
  Serial.print("Arch 3: ");
  Serial.println(myData.arch3);
  Serial.print("Arch 4: ");
  Serial.println(myData.arch4);
  Serial.print("Arch 5: ");
  Serial.println(myData.arch5);
  Serial.print("Arch 6: ");
  Serial.println(myData.arch6);
  Serial.print("Arch 7: ");
  Serial.println(myData.arch7);
  Serial.print("Arch 8: ");
  Serial.println(myData.arch8);
  Serial.print("Arch 9: ");
  Serial.println(myData.arch9);
  Serial.print("Arch 10: ");
  Serial.println(myData.arch10);
  Serial.print("Arch 11: ");
  Serial.println(myData.arch11);
  Serial.print("Arch 12: ");
  Serial.println(myData.arch12);
  Serial.print("Arch 13: ");
  Serial.println(myData.arch13);
  Serial.print("Arch 14: ");
  Serial.println(myData.arch14);
  Serial.print("Arch 15: ");
  Serial.println(myData.arch15);
  Serial.print("Arch 16: ");
  Serial.println(myData.arch16);
  Serial.print("Arch 17: ");
  Serial.println(myData.arch17);
  Serial.print("Arch 18: ");
  Serial.println(myData.arch18);
  Serial.print("Arch 19: ");
  Serial.println(myData.arch19);
  Serial.print("Arch 20: ");
  Serial.println(myData.arch20);
  Serial.print("Arch 21: ");
  Serial.println(myData.arch21);
  Serial.print("Arch 22: ");
  Serial.println(myData.arch22);
  Serial.println();
}

How do I do this with a for loop?

  for (int i = 1; i <= 22; i++) {
      Serial.print("Arch");Serial.print(i);Serial.print(": ");
      Serial.println(myData.arch#); 
  }

First... Is that for loop counting to 22?
Second... how do I incorporate the value 'i' into the 'myData.arch#' command?

You cannot iterate through a struct like that. The name of all variables, including structs, is not known in the binary code output by the compiler

In order to help we need to know more about the struct. For instance, what data types are the elements of the struct. Please post a full sketch that illustrates what you want to do, using code tags when you do

At first sight your data item names look as though an array might be a better data structure than a struct but without seeing it, who knows ?

seems you would be better off with

struct Payload {
  uint8_t arch[22]; // or whatever suitable type for your arch data
};

then you could indeed do

for (byte i = 0; i<22; i++) {
  Serial.print("Arch "); Serial.print(i+1); // +1 because you want the user interface to count from 1
  Serial.print(": "); Serial.println(myData.arch[i]); 
}

Oh OK. I was trying to work out how to use ESPnow to send data from one ESP32 out to 22 slave ESP32's.

I was using an online example (probably a bad idea to start with).

The ESPnow example in the IDE doesn't compile.

Let me get the code and post it so you can laugh!

always up for a good laugh at the start of the year :slight_smile: (and later too)

HI @baffled2023 ,

sending and receiving a struct might by a good idea if you have a set of variables of different data types:

/*
   Source: https://randomnerdtutorials.com/esp-now-esp32-arduino-ide/
*/

// Structure example to send data
// Must match the receiver 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;

So it might depend on what you are transmitting ...

ec2021

P.S.: You could also have an array of struct data of course!

Dunno if you noticed.... I have no idea what I am doing....

time for a walk then :slight_smile:

Right... this will make you laugh #TerribleJanuaryCode

Overview:

One ESP32 master transmits 22x 0-255 values to 22 receiving ESP32s.

These receivers all have the same code and take their allocated arch number (allocated by their MAC address) and they will operate a LED using PWM out.

I know this is terrible code. I was basically playing around to see if this would work.
I also don't really use ESP32's, so all a bit new.

Using the online tutorial I found:

Receiver:

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

typedef struct test_struct {
  byte arch1;
  byte arch2;
  byte arch3;
  byte arch4;
  byte arch5;
  byte arch6;
  byte arch7;
  byte arch8;
  byte arch9;
  byte arch10;
  byte arch11;
  byte arch12;
  byte arch13;
  byte arch14;
  byte arch15;
  byte arch16;
  byte arch17;
  byte arch18;
  byte arch19;
  byte arch20;
  byte arch21;
  byte arch22;
} test_struct;

test_struct myData;

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("Arch 1: ");
  Serial.println(myData.arch1);
  Serial.print("Arch 2: ");
  Serial.println(myData.arch2);
  Serial.print("Arch 3: ");
  Serial.println(myData.arch3);
  Serial.print("Arch 4: ");
  Serial.println(myData.arch4);
  Serial.print("Arch 5: ");
  Serial.println(myData.arch5);
  Serial.print("Arch 6: ");
  Serial.println(myData.arch6);
  Serial.print("Arch 7: ");
  Serial.println(myData.arch7);
  Serial.print("Arch 8: ");
  Serial.println(myData.arch8);
  Serial.print("Arch 9: ");
  Serial.println(myData.arch9);
  Serial.print("Arch 10: ");
  Serial.println(myData.arch10);
  Serial.print("Arch 11: ");
  Serial.println(myData.arch11);
  Serial.print("Arch 12: ");
  Serial.println(myData.arch12);
  Serial.print("Arch 13: ");
  Serial.println(myData.arch13);
  Serial.print("Arch 14: ");
  Serial.println(myData.arch14);
  Serial.print("Arch 15: ");
  Serial.println(myData.arch15);
  Serial.print("Arch 16: ");
  Serial.println(myData.arch16);
  Serial.print("Arch 17: ");
  Serial.println(myData.arch17);
  Serial.print("Arch 18: ");
  Serial.println(myData.arch18);
  Serial.print("Arch 19: ");
  Serial.println(myData.arch19);
  Serial.print("Arch 20: ");
  Serial.println(myData.arch20);
  Serial.print("Arch 21: ");
  Serial.println(myData.arch21);
  Serial.print("Arch 22: ");
  Serial.println(myData.arch22);
  Serial.println();
}

#define testLED 27



void setup() {
  Serial.begin(115200);
  pinMode (testLED, OUTPUT);

  WiFi.mode(WIFI_STA);                                                                            // Set device as a Wi-Fi Station

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

  esp_now_register_recv_cb(esp_now_recv_cb_t(OnDataRecv));

  digitalWrite(testLED, HIGH);
  delay(1000);
  digitalWrite(testLED, LOW);
  Serial.println("Receiver online");
}


void loop() {

  if (myData.arch1 == 255) {
    digitalWrite(testLED, HIGH);
  }
  if (myData.arch1 == 0) {
    digitalWrite(testLED, LOW);
  }

    if (myData.arch15 == 255) {
    digitalWrite(testLED, HIGH);
  }
  if (myData.arch15 == 0) {
    digitalWrite(testLED, LOW);
  }

}

YES... The struct could be far smaller (I could not get arch[22] to work?)
And the print statements are stupid - but that was for testing and could go eventually (or be made far nicer).

The transmit code: (get ready)

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

uint8_t broadcastAddress1[] = {0x3C, 0x8A, 0x1F, 0x0B, 0x6E, 0xC4};                                               // Test address 1
uint8_t broadcastAddress2[] = {0x3C, 0x8A, 0x1F, 0x0B, 0x73, 0xE1};
uint8_t broadcastAddress3[] = {0x3C, 0x8A, 0x1F, 0x0B, 0x73, 0xD2};
uint8_t broadcastAddress4[] = {0x3C, 0x8A, 0x1F, 0x0B, 0x73, 0xA1};
uint8_t broadcastAddress5[] = {0x3C, 0x8A, 0x1F, 0x0B, 0x73, 0xA2};
uint8_t broadcastAddress6[] = {0x3C, 0x8A, 0x1F, 0x0B, 0x73, 0xA3};
uint8_t broadcastAddress7[] = {0x3C, 0x8A, 0x1F, 0x0B, 0x73, 0xA4};
uint8_t broadcastAddress8[] = {0x3C, 0x8A, 0x1F, 0x0B, 0x73, 0xB1};
uint8_t broadcastAddress9[] = {0x3C, 0x8A, 0x1F, 0x0B, 0x73, 0xB2};
uint8_t broadcastAddress10[] = {0x3C, 0x8A, 0x1F, 0x0B, 0x73, 0xB3};
uint8_t broadcastAddress11[] = {0x3C, 0x8A, 0x1F, 0x0B, 0x73, 0xB4};
uint8_t broadcastAddress12[] = {0x3C, 0x8A, 0x1F, 0x0B, 0x73, 0xC1};
uint8_t broadcastAddress13[] = {0x3C, 0x8A, 0x1F, 0x0B, 0x73, 0xC2};
uint8_t broadcastAddress14[] = {0x3C, 0x8A, 0x1F, 0x0B, 0x73, 0xC3};
uint8_t broadcastAddress15[] = {0x3C, 0x8A, 0x1F, 0x0B, 0x73, 0xD4};                                              // Test address 15
uint8_t broadcastAddress16[] = {0x3C, 0x8A, 0x1F, 0x0B, 0x73, 0xE2};
uint8_t broadcastAddress17[] = {0x3C, 0x8A, 0x1F, 0x0B, 0x73, 0xE3};
uint8_t broadcastAddress18[] = {0x3C, 0x8A, 0x1F, 0x0B, 0x73, 0xE4};
uint8_t broadcastAddress19[] = {0x3C, 0x8A, 0x1F, 0x0B, 0x73, 0xF1};
uint8_t broadcastAddress20[] = {0x3C, 0x8A, 0x1F, 0x0B, 0x73, 0xF2};
uint8_t broadcastAddress21[] = {0x3C, 0x8A, 0x1F, 0x0B, 0x73, 0xF3};
uint8_t broadcastAddress22[] = {0x3C, 0x8A, 0x1F, 0x0B, 0x73, 0xF4};


typedef struct test_struct {
  byte arch1;
  byte arch2;
  byte arch3;
  byte arch4;
  byte arch5;
  byte arch6;
  byte arch7;
  byte arch8;
  byte arch9;
  byte arch10;
  byte arch11;
  byte arch12;
  byte arch13;
  byte arch14;
  byte arch15;
  byte arch16;
  byte arch17;
  byte arch18;
  byte arch19;
  byte arch20;
  byte arch21;
  byte arch22;
} test_struct;

test_struct test;

esp_now_peer_info_t peerInfo;

void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {                                           // callback when data is sent
  char macStr[18];
  Serial.print("Packet to: ");
  snprintf(macStr, sizeof(macStr), "%02x:%02x:%02x:%02x:%02x:%02x",                                                // Copies the sender mac address to a string
           mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
  Serial.print(macStr);
  Serial.print(" send status:\t");
  Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success" : "Delivery Fail");
}


void setup() {
  Serial.begin(115200);

  WiFi.mode(WIFI_STA);

  if (esp_now_init() != ESP_OK) {
    Serial.println("Error initialising ESP-NOW");
    return;
  }

  esp_now_register_send_cb(OnDataSent);

  peerInfo.channel = 0;                                                       // register all the recevier peers....
  peerInfo.encrypt = false;

  memcpy(peerInfo.peer_addr, broadcastAddress1, 6);                           // register 1st peer
  if (esp_now_add_peer(&peerInfo) != ESP_OK) {
    Serial.println("Failed to add 1st arch");
    return;
  }
  else
  {
    Serial.println("1st arch online");
  }
  delay(300);


  memcpy(peerInfo.peer_addr, broadcastAddress2, 6);                           // register 2nd peer
  if (esp_now_add_peer(&peerInfo) != ESP_OK) {
    Serial.println("Failed to add 2nd arch");
    return;
  }
  else
  {
    Serial.println("2nd arch online");
  }
  delay(300);


  memcpy(peerInfo.peer_addr, broadcastAddress3, 6);                           // register 3rd peer
  if (esp_now_add_peer(&peerInfo) != ESP_OK) {
    Serial.println("Failed to add 3rd arch");
    return;
  }
  else
  {
    Serial.println("3rd arch online");
  }
  delay(300);

  memcpy(peerInfo.peer_addr, broadcastAddress4, 6);                           // register 4th peer
  if (esp_now_add_peer(&peerInfo) != ESP_OK) {
    Serial.println("Failed to add 4th arch");
    return;
  }
  else
  {
    Serial.println("4th arch online");
  }
  delay(300);

  memcpy(peerInfo.peer_addr, broadcastAddress5, 6);                           // register 5th peer
  if (esp_now_add_peer(&peerInfo) != ESP_OK) {
    Serial.println("Failed to add 5th arch");
    return;
  }
  else
  {
    Serial.println("5th arch online");
  }
  delay(300);

  memcpy(peerInfo.peer_addr, broadcastAddress6, 6);                           // register 6th peer
  if (esp_now_add_peer(&peerInfo) != ESP_OK) {
    Serial.println("Failed to add 6th arch");
    return;
  }
  else
  {
    Serial.println("6th arch online");
  }
  delay(300);

  memcpy(peerInfo.peer_addr, broadcastAddress7, 6);                           // register 7th peer
  if (esp_now_add_peer(&peerInfo) != ESP_OK) {
    Serial.println("Failed to add 7th arch");
    return;
  }
  else
  {
    Serial.println("7th arch online");
  }
  delay(300);

  memcpy(peerInfo.peer_addr, broadcastAddress8, 6);                           // register 8th peer
  if (esp_now_add_peer(&peerInfo) != ESP_OK) {
    Serial.println("Failed to add 8th arch");
    return;
  }
  else
  {
    Serial.println("8th arch online");
  }
  delay(300);

  memcpy(peerInfo.peer_addr, broadcastAddress9, 6);                           // register 9th peer
  if (esp_now_add_peer(&peerInfo) != ESP_OK) {
    Serial.println("Failed to add 9th arch");
    return;
  }
  else
  {
    Serial.println("9th arch online");
  }
  delay(300);

  memcpy(peerInfo.peer_addr, broadcastAddress10, 6);                           // register 10th peer
  if (esp_now_add_peer(&peerInfo) != ESP_OK) {
    Serial.println("Failed to add 10th arch");
    return;
  }
  else
  {
    Serial.println("10th arch online");
  }
  delay(300);

  memcpy(peerInfo.peer_addr, broadcastAddress11, 6);                           // register 11th peer
  if (esp_now_add_peer(&peerInfo) != ESP_OK) {
    Serial.println("Failed to add 11th arch");
    return;
  }
  else
  {
    Serial.println("11th arch online");
  }
  delay(300);

  memcpy(peerInfo.peer_addr, broadcastAddress12, 6);                           // register 12th peer
  if (esp_now_add_peer(&peerInfo) != ESP_OK) {
    Serial.println("Failed to add 12th arch");
    return;
  }
  else
  {
    Serial.println("12th arch online");
  }
  delay(300);

  memcpy(peerInfo.peer_addr, broadcastAddress13, 6);                           // register 13th peer
  if (esp_now_add_peer(&peerInfo) != ESP_OK) {
    Serial.println("Failed to add 13th arch");
    return;
  }
  else
  {
    Serial.println("13th arch online");
  }
  delay(300);

  memcpy(peerInfo.peer_addr, broadcastAddress14, 6);                           // register 14th peer
  if (esp_now_add_peer(&peerInfo) != ESP_OK) {
    Serial.println("Failed to add 14th arch");
    return;
  }
  else
  {
    Serial.println("14th arch online");
  }
  delay(300);

  memcpy(peerInfo.peer_addr, broadcastAddress15, 6);                           // register 15th peer
  if (esp_now_add_peer(&peerInfo) != ESP_OK) {
    Serial.println("Failed to add 15th arch");
    return;
  }
  else
  {
    Serial.println("15th arch online");
  }
  delay(300);

  memcpy(peerInfo.peer_addr, broadcastAddress16, 6);                           // register 16th peer
  if (esp_now_add_peer(&peerInfo) != ESP_OK) {
    Serial.println("Failed to add 16th arch");
    return;
  }
  else
  {
    Serial.println("16th arch online");
  }
  delay(300);

  memcpy(peerInfo.peer_addr, broadcastAddress17, 6);                           // register 17th peer
  if (esp_now_add_peer(&peerInfo) != ESP_OK) {
    Serial.println("Failed to add 17th arch");
    return;
  }
  else
  {
    Serial.println("17th arch online");
  }
  delay(300);

  memcpy(peerInfo.peer_addr, broadcastAddress18, 6);                           // register 18th peer
  if (esp_now_add_peer(&peerInfo) != ESP_OK) {
    Serial.println("Failed to add 18th arch");
    return;
  }
  else
  {
    Serial.println("18th arch online");
  }
  delay(300);

  memcpy(peerInfo.peer_addr, broadcastAddress19, 6);                           // register 19th peer
  if (esp_now_add_peer(&peerInfo) != ESP_OK) {
    Serial.println("Failed to add 19th arch");
    return;
  }
  else
  {
    Serial.println("19th arch online");
  }
  delay(300);

  memcpy(peerInfo.peer_addr, broadcastAddress20, 6);                           // register 20th peer
  if (esp_now_add_peer(&peerInfo) != ESP_OK) {
    Serial.println("Failed to add 20th arch");
    return;
  }
  else
  {
    Serial.println("20th arch online");
  }
  delay(300);

  memcpy(peerInfo.peer_addr, broadcastAddress21, 6);                           // register 21st peer
  if (esp_now_add_peer(&peerInfo) != ESP_OK) {
    Serial.println("Failed to add 21st arch");
    return;
  }
  else
  {
    Serial.println("21st arch online");
  }
  delay(300);

  memcpy(peerInfo.peer_addr, broadcastAddress22, 6);                           // register 22nd peer
  if (esp_now_add_peer(&peerInfo) != ESP_OK) {
    Serial.println("Failed to add 22nd arch");
    return;
  }
  else
  {
    Serial.println("22nd arch online");
  }
  delay(300);

}


void loop() {

  test.arch1 = 255;                                                         // Some test values
  delay(2000);
  transmit();

  test.arch15 = 255;
  delay(2000);
  transmit();

  test.arch1 = 0;
  delay(2000);
  transmit();

  test.arch15 = 0;
  delay(2000);
  transmit();

  esp_err_t result = esp_now_send(0, (uint8_t *) &test, sizeof(test_struct));

  if (result == ESP_OK) {
    Serial.println("Sent with success");
  }
  else {
    Serial.println("Error sending the data");
  }
  delay(2000);
}


void transmit() {
  esp_err_t result = esp_now_send(0, (uint8_t *) &test, sizeof(test_struct));

  if (result == ESP_OK) {
    Serial.println("Sent with success");
  }
  else {
    Serial.println("Error sending the data");
  }
}

LOTS of repeat code that needs to be changed, but copy/paste was a quick fix.

The broadcast MAC address could go in 'broadcastAddress[22]' I imagine
Then the ridiculous amount of peer connection check repeats could be removed.

BUT.... THIS ENTIRE THING FAILS...
I think the maximum amount of peers is 20 on ESPnow, so the whole idea dies there.

I have entirely abandoned this. Its outside the abilities of an ESP32.
The max amount of slave ESP32s with ESPnow is either 4 or 20, depending where you read from). I think it's 20, as my code stops trying at 20.

It does actually kinda work. But it's not enough channels.

I then thought of an APmode Wifi system, but the max stations is 10.

So, I am going to use wireless serial links or something instead.

If you use broadcast mode on the master board then I don't see why there should be any limit to the number of slaves as long as they are in wireless range

To be more precise in terminology:

ESP-Now supports broadcast, multicast, and unicast. Each sender has a peer list for up to, as you found, maybe twenty MAC addresses. Each recipient has to be added to the list to send there: a unicast. You can also send to everyone on the list: a multicast

To broadcast, the special all-0xFF address is used. You add that as a peer, and then send to it. Then everyone in range may receive it. There are various factors that determine whether a receiver gets any particular message. So you would probably broadcast periodically for a while.

The receiver always gets the sender's MAC in the callback. So now the receiver knows there is someone out there with that MAC, which "completes the circle", and in theory they can talk to each other.

And while it is unlikely to get a unicast message incorrectly sent to you, a receiver is likely to receive broadcasts from random senders nearby. That means you need some way of verifying the payload, and not to blindly act upon it. At a minimum by checking the length and format; and most securely by using cryptographic message signatures.

DroneBotWorkShop (uses Initiator/Responder rather than master/slave): ESP NOW - Peer to Peer ESP32 Communications

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.