Begriff mit Wert über Serial senden/empfangen

Hallo zusammen

Habe heute nochmals bisschen Zeit gefunden, das Beispiel von Tommy weiter zu studieren. Das hat mir glaube ich wirklich geholfen. Ich muss nur noch den letzten Teil bei mir einbauen, wo mit switch/case die Parameter zugeordnet werden - das wollte ich ja haben. Nun aber noch ein paar Fragen dazu. Habe mal Dein Teil kopiert der mir noch fehlt und versuch zu verstehen was da passiert.

boolean auswerten() {
char *ptr, *p, *savePtr, *saveP;
const char delim[] = ",";
char first;
boolean status = false;
int wert;

// inStr zerlegen an ,
  // strtok ist nicht wiedereintrittsfähig,
  // deshalb strtok_r nehmen, um auch den Doppelpunkt auszuwerten zu koennen
  ptr = strtok_r(inStr,delim,&savePtr); //separiert String inStr bei delim und speichert es in ptr und savePtr
  while (ptr != NULL) { 
    // ist ein Doppelpunkt drin?
    if (strchr(ptr,':')) { //wenn in ptr ein : drin ist, dann...
      // mit Doppelpunkt
      // neuer Stringtokenizer
      p = strtok_r(ptr,":",&saveP); //separiere String ptr bei : und speichere es in p und saveP
      if (p != NULL) {
        // erster Teil Farbe
        first = p[0];
      }
      p = strtok_r(NULL,":",&saveP); //separiert nächsten Abschnitt im String ptr bis zum : und speichert es in p und saveP
      if (p != NULL) {
        // zweiter Teil Farbwert
        wert = atoi(p); //konvertiert separierter String p zu int
      }
    }
    else {
      // ohne Doppelpunkt
      first = ptr[0]; //speichert separierter String in first
      wert = atoi(ptr+1); //konvertiert separierter String ptr[1] zu int
    }
    // begrenzen auf 255
    if (wert > 255) {
      wert = 255;
    }
    // keine negativen Werte
    if (wert < 0) {
      wert = 0;
    }
    switch (first) {
      case 'a':   // alles aus
      case 'A':    hellRot = dunkel;
                  hellGruen = dunkel;
                  hellBlau = dunkel;
                  status = true;
                  break;
      case 'r':    // rot
      case 'R':    hellRot = wert;
                  status = true;
                  break;
      case 'g':    // gruen
      case 'G':    hellGruen = wert;
                  status = true;
                  break;
      case 'b':    // blau
      case 'B':    hellBlau = wert;
                  status = true;
                  break;
    }
    #ifdef DEBUG
    Serial.print("Farbe: ");
    Serial.print(first);
    Serial.print(" Wert: ");
    Serial.println(wert);
    #endif
    // naechster Token. NULL, wenn nichts gefunden
    ptr = strtok_r(NULL,delim,&savePtr);
  }
  return status;
}

Nun zu den Fragen: - Ich sollte in diesem Fall strtok_r anstelle wie aktuell bei mir strtok, da ich ja gewisse Buchstaben, Werten zuordnen muss und daher auch zwei Separierzeichen brauche. Was aber ist der dritte Parameter in strtok_r? Ich habe mal kommentiert "speichert zusätzlich in savePtr, aber das kann ja nicht sein, oder? Ich habe was gelesen, dass das das zweite Separierzeichen sein sollte, aber das ist es bei Dir ja nicht? - Unten bei "else", wenn kein Doppelpunkt vorhanden ist, dann wird der String zuerst in char first und dann in int wert konvertiert. Dieser String ptr besteht ja aber aus Buchstabe und Zahl (b200). Wird dann automatisch weil first als charakter definiert ist nur das b annehmen und der wert, weil in integer umgewandelt nur die Zahl?

Diesen Teil werde ich morgen bei Gelegenheit mal versuchen noch einzubauen. Mal sehen wie es dann funktioniert.

@Andreas: Dem Xbee muss aber der Befehl dafür gesendet werden, und das geschieht ja (so wie ich das verstanden habe) über die HEX Werte beginnend mit 0x7E als Startdelimeter, dann die Datenlänge, ID und was weiss ich. Wenn das nicht in dem Format gesendet wird, dann gibt der Xbee auch keine Antwort zurück. Das hiesst ich muss ihm die FramID 0x01 in der vierten Stelle vor meinen Daten mitsenden, damit ich vom anderen Xbee die Rückmeldung 0x89 und 0 bekomme, dass die Daten gesendet wurden. Die FrameID kann ja varieren, da kann ich ja dann auch was anderes mitsenden, sodass ich wie in Deinem Beispiel die Rückmeldung über Signalstärke erhalte. Wenn ich das aber nicht senden kann, dann nütz mir der API Modus rein gar nichts. Die Xbee geben nicht einfach so Rückmeldung. Das habe ich gemeint und hat mich verwirrt. Aber es wird glaube ich klarer...

