ESP8266 2 master's 1 slave

I'm trying to send data over 2 ESP8266's to one salve but I just get big number even though both strucuts are the same.
I've used this tutorial from here
https://randomnerdtutorials.com/esp-now-many-to-one-esp8266-nodemcu/

I've got this working as described in the tutorial, But I have incoming char data from the serial port on Board1 and Board2 and would like to send this data from each board to the salve so that I can display it on a TFT screen.
At the moment I'm just trying to get it working correctly from one master and then hopefully get it working with the 2 boards.

This is the TX code(all working on getting the serial data and displaying it in the serial monitor.

#include <ESP8266WiFi.h>
#include <espnow.h>
#include <TimedAction.h>
#include <SoftwareSerial.h>
//##########################
//# SET UP VARIABLES       #
//##########################
SoftwareSerial ESPserial(2, 4); // RX | TX
const byte numChars = 9; //Number of bits to get
// REPLACE WITH RECEIVER MAC Address
uint8_t broadcastAddress[] = {0x8C, 0xAA, 0xB5, 0x7C, 0x76, 0xE9};//8C:AA:B5:7C:76:E9
boolean newData = false;
// Set your Board ID (ESP32 Sender #1 = BOARD_ID 1, ESP32 Sender #2 = BOARD_ID 2, etc)
#define BOARD_ID 1
#define ECHO_TO_SERIAL 1 //change to zero = no serial output
// Structure example to send data
// Must match the receiver structure
typedef struct struct_message {
  int id;
  char receivedChars[numChars];   // an array to store the received data
} struct_message;

// Create a struct_message called test to store variables to be sent
struct_message myData;

unsigned long lastTime = 0;
unsigned long timerDelay = 500;
// Callback when data is sent
void OnDataSent(uint8_t *mac_addr, uint8_t sendStatus) {
  Serial.print("\r\nLast Packet Send Status: ");
  if (sendStatus == 0) {
    Serial.println("Delivery success");
  }
  else {
    Serial.println("Delivery fail");
  }
}
void printRecord(Print* pr, char sep = ',') {
  pr->print(myData.receivedChars); // Print data
  pr->println();
}
void setup() {
  ESPserial.begin(9600);
  Serial.begin(115200);

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

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

  // 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
  esp_now_add_peer(broadcastAddress, ESP_NOW_ROLE_SLAVE, 1, NULL, 0);

}

void loop() {
  recvWithEndMarker();
  if (newData ) { //new data received from eLevel
    newData = false;
    myData.id = BOARD_ID;
    //  myData.PRO3600_Disconnected = 10;
    Send_data();
  }
  if ((millis() - lastTime) > timerDelay) {
#if ECHO_TO_SERIAL // Send debug to serial port if enabled
    printRecord(&Serial);
#endif //ECHO_TO_SERIAL

    lastTime = millis();
  }

  //byte receivedChars[numChars];   // an array to store the received data

}
void Send_data() {
  // Send message via ESP-NOW
  esp_now_send(0, (uint8_t *) &myData, sizeof(myData));
}
void recvWithEndMarker() {
  static byte ndx = 0;
  char endMarker = '\n';
  char rc;
  if (ESPserial.available() > 0 && newData == false) { // Tried this
    //   while (gtSerial.available() > 0 && newData == false) { //tried this
    rc = ESPserial.read();
    if (rc != endMarker) {
      myData.receivedChars[ndx] = rc;
      ndx++;
      if (ndx >= numChars) {
        ndx = numChars - 1;
      }
    }
    else {
      myData.receivedChars[ndx] = '\0'; // terminate the string
      ndx = 0;
      newData = true;
      //  receiveUntilTimeout = true; //tried here
    }
  }
}

This is the RX side.

#include <ESP8266WiFi.h>
#include <espnow.h>
#include "SPI.h"
#include "TFT_eSPI.h"
#include "U8g2_for_TFT_eSPI.h"
//#define firstScreenCS D4
TFT_eSPI tft = TFT_eSPI();       // Invoke custom library
U8g2_for_TFT_eSPI u8f;       // U8g2 font instance
const byte numChars = 9; //Number of bits to get
unsigned long lastTime = 0;
unsigned long timerDelay = 500;
// Structure example to receive data
// Must match the sender structure
char buf[20];
#define ECHO_TO_SERIAL 1 //change to zero = no serial output
typedef struct struct_message {
  int id;
  char receivedChars[numChars];   // an array to store the received data   // an array to store the received data
} struct_message;

// Create a struct_message called myData
struct_message myData;

// Create a structure to hold the readings from each board
struct_message Platfomrm_Level;
struct_message Platform_Angle;

// Create an array with all the structures
struct_message boardsStruct[2] = {Platfomrm_Level, Platform_Angle};

// Callback function that will be executed when data is received
void OnDataRecv(uint8_t * mac_addr, uint8_t *incomingData, uint8_t len) {
  char macStr[18];
  Serial.print("Packet received from: ");
  snprintf(macStr, sizeof(macStr), "%02x:%02x:%02x:%02x:%02x:%02x",
           mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
  Serial.println(macStr);
  memcpy(&myData, incomingData, sizeof(myData));
  Serial.printf("Board ID %u: %u bytes\n", myData.id, len);
  // Update the structures with the new incoming data
  // boardsStruct[myData.id - 1].receivedChars[numChars] = myData.receivedChars[numChars]; //this just reads 1073669036 in serial monitor
  boardsStruct[myData.id - 1].receivedChars = myData.receivedChars;//  invalid array assignment boardsStruct[myData.id - 1].receivedChars = myData.receivedChars;

  Serial.printf("TILT: %d \n", boardsStruct[myData.id - 1].receivedChars);
  Serial.println();
}
void printRecord(Print* pr, char sep = ',') {
  pr->print(myData.receivedChars); // Print data
  pr->println();
}
void setup() {
  // Initialize Serial Monitor
  Serial.begin(115200);
  tft.init();
  u8f.begin(tft);
  tft.setRotation(3);
  tft.fillScreen(TFT_BLACK);
  // Set device as a Wi-Fi Station
  WiFi.mode(WIFI_STA);
  WiFi.disconnect();
  // Init ESP-NOW
  if (esp_now_init() != 0) {
    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_set_self_role(ESP_NOW_ROLE_SLAVE);
  esp_now_register_recv_cb(OnDataRecv);
}

void loop() {
  // Access the variables for each board
  // char board1X = boardsStruct[0].receivedChars; // If I unhighlight this i get error invalid conversion from 'char*' to 'char'

  if ((millis() - lastTime) > timerDelay) {
#if ECHO_TO_SERIAL // Send debug to serial port if enabled
    printRecord(&Serial);
#endif //ECHO_TO_SERIAL

    lastTime = millis();
  }
  /*
    u8f.setFontMode(0);                 // use u8g2 none transparent mode
    u8f.setFontDirection(0);            // left to right (this is default)
    // digitalWrite(firstScreenCS, LOW);
    u8f.setFontMode(0);
    u8f.setFontDirection(0);
    u8f.setFont(u8g2_font_logisoso58_tf);
    u8f.setForegroundColor(TFT_GREEN);  // apply color// start writing at this position
    u8f.setCursor(230, 100);
    u8f.println(" V "); // numerical value
    u8f.setFont(u8g2_font_inb63_mn);    // select u8g2 font from here: https://github.com/olikraus/u8g2/wiki/fntlistall
    u8f.setForegroundColor(TFT_GREEN);  // apply color// start writing at this position
    u8f.setCursor(20, 100);
    //  u8f.print(board1D);
    //u8f.print(" "); // numerical value
    u8f.setForegroundColor(TFT_YELLOW);  // apply color
    // u8f.print(" "); // numerical value
    u8f.setCursor(20, 180);
    //  u8f.print(board1.y);
    // u8f.print(" "); // numerical value
    // digitalWrite(firstScreenCS, HIGH);

  */
}

I've not yet accessed the variables for each board yet so I can display both values on the lcd.
I've placed comments in the code for different error's or whats happening.
The incoming receivedChars is coming correctly as this print's on the Serial monitor (debug enabled), I've tried to create another struct so that I can get data from both boards data coming in.

here you write that it does not work

and here you are writing that it does work

but a real question is missing.
it would be very good if you post what the serial monitor is showing. Be very precise to add information that makes it possible for others to clearly identify which output comes from which code

Your kind of printing with commands like

are unusal
why don't you use straight forward serial.print?

best regards Stefan

your call for esp_now_send() has a simple zero as the mac-adress
(the first parameter) is this really the same in the sketch of random-nerd-tutorials?

best regards Stefan

Hi ,
I will try and explain a bit more by the way it's not working the way I thought it would or should.
The way I use the Serial print command so when I change #define ECHO_TO_SERIAL 1 //change to zero = no serial output to a 0 it does not print that data saving having to highlight lots of lines if I don't want to send serial data out for debugging.
This is the data I get on the serial monitor

+  0.46 // this is the value of the myData.receivedChars (this would be OK if I only wanted to receive data from one sensor But I want 2 sensors)

Packet received from: 3c:61:05:d1:02:38 //ID device
Board ID 1: 16 bytes //received ID and number of bytes
TILT: 1073669036 // I thought the it should be +  0.46 the same has 

/*
This line of code complies
 boardsStruct[myData.id - 1].receivedChars[numChars] = myData.receivedChars[numChars]; //this just reads 1073669036 in serial monitor
But gives  1073669036 printing from this 
 Serial.printf("TILT: %d \n", boardsStruct[myData.id - 1].receivedChars);
  Serial.println();
*/
//*
If I try this way I get the error steated below.
boardsStruct[myData.id - 1].receivedChars = myData.receivedChars;
error: invalid array assignment
   boardsStruct[myData.id - 1].receivedChars = myData.receivedChars;

/*
If I try this to access the data from board 1 ID 1
 char board1X = boardsStruct[0].receivedChars;
*/

/*
Changing this part to this 
// Access the variables for each board
   char board1X = boardsStruct[0].receivedChars[numChars]; // If I unhighlight this i get error
I get this in 
+  0.46

Packet received from: 3c:61:05:d1:02:38
Board ID 1: 16 bytes
TILT: 1073669036 // I though this should be + 0.46
*/

These are the codes I first started playing with to carry out the testing and get an understanding how they work.
Sender code for board 1 and 2 (I just change the ID before uploading)

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

// REPLACE WITH RECEIVER MAC Address
uint8_t broadcastAddress[] = {0x8C, 0xAA, 0xB5, 0x7C, 0x76, 0xE9};//8C:AA:B5:7C:76:E9

// Set your Board ID (ESP32 Sender #1 = BOARD_ID 1, ESP32 Sender #2 = BOARD_ID 2, etc)
#define BOARD_ID 1

// Structure example to send data
// Must match the receiver structure
typedef struct struct_message {
    int id;
    int x;
    int y;
} struct_message;

// Create a struct_message called test to store variables to be sent
struct_message myData;

unsigned long lastTime = 0;
unsigned long timerDelay = 10000;

// Callback when data is sent
void OnDataSent(uint8_t *mac_addr, uint8_t sendStatus) {
  Serial.print("\r\nLast 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);
  WiFi.disconnect();

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

  // 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
  esp_now_add_peer(broadcastAddress, ESP_NOW_ROLE_SLAVE, 1, NULL, 0);

}
 
void loop() {
  if ((millis() - lastTime) > timerDelay) {
    // Set values to send
    myData.id = BOARD_ID;
    myData.x = random(1, 50);
    myData.y = random(1, 50);

    // Send message via ESP-NOW
    esp_now_send(0, (uint8_t *) &myData, sizeof(myData));
    lastTime = millis();
  }
}

and this is the Slave code.

#include <ESP8266WiFi.h>
#include <espnow.h>
#include "SPI.h"
#include "TFT_eSPI.h"
#include "U8g2_for_TFT_eSPI.h"
//#define firstScreenCS D4
TFT_eSPI tft = TFT_eSPI();       // Invoke custom library
U8g2_for_TFT_eSPI u8f;       // U8g2 font instance
#define ECHO_TO_SERIAL 1 //change to zero = no serial output
// Structure example to receive dataunsigned long lastTime = 0;
unsigned long lastTime = 0;
unsigned long timerDelay = 500;
int board1X ;
int board1Y;
int board2X;
int board2Y;
// Must match the sender structure
typedef struct struct_message {
  int id;
  int x;
  int y;
} struct_message;

// Create a struct_message called myData
struct_message myData;

// Create a structure to hold the readings from each board
struct_message board1;
struct_message board2;

// Create an array with all the structures
struct_message boardsStruct[2] = {board1, board2};

// Callback function that will be executed when data is received
void OnDataRecv(uint8_t * mac_addr, uint8_t *incomingData, uint8_t len) {
  char macStr[18];
  Serial.print("Packet received from: ");
  snprintf(macStr, sizeof(macStr), "%02x:%02x:%02x:%02x:%02x:%02x",
           mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
  Serial.println(macStr);
  memcpy(&myData, incomingData, sizeof(myData));
  Serial.printf("Board ID %u: %u bytes\n", myData.id, len);
  // Update the structures with the new incoming data
  boardsStruct[myData.id - 1].x = myData.x;
  boardsStruct[myData.id - 1].y = myData.y;
  Serial.printf("x value: %d \n", boardsStruct[myData.id - 1].x);
  Serial.printf("y value: %d \n", boardsStruct[myData.id - 1].y);
  Serial.println();
}
void printRecord(Print* pr, char sep = ',') {
  pr->print(board1X); // Print data
  pr->print(","); // Print data
  pr->print(board1Y); // Print data
  pr->print(","); // Print data
  pr->print(board2X); // Print data
  pr->print(","); // Print data
  pr->print(board2Y); // Print data
  pr->println();
}
void setup() {
  // Initialize Serial Monitor
  Serial.begin(115200);
  tft.init();
  u8f.begin(tft);
  tft.setRotation(3);
  tft.fillScreen(TFT_BLACK);
  // Set device as a Wi-Fi Station
  WiFi.mode(WIFI_STA);
  WiFi.disconnect();

  // Init ESP-NOW
  if (esp_now_init() != 0) {
    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_set_self_role(ESP_NOW_ROLE_SLAVE);
  esp_now_register_recv_cb(OnDataRecv);
}

void loop() {
  // Access the variables for each board
  board1X = boardsStruct[0].x;
  board1Y = boardsStruct[0].y;
  board2X = boardsStruct[1].x;
  board2Y = boardsStruct[1].y;
  u8f.setFontMode(0);                 // use u8g2 none transparent mode
  u8f.setFontDirection(0);            // left to right (this is default)
  // digitalWrite(firstScreenCS, LOW);
  u8f.setFontMode(0);
  u8f.setFontDirection(0);
  u8f.setFont(u8g2_font_inb63_mn);    // select u8g2 font from here: https://github.com/olikraus/u8g2/wiki/fntlistall
  u8f.setForegroundColor(TFT_GREEN);  // apply color// start writing at this position
  u8f.setCursor(20, 100);
  u8f.print(board1X);
  //u8f.print(" "); // numerical value
  u8f.setForegroundColor(TFT_YELLOW);  // apply color
  // u8f.print(" "); // numerical value
  u8f.setCursor(20, 180);
  u8f.print(board1Y);
  //###########ID 2 ###############
  u8f.setForegroundColor(TFT_GREEN);  // apply color// start writing at this position
  u8f.setCursor(200, 100);
  u8f.print(board2X);
  //u8f.print(" "); // numerical value
  u8f.setForegroundColor(TFT_YELLOW);  // apply color
  // u8f.print(" "); // numerical value
  u8f.setCursor(200, 180);
  u8f.print(board2Y);
  if ((millis() - lastTime) > timerDelay) {
#if ECHO_TO_SERIAL // Send debug to serial port if enabled
    printRecord(&Serial);
#endif //ECHO_TO_SERIAL

    lastTime = millis();
  }
}

This works as expected to can I get the same data on the LCD and Serial monitor

Packet received from: c4:5b:be:62:e4:e7
Board ID 2: 12 bytes
x value: 12 
y value: 34 

17,7,12,34
Packet received from: 3c:61:05:d1:02:38
Board ID 1: 12 bytes
x value: 10 
y value: 29 

10,29,12,34

What I want now instead of sending an int with random numbers I want to send a char value instead and when I've tried to change it to char at both ends I get the compile error or does not print the correct data when I try to change it to send char the ways that I've tried so far

OK lots of information in the posting above. You tried to change the struct from

typedef struct struct_message {
    int id;
    int x;
    int y;
} struct_message;

to

?
and get what compiler-error? at which line?

for the printing How about a simple boolean constant?

const boolean debugPrinting = true;

and then

void printRecord(char sep = ',') {
  if (debugPrinting) {
    Serial.print ......
  }
}

what I do not understand is:
You have two ESP8266-boards that send data with identical structure
but you define

// Create a structure to hold the readings from each board
struct_message board1;
struct_message board2;

// Create an array with all the structures
struct_message boardsStruct[2] = {board1, board2};

all in all this means you have four times space for the data

best regards Stefan

Thanks for your help,
I've changed from this

Blockquote
// Must match the receiver structure
typedef struct struct_message {
int id;
char receivedChars[numChars]; // an array to store the received data
} struct_message;

To

Blockquote// Must match the receiver structure
typedef struct struct_message {
int id;
char receivedChars[numChars]; // an array to store the received data
} struct_message;

On both the Master and slave.
When I just print myData.receivedChars in the serial monitor on the salve uint I get the exact same data been sent from sensor 1.
From that web page it say's we are creating
1.Create a structure to receive the data. This structure should be the same defined in the sender sketch.
2. Create a struct_message variable called myData that will hold the data received.

typedef struct struct_message {
  int id;
  char receivedChars[numChars];   // an array to store the received data   // an array to store the received data
} struct_message;

// Create a struct_message called myData
struct_message myData;

3.Then, create a struct_message variable for each board, so that we can assign the received data to the corresponding board. Here we’re creating structures for two sender boards.

struct_message board1;
struct_message board2;

4.Create an array that contains all the board structures.

struct_message boardsStruct[2] = {board1, board2};
  1. This way, we can assign the values received to the corresponding boards on the boardsStruct array:
boardsStruct[myData.id-1].x = myData.x;
boardsStruct[myData.id-1].y = myData.y;

For example, imagine you receive a packet from board with id 2. The value of myData.id is 2.

So, you want to update the values of the board2 structure. The board2 structure is the element with index 1 on the boardsStruct array. That’s why we subtract 1, because arrays in C have 0 indexing.
So with the struct_message coming in myData is correct according to the serial monitor.

So now I think because now that I'm sending a the char value message with holds the 9 bytes I'm losing it trying to send to the other structs so I can assign them to each board.
Because with this line it complies without no problems.

 boardsStruct[myData.id - 1].receivedChars[numChars] = myData.receivedChars[numChars];

I just get TILT: 1073669036 been printed on the serial monitor.I thought it should of been + 0.46 and I've also printed the board1X which remains blank.

And when I change the same line to.

 boardsStruct[myData.id - 1].receivedChars = myData.receivedChars;//

I get error code invalid array assignment boardsStruct[myData.id - 1].receivedChars = myData.receivedChars;

Has this code below complies and just prints 1073669036 in the serial monitor when I turn off the echo print function.

#include <ESP8266WiFi.h>
#include <espnow.h>
#include "SPI.h"
#include "TFT_eSPI.h"
#include "U8g2_for_TFT_eSPI.h"
//#define firstScreenCS D4
TFT_eSPI tft = TFT_eSPI();       // Invoke custom library
U8g2_for_TFT_eSPI u8f;       // U8g2 font instance
const byte numChars = 9; //Number of bits to get
unsigned long lastTime = 0;
unsigned long timerDelay = 500;
// Structure example to receive data
// Must match the sender structure
char board1X;
#define ECHO_TO_SERIAL 1 //change to zero = no serial output
typedef struct struct_message {
  int id;
  char receivedChars[numChars];   // an array to store the received data   // an array to store the received data
} struct_message;

// Create a struct_message called myData
struct_message myData;

// Create a structure to hold the readings from each board
struct_message Platfomrm_Level;
struct_message Platform_Angle;

// Create an array with all the structures
struct_message boardsStruct[2] = {Platfomrm_Level, Platform_Angle};

// Callback function that will be executed when data is received
void OnDataRecv(uint8_t * mac_addr, uint8_t *incomingData, uint8_t len) {
  char macStr[18];
  Serial.print("Packet received from: ");
  snprintf(macStr, sizeof(macStr), "%02x:%02x:%02x:%02x:%02x:%02x",
           mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
  Serial.println(macStr);
  memcpy(&myData, incomingData, sizeof(myData));
  Serial.printf("Board ID %u: %u bytes\n", myData.id, len);
  // Update the structures with the new incoming data
  boardsStruct[myData.id - 1].receivedChars[numChars] = myData.receivedChars[numChars]; //this just reads 1073669036 in serial monitor
  // boardsStruct[myData.id - 1].receivedChars = myData.receivedChars;//  invalid array assignment boardsStruct[myData.id - 1].receivedChars = myData.receivedChars;

  Serial.printf("TILT: %d \n", boardsStruct[myData.id - 1].receivedChars);
  Serial.println();
}
void printRecord(Print* pr, char sep = ',') {
  pr->print(myData.receivedChars); // Print data
  pr->print(",");
  pr->print(board1X); // Print data
  pr->println(); //board1X

}
void setup() {
  // Initialize Serial Monitor
  Serial.begin(115200);
  tft.init();
  u8f.begin(tft);
  tft.setRotation(3);
  tft.fillScreen(TFT_BLACK);
  // Set device as a Wi-Fi Station
  WiFi.mode(WIFI_STA);
  WiFi.disconnect();
  // Init ESP-NOW
  if (esp_now_init() != 0) {
    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_set_self_role(ESP_NOW_ROLE_SLAVE);
  esp_now_register_recv_cb(OnDataRecv);
}

void loop() {
  // Access the variables for each board
  board1X = boardsStruct[0].receivedChars[numChars]; // If I unhighlight this i get error invalid conversion from 'char*' to 'char'

  if ((millis() - lastTime) > timerDelay) {
#if ECHO_TO_SERIAL // Send debug to serial port if enabled
    printRecord(&Serial);
#endif //ECHO_TO_SERIAL

    lastTime = millis();
  }
  
}

How about trying to calculating

int Idx = myData.id-1

and then code

boardsStruct[Idx].x = myData.x;

maybe the reason why it did work for RNT is that he disabled a lot of compiler-warnings
But I'm not sure about that.

These arrays allow to use the same functions for everything. As you have only two boards
you could try a less complex structure of simply using board1 board2 directly

best regards Stefan

The 2 set's of codes in post 4 work OK with int's and get no compile errors and receicing both sets of codes, But not when I change it to a char value

I will try what you suggested

thanks
Steve

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