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

Hallo und guten Abend Arduino-Gemeinde, ich bin als blutjunger Anfänger mal wieder komplett überfordert.
In meinem Projekt gehts darum, Serial-Daten von einem Computer einzulesen aufzuteilen (bis dahin funktioniert es Dank agmue und xy-projekt.) Nun möchte ich die Daten gern noch über NRF24 an diverse mehrere Anzeigen versenden.

Alles was ich bis jetzt hinbekommen habe ist das ich einen Struct sauber versenden und empfangen kann, aber eben nur einen. Sobald ich einen zweiten hinterher sende kommt nur Datenmüll heraus. Frage ist es den überhaupt möglich mehrere unterschiedliche Datensätze zu versenden.

Bedanke mich vorab, für Eure Hilfe.

[code]

#include <Wire.h>
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>

// Variablen für die zu versendenen Daten

struct Daten {
  unsigned int BRZv;
  unsigned int BRZn;
  char BRF[20];
  int BRS;
} Info;

struct Daten1 {
  int Ar1;
  unsigned int RZ1v;
  unsigned int RZ1n;
  char F1[20];
} Spur1;

struct Daten2 {
  int Ar2;
  unsigned int RZ2v;
  unsigned int RZ2n;
  char F2[20];
} Spur2;

struct Daten3 {
  int Ar3;
  unsigned int RZ3v;
  unsigned int RZ3n;
  char F3[20];
} Spur3;

struct Daten4 {
  int Ar4;
  unsigned int RZ4v;
  unsigned int RZ4n;
  char F4[20];
} Spur4;

// Reserve falls Bahn ausgebaut wird
struct Daten5 {
  int Ar5;
  unsigned int RZ5v;
  unsigned int RZ5n;
  char F5[20];
} Spur5;
// Reserve falls Bahn ausgebaut wird
struct Daten6 {
  int Ar6;
  unsigned int RZ6v;
  unsigned int RZ6n;
  char F6[20];
} Spur6;

const byte address[6] = "00001"; // Sender-Adresse

RF24 radio(9, 10);                        // CE, CSN - die Zahlen geben die Digitalports am Arduino an,  Instatz um das Modul zu starten

const byte numChars = 40;
char buf[numChars];

const byte brf_1 = 20;
char brf[brf_1];
const byte f1_l = 20;
char f1[f1_l];
const byte f2_2 = 20;
char f2[f2_2];
const byte f3_3 = 20;
char f3[f3_3];
const byte f4_4 = 20;
char f4[f4_4];
const byte f5_5 = 20; // Reserve falls Bahn erweitert wird
char f5[f5_5];
const byte f6_6 = 20; // Reserve falls Bahn erweitert wird
char f6[f6_6];


void setup() {
  Serial.begin(9600);
  radio.begin();                      // Start der 2,4 GHz Wireless Kommunikation
  radio.openWritingPipe(address);     // Setzen der Sendeadresse
  radio.setDataRate(RF24_1MBPS);      // Setzen der Übertragungsgeschwindigkeit
  radio.setPALevel(RF24_PA_HIGH);     // Leistung des NRF(MAX,HIGH,LOW,MIN)
  radio.stopListening();              // Das angeschlossene Modul als Sender konfiguriert
}