Die Seiten 64 ist die Einstellung des PowerLevels, das ist klar, muss ich dann einstellen was für mich funktioniert (muss ich dann versuchen was noch geht und was nicht), und Seite 84 die DB Werte.... Das ist ja noch in den normalen Einstellungen ohne API! Das bedeutet, ich könnte vermutlich den Wert vom Xbee erhalten und muss den erhaltenen HEX Wert dann einfach so programmieren, dass wenn er so und so ist, der letzte mögliche Befehl gesendet wird damit alles stoppt und ich mein Notaus habe. Muss ich dann nochmals genauer lesen, wie dieser Wert automatisch an den Arduino gegeben wird. => Dann brauche ich diesen doofen API Modus ja gar nicht und muss da nicht unnötige Daten generiern und mitsenden!

Müsste dann nicht eigentlich mein erster Sketch mit switch/case und den Probewerten A und B ausreichen? Die Frage wäre dort nur, warum kann ich keine HEX Werte in case schreiben und dann unter einem definierten int speichern? Ich erhalte da immer 0. Oder ist mein jüngster Sketch ohnehin besser geeignet? Ich werde morgen mal den letzten Teil versuchen zu ergänzen.

Grüsse

Stef

Ja, der savePtr ist ein Pointer der Art -- wo war ich bisher, wo muss ich weiter machen. Die verschiedenen Versionen rühren daher, dass das Format ziemlich frei gehalten wurde. Das ist als Kommentar oben drin beschrieben.

Das muss man nicht so frei halten. Man kann auch festlegen, dass immer ein Doppelpunkt drin sein muss oder andere Festlegungen.

Wichtig ist, dass man weiß, wie man das Format aufgebaut haben will.

Gruß Tommy

Ja, das habe ich schon gelesen. Wenn ich diesen Sketch (von mir bisschen abgeändert wie im letzten Post auf Seite eins, zweiter Sketch) so brauche, dann würde ich die HEX Werte mit Leerschlag oder Komma trennen und meine Werte die ich mit Buchstaben sende mit einem anderen Trennzeichen. Aber zum Testen könnte ich natürlich auch einfach nur alles mit einem Trennzeichen trennen - ist ja auch einfacher zu schreiben... stimmt schon! Dann schau ich mir das morgen mal an, ob es dann läuft wies soll.

Den anderen Sketch mit switch/case habe ich hinbekommen, HEX zu senden und empfangen und Buchstaben mit Zahlenwerten. Vom Gefühl her, braucht das länger als die Methode im anderen Sketch, sprich wie bei Dir, Tommy. Oder täusche ich mich da? Auch finde ich bei Deinem Sketch elegant gelöst, dass es nicht einfach immer im Empfagsmodus steckt, sondern nur wenn wirklich Daten reinkommen - ob das dann so wichtig ist, da die Loop ja eh weiterläuft wenn keine Daten kommen, aber sicherlich eleganter :)

Hier noch der aktualisiert Sketch switch/case mit HEX und Buchstaben/Zahlenwerte.

Sender:

int wert = 1023;
int wert2 = 825;

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

}

void loop() {
  Serial.write(0x7E);
  Serial.println(wert);
  Serial.flush();

  Serial.print("B");
  Serial.println(wert2);
  Serial.flush();

}

Empfänger:

int eins = 0;
int zwei = 0;
char var;

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

}

void loop() {
  while(Serial.available() > 0){
    var = Serial.read();
    switch (var){
      case 0x7E : eins = Serial.parseInt();
                    break;
      case 'B' : zwei = Serial.parseInt();
                    break;
    }
  }
Serial.print("eins =");
Serial.println(eins);
Serial.print("zwei =");
Serial.println(zwei);
  
}

Grüsse

Stef

Ob Du HEX (0xff) oder dezimal (255) benutzt, ist dem prozessor sowas von egal. Für ihn ist beides B11111111, also ein Byte, bei dem alle Bits 1 sind.
Alle anderen Darstellungen sind nur zum Verständnis für die Nase vor dem Monitor.

Gruß Tommy

Stimmt schon, aber gemäss Handbuch der Xbees müsste im Hex Format gesendet werden, damit die eine Rückmeldung geben. Wenn ich das jetzt aber ohne API gedöns über den DB Wert machen kann, dann sendet mir das Xbee ja den Wert und da weiss ich er sollte in Hex das und das haben, dann spielt es keine Rolle, muss nur richtig definiert sein. Der Einfachheit halber wäre aber Hex auch besser, dann kann man nachvollziehen was das für Werte sind und warum und kann mit dem Handbuch abgleichen.

Grüsse

Stef

aber gemäss Handbuch der Xbees müsste im Hex Format gesendet werden,

Nein! Im Handbuch wurde die hexadezimale Repräsentation/Darstellung der Daten gewählt. Damit du sie leicht lesen kannst.

Bitte unterscheide zwischen Daten und Repräsentation. (Dein Xbee kann es nicht, für den sieht alles gleich aus) Hier wird dir jeder Buchstabe in den üblichsten Repräsentationen vorgeführt Keine Sorge, es gibt noch viel mehr.

Hallo

Ja, stimmt! Ist eigentlich alles 0 und 1, aber allein wegen der Lesbarkeit des Sketchs wäre es von Vorteil. Aber das ist ja auch egal, am Ende muss er ja was senden und das selbe wieder Empfangen.

Ich habe heute mal den Sketch von mir statt mit strtok, mit strtok_r abgeändert. Nun empfange ich gar nichts mehr. Ich sehe momentan grad nicht was fehlt. Könnte da mal jemand einen Blick drüber werfen? Ich schau mir das ganze morgen nochmals an, hab für heute genug :neutral_face:

Sender:

int wert = 1023;
int wert2 = 825;

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

}

void loop() {
  Serial.print(0x7E);
  Serial.print(' ');
  Serial.print(0x89);
  Serial.print(' ');
  Serial.print(0x00);
  Serial.print(' ');
  Serial.print(0x01);
  Serial.print(' ');
  Serial.print("A");
  Serial.print(',');
  Serial.print(wert);
  Serial.print(' ');

  Serial.print("B");
  Serial.print(',');
  Serial.println(wert2);
  
  Serial.flush();

}

Ich habe überall Serial.print drin gelassen. Habe mal gelesen, dass Serial.print in Serial.write umgewandelt wird? Spielt aber nicht so eine Rolle, oder? Ist ja doof im Sendeteil Für HEX write zu nehmen und für die Zeichen dann wieder print...

Empfänger:

const int SERIAL_BUFFER_SIZE = 20; //Speicher für 20 gesendete Werte
char serialBuffer[SERIAL_BUFFER_SIZE]; //Array serialBuffer

int startDelimeter;
int lengthByte;
int apiIdentifier;
int apiFrameId;
int A;
int B;

void setup()
{
  Serial.begin(9600);
}

void loop()
{
  if (readSerial())
  {
    parseSerial();

      Serial.print("serialBuffer = ");
      Serial.println(serialBuffer);
      Serial.print("startDelimeter = ");
      Serial.println(startDelimeter);
      Serial.print("lengthByte = ");
      Serial.println(lengthByte);
      Serial.print("apiIdentifier = ");
      Serial.println(apiIdentifier);
      Serial.print("apiFrameId = ");
      Serial.println(apiFrameId);
      Serial.print("A = ");
      Serial.println(A);
      Serial.print("B = ");
      Serial.println(B);
  
  }
}

bool readSerial()
{
  static byte index;

  while (Serial.available())
  {
    char c = Serial.read();

    if (c >= 0 && index < SERIAL_BUFFER_SIZE - 1)
    {
      serialBuffer[index++] = c; //Array serialBuffer [index +1] gleich gelesene Daten c
    }
    else if (c == '\n') //wenn c gleich "Ende der Daten" erkannt...
    {
      serialBuffer[0] = '\0'; //Array auf null zurücksetzen
      index = 0;
      return true; //Daten wurden gelesen
    }
  }
  return false; //Daten wurden noch nicht gelesen
}

void parseSerial()
{
  char* ptr, * p, * savePtr, * saveP;
  char first;
  char def;
  int wert;
  
  ptr = strtok_r(serialBuffer, ' ', &savePtr); //separiert gelesenen String serialBuffer bis zum Leerschlag und speichert es in ptr und savePtr

  while(ptr != NULL){
    if (strchr(ptr,',')){ //wenn in ptr ein , drin ist, dann...
      p = strtok_r(ptr,',',&saveP); //separiert String ptr beim , und speichert es in p und saveP
      if (p != NULL){
        def = p[0]; //erster Teil Bezeichnung
      }
      p = strtok_r(NULL, ',', &saveP); //separiert nächsten Abschnitt im String p bis zum , und speichert es in p und saveP
      if (p != NULL){
        wert = atoi(p); //konvertiert zweiten Teil des separierten Strings p zu int
      }
    }
    else { //wenn kein , vorhanden
    first = ptr; //speichert separierten String ptr in first (HEX Werte)
  }

  switch (first, def){

    case 0x7E: startDelimeter = first;
               break;
    case 0x89: lengthByte = first;
               break;
    case 0x00: apiIdentifier = first;
               break;
    case 0x01: apiFrameId = first;
               break;
    case 'A':  A = wert;
               break;
    case 'B':  B = wert;
               break;

  }

    ptr = strtok_r(NULL, ' ', &savePtr); //separiert nächsten Abschnitt im String ptr bis zum Leerzeichen
    
  }
}

Grüsse

Stef

Wenn Du die Daten vor dem Lesen vernichtest, kann er auch nichts empfangen:

serialBuffer[0] = '\0'; //Array auf null zurücksetzen

Das darfst Du erst machen, wenn Du alles ausgewertet hast.

Gruß Tommy

Danke, habe dort eigentlich “serialBuffer[index] = ‘\0’;” als Abschlusszeichen drin gehabt.
Habe jetzt als Abschluss ein ‘\n’ drin und unten eine if-Abfrage, sobald ‘\n’, dann soll er den Buffer zurücksetzen. Funktioniert jetzt auch, dass ich Daten erhalte, aber sie werden nicht zugeordnet. Auch stimmt der Empfangene Datensatz nicht immer überein. Wo liegt da noch der Hund begraben, dass die getrennten Strings nicht zugewiesen werden?

Empfänger sieht jetzt so aus:

const int SERIAL_BUFFER_SIZE = 30; //Speicher für 20 gesendete Werte
char serialBuffer[SERIAL_BUFFER_SIZE]; //Array serialBuffer

int startDelimeter;
int lengthByte;
int apiIdentifier;
int apiFrameId;
int A;
int B;

void setup()
{
  Serial.begin(9600);
}

void loop()
{
  if (readSerial())
  {
    parseSerial();

      Serial.print("serialBuffer = ");
      Serial.println(serialBuffer);
      Serial.print("startDelimeter = ");
      Serial.println(startDelimeter);
      Serial.print("lengthByte = ");
      Serial.println(lengthByte);
      Serial.print("apiIdentifier = ");
      Serial.println(apiIdentifier);
      Serial.print("apiFrameId = ");
      Serial.println(apiFrameId);
      Serial.print("A = ");
      Serial.println(A);
      Serial.print("B = ");
      Serial.println(B);
  
  }
}

bool readSerial()
{
  static byte index;

  while (Serial.available())
  {
    char c = Serial.read();

    if (c >= 0 && index < SERIAL_BUFFER_SIZE - 1 && c != '\n')
    {
      serialBuffer[index++] = c; //Array serialBuffer [index +1] gleich gelesene Daten c
    }
    else if (c == '\n') //wenn c gleich "Ende der Daten" erkannt...
    {
      serialBuffer[index] = '\n';
      index = 0;
      return true; //Daten wurden gelesen
    }
  }
  return false; //Daten wurden noch nicht gelesen
}

void parseSerial()
{
  char* ptr, * p, * savePtr, * saveP;
  char first;
  char def;
  int wert;
  
  ptr = strtok_r(serialBuffer, ' ', &savePtr); //separiert gelesenen String serialBuffer bis zum Leerschlag und speichert es in ptr und savePtr

  while(ptr != NULL){
    if (strchr(ptr,',')){ //wenn in ptr ein , drin ist, dann...
      p = strtok_r(ptr,',',&saveP); //separiert String ptr beim , und speichert es in p und saveP
      if (p != NULL){
        def = p; //erster Teil Bezeichnung
      }
      p = strtok_r(NULL, ',', &saveP); //separiert nächsten Abschnitt im String p bis zum , und speichert es in p und saveP
      if (p != NULL){
        wert = atoi(p); //konvertiert zweiten Teil des separierten Strings p zu int
      }
    }
    else { //wenn kein , vorhanden
    first = atoi(ptr); //speichert separierten String ptr in first (HEX Werte)
  }

  switch (first, def){

    case 0x7E: startDelimeter = first;
               break;
    case 0x89: lengthByte = first;
               break;
    case 0x00: apiIdentifier = first;
               break;
    case 0x01: apiFrameId = first;
               break;
    case 'A':  A = wert;
               break;
    case 'B':  B = wert;
               break;

  }

    ptr = strtok_r(NULL, ' ', &savePtr); //separiert nächsten Abschnitt im String ptr bis zum Leerzeichen
    
  }

  if (ptr == '\n' && p == '\n'){
    serialBuffer[0] = '\0'; //Array auf null zurücksetzen
  }
}

Grüsse

Stef

Wo liegt da noch der Hund begraben, dass die getrennten Strings nicht zugewiesen werden?

Vermutlich ein Fehler im Parser. Oder noch tiefer, schon in der Grammatik.

Und genau diese Grammatik, welche du da verwenden möchtest, ist mir noch nicht klar.

Falls dir nicht klar ist, was ich hier mit "Grammatik" meine: In natürlichen/menschlichen Sprachen ist eine Grammatik/Satzbau einzuhalten, damit Sprecher und Hörer erfolgreich kommunizieren können. Auch ist ein gemeinsames Vokabular unabdingbar.

Menschen können eine fehlerhafte Grammatik und Schreibfehler teilweise korrigieren. Arduinos können das nicht.

Die Lösung deiner Probleme beginnt also erstmal damit, eine Glas harte, messerscharfe Grammatik zu erfinden! Zu definieren.

Diese Definition muss dann für Sender und Empfänger identisch sein.

Diese Definition hätte ich jetzt mal gerne gesehen, um prüfen zu können, ob dein Parser diese abarbeiten kann.

(fertige Alternativen interessieren dich nicht, oder?)

Hier nochmals mein Sender:

int wert = 1023;
int wert2 = 825;

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

}

void loop() {
  Serial.print(0x7E);
  Serial.print(' ');
  Serial.print(0x89);
  Serial.print(' ');
  Serial.print(0x00);
  Serial.print(' ');
  Serial.print(0x01);
  Serial.print(' ');
  Serial.print("A");
  Serial.print(',');
  Serial.print(wert);
  Serial.print(' ');

  Serial.print("B");
  Serial.print(',');
  Serial.println(wert2);
  
  Serial.flush();

}

und Empfänger:

const int SERIAL_BUFFER_SIZE = 30; //Speicher für 20 gesendete Werte
char serialBuffer[SERIAL_BUFFER_SIZE]; //Array serialBuffer

int startDelimeter = 0;
int lengthByte = 0;
int apiIdentifier = 0;
int apiFrameId = 0;
int A = 0;
int B = 0;

void setup()
{
  Serial.begin(9600);
}

void loop()
{
  if (readSerial())
  {
    parseSerial();

      Serial.print("serialBuffer = ");
      Serial.println(serialBuffer);
      Serial.print("startDelimeter = ");
      Serial.println(startDelimeter);
      Serial.print("lengthByte = ");
      Serial.println(lengthByte);
      Serial.print("apiIdentifier = ");
      Serial.println(apiIdentifier);
      Serial.print("apiFrameId = ");
      Serial.println(apiFrameId);
      Serial.print("A = ");
      Serial.println(A);
      Serial.print("B = ");
      Serial.println(B);
  
  }
}

bool readSerial()
{
  static byte index;

  while (Serial.available())
  {
    char c = Serial.read();

    if (c >= 0 && index < SERIAL_BUFFER_SIZE - 1 && c != '\n')
    {
      serialBuffer[index++] = c; //Array serialBuffer [index +1] gleich gelesene Daten c
    }
    else if (c == '\n') //wenn c gleich "Ende der Daten" erkannt...
    {
      serialBuffer[index] = '\n';
      index = 0;
      return true; //Daten wurden gelesen
    }
  }
  return false; //Daten wurden noch nicht gelesen
}

void parseSerial()
{
  char* ptr, * p, * savePtr, * saveP;
  char first;
  char def;
  int wert;
  
  ptr = strtok_r(serialBuffer, ' ', &savePtr); //separiert gelesenen String serialBuffer bis zum Leerschlag und speichert es in ptr und savePtr

  while(ptr != NULL){
    if (strchr(ptr,',')){ //wenn in ptr ein , drin ist, dann...
      p = strtok_r(ptr,',',&saveP); //separiert String ptr beim , und speichert es in p und saveP
      if (p != NULL){
        def = p; //erster Teil Bezeichnung
      }
      p = strtok_r(NULL, ',', &saveP); //separiert nächsten Abschnitt im String p bis zum , und speichert es in p und saveP
      if (p != NULL){
        wert = atoi(p); //konvertiert zweiten Teil des separierten Strings p zu int
      }
    }
    else { //wenn kein , vorhanden
    first = atoi(ptr); //speichert separierten String ptr in first (HEX Werte)
  }

  switch (first, def){

    case 0x7E: startDelimeter = first;
               break;
    case 0x89: lengthByte = first;
               break;
    case 0x00: apiIdentifier = first;
               break;
    case 0x01: apiFrameId = first;
               break;
    case 'A':  A = wert;
               break;
    case 'B':  B = wert;
               break;

  }

    ptr = strtok_r(NULL, ' ', &savePtr); //separiert nächsten Abschnitt im String ptr bis zum Leerzeichen
    
  }

  if (ptr == '\n' && p == '\n'){
    serialBuffer[0] = '\0'; //Array auf null zurücksetzen
  }
}

Alternativen gehen schon auch, sofern ich sie gebrauchen kann. Ich habe hier eigentlich die ganze Grammatik definiert, dass es funktionieren müsste - ich sehe nichts mehr was nicht stimmen könnte.

Du solltest den Abschluß sauber machen (mit '\0' abschließen, nicht mit '\n'): serialBuffer[index] = '\0';

Gruß Tommy

Das habe ich gemacht, aber dann bekomme ich noch komischere Werte eingelesen. Switch/Case funktioniert aber trotzdem nicht, erhalte die Werte nur am Stück eingelesen.

Hier mal die Ausgabe aus dem Seriellen Monitor:

serialBuffer = 126 137 0 1 A,1023 B,825

startDelimeter = 0
lengthByte = 0
apiIdentifier = 0
apiFrameId = 0
A = 0
B = 0
serialBuffer = 126 137 0 1 A,1023 B,825

startDelimeter = 0
lengthByte = 0
apiIdentifier = 0
apiFrameId = 0
A = 0
B = 0
serialBuffer = 126 137 0 1 A,1023 B,825

startDelimeter = 0
lengthByte = 0
apiIdentifier = 0
apiFrameId = 0
A = 0
B = 0
serialBuffer = 126 137 0 1023 B,825

startDelimeter = 0
lengthByte = 0
apiIdentifier = 0
apiFrameId = 0
A = 0
B = 0
serialBuffer = 126 137 0 1 A,1A,1023 B,825

startDelimeter = 0
lengthByte = 0
apiIdentifier = 0
apiFrameId = 0
A = 0
B = 0
serialBuffer = 126 137 0 1 0 1 A,1023 B,825

startDelimeter = 0
lengthByte = 0
apiIdentifier = 0
apiFrameId = 0
A = 0
B = 0
serialBuffer = 126 26 137 0 1 A,1023 B,825

startDelimeter = 0
lengthByte = 0
apiIdentifier = 0
apiFrameId = 0
A = 0
B = 0
serialBuffer = 126 126 137 0 1 A,1023 B,825

startDelimeter = 0
lengthByte = 0
apiIdentifier = 0
apiFrameId = 0
A = 0
B = 0
serialBuffer = 126 26 137 0 1 A,1023 B,825

startDelimeter = 0
lengthByte = 0
apiIdentifier = 0
apiFrameId = 0
A = 0
B = 0
serialBuffer = 126 126 137 0 1 A,1023 B,825

startDelimeter = 0
lengthByte = 0
apiIdentifier = 0
apiFrameId = 0
A = 0
B = 0
serialBuffer = 126 26 137 0 1 A,1023 B,825

startDelimeter = 0
lengthByte = 0
apiIdentifier = 0
apiFrameId = 0
A = 0
B = 0
serialBuffer = 126 126 137 0 1 A,1023 B,825

startDelimeter = 0
lengthByte = 0
apiIdentifier = 0
apiFrameId = 0
A = 0
B = 0
serialBuffer = 126 26 137 0 1 A,1023 B,825

startDelimeter = 0
lengthByte = 0
apiIdentifier = 0
apiFrameId = 0
A = 0
B = 0
serialBuffer = 126 26 137 0 1 A,1023 B,825

startDelimeter = 0
lengthByte = 0
apiIdentifier = 0
apiFrameId = 0
A = 0
B = 0
serialBuffer = 126 126 137 0 1 A,1023 B,825

startDelimeter = 0
lengthByte = 0
apiIdentifier = 0
apiFrameId = 0
A = 0
B = 0
serialBuffer = 126 26 137 0 1 A,1023 B,825

startDelimeter = 0
lengthByte = 0
apiIdentifier = 0
apiFrameId = 0
A = 0
B = 0
serialBuffer = 126 126 137 0 1 A,1023 B,825

startDelimeter = 0
lengthByte = 0
apiIdentifier = 0
apiFrameId = 0
A = 0
B = 0
serialBuffer = 126 26 137 0 1 A,1023 B,825

startDelimeter = 0
lengthByte = 0
apiIdentifier = 0
apiFrameId = 0
A = 0
B = 0
serialBuffer = 126 126 137 0 1 A,1023 B,825

startDelimeter = 0
lengthByte = 0
apiIdentifier = 0
apiFrameId = 0
A = 0
B = 0
serialBuffer = 126 26 137 0 1 A,1023 B,825

startDelimeter = 0
lengthByte = 0
apiIdentifier = 0
apiFrameId = 0
A = 0
B = 0
serialBuffer = 126 26 137 0 1 A,1023 B,825

startDelimeter = 0
lengthByte = 0
apiIdentifier = 0
apiFrameId = 0
A = 0
B = 0

Das stimmt: serialBuffer = 126 137 0 1 A,1023 B,825, dann setzt er Werte ein die es nicht gibt oder macht Zusatzwerte in die Folge.

Ich habe hier eigentlich die ganze Grammatik definiert,

Nein, ich sehe nur Programmcode. Und dieser ist offensichtlich nicht korrekt, bzw. tut nicht das, was du willst. Darum kann ich auch keine korrekte Grammatik daraus ableiten.

Folgendes wäre eine Definition, mit der man arbeiten könnte: 1. Verwendet wird der 7Bit ASCII Zeichensatz 2. Komma und Semikolon sind reserviert und dürfen nicht in den Daten vor kommen 3. Ein Datensatz besteht aus Bezeichner und Value. 4. Der Bezeichner darf maximal 20 Zeichen lang sein. Erlaubt sind alle Buchstaben des Zeichesatzes 5. Das Value entspricht dem Datentype int. Besteht aus den Zahlen 0 bis 9 und evtl Vorzeichen 6. Bezeichner und Value werden durch Komma getrennt 7. Ein Datensatz wird mit Semikolon abgeschlossen

Damit sind dieses 3 gültige Datensätze:

led,4;
frosch,42;
Zwiebelkuchen,-4711;

Der Vorteil: Die gesendeten Daten sind für Mensch und Maschine leicht lesbar und generierbar.

Um Datensätze dieses Musters zu generieren, eignet sich sprintf(). Um Datensätze dieses Musters zu parsen, eignet sich sscanf().

Also, ich versuche mal zu definieren:

  • der 7bit ASCII Zeichensatz, klar - gibt es andere?
  • Leerzeichen und Komma sind reserviert für Wertetrennung
  • Ein Datensatz besteht wie Du vielleicht gesehen hast, im ersten Teil aus values (HEX) mit Leerzeichen getrennt und im zweiten Teil aus Bezeichner und value mit Komme getrennt. Daher geht sscanf() nicht so richtig.
  • Mit der Switch/Case Abfrage bin ich auf einzelne Buchstaben und HEX beschränkt. Wörter habe ich ja versucht, funktioniet aber nicht.
  • Values bestehen aus int, Zahlen 0-9 ohne Vorzeichen
  • Datensatz wird bei mir einfach mit einer neuen Zeile abgeschlossen (Serial.println()). Spielt das eine Rolle? Ich hatte vorher mal ein Semikolon als Endzeichen drin, ist mir aber überflüssig vorgekommen.
  • der 7bit ASCII Zeichensatz, klar - gibt es andere?

Dutzende!

Daher geht sscanf() nicht so richtig. - Mit der Switch/Case Abfrage bin ich auf einzelne Buchstaben und HEX beschränkt. Wörter habe ich ja versucht, funktioniet aber nicht.

Jammern gehört nicht in eine Definition.

  • Datensatz wird bei mir einfach mit einer neuen Zeile abgeschlossen (Serial.println()). Spielt das eine Rolle? Ich hatte vorher mal ein Semikolon als Endzeichen drin, ist mir aber überflüssig vorgekommen.

Jammern gehört nicht in eine Definition. Und wenn dir \n lieber ist, meine Sorge solls nicht sein. Wobei ich "nicht darstellbare Zeichen" in solchen Formaten hasse wie die Pest. Z.b. Tab und Leerzeichen sind leicht zu verwechseln. Verschiedene Zeilenenden Alte Mac: \r Linux und neue Mac:\n Windows: \r\n

Keine gültigen Beispiele angegeben. Damit kann ich dann auch keinen Parser testen.

Warum sscanf() nicht funktioniert, hast du nicht begründet.

Mit jammern hat das wohl wenig zu tun....

Naja.

Beispiel:

0x7E 0x89 0x00 0x01 A,1023 B,825

Der Sendesketch funktioniert soweit ich das beurteilen kann, im Seriellen Monitor wird mit genau das angezeigt, einfach in Zahlenwerten wie z.B. für 0x7E = 126 oder 0x89 = 137. Beim Empfänger kommt auch was an, aber wie in Post

stef308: Das habe ich gemacht, aber dann bekomme ich noch komischere Werte eingelesen. Switch/Case funktioniert aber trotzdem nicht, erhalte die Werte nur am Stück eingelesen.

Hier mal die Ausgabe aus dem Seriellen Monitor:

serialBuffer = 126 137 0 1 A,1023 B,825

startDelimeter = 0 lengthByte = 0 apiIdentifier = 0 apiFrameId = 0 A = 0 B = 0 serialBuffer = 126 137 0 1 A,1023 B,825

startDelimeter = 0 lengthByte = 0 apiIdentifier = 0 apiFrameId = 0 A = 0 B = 0 serialBuffer = 126 137 0 1 A,1023 B,825

startDelimeter = 0 lengthByte = 0 apiIdentifier = 0 apiFrameId = 0 A = 0 B = 0 serialBuffer = 126 137 0 1023 B,825

startDelimeter = 0 lengthByte = 0 apiIdentifier = 0 apiFrameId = 0 A = 0 B = 0 serialBuffer = 126 137 0 1 A,1A,1023 B,825

startDelimeter = 0 lengthByte = 0 apiIdentifier = 0 apiFrameId = 0 A = 0 B = 0 serialBuffer = 126 137 0 1 0 1 A,1023 B,825

startDelimeter = 0 lengthByte = 0 apiIdentifier = 0 apiFrameId = 0 A = 0 B = 0 serialBuffer = 126 26 137 0 1 A,1023 B,825

startDelimeter = 0 lengthByte = 0 apiIdentifier = 0 apiFrameId = 0 A = 0 B = 0 serialBuffer = 126 126 137 0 1 A,1023 B,825

startDelimeter = 0 lengthByte = 0 apiIdentifier = 0 apiFrameId = 0 A = 0 B = 0 serialBuffer = 126 26 137 0 1 A,1023 B,825

startDelimeter = 0 lengthByte = 0 apiIdentifier = 0 apiFrameId = 0 A = 0 B = 0 serialBuffer = 126 126 137 0 1 A,1023 B,825

startDelimeter = 0 lengthByte = 0 apiIdentifier = 0 apiFrameId = 0 A = 0 B = 0 serialBuffer = 126 26 137 0 1 A,1023 B,825

startDelimeter = 0 lengthByte = 0 apiIdentifier = 0 apiFrameId = 0 A = 0 B = 0 serialBuffer = 126 126 137 0 1 A,1023 B,825

startDelimeter = 0 lengthByte = 0 apiIdentifier = 0 apiFrameId = 0 A = 0 B = 0 serialBuffer = 126 26 137 0 1 A,1023 B,825

startDelimeter = 0 lengthByte = 0 apiIdentifier = 0 apiFrameId = 0 A = 0 B = 0 serialBuffer = 126 26 137 0 1 A,1023 B,825

startDelimeter = 0 lengthByte = 0 apiIdentifier = 0 apiFrameId = 0 A = 0 B = 0 serialBuffer = 126 126 137 0 1 A,1023 B,825

startDelimeter = 0 lengthByte = 0 apiIdentifier = 0 apiFrameId = 0 A = 0 B = 0 serialBuffer = 126 26 137 0 1 A,1023 B,825

startDelimeter = 0 lengthByte = 0 apiIdentifier = 0 apiFrameId = 0 A = 0 B = 0 serialBuffer = 126 126 137 0 1 A,1023 B,825

startDelimeter = 0 lengthByte = 0 apiIdentifier = 0 apiFrameId = 0 A = 0 B = 0 serialBuffer = 126 26 137 0 1 A,1023 B,825

startDelimeter = 0 lengthByte = 0 apiIdentifier = 0 apiFrameId = 0 A = 0 B = 0 serialBuffer = 126 126 137 0 1 A,1023 B,825

startDelimeter = 0 lengthByte = 0 apiIdentifier = 0 apiFrameId = 0 A = 0 B = 0 serialBuffer = 126 26 137 0 1 A,1023 B,825

startDelimeter = 0 lengthByte = 0 apiIdentifier = 0 apiFrameId = 0 A = 0 B = 0 serialBuffer = 126 26 137 0 1 A,1023 B,825

startDelimeter = 0 lengthByte = 0 apiIdentifier = 0 apiFrameId = 0 A = 0 B = 0




Das stimmt: serialBuffer = 126 137 0 1 A,1023 B,825, dann setzt er Werte ein die es nicht gibt oder macht Zusatzwerte in die Folge.

erwähnt, macht er zum Teil andere Werte hinein oder lässt sie weg. Das einordnen/parsen geht wohl nicht da immer 0 für alle Bezeichnungen ausgegeben wird.

sscanf(): Habe ich mir angeschaut und was versucht, doch da müssten ja immer die gleichen Trennzeichen vorhanden sein und gleiche Datenlänge, nicht? So habe ich das mal verstanden. Bei mir ist die Datenlänge nicht immer gleich und die Trennzeichen wie oben erwähnt...

Also war deine Definition nicht korrekt/unvollständig!

im ersten Teil aus values (HEX) mit Leerzeichen getrennt Hier fehlt die Anzahl! Ist die immer gleich?

im zweiten Teil aus Bezeichner und value mit Komme getrennt. Bezeichner immer Einbuchstabig? Immer die gleiche Anzahl Paarungen?

Bitte.. Die Definition muss eineindeutig sein.

Mit jammern hat das wohl wenig zu tun....

Wer will, findet Wege. Wer nicht will, findet Gründe.

Und diese Gründe kommen wie Jammern bei mir an.

Hallo,
“(fertige Alternativen interessieren dich nicht, oder?)”

Der hat sich an seinem Sketch festgebissen wie ein Terrier am Schienbein…

Bei der seriellen Kommunikation mit dem Arduino sind schon ganz andere untergegangen. Da sollte (muss) man (auch Frau)
bei Null anfangen.

“Wörter habe ich ja versucht, funktioniet aber nicht.”
An diesem und anderem kann man dann sehen das hier nur probiert wird, was denn schon alles sagt.

Ich will hier ja nicht meckern, aber Stef- so läuft das nicht.
Was ist denn hiermit?
Das könnte vielleicht etwas hilfreich sein.
Tommy knallt Dir hier einen für die vollen rein, damit kommst Du nicht klar. combie läßt hier den AnfängerKurs raus, und den
plappers Du nur nach. Du scheinst zu wissen, was Du willst, hast aber keine Ahnung und noch viel weniger Konzept für Deinen Sketch.
Ich kann Dir nur raten da von vorne anzufangen.
Einen schönen Tag, noch!
Gruß und Spaß
Andreas
Ich habe da auch geblutet, weiß also tatsächlich mal wovon ich rede.

Erster Teil: Anzahl HEX Werte? Alle ein HEX Wert ausser einer wäre aus zwei HEX bestehend, habe ich hier aber mal weggelassen.

Zweiter Teil: Bezeichner immer Einbuchstabig, war mal so angedacht ja. Wie schon gesagt, wegen der Switch/Case anweisung geht ja nur Einbuchstabig... Nein, es kann sowohl nur eine Paarung kommen, es können aber auch sieben Paarungen kommen die dann eingeordnet werden sollen.