Mit einem Nrf24 unterschiedliche Struct-Daten an mehrere Empfänger versenden

agmue:
Darum RS485!

Nu ist das mit dem 24L01 nichts weiter als ein Kabel ohne Draht.
Er macht Point2Multipoint ohne ACK.
Die Daten werden fortlaufend (aus den Array's) :wink: gesendet und am Empfänger aufbereitet.
Prinzipiell könnte sogar der Stream genommen werden und nach jedem Ende des Feldes ( ; ) genau dieser Buffer auf die Antenne gelegt werden.
Nach dem Blockbild ist das wirklich das allerkleinste Übel.

Allerdings geht das hier zu weit für den, der andren Teil nicht mitbekommen hat.

my_xy_projekt:
Prinzipiell könnte sogar der Stream genommen werden und nach jedem Ende des Feldes ( ; ) genau dieser Buffer auf die Antenne gelegt werden.

Dieser Ansatz könnte erfolgversprechend sein :slight_smile:

Leider kenne ich NRF24 nicht, daher halte ich mich zurück.

my_xy_projekt:
Start:
https://forum.arduino.cc/index.php?topic=694542.0
los geht es dieses Jahr:
https://forum.arduino.cc/index.php?topic=694542.msg4922373#msg4922373

Erklärung der Inhalte:
https://forum.arduino.cc/index.php?topic=694542.msg4924472#msg4924472

elektrischer Aufbau Blockschema:
https://forum.arduino.cc/index.php?action=dlattach;topic=694542.0;attach=410846

Ah, ja....
Das ist also die Vorgeschichte....

Dann werde ich mich auch mal raushalten.

  1. Viele Köche verd.....
  2. Immer noch liegen viele Teile im Nebel, trotz aufmerksamen lesen

combie:
Dann werde ich mich auch mal raushalten.

Du kannst Dich entspannt zurücklehnen, denn my_xy_projekt hat die Übersicht und er hat einen Plan! könnte ein Zitat aus “Dr. Who” sein :slight_smile:

Ich werde ihn bei “divide et impera” unterstützen, soweit es mir möglich ist. Strukturen kommen da eher nicht vor, zumindest sehe ich derzeit keine.

Selbstverständlich werde ich keine Sekunde zögern, bei Bedarf Deinen psychologischen Rat einzuholen 8)

“Was bin ich wieder für ein Schelm!” Heinz Erhardt

agmue:
hat die Übersicht und er hat einen Plan!

Ersteres sollte der TO haben und letzteres ist wohl eher Wunschdenken :wink:

Der jenige der immer einen totsicheren Plan hatte: Egon Olsen.

@my_xy_projekt: Wenn man keinen Plan hat, sollte man jemanden kennen, der einen hat: Mich!

Anfänger finden lustige Lösungen, aufgrund von lustigen Ideen.

Ich hatte geschrieben: "Aus meinem 'Erfahrungsschatz' könnte ich nur noch ESP32 beisteuern, ... Das wäre doch eine lustige Idee :grin: "

Heute ist ja ein besonderes Datum, da wollte ich einen Scherz machen und habe mir mal ESP-NOW angesehen. Zu meiner Überraschung ist ein funktionierendes Programm draus geworden. Ich habe mich also selbst veräppelt.

Ausgabe beim Empfänger:

[sup][color=maroon]Bytes received: 204
x: 7
y: 16
t: BRZ:15,015;BRF:Paul Mustermann;BRS:4;AR1:0;RZ1:0,000;F1:Friedhelm Busch;AR2:0;RZ2:0,000;F2:Max Jägermeister;AR3:0;RZ3:0,000;F3:Paul Mustermann;AR4:0;RZ4:0,000;F4:Thorsten Hesse;

Bytes received: 204
x: 9
y: 18
t: BRZ:15,015;BRF:Paul Mustermann;BRS:4;AR1:0;RZ1:0,000;F1:Friedhelm Busch;AR2:0;RZ2:0,000;F2:Max Jägermeister;AR3:0;RZ3:0,000;F3:Paul Mustermann;AR4:0;RZ4:0,000;F4:Thorsten Hesse;[/color][/sup]

Die Variablen x und y sind nur Zufallszahlen, damit sich was ändert.

@Benziner: Würdest Du auf ESP32 umsteigen?

Quellenangabe:

Rui Santos
Complete project details at ESP-NOW with ESP32: Send Data to Multiple Boards (one-to-many) | Random Nerd Tutorials

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.

Ich habe mal meine "lustige Idee" weitergeführt, um zu zeigen, wie eine Datenstruktur mittels ESP-NOW übertragen werden kann. Dabei habe ich mich selbstverständlich bei den bereits gezeigten Programmen zu diesem Projekt bedient.

Datenfluß: UNO (anstelle Renn-PC) → ESP-NOW-Sender → ESP-NOW-Empfänger → MAX7219-Anzeige für Spur 1

Ausgabe ESP-NOW Sender:

[sup][color=maroon]BRZ:15,015;BRF:Paul Mustermann;BRS:3;AR1:0;RZ1:5,866;F1:Friedhelm Busch;AR2:0;RZ2:0,000;F2:Max Jägermeister;AR3:0;RZ3:15,015;F3:Paul Mustermann;AR4:0;RZ4:0,000;F4:Thorsten Hesse;
BRS: 3 BRZ: 15 - 15 BRF: Paul Mustermann
AR1: 0 RZ1: 5 - 866 F1: Friedhelm Busch
AR2: 0 RZ2: 0 - 0 F2: Max Jägermeister
AR3: 0 RZ3: 15 - 15 F3: Paul Mustermann
AR4: 0 RZ4: 0 - 0 F4: Thorsten Hesse
Sent with success

Packet to: 8c:aa:b5:8c:1c:20 send status: Delivery Success[/color][/sup]

Ausgabe ESP-NOW Empfänger:

[sup][color=maroon]Bytes received: 160

BRS: 3 BRZ: 15 - 15 BRF: Paul Mustermann
AR1: 0 RZ1: 5 - 866 F1: Friedhelm Busch
AR2: 0 RZ2: 0 - 0 F2: Max Jägermeister
AR3: 0 RZ3: 15 - 15 F3: Paul Mustermann
AR4: 0 RZ4: 0 - 0 F4: Thorsten Hesse[/color][/sup]

Programm ESP-NOW Sender:

#include <esp_now.h>
#include <WiFi.h>
/* verwendet wird Hardware Serial2
 ESP32 UART2 RX = GPIO16
 ESP32 UART2 TX = GPIO17
 */

// REPLACE WITH YOUR ESP RECEIVER'S MAC ADDRESS
uint8_t broadcastAddress1[] = {0x8C, 0xAA, 0xB5, 0x8C, 0x1C, 0x20};
//uint8_t broadcastAddress2[] = {0xFF, , , , , };
//uint8_t broadcastAddress3[] = {0xFF, , , , , };

// Variablen für die zu versendenen Daten
const byte MAXZEICHEN = 26;
const byte SPUREN = 4;
bool ausgabe = false;     // Wartet auf Vollständigkeit

struct renn_struct {
  uint16_t BRZvk;
  uint16_t BRZnk;
  char BRF[MAXZEICHEN];
  byte BRS;
  // Spuren
  uint16_t AR[SPUREN];
  uint16_t RZvk[SPUREN];
  uint16_t RZnk[SPUREN];
  char F[SPUREN][MAXZEICHEN];
} myData;

void readSerial() {
  const int breakTimeRead = 500;       // Abbruchzeit in ms
  char readChar;                       // Einzelnes Zeichen
  static byte x = 0;                   // Position im Array
  static char buf[30] = {0};           // Zwischenspeicher

  unsigned long lastmillis = millis(); // Startzeit merken...
  while (Serial2.available() > 0 && millis() - lastmillis < breakTimeRead) {
    readChar = Serial2.read();         // Einlesen
    Serial.print(readChar);
    if (readChar == ';') {             // Feldende
      teileBuf(buf);                   // Übergeben zum teilen
      x = 0;                           // Position im Array rücksetzen
    } else {
      if (!isControl(readChar)) {      // Zeichen ist kein Steuierzeichen
        buf[x] = readChar;             // Dann aufnehmen
        if (x < 29) x++;               // neue Position setzen
        buf[x] = '\0';                 // CharArray abschliessen
      }
    }
  }
}

void teileBuf(char *buf) {                    // Teilt den Puffer
  char *c;                                    // Zwischenspeicher
  c = strtok(buf, ":");                       // Übernehme bis Trennzeichen 1

  if (!strncmp(c, "BRZ", 3)) {                // Feldname
    myData.BRZvk = atoi(strtok(NULL, ","));   // Erste Zahl - Trenner ist ,
    myData.BRZnk = atoi(strtok(NULL, ","));   // zweite Zahl
  }
  else if (!strncmp(c, "BRF", 3)) {           // Feldname
    strcpy(myData.BRF, strtok(NULL, ":"));    // Fahrername - Trenner ist :
  }
  else if (!strncmp(c, "BRS", 3)) {           // Feldname
    myData.BRS = atoi(strtok(NULL, ":"));     // Zahl
  }
  else if (!strncmp(c, "AR", 2)) {
    int x = c[2] - 49;
    myData.AR[x] = atoi(strtok(NULL, ":"));
  }
  else if (!strncmp(c, "RZ", 2)) {
    int x = c[2] - 49;
    myData.RZvk[x] = atoi(strtok(NULL, ","));
    myData.RZnk[x] = atoi(strtok(NULL, ","));
  }
  else if (!strncmp(c, "F", 1)) {
    int x = c[1] - 49;
    strcpy(myData.F[x], strtok(NULL, ":"));
    if (x == SPUREN - 1) {                    // Datensatz endet mit Fahrername 4 / Array endet mit 3(!)
      ausgabe = true;                  // Freigabe für SerMon
    }
  }
  memset(buf, 0, 30);
}

