Seriell mehrere Daten schicken

Hallo zusammen,

da das nicht ganz zum vorherigen Thema passt, doch schnell ein eigener Thread, da ich darüber bisher auch noch nichts gefunden habe.

Folgendes:

Der Master soll an jeden Slave (oder anders herum) mehrere Datensätze schicken, nämlich die ID des Slaves (damit sie an den richtigen gehen), und dann 12 3-stellige Zahlen.
Wie kann ich die schicken, dass die richtig gegliedert ankommen? Bin mir nicht ganz sicher, ob das so funktioniert:

void senden()
{
  Serial.println(scheibe);
  Serial.println(schuetze_1_ringe);
  Serial.println(schuetze_1_x);
  Serial.println(schuetze_1_10);
  Serial.println(schuetze_2_ringe);
  Serial.println(schuetze_2_x);
  Serial.println(schuetze_2_10);
  Serial.println(schuetze_3_ringe);
  Serial.println(schuetze_3_x);
  Serial.println(schuetze_3_10);
  Serial.println(schuetze_4_ringe);
  Serial.println(schuetze_4_x);
  Serial.println(schuetze_4_10);
}
void empfangen()
{
  int an_scheibe = Serial.read();
  
  if (an_scheibe == ich_bin)
  {
    int schuetze_1_ringe = Serial.read();
    int schuetze_1_x = Serial.read();
    int schuetze_1_10 = Serial.read();
    int schuetze_2_ringe = Serial.read();
    int schuetze_2_x = Serial.read();
    int schuetze_2_10 = Serial.read();
    int schuetze_3_ringe = Serial.read();
    int schuetze_3_x = Serial.read();
    int schuetze_3_10 = Serial.read();
    int schuetze_4_ringe = Serial.read();
    int schuetze_4_x = Serial.read();
    int schuetze_4_10 = Serial.read();
  }
}

Oder wie kann/sollte ich das sonst realisieren?

Vielen Dank schonmal

LG

Fipsi

Hi Fipsi,
serial.Read() liest immer nur 1 Byte.
Du könntest die Werte durch Semikolon trennen und ReadBytesUntil() verwenden.

Grüße,
Jürgen

Hey Jürgen,

und wie arbeite ich dann mit ReadBytesUntil(); ? Hab mir gerade die Funktion angeschaut (Serial.readBytesUntil() - Arduino Reference), aber mit meinem Englisch komm ich da im Verständnis nicht weit..^^

LG

Fipsi

Serial.readBytesUntil(character, buffer, length)
character - das Zeichen auf das gewartet werden soll - also das Trennzeichen.
buffer - da kommen die Empfangsdaten rein
length - die maximale Anzahl Byte

also z.B.

char empfBuffer[128]; 

Serial.readBytesUntil(',', empfBuffer, 4);

Dann müsste das so aussehen, oder?

void empfangen()
{
  int an_scheibe = Serial.readBytesUntil(";", schuetze_1_ringe, 3);
  
  if (an_scheibe == ich_bin)
  {
    Serial.readBytesUntil(";", schuetze_1_ringe, 3);
    Serial.readBytesUntil(";", schuetze_1_x, 3);
    Serial.readBytesUntil(";", schuetze_1_10, 3);
    Serial.readBytesUntil(";", schuetze_2_ringe, 3);
    Serial.readBytesUntil(";", schuetze_2_x, 3);
    Serial.readBytesUntil(";", schuetze_2_10, 3);
    Serial.readBytesUntil(";", schuetze_3_ringe, 3);
    Serial.readBytesUntil(";", schuetze_3_x, 3);
    Serial.readBytesUntil(";", schuetze_3_10, 3);
    Serial.readBytesUntil(";", schuetze_4_ringe, 3);
    Serial.readBytesUntil(";", schuetze_4_x, 3);
    Serial.readBytesUntil(";", schuetze_4_10, 3);
  }
}

LG

Fipsi

wenn die Empfangsbuffer ein char_Array sind - ja

Zu Deutsch bitte^^

LG

Fipsi

na so:

char empfBuffer[128];
char schuetze_1_ringe[5];

Gruss,
Jürgen

Was sagt da jetzt die 128 oder 5? Bit? Byte? Oder wieder ganz was anderes?

die Anzahl Byte des Array

Okay, das wären ja dann jeweils 3.
Aber jetzt doch die Frage: Warum Array? Array ist mir als ein anderer Variablen-Typ bekannt:
(Ungefähr so:)

array = array(
  1 =>  "bla",
  2 =>  "blu",
  3 =>  "bli"
  ...);

Serial.print(array(3));  // Versendet "bli"

Und so verwende ich das ja nicht.

LG

Fipsi

Das solltest dich mal um die Grundlagen von c kümmern.

  • Den Datentyp array gibt es nicht
  • Runde Klammern werden verwendet entweder bei Funktionsaufrufen, oder um die Reihenfolge von Operationen festzulegen
    array(3) ist der Funktionsaufruf einer Funktion namens array.

Serial.readBytesUntil() returns the number of characters read into the buffer. A 0 means no valid data was found.

Solltest du rauskriegen, was das bedeutet, und dich dann fragen, ob

  int an_scheibe = Serial.readBytesUntil(";", schuetze_1_ringe, 3); 
  if (an_scheibe == ich_bin) { ....

das macht was du willst.

michael_x:
Das solltest dich mal um die Grundlagen von c kümmern.

  • Den Datentyp array gibt es nicht
  • Runde Klammern werden verwendet entweder bei Funktionsaufrufen, oder um die Reihenfolge von Operationen festzulegen
    array(3) ist der Funktionsaufruf einer Funktion namens array.

Sorry, ich komm von PHP :blush: ^^

michael_x:

Serial.readBytesUntil() returns the number of characters read into the buffer. A 0 means no valid data was found.

Solltest du rauskriegen, was das bedeutet, und dich dann fragen, ob

  int an_scheibe = Serial.readBytesUntil(";", schuetze_1_ringe, 3); 

if (an_scheibe == ich_bin) { ....



das macht was du willst.

Muss ich jetzt zugeben, diese Zeile hab ich mir nicht mehr angeschaut^^.

Zumindest was die Variable angeht dann folgendes:

  char an_scheibe(3);
  an_scheibe = Serial.readBytesUntil(";", schuetze_1_ringe, 3);

Und was ich an der if-Abfrage ändern muss, hab ich keinen blassen Schimmer.

LG

Fipsi

Sorry, ich komm von PHP :blush: ^^

Aber da willst du doch nicht bleiben. Ein Stück weiter in Richtung "richtig programmieren" :wink: musst du schon noch gehen.
Meinst du eventuell:

// Erwartete Daten: "001;blabla; "
char an_scheibe[4];  
int ergebnis = Serial.readBytesUntil(";", an_scheibe, 3);
if (ergebnis==3)
{
   lcd.print("Scheibe: ");
   lcd.print(an_scheibe);
   if ( strcmp(an_scheibe, "001") == 0) { /* Eine Zeile für Scheibe "001" ...  */  }
   while (Serial.read() != -1)      delay(2);   // Rest der Nachricht lesen und wegwerfen
}
else 
{
   // keine 3 Zeichen vor dem Semikolon
}

michael_x:

Sorry, ich komm von PHP :blush: ^^

Aber da willst du doch nicht bleiben. Ein Stück weiter in Richtung "richtig programmieren" :wink: musst du schon noch gehen.

Soooo ein rießiger Unterschied ist da jetzt nicht wirklich :wink:

michael_x:
Meinst du eventuell:

// Erwartete Daten: "001;blabla; "

char an_scheibe[4]; 
int ergebnis = Serial.readBytesUntil(";", an_scheibe, 3);
if (ergebnis==3)
{
   lcd.print("Scheibe: ");
   lcd.print(an_scheibe);
   if ( strcmp(an_scheibe, "001") == 0) { /* Eine Zeile für Scheibe "001" ...  */  }
   while (Serial.read() != -1)      delay(2);   // Rest der Nachricht lesen und wegwerfen
}
else
{
   // keine 3 Zeichen vor dem Semikolon
}

ich versuch's mal zu verstehen gg.

Die if-Abfrage ist aber unsinnig, da vor dem Semikolon immer was steht wird^^

Was macht der Befehl strcmp? Konnte den unter Referenzen nicht finden.

LG

Fipsi

strcmp vergleicht einen String!

Ah, danke für den Link :slight_smile:

Und ich glaube zwar, der vorher genannte Code hat die folgende Frage schon beantwortet, aber ich stell sie mal sicherheitshalber trotzdem:

Als Beispiel hab ich jetzt 35 dieser Terminals, wobei jedes einzelne vom Steuergerät mit Daten versorgt wird. Also schick ich dann an alle Geräte alle Daten auf die Reise. Und über die if-Abfrage mit der eben genannten Funktion schau ich dann, ob das, was kommt, für diese Scheibe interessant ist, ansonsten wird's übersprungen und gelöscht und auf das nächste gewartet?

LG

Fipsi

Als Beispiel hab ich jetzt 35 dieser Terminals, wobei jedes einzelne vom Steuergerät mit Daten versorgt wird. Also schick ich dann an alle Geräte alle Daten auf die Reise. Und über die if-Abfrage mit der eben genannten Funktion schau ich dann, ob das, was kommt, für diese Scheibe interessant ist, ansonsten wird's übersprungen und gelöscht und auf das nächste gewartet?

Wer ist "ich" ?

Also schick ich dann an alle Geräte alle Daten auf die Reise

Alle Slaves und der Master hängen an einer Leitung. Auf diese eine Leitung schreibt der Master.

Entweder mit der Adresse eines bestimmten slave, oder mit einer generellen Adresse, wenn die Daten für alle slaves gelten.

Jeder slave muss wissen, wie er selber heisst und nur das für ihn bestimmte auswerten.
Wenn er den Auftrag zu antworten bekommen hat, antwortet er (möglichst mit seiner Adresse in der Nachricht) ...

Wenn der Master was gesendet hat, worauf er eine Antwort verlangt, muss er halt abwarten ob diese kommt.
Wenn nichts kommt, ist der betreffende slave eben nicht bereit.

michael_x:

Als Beispiel hab ich jetzt 35 dieser Terminals, wobei jedes einzelne vom Steuergerät mit Daten versorgt wird. Also schick ich dann an alle Geräte alle Daten auf die Reise. Und über die if-Abfrage mit der eben genannten Funktion schau ich dann, ob das, was kommt, für diese Scheibe interessant ist, ansonsten wird's übersprungen und gelöscht und auf das nächste gewartet?

Wer ist "ich" ?

Beim zweiten ich der Master, beim dritten ich der Slave.

michael_x:

Also schick ich dann an alle Geräte alle Daten auf die Reise

Alle Slaves und der Master hängen an einer Leitung. Auf diese eine Leitung schreibt der Master.

Entweder mit der Adresse eines bestimmten slave, oder mit einer generellen Adresse, wenn die Daten für alle slaves gelten.

Jeder slave muss wissen, wie er selber heisst und nur das für ihn bestimmte auswerten.
Wenn er den Auftrag zu antworten bekommen hat, antwortet er (möglichst mit seiner Adresse in der Nachricht) ...

Wenn der Master was gesendet hat, worauf er eine Antwort verlangt, muss er halt abwarten ob diese kommt.
Wenn nichts kommt, ist der betreffende slave eben nicht bereit.

Genau, das wollte ich auch noch fragen:
Ich mach ich das mit dem warten?

  Serial.println("bla, bla");
  
  if (Serial.available())
  {
    Serial.read();
  }

oder muss nach dem print noch ein delay(); oder wie mach ich das am geschicktesten?

LG

Fipsi

entsprechend dem berühmten BlinkWithoutDelay machst du ( Master ) natürlich WaitWithoutDelay:

Dazu brauchst du die Zeit des letzten Sendens und den Status, dass du gerade wartest ( Sendebereit == false )

boolean Sendebereit;
unsigned long Sendezeit;
void loop {
  Wenn gerade eine Antort kommt:
   {
      Lesen();
      Wenn Antwort komplett :  { Auswerten(); Sendebereit = true; }
      return; 
   } 
   Wenn (Sendebereit == false && (millis() - Sendezeit > MaxVerzögerung ) )
   { 
       SlaveAntwortetNicht(); Sendebereit = true;
    } 
   Wenn (Sendebereit && es ist etwas zu tun):
   {
      Senden();
      Wenn (Dieses Kommando eine Antwort erwartet)
       {
              SendeZeit = millis();
              Sendebereit = false;
       }
   }
}

edit: Auch PseudoCode sieht in Code Tags besser aus