void loop() {

  // BRZ:6,777 ; BRF:TEXT ; BRS:4 ; AR1:0 ; RZ1:0,000 ; F1:TEXT ; AR2:0 ; RZ2:0,000 ; F2:TEXT ; AR3:0 ; RZ3:0,000 ; F3:TEXT ; AR4:0 ; RZ4:0,000 ; F4:TEXT;

  static uint16_t ndx = 0;
  char rc;
  while (Serial.available() > 0) {
    rc = Serial.read();
    //Serial.print(rc);
    if (rc == ';') {
      buf[ndx] = '\0';
      ndx = 0;

      char * bez = strtok(buf, ":");
      char * inh = strtok(NULL, ":");
      char buf2[8];

      if (!strncmp(bez, "BRZ", numChars)) {         // Beste Rundenzeit von Heute
        sscanf(inh, "%i,%s", &Info.BRZv, &buf2);
        Info.BRZn = atoi(buf2);
        //rz = vorkomma + (atoi(buf2) / 1000.0);
      }

      if (!strncmp(bez, "BRF", numChars)) {         // Bester Fahrer von Heute
        //strncpy ( f1, inh, f1_l );
        strncpy (Info.BRF, inh, brf_1 );
      }

      if (!strncmp(bez, "BRS", numChars)) {         // Beste Runde auf Spur X
        Info.BRS = atoi(inh);
        //radio.write(&Info, sizeof(Info));
        //DatenSenden;
      }

      if (!strncmp(bez, "AR1", numChars)) {         // Runden von Spur 1
        Spur1.Ar1 = atoi(inh);
      }

      if (!strncmp(bez, "RZ1", numChars)) {         // Rundenzeit Vorkomma / Nachkomma von Spur 1
        sscanf(inh, "%i,%s", &Spur1.RZ1v, &buf2);
        Spur1.RZ1n = atoi(buf2);
        //rz = vorkomma + (atoi(buf2) / 1000.0);
      }

      if (!strncmp(bez, "F1", numChars)) {          // Fahrername von Spur 1
        strncpy (Spur1.F1, inh, f1_l );
                radio.write(&Spur1, sizeof(Spur1));

        if (!strncmp(bez, "AR2", numChars)) {       // Runden von Spur 2
          Spur2.Ar2 = atoi(inh);
        }

        if (!strncmp(bez, "RZ2", numChars)) {       // Rundenzeit Vorkomma / Nachkomma von Spur 2
          sscanf(inh, "%i,%s", &Spur2.RZ2v, &buf2);
          Spur2.RZ2n = atoi(buf2);
          //rz = vorkomma + (atoi(buf2) / 1000.0);
        }

        if (!strncmp(bez, "F2", numChars)) {       // Fahrername von Spur 2
          strncpy (Spur2.F2, inh, f2_2 );
          //        radio.write(&Spur2, sizeof(Spur2));
        }


        if (!strncmp(bez, "AR3", numChars)) {       // Runden von Spur 3
          Spur3.Ar3 = atoi(inh);
        }

        if (!strncmp(bez, "RZ3", numChars)) {       // Rundenzeit Vorkomma / Nachkomma von Spur 3
          sscanf(inh, "%i,%s", &Spur3.RZ3v, &buf2);
          Spur3.RZ3n = atoi(buf2);
          //rz = vorkomma + (atoi(buf2) / 1000.0);
        }

        if (!strncmp(bez, "F3", numChars)) {       // Fahrername von Spur 3
          strncpy (Spur3.F3, inh, f3_3 );
          //        radio.write(&Spur3, sizeof(Spur3));
        }

        if (!strncmp(bez, "AR4", numChars)) {       // Runden von Spur 4
          Spur4.Ar4 = atoi(inh);
        }

        if (!strncmp(bez, "RZ4", numChars)) {       // Rundenzeit Vorkomma / Nachkomma von Spur 4
          sscanf(inh, "%i,%s", &Spur4.RZ4v, &buf2);
          Spur4.RZ4n = atoi(buf2);
          //rz = vorkomma + (atoi(buf2) / 1000.0);
        }

        if (!strncmp(bez, "F4", numChars)) {       // Fahrername von Spur 4
          strncpy (Spur4.F4, inh, f4_4 );
          //        radio.write(&Spur4, sizeof(Spur4));
        }

      }

    }

    else {
      buf[ndx] = rc;
      ndx = (1 + ndx) % numChars;
    }

  }


}