void serMon() {
  if (ausgabe) { // Wenn Ausgabe frei
    Serial.println();
    Serial.print("BRS: ");  Serial.print(myData.BRS);
    Serial.print(" BRZ: "); Serial.print(myData.BRZvk); Serial.print(" - "); Serial.print(myData.BRZnk);
    Serial.print(" BRF: "); Serial.println(myData.BRF);

    for (int j = 0; j < SPUREN; j++) {
      Serial.print("AR"); Serial.print(j + 1); Serial.print(": "); Serial.print (myData.AR[j]);
      Serial.print(" RZ"); Serial.print(j + 1); Serial.print(": "); Serial.print(myData.RZvk[j]); Serial.print(" - "); Serial.print(myData.RZnk[j]);
      Serial.print(" F"); Serial.print(j + 1); Serial.print(": "); Serial.println(myData.F[j]);
    }
  }
}

void senden() {
  if (ausgabe) {  // Wenn Ausgabe frei
    ausgabe = false;
    esp_err_t result = esp_now_send(0, (uint8_t *) &myData, sizeof(renn_struct));
    Serial.println(result == ESP_OK ? "Sent with success" : "Error sending the data");
    Serial.println();
  }
}

// callback when data is sent
void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
  char macStr[18];
  Serial.print("Packet to: ");
  // Copies the sender mac address to a string
  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.print(macStr);
  Serial.print(" send status:\t");
  Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success" : "Delivery Fail");
}

void setup() {
  Serial.begin(115200);
  Serial2.begin(9600); // zum Empfang der Daten; UNO anstelle PC
  delay(1000);
  Serial.println("Start ESP-NOW sender");

  WiFi.mode(WIFI_STA);

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

  esp_now_register_send_cb(OnDataSent);

  // register peer
  esp_now_peer_info_t peerInfo;
  peerInfo.channel = 0;
  peerInfo.encrypt = false;
  // register first peer
  memcpy(peerInfo.peer_addr, broadcastAddress1, 6);
  if (esp_now_add_peer(&peerInfo) != ESP_OK) {
    Serial.println("Failed to add peer");
    return;
  }
  /*
    // register second peer
    memcpy(peerInfo.peer_addr, broadcastAddress2, 6);
    if (esp_now_add_peer(&peerInfo) != ESP_OK){
    Serial.println("Failed to add peer");
    return;
    }
    /// register third peer
    memcpy(peerInfo.peer_addr, broadcastAddress3, 6);
    if (esp_now_add_peer(&peerInfo) != ESP_OK){
    Serial.println("Failed to add peer");
    return;
    }
  */
}

void loop() {
  readSerial();
  serMon();
  senden();
}

Programm ESP-NOW Empfänger:

#include <esp_now.h>
#include <WiFi.h>
#include <Adafruit_GFX.h>
#include <SPI.h>
#include <Max72xxPanel.h>
/*
  MAX7219 - ESP32
  GND - GND
  VDD - 3,3V
  CLK - 18 (VSPI CLK)
  DIN - 23 (VSPI MOSI)
  CS -   5 (VSPI CS0)
*/
const byte pinCS = 5; // Attach CS=5, DIN=23, CLK=18
const byte numberOfHorizontalDisplays = 4;
const byte numberOfVerticalDisplays = 1;
Max72xxPanel matrix = Max72xxPanel(pinCS, numberOfHorizontalDisplays, numberOfVerticalDisplays);

//Must match the sender structure
const byte MAXZEICHEN = 26;
const byte SPUREN = 4;

struct renn_struct {
  uint16_t BRZvk;
  uint16_t BRZnk;
  char BRF[MAXZEICHEN];
  byte BRS;
  // Spuren
  uint16_t AR[SPUREN];
  uint16_t RZvk[SPUREN];
  uint16_t RZnk[SPUREN];
  char F[SPUREN][MAXZEICHEN];
} myData;

void serMon() {
  Serial.println();
  Serial.print("BRS: ");  Serial.print(myData.BRS);
  Serial.print(" BRZ: "); Serial.print(myData.BRZvk); Serial.print(" - "); Serial.print(myData.BRZnk);
  Serial.print(" BRF: "); Serial.println(myData.BRF);

  for (int j = 0; j < SPUREN; j++) {
    Serial.print("AR"); Serial.print(j + 1); Serial.print(": "); Serial.print (myData.AR[j]);
    Serial.print(" RZ"); Serial.print(j + 1); Serial.print(": "); Serial.print(myData.RZvk[j]); Serial.print(" - "); Serial.print(myData.RZnk[j]);
    Serial.print(" F"); Serial.print(j + 1); Serial.print(": "); Serial.println(myData.F[j]);
  }
  Serial.println();
}

//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);
  ausgabeRZ(myData.RZvk[0], myData.RZnk[0]);
  serMon();
}

void ausgabeRZ(const int vk, const int nk)
{
  matrix.fillScreen(LOW);
  if (vk < 10) {
    matrix.setCursor(6, 0);
  } else {
    matrix.setCursor(0, 0);
  }
  matrix.print(vk);
  matrix.drawPixel(12, 6, HIGH);
  matrix.drawPixel(12, 7, HIGH);
  matrix.setCursor(14, 0);
  if (nk < 100) {
    matrix.print("0");
  }
  if (nk < 10) {
    matrix.print("0");
  }
  matrix.print(nk);
  matrix.write();
}

void setup() {
  matrix.setIntensity(2); // Use a value between 0 and 15 for brightness
  matrix.setRotation(0, 1);    // The first display is position upside down
  matrix.setRotation(1, 1);    // The first display is position upside down
  matrix.setRotation(2, 1);    // The first display is position upside down
  matrix.setRotation(3, 1);    // The first display is position upside down
  matrix.setTextSize(0);
  matrix.setCursor(1, 0);
  matrix.print("-----");
  matrix.write();
  delay(500);
  //Initialize Serial Monitor
  Serial.begin(115200);
  Serial.println("Start ESP-NOW receiver");
  Serial.print("ESP Board MAC Address:  ");
  Serial.println(WiFi.macAddress());
  //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() {}

Während meiner Ausbildung habe ich gerne DDR-Bücher gelesen, die eine Einführung enthielten, warum dieses Buch für den Sozialismus der DDR von Nutzen sei. In Erinnerung daran möchte ich das auch mal auf dieses Thema bezogen tun.

Da die NRF24 des Themenstellers wohl wieder aus dem Keller hervorgeholt werden, ich aber keine NRF24 habe, versuche ich die Situation mit der Beschränkung auf wenige Bytes (NRF24 maximal 32) mittels ESP-NOW nachzustellen. Ob es sich um ein sinnvolles Unterfangen handelt, weiß man erst, wenn man ESP-NOW auf NRF24 umgestellt bekommen hat.

Der Aufbau entspricht #25 und #26, nur die Software von ESP-NOW-Sender und -Empfänger ändert sich.

Übertragene Zeichen:

BRZ:15,015;BRF:Paul Mustermann;BRS:4;AR1:0;RZ1:0,000;F1:Friedhelm Busch;AR2:0;RZ2:0,000;F2:Max Jägermeister;AR3:0;RZ3:0,000;F3:Paul Mustermann;AR4:0;RZ4:0,000;F4:Thorsten Hesse;

Grundsätzlich könnte man Teilzeichenketten von Semikolon zu Semikolon bilden und diese übertragen. Da es aber durchaus sinnvoll erscheint, die Zeichenkette vor dem Doppelpunkt in ein Byte zu komprimieren, und dieses Thema ja das Wort “Struktur” enthält, wandle ich im ESP-NOW-Sender eine Teilzeichenkette in eine Struktur aus einem Byte und einer Zeichenkette um. Die Struktur wird zum ESP-NOW-Empfänger übertragen und dort interpretiert. RZ1 (=0x21) wird auf dem Display angezeigt.

Zur Veranschaulichung zeigt der serielle Monitor viele Informationen an.

ESP-NOW-Sender:

#include <esp_now.h>
#include <WiFi.h>
/* verwendet wird Hardware Serial2
  ESP32 UART2 RX = GPIO16
  ESP32 UART2 TX = GPIO17
*/

// REPLACE WITH YOUR ESP RECEIVER'S MAC ADDRESS
uint8_t broadcastAddress1[] = {0x8C, 0xAA, 0xB5, 0x8C, 0x1C, 0x20};
//uint8_t broadcastAddress2[] = {0xFF, , , , , };
//uint8_t broadcastAddress3[] = {0xFF, , , , , };

// Variablen für die zu versendenen Daten
const byte MAXZEICHEN = 26;
const byte SPUREN = 4;
bool ausgabe = false;     // Wartet auf Vollständigkeit

struct renn_struct {
  uint8_t bed;             // Bedeutung des nachfolgenden Textes
  char txt[MAXZEICHEN];    // Text
} myData;

void readSerial() {
  char readChar;                       // Einzelnes Zeichen
  static byte pos = 0;                 // Position im Array
  static char buf[MAXZEICHEN] = {0};   // Zwischenspeicher

  while (Serial2.available() > 0) {
    readChar = Serial2.read();         // Einlesen
    //Serial.print(readChar);
    if (readChar == ';') {             // Feldende
      //Serial.println();
      teileBuf(buf);                   // Übergeben zum teilen
      pos = 0;                         // Position im Array rücksetzen
    } else {
      if (!isControl(readChar)) {      // Zeichen ist kein Steuierzeichen
        buf[pos] = readChar;           // Dann aufnehmen
        if (pos < MAXZEICHEN - 1) pos++;           // neue Position setzen (geändert 18.4.21)
        buf[pos] = '\0';               // CharArray abschliessen
      }
    }
  }
}

void teileBuf(char *buf) {                    // Teilt den Puffer
  Serial.print("buf: ");  Serial.println(buf);
  char *c;                                    // Zeiger innerhalb des Puffers
  c = strtok(buf, ":");                       // Übernehme bis Trennzeichen 1
  myData.bed = 0;
  
  if (!strncmp(c, "BRZ", 3)) {                // Feldname
    myData.bed = 0x10;  // BRZ
    strncpy(myData.txt, strtok(NULL, ":"), MAXZEICHEN);
  }
  else if (!strncmp(c, "BRF", 3)) {           // Feldname
    myData.bed = 0x20;  // BRF
    strncpy(myData.txt, strtok(NULL, ":"), MAXZEICHEN);
  }
  else if (!strncmp(c, "BRS", 3)) {           // Feldname
    myData.bed = 0x30;  // BRS
    strncpy(myData.txt, strtok(NULL, ":"), MAXZEICHEN);
  }
  else if (!strncmp(c, "AR", 2)) {            // Feldname
    myData.bed = 0x10 + (c[2] - '0');          // ARn
    strncpy(myData.txt, strtok(NULL, ":"), MAXZEICHEN);
  }
  else if (!strncmp(c, "RZ", 2)) {
    myData.bed = 0x20 + (c[2] - '0');          // RZn
    strncpy(myData.txt, strtok(NULL, ":"), MAXZEICHEN);
  }
  else if (!strncmp(c, "F", 1)) {
    myData.bed = 0x30 + (c[1] - '0');          // Fn
    strncpy(myData.txt, strtok(NULL, ":"), MAXZEICHEN);
  }
  serMon(c);
  senden();
  memset(buf, 0, MAXZEICHEN);
}

void serMon(char * c) {
    Serial.print("  c: ");  Serial.println(c);
    Serial.print("myData.bed: 0x");  Serial.println(myData.bed, HEX);
    Serial.print("myData.txt: ");  Serial.println(myData.txt);
}

void senden() {
    esp_err_t result = esp_now_send(0, (uint8_t *) &myData, sizeof(renn_struct));
    Serial.println(result == ESP_OK ? "Sent with success" : "Error sending the data");
}

// callback when data is sent
void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
  char macStr[18];
  Serial.print("Packet to: ");
  // Copies the sender mac address to a string
  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.print(macStr);
  Serial.print(" send status:\t");
  Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success" : "Delivery Fail");
}

void setup() {
  Serial.begin(115200);
  Serial2.begin(9600); // zum Empfang der Daten; UNO anstelle PC
  delay(1000);
  Serial.println("Start ESP-NOW sender");

  WiFi.mode(WIFI_STA);

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

  esp_now_register_send_cb(OnDataSent);

  // register peer
  esp_now_peer_info_t peerInfo;
  peerInfo.channel = 0;
  peerInfo.encrypt = false;
  // register first peer
  memcpy(peerInfo.peer_addr, broadcastAddress1, 6);
  if (esp_now_add_peer(&peerInfo) != ESP_OK) {
    Serial.println("Failed to add peer");
    return;
  }
  /*
    // register second peer
    memcpy(peerInfo.peer_addr, broadcastAddress2, 6);
    if (esp_now_add_peer(&peerInfo) != ESP_OK){
    Serial.println("Failed to add peer");
    return;
    }
    /// register third peer
    memcpy(peerInfo.peer_addr, broadcastAddress3, 6);
    if (esp_now_add_peer(&peerInfo) != ESP_OK){
    Serial.println("Failed to add peer");
    return;
    }
  */
}

void loop() {
  readSerial();
}

EDIT Zeile 40: MAXZEICHEN - 1

ESP-NOW-Empfänger:

#include <esp_now.h>
#include <WiFi.h>
#include <Adafruit_GFX.h>
#include <SPI.h>
#include <Max72xxPanel.h>
/*
  MAX7219 - ESP32
  GND - GND
  VDD - 3,3V
  CLK - 18 (VSPI CLK)
  DIN - 23 (VSPI MOSI)
  CS -   5 (VSPI CS0)
*/
const byte pinCS = 5; // Attach CS=5, DIN=23, CLK=18
const byte numberOfHorizontalDisplays = 4;
const byte numberOfVerticalDisplays = 1;
Max72xxPanel matrix = Max72xxPanel(pinCS, numberOfHorizontalDisplays, numberOfVerticalDisplays);

//Must match the sender structure
const byte MAXZEICHEN = 26;
const byte SPUREN = 4;

struct renn_struct {
  uint8_t bed;             // Bedeutung des nachfolgenden Textes
  char txt[MAXZEICHEN];    // Text
} myData;

void serMon() {
  Serial.print("bed: 0x");  Serial.print(myData.bed, HEX);
  Serial.print("\ttxt: "); Serial.print(myData.txt);
  Serial.println();
}

//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);
  serMon();
  if (myData.bed == 0x21) ausgabeRZ();
}

void ausgabeRZ() {
  char * buf = myData.txt;
  int vk, nk;
  vk = atoi(strtok(buf, ","));   // Erste Zahl - Trenner ist ,
  nk = atoi(strtok(NULL, ","));   // zweite Zahl
  Serial.print("vk: "); Serial.print(vk); Serial.print("\tnk: "); Serial.println(nk);
  

  matrix.fillScreen(LOW);
  if (vk < 10) {
    matrix.setCursor(6, 0);
  } else {
    matrix.setCursor(0, 0);
  }
  matrix.print(vk);
  matrix.drawPixel(12, 6, HIGH);
  matrix.drawPixel(12, 7, HIGH);
  matrix.setCursor(14, 0);
  if (nk < 100) {
    matrix.print("0");
  }
  if (nk < 10) {
    matrix.print("0");
  }
  matrix.print(nk);
  matrix.write();
  
}

void setup() {
  matrix.setIntensity(2); // Use a value between 0 and 15 for brightness
  matrix.setRotation(0, 1);    // The first display is position upside down
  matrix.setRotation(1, 1);    // The first display is position upside down
  matrix.setRotation(2, 1);    // The first display is position upside down
  matrix.setRotation(3, 1);    // The first display is position upside down
  matrix.setTextSize(0);
  matrix.setCursor(1, 0);
  matrix.print("-----");
  matrix.write();
  delay(500);
  //Initialize Serial Monitor
  Serial.begin(115200);
  Serial.println("Start ESP-NOW receiver");
  Serial.print("ESP Board MAC Address:  ");
  Serial.println(WiFi.macAddress());
  //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() {}

Der ESP-NOW-Empfänger soll je Spur eine Matrixanzeige für die Rundenzeit haben. Bislang habe ich nur die Rundenzeit für Spur 1 angezeigt, das möchte ich nun erweitern. Die Anzeigen sind identisch und werden am SPI-Bus angeschlossen. Lediglich die CS-Pins sind für die Anzeigen unterschiedlich. Die Methode init() der Klasse RennAnzeige initialisiert die Instanz und die Methode ausgabeRZ() formatiert die Anzeige. Durch die Verwendung einer Klasse erspart man sich Felder, das erscheint mir übersichtlicher.

Getestet mit ESP32 und Programm für ESP-NOW-Sender unverändert (siehe #28):

// https://forum.arduino.cc/index.php?topic=734530.msg4949403#msg4949403
// Mit einem ESP32 und ESP-NOW Struct-Daten an mehrere Empfänger versenden
#include <esp_now.h>
#include <WiFi.h>
#include <Adafruit_GFX.h>
#include <SPI.h>
#include <Max72xxPanel.h>
/*
  MAX7219 - ESP32
  GND - GND
  VDD - 3,3V
  CLK - 18 (VSPI CLK)
  DIN - 23 (VSPI MOSI)
  CS -   5 (VSPI CS0)
*/
//Must match the sender structure
const byte MAXZEICHEN = 26;
const byte SPUREN = 4;

struct renn_struct {
  uint8_t bed;             // Bedeutung des nachfolgenden Textes
  char txt[MAXZEICHEN];    // Text
} myData;

class RennAnzeige {
    const byte numberOfHorizontalDisplays = 4;
    const byte numberOfVerticalDisplays = 1;
    const byte pinCS;
    Max72xxPanel matrix;
  public:
    RennAnzeige(const byte pinCS): pinCS(pinCS), matrix(Max72xxPanel(pinCS, numberOfHorizontalDisplays, numberOfVerticalDisplays)) {}

    void init() {
      matrix.setIntensity(2); // Use a value between 0 and 15 for brightness
      matrix.setRotation(0, 1);    // The first display is position upside down
      matrix.setRotation(1, 1);    // The first display is position upside down
      matrix.setRotation(2, 1);    // The first display is position upside down
      matrix.setRotation(3, 1);    // The first display is position upside down
      matrix.setTextSize(0);
      matrix.setCursor(1, 0);
      matrix.print("-----");
      matrix.write();
    }

    void ausgabeRZ() {
      char * buf = myData.txt;
      int vk, nk;
      vk = atoi(strtok(buf, ","));   // Erste Zahl - Trenner ist ,
      nk = atoi(strtok(NULL, ","));   // zweite Zahl
      Serial.print("vk: "); Serial.print(vk); Serial.print("\tnk: "); Serial.println(nk);

      matrix.fillScreen(LOW);
      if (vk < 10) {
        matrix.setCursor(6, 0);
      } else {
        matrix.setCursor(0, 0);
      }
      matrix.print(vk);
      matrix.drawPixel(12, 6, HIGH);
      matrix.drawPixel(12, 7, HIGH);
      matrix.setCursor(14, 0);
      if (nk < 100) {
        matrix.print("0");
      }
      if (nk < 10) {
        matrix.print("0");
      }
      matrix.print(nk);
      matrix.write();
    }
};

RennAnzeige rennAnzeige[] { // pinCS für Anzeige
  {5}, {17}, {16}, {4}
};

void serMon() {
  Serial.print("bed: 0x");  Serial.print(myData.bed, HEX);
  Serial.print("\ttxt: "); Serial.print(myData.txt);
  Serial.println();
}

//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);
  serMon();
  if (myData.bed == 0x21) rennAnzeige[0].ausgabeRZ();
  if (myData.bed == 0x22) rennAnzeige[1].ausgabeRZ();
  if (myData.bed == 0x23) rennAnzeige[2].ausgabeRZ();
  if (myData.bed == 0x24) rennAnzeige[3].ausgabeRZ();
}

void setup() {
  for (auto &r : rennAnzeige) r.init();
  delay(500);
  //Initialize Serial Monitor
  Serial.begin(115200);
  Serial.println("Start ESP-NOW receiver");
  Serial.print("ESP Board MAC Address:  ");
  Serial.println(WiFi.macAddress());
  //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() {}

Dieses Programm kann wegen der kurzen Datenstruktur (<32) für NRF24 umgeschrieben werden.

agmue:

Dieses Programm kann wegen der kurzen Datenstruktur (<32) für NRF24 umgeschrieben werden.

Nun ja, mit viel Zeit und Geduld schaffe ich? mit Eurer Hilfe es bestimmt mal.

Aber nochmal Grundsätzlich, kann ich den Mega aufrüsten für das senden an die ESP32. Würde den Mega als Converter schon gern behalten wollen. Als Plan B falls es mit dem Funk doch nicht klappen sollte. Denke da an die Serielle Schnittstellen.

Benziner:
Aber nochmal Grundsätzlich, kann ich den Mega aufrüsten für das senden an die ESP32.

Ja.

my_xy_projekt:
Ja.

Kannst Du mir bitte auch verraten was ich da holen sollte?
Danke
So, ich melde mich mal für nee Woche ab....ist in den letzten Tagen zuviel auf der Strecke geblieben... :confused:
Passt schön auf Euch auf, und bleibt Gesund.

Hallo und guten Abend.
Da die ESP32´s die Woche gekommen sind … konnte ich die Finger nicht stillhalten und habe mal getestet. Die neugierig war einfach zu groß, da mussten die anderen Dinge halt warten.

@agmue
Der sketch läuft soweit, alle Daten kommen an, das wäre für mein Projekt genau das richtige(sollen Irgendwann auch mal Nextion´s dazukommen) jetzt kommt das aber… Bei schneller datenfolge mag der empfänger nicht mehr mitspielen. Das heiß er bootet zwischen durch neu. Hier mal die Meldung:

21:40:20.298 → Guru Meditation Error: Core 0 panic’ed (LoadProhibited). Exception was unhandled.
21:40:20.298 → Core 0 register dump:
21:40:20.298 → PC : 0x40056722 PS : 0x00060230 A0 : 0x8005682e A1 : 0x3ffb5440
21:40:20.298 → A2 : 0x3ffb582c A3 : 0x00000000 A4 : 0x00000000 A5 : 0x0000000a
21:40:20.298 → A6 : 0x00000000 A7 : 0x00000008 A8 : 0x8000be99 A9 : 0x3ffb5430
21:40:20.338 → A10 : 0x3ffb582c A11 : 0x00060223 A12 : 0x00060220 A13 : 0x0ccccccc
21:40:20.338 → A14 : 0x00000000 A15 : 0x00000004 SAR : 0x00000018 EXCCAUSE: 0x0000001c
21:40:20.338 → EXCVADDR: 0x00000000 LBEG : 0x400014fd LEND : 0x4000150d LCOUNT : 0xffffffff
21:40:20.338 →
21:40:20.338 → ELF file SHA256: 0000000000000000
21:40:20.338 →
21:40:20.338 → Backtrace: 0x40056722:0x3ffb5440 0x4005682b:0x3ffb5470 0x400566cd:0x3ffb5490 0x400d059c:0x3ffb54b0 0x400d06ce:0x3ffb54d0 0x40130369:0x3ffb54f0 0x400ec9e9:0x3ffb5510 0x400ec8d8:0x3ffb5540 0x400e85be:0x3ffb5560 0x400e875d:0x3ffb56a0 0x400ffc09:0x3ffb56c0 0x40101780:0x3ffb5700 0x400897fa:0x3ffb5730
21:40:20.378 →
21:40:20.378 → Rebooting…
21:40:20.378 → ets Jun 8 2016 00:22:57
21:40:20.378 →
21:40:20.378 → rst:0xc (SW_CPU_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
21:40:20.378 → configsip: 0, SPIWP:0xee
21:40:20.378 → clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
21:40:20.378 → mode:DIO, clock div:1
21:40:20.378 → load:0x3fff0018,len:4
21:40:20.418 → load:0x3fff001c,len:1216
21:40:20.418 → ho 0 tail 12 room 4
21:40:20.418 → load:0x40078000,len:10944
21:40:20.418 → load:0x40080400,len:6388
21:40:20.418 → entry 0x400806b4
21:40:21.138 → Start ESP-NOW receiver
21:40:21.138 → ESP Board MAC Address: 3C:61:05:30:21:28
21:40:21.258 → Bytes received: 27

Das sind für mich böhmische Dörfer, kannst Du etwas damit anfangen?
@my_xy_projekt
Habe bitte nachsicht mit mir das ich die Hausaufgabe noch nicht gemacht habe :wink:

Dein Code. Deine Bahn. Deine Entscheidung.

Im Übrigen sind gestern die nRF hier auf dem Tisch gelandet. Von 20 waren 2 kaputt. 11 sind schon verplant - da müssen zum Teil die Pins ausgelötet werden.

Testaufbau mit 1 Sender / 1 Empfänger fürs WE angepeilt.
Dann baue ich meinen RF-Code um und dann schaun wa mal…

Ich würde ehr sagen…Mein Wunsch nach Input ,Unser Code der gemeinsam gewachsen ist , Leider ist es nicht meine Bahn aber von einem sehr guter Freund. Aber nur aufgeschoben, nicht aufgehoben. Ich werde dir dazu noch nee antwort geben.

Ja das mit den defekten NFR24 kenne ich auch, auch die Adapter sind oft nicht i.O. das war auch der Grund warum ich die ESP ausprobiert habe. Obwohl wenn der Nrf24 einmal läuft…tut er seinen Dienst recht gut. Bin mal mit Akku und Nano und Matrix raus auf die Straße gegangen, gute 300 Meter mit einer dicken Mauer dazwischen. Auch der schnelle Datenstrom war kein Problem. Das mit dem SPI auf mehrer Nano´s lasse ich besser, da mehme ich lieber ein Empfänger mehr, sei es nun ein Nano oder ein ESP32. Da höre ich lieber auf Euch, den Ihr seit die Profis und wisst am besten was läuft.

Nein, eigentlich nicht, denn die Beschränkung auf wenige Bytes (<32) ist für den ESP32 unsinnig. Ab #29 habe ich ESP32 anstelle NRF24 wie eine Simulation verwendet. Wenn Du ESP32 einsetzen möchtest, dann solltest Du mit #27 und #28 arbeiten, wo ein ganzes Datenpaket auf einen Rutsch übertragen wird. Da kann man auch die Anzeige von #31 anhängen.

EDIT: Da habe ich mich geirrt, #27 und #28 arbeiten auch schon mit <32 Bytes.

Das hatte ich auch schon mal. Wie hast Du die Anzeigen mit Strom versorgt? Schließe die mal an 5V an.

Sonst läuft ein Feld über oder ein Buffer. Ich habe jede Sekunde ein Datenpaket gesendet, was macht Dein Renncomputer?

Genau die beiden sind im Einsatz.

Waren zuerst an 3,3V habe nun mit 5V getestet. Gleiches Ergebnis