void DatenSenden()
{
  Serial.println("sende!");
  radio.write(&Info, sizeof(Info));                               // Senden der Bahnrekorde zum Empfänger
  //radio.write(&Spur1, sizeof(Spur1));                           // Senden der Spur1-Daten zum Empfänger
  //radio.write(&Spur2, sizeof(Spur2));                           // Senden der Spur2-Daten zum Empfänger
  //radio.write(&Spur3, sizeof(Spur3));                           // Senden der Spur3-Daten zum Empfänger
  //radio.write(&Spur4, sizeof(Spur4));                           // Senden der Spur4-Daten zum Empfänger
  //radio.write(&Spur5, sizeof(Spur5));                           // Senden der Spur6-Daten zum Empfänger Reserve falls Bahn erweitert wird
  //radio.write(&Spur6, sizeof(Spur6));                           // Senden der Spur6-Daten zum Empfänger Reserve falls Bahn erweitert wird
}

[/code]

Das ist übrigens nicht der wirklich wie Strukturen normal verwendet werden. Es ist schlechtes Design wenn du mehrere Strukturen hast die sich nur in den Namen der enthaltenen Variablen unterscheiden. Diese Unterscheidung kannst du auch im Namen der Instanz einer Struktur machen

struct Daten
{
  int Ar;
  unsigned int RZv;
  unsigned int RZn;
  char F[20];
};

Daten spur1, spur2, spur3 ...;

Oder auch ein Array aus Strukturen. Dann hat man die Nummer im Array Index.

In dem Namen der Instanzen steckt schon eine Nummer. Wieso willst du da nochmal die Variablen in der Struktur durchnummerieren?

Ist zwar nicht der Grund weshalb da was falsch gesendet wird, aber das solltest du nochmal durchdenken.

Hallo Serenifly,
vielen Dank für Deine Rückmeldung, halbwegs habe ich es verstanden, jetzt kommt das Anfänger Aber.... folgende Daten sind zu groß für einen Struct Oder?

  unsigned int BRZv;
  unsigned int BRZn;
  char BRF[20];
  int BRS;
  int Ar;
  unsigned int RZv;
  unsigned int RNn;
  char F[20];

Eine Struktur an sich kann beliebig groß sein. Eventuelle Limitationen liegen nur an der Kommunikations-Bibliothek und/oder der Funksender-Hardware

Strukturen kann man auch verschachteln wenn du noch mehr Organisation willst. D.h. eine Struktur kann andere Strukturen enthalten

Die nRF24L01+ haben halt nur (5+1) 32Byte FiFos.
Größere Strukturen muss man also in Häppchen aufteilen.

@Serenifly
Jetzt happerts schon wieder... Struktur in einer Struktur okay,aber da wird doch der benötigte Speicherplatz nicht weniger durch. Oder verstehe ich da was falsch?Der NRF24 kann doch nur die 32 Byte.

@Combie
auch an Dich vielen Dank für die Rückmeldung. Du hast es auf den Kopf getroffen was ich versucht habe zu sagen. Kannst Du mir vielleicht verraten wie man die in Häppchen aufteilt?
Hab Dank

Benziner:
Jetzt happerts schon wieder… Struktur in einer Struktur okay,aber da wird doch der benötigte Speicherplatz nicht weniger durch.

Nein. Das war auch nur nebenbei bemerkt. Bei der Verwendung von Strukturen geht es auch in erster Line darum dass der Code übersichtlicher wird.

Ich hatte das glaube auch etwas falsch gesehen. So wie es aussieht will du Info 1 mal und dann N mal Spur. Ich dachte da irgendwie dass jede Spur auch immer Info enthält. Aber im ersten Post ist das anders

Da kann man z.B. sowas machen:

struct Info
{
  int BRS;
  unsigned int BRZv;
  unsigned int BRZn;
  char BRF[20];
};

struct Spur
{
  int Ar;
  unsigned int RZv;
  unsigned int RNn;
  char F[20];
};

Oder wie auch immer du das brauchst. Dann hat man das zusammengelegt was zusammen gehört. Und jede Struktur ist kleiner als 32 Bytes.
Aber es gibt zig Optionen wie man das machen kann. Je nachdem was man an Daten hat und wie man die organisieren möchte. Theoretisch könnte man da jetzt eine dritte Struktur anlegen die je eine Instanz von Info und Spur enthält. Aber das passt hier glaube ich doch nicht. Also vergiss das vielleicht wieder.

Vielleicht musst du zwischen dem Senden von zwei Paketen auch etwas warten bis das erste verschickt wurde. Da habe ich keine Erfahrung.

Kannst Du mir vielleicht verraten wie man die in Häppchen aufteilt?

Wenn das men so einfach wäre....

Mache dich mal über das "OSI Schichten Model" kundig.
Das ist im Prinzip seit fast 50 Jahren ein unumstößliches Regelwerk für zuverlässige Netzwerkverbindungen.
Vieles davon kann man bei solchen µC Anwendungen vereinfachen,

Die ersten Schichten liefert dir die Lib.
Die höheren muss man nachbauen.
Gerade auch weil Übertragungen doch mal fehlschlagen können...


Vielleicht ist es ja auch angesagter, das Problem, dein Problem, nochmal zu analysieren.
Evtl. gibt es ja einfachere Möglichkeiten.

Benziner:
sagen. Kannst Du mir vielleicht verraten wie man die in Häppchen aufteilt?

Bei I2C hat man ja ein ähnliches Problem, wenn die Struktut größer als der I2C-Puffer ist. Ich habe das hier mal implementiet, evtl. kannst Du Dir da Anregungen holen.

Gruß Tommy

combie:
Wenn das men so einfach wäre....

Okay, mein Motto heißt zwar "Aufgeben ist auch keine Option" aber in diesem Fall definitiv "over and out" Ich beschäftige mich gerade mal ein dreiviertel Jahr mit Arduino und seine unendlichen Weiten.... und das nur nach Feierabend.Soviel am Stück gelesen, hab ich seit 40 Jahren nicht mehr. Und wenn ich ehrlich bin, übersteigt mein Projekt gerade wohl meinen Verstand. Eigendlich schade, aber wie heißt es so schön... einem alten Pferd kannste ja auch keine neuen Kunststücke mehr beibringen. :wink:

Ich möchte mich bei allen bedanken, die versucht haben für mich hier ein Lösungsweg zu finden. Leider war es nur schwere Kost für mich. Aber vielleicht denächst bei einem leichteren Projekt...es sei den, es fällt Hirn vom Himmel dann ich mach weiter.
LOB AN EUCH ALLE

Leg es nicht ganz weg. Mit jeder Erkenntnis (evtl. beim neuen Projekt) steigt die Wahrscheinlichkeit, dass es später doch noch wird.

Gruß Tommy

aber in diesem Fall definitiv "over and out"

Wenn die Lösung so nicht will, könnte man evtl. das Problem modifizieren.

Also nicht sofort die Flinte in den Sand stecken, oder den Kopf ins Korn werfen.

@ Tommy
im Moment ist meine motivation im Keller :frowning: , und da werden die NRF24 auch zu finden sein !!!
Vielleicht bin ich in ein paar Jahren soweit, um mich denen wieder anzunehmen. :sunglasses:

@Combie
Na ja, auf dem Weg war ich auch schon, halt die Namen weglassen und nur die nackten Zahlen übertragen.
Da würde ich bei 6 Spuren für Zeiten und Runden an die 30 Byte kommen.
Aber es sind eben nicht alle Daten die zur Verfügung stehen, und damit kann ich mich leider nur schwer trösten.

Benziner:
@Combie
Na ja, auf dem Weg war ich auch schon, halt die Namen weglassen und nur die nackten Zahlen übertragen.
Da würde ich bei 6 Spuren für Zeiten und Runden an die 30 Byte kommen.
Aber es sind eben nicht alle Daten die zur Verfügung stehen, und damit kann ich mich leider nur schwer trösten.

Anfangs sagtest du:

ich bin als blutjunger Anfänger
Angenommen, ich würde das glauben....

Dann sage ich dir:
Anfänger finden lustige Lösungen, aufgrund von lustigen Ideen.

Das ist natürlich einerseits gut!
Aber andererseits verstellt es auch den Blick für bessere Lösungen.

Das war die eine Seite der Geschichte!
Jetzt die andere:

Leider habe ich nicht verstanden, was du "wirklich" erreichen willst.
Auch das "Warum" und auch das "Wozu" liegt für mich im dunklen.
Das ganze übergeordnete Konzept liegt im dichten Nebel.

Das macht es mir unmöglich über Alternativen nachzudenken und damit auch das helfen.

Die dritte Seite:
Du kennst "rubber duck debugging"?

Nein?

Dann die Alternative:
Erkläre mir dein Problem, so oft und so lange, bis du selber verstanden hast, wie es geht.
Oder bis ich es verstanden habe.

Dies ist ein spekulativer Beitrag ;D

combie:
Das ganze übergeordnete Konzept liegt im dichten Nebel.
...
Erkläre mir dein Problem, ...

Es geht um eine Rennbahn und die Anzeige der zentral ermittelten Rundenzeiten an vier bis sechs Stellen.

Problem: Der zentrale Mega2560 hat keine sechs serielle Schnittstellen.

Lösung: Radio, denn ein Sender hat viele Empfänger.

Da ich mich mit NRF24 nicht auskenne, wäre meine Lösung: Viele RX an einen TX (ohne Rückkanal). Elektrisch würde ich das mit RS485 lösen, da ich mich vor den Störungen der Autos fürchten würde und viel RX an einem TX bei RS485 Teil der Busspezifikation ist.

So sieht mein spekulativer Blick auf dieses Projekt aus.

Ich hoffe, ich konnte den Nebel etwas lüften ::slight_smile:

Aha, ja...
Eine Rennbahn....

Immerhin!

Klar:

Wer Funk kennt, nimmt lieber Kabel!

Wobei ich mich frage:
Wozu der Mega, wenn die Daten doch vom PC kommen?
Was sind das für Anzeigen?

Wieso sind die Bezeichner im Programm so kryptisch benannt?

combie:
Wozu der Mega, wenn die Daten doch vom PC kommen?

Vermutlich um die Daten auf mehrere serielle Schnittstellen (UART) zu verteilen.

combie:
Was sind das für Anzeigen?

combie:
Wieso sind die Bezeichner im Programm so kryptisch benannt?

Die stammen aus dem Datenfluß:

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;

Ich rate mal:

BRZ: beste Rundenzeit
BRF: bester Fahrer
BRS: beste Spur
RZ1: Rundenzeit Spur 1
F1: Fahrer Spur 1

Alle Angaben ohne Gewähr ::slight_smile:

combie:
Wobei ich mich frage:
Wozu der Mega, wenn die Daten doch vom PC kommen?
Was sind das für Anzeigen?

Wieso sind die Bezeichner im Programm so kryptisch benannt?

Start:

los geht es dieses Jahr:

Erklärung der Inhalte:

elektrischer Aufbau Blockschema:

agmue:
Alle Angaben ohne Gewähr ::slight_smile:

Danke agmue :slight_smile: , besser hätte ich es auch nicht erklären können!
Du steckst aber auch schon, ganz tief drin.... Danke

combie:

Wer Funk kennt, nimmt lieber Kabel!

10 bis 15 Meter Kabel sollen auf der Länge auch sehr empfänglich sein :wink:

Und das Kabel wären zusätzliche stolperfallen....
Die Bahn ist mehrfach mit Scheibenkondensatoren ausgestattet, sollte funzen. Ein Mega mit 100 WsLeds läuft störungsfrei an der Bahn.

Benziner:
10 bis 15 Meter Kabel sollen auf der Länge auch sehr empfänglich sein :wink:

Darum RS485!

Benziner:
Und das Kabel wären zusätzliche stolperfallen…

Das ist schlecht.

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

Aus meinem “Erfahrungsschatz” könnte ich nur noch ESP32 beisteuern, da werden ganze HTML-Seiten übertragen, nicht nur ca. 200 Zeichen. Das wäre doch eine lustige Idee :grin:

Leider kann ich nur Stolperfallen oder lustige Ideen beisteuern, sorry.