Serial eine einfache Fehler Überprüfung

Hallo

Wie kann ich bei einer seriell Verbindung zwischen 2 Arduinos eine Art Fehler Behandlung oder Testung der daten umsetzten ?

Zur Zeit übertrage ich meine daten so:

Nur ein zwanziger ausschnitt Verwendet werden A-Y und a-y ( zahlen haben zu großen Fehleranteil beim auslesen.

Sender: Mega2560

 Sender++;
(mache was -- 1 bis 2 Sek. später) 

 if (Sender ==0) {
    Serial3.println("A");
    delay(10);
    Serial3.println(Wert1);( werte liegen zw 2900-3600 o. Komma / Wird als String gesendet)
  }
  if (Sender == 1) {
    Serial3.println("B");
    delay(10);
    Serial3.println(Wert2);
  }
und so weiter dann gibt es aber noch eine Übertragung OHNE werte.
Zb so hier:  

if (Sender == 2) {
    Serial3.println("C"); // Mache licht xyz an..
  }

Werte werden alle 1-2 Sekunden gesendet.

Empfänger Due

if (Serial3.available())
  {
    S3 = Serial3.read();
    Serial.print(S3);
    if (S3 == 'A") 
    {
      {
     Wert1 = Serial3.readString();
      Wert1F = Wert1.toFloat();
      if ((Wert1F < 3700) && (Wert1F > 2500))
      {
        if (Wert1F > Wert1maxi)
        {
          Wert1maxi = Wert1F;
        }
        if (Wert1F < Wert1mini)
        {
          Wert1mini = Wert1F;
        }
      }
      S3 = Z;
    }

    if (S3 == 'B') //
    {
      {
     Wert2 = Serial3.readString();
      Wert2F = Wert2.toFloat();
      if ((Wert2F < 3700) && (Wert2F > 2500))
      {
        if (Wert2F > Wert2maxi)
        {
          Wert2maxi = Wert2F;
        }
        if (Wert2F < Wert2mini)
        {
          Wert2mini = Wert2F;
        }
      }
      S3 = Z;
    }
if (S3 == 'C') //
    {
     Mache licht xyz an.     
      S3 = Z;
    }

und so weiter halt.

Das geht so weit auch ganz gut.
Aber es Passieren immer wieder mal übertragungsfehler.
Die kommen ganz spontan wo dann Falsche "Daten" ankommen und Anstelle eines A zb C ausgelöst wird. wo dann zb Kein wert gespeichert wird sondern ein Licht an geht.

mit if ((Zelle1F < 3700) && (Zelle1F > 2000)) stelle ich zumindest schon mal sicher das der wert 4 zahlen hat ehe eine weiter Verarbeitung kommt.

Aber das gelbe vom ei ist es noch nicht.
Da die Zuordnung von S3 scheinbar nicht immer sauber läuft.

Jemand eine Idee wie man das EINFACH/Verbessert umsetzten könnte ?

Vielen lieben dank:

  1. delay entfernen
  2. Checksumme einfügen
  3. Rückantwort ob Übertragung erfolgreich und ggf Wiederholung

Ehm danke
Aber geht das GENAUER ?

Das delay ist nötig damit klar ist das die Übertragung von teil 1 (A) Fertig ist,

Das ist schon einer der größten Fehler.

Sende doch z.B. folgendes
<STX>A1234<ETX>

Deine Empfangsfunktion ließt jetzt so lange Bytes, bis sie <STX> findet.
Dann ließt sie EIN Zeichen --> abspeichern
Dann ließt sie 4 Zeichen --> abspeichern
Dann ließt sie EIN Zeichen, wenn dies nicht <ETX> ist, ist es ein Übertragungsfehler und alles wird verworfen

Und das geht ohne jedes delay.

Und ich hoffe, du hast

das nicht 20 mal kopiert

Vor allem sollte er es mal ordentlich formatieren.

Gruß Tommy

Danke euch für euere Hilfe Stellung leider verstehe ich es noch nicht.
Wäre es möglich das für einen Totalen Anfänger mal mit Code Beispielen zu erklären ?

So weit wie ich das verstanden habe gibt ETX ( wie auch immer das verwendet wird) nur an das die Übertragung zu ende ist ? Das tut ln doch aber auch oder liege ich da falsch?

Und nein natürlich nicht sind mehr wie 20 glaube 26 stück welche auf diese weise zz getrennt übertragen werden.

Ja, zeige bitte einmal deinen kompletten Code (in Code Tags).

Dann kann man den Stück für Stück verbessern.

Der ist doch ein 3.3V System, durch direkte Verbindung mit Mega machst du die Pins kaputt.

"Warning: Unlike most Arduino boards, the Arduino Due board runs at 3.3V. The maximum voltage that the I/O pins can tolerate is 3.3V. Applying voltages higher than 3.3V to any I/O pin could damage the board."

Empfänger
 if (Serial3.available())
  {
    S3 = Serial3.read();
    Serial.print(S3);
    if (S3 == 'g') //
    {
      result2 = node2.writeSingleCoil(0x0002, 0); 
      Reglerausgang1H = (0);
      USBLADEZEIT1 = 2147483600;
      S3 = Z;
    }
    if (S3 == 'a') //USB 1H Einschalten 1
    {
      result2 = node2.writeSingleCoil(0x0002, 1);
      Reglerausgang1H = 1;
      USBLADEZEIT1 = millis() + 3600000;
      S3 = Z;
    }
    if (S3 == 'b')
    {
      if (t2 == true) {
        Pin2ON = true;
        digitalWrite(40, HIGH);
        BWMELDERabfrage = (0);
        t2 = false;
        S3 = Z;
      }
    }
    if (S3 == 'b')
    {
      if (t2 == false)    {
        Pin2ON = false;
        BWMELDERabfrage = (1);
        digitalWrite(40, LOW);
        t2 = true;
        S3 = Z;
      }
    }
    if (S3 == 'g') 
    {
      if (t3 == true)
      {
        result = node.writeSingleCoil(0x0002, 1); 
        Reglerausgang20 = 1;
        t3 = false;
        S3 = Z;
      }
    }
    if (S3 == 'g') 
    {
      if (t3 == false)
      {
        result = node.writeSingleCoil(0x0002, 0); 
        Reglerausgang20 = 0;
        t3 = true;
        S3 = Z;
      }
    }
    if (S3 == 'h') //Türzeitreset  4
    {
      Tuerzeitvt = (0);
      TueraufVZS0 = (0); //Stunden Tür
      TueraufVZM0 = (0); // Minuten
      TueraufVZS1 = (0); //Stunden
      TueraufVZM1 = (0); // Minuten
      TueraufVZS2 = (0); //Stunden
      TueraufVZM2 = (0); // Minuten
      TueraufVZS3 = (0); //Stunden
      TueraufVZM3 = (0); // Minuten
      TueraufVZS4 = (0); //Stunden
      TueraufVZM4 = (0); // Minuten
      TueraufVZS5 = (0); //Stunden
      TueraufVZM5 = (0); // Minuten
      TueraufVZS6 = (0); //Stunden
      TueraufVZM6 = (0); // Minuten
      S3 = Z;
    }
    if (S3 == 'i') //5
    {
      S3 = Z;
    }
    if (S3 == 'j') //6
    {
      S3 = Z;
    }
    if (S3 == 'k')
    {
      if (t7 == false)    {
        Pin7ON = true;
        digitalWrite(A5, LOW);
        digitalWrite(A4, HIGH); 
        t7 = true;
        S3 = Z;
      }
    }
    if (S3 == 'k')
    {
      if (t7 == true)    {
        Pin7ON = false;
        digitalWrite(A4, LOW); 
        delay(1000);
        digitalWrite(A5, HIGH);
        t7 = false;
        S3 = Z;
      }
    }
    if (S3 == 'l') //8
    {
      S3 = Z;
    }
    if (S3 == 'm') 
    {
      if (t9 == true) {
        Pin9ON = true;
        LZMAUSIRADIO = millis() + 4500000; 
        digitalWrite(39, HIGH);
        S3 = Z;
      }
    }
    if (S3 == 'm') 
    {
      if (t9 == false) {
        Pin9ON = false;
        digitalWrite(39, LOW);
        LZMAUSIRADIO = 2147483600;
        S3 = Z;
      }
    }
    if (S3 == 'a') //Aus
    {
      zahlLEDwahl = 5;
      LEDON = false;
      LEDSAUS ();
      S3 = Z;
    }
    if (S3 == 'b') //Blau
    {
      LEDSAUS ();
      LEDON = true;
      colorWipe2(strip.Color(0, 0, 250), 250);
      S3 = Z;
    }
    if (S3 == 'c') //Rot
    {
      LEDSAUS ();
      LEDON = true;
      colorWipe2(strip.Color(250, 0, 0), 250);
      S3 = Z;
    }
    if (S3 == 'd') //Weis
    {
      LEDSAUS ();
      LEDON = true;
      colorWipe2(strip.Color(250, 250, 250), 250);
      S3 = Z;
    }
    if (S3 == 'E') //zellspannung1
    {
      Zelle1 = Serial3.readString();
      Zelle1F = Zelle1.toFloat();
      if ((Zelle1F < 3700) && (Zelle1F > 2000))
      {
        if (Zelle1F > Zelle1maxi)
        {
          Zelle1maxi = Zelle1F;
        }
        if (Zelle1F < Zelle1mini)
        {
          Zelle1mini = Zelle1F;
        }
      }
      S3 = Z;
    }
    if (S3 == 'F') //zellspannung2
    {
      Zelle2 = Serial3.readString();
      Zelle2F = Zelle2.toFloat();
      if ((Zelle2F < 3700) && (Zelle2F > 2000))
      {
        if (Zelle2F > Zelle2maxi)
        {
          Zelle2maxi = Zelle2F;
        }
        if (Zelle2F < Zelle2mini)
        {
          Zelle2mini = Zelle2F;
        }
      }
      S3 = Z;
    }
    if (S3 == 'Y') //zellspannung3
    {
      Zelle3 = Serial3.readString();
      Zelle3F = Zelle3.toFloat();
      if ((Zelle3F < 3700) && (Zelle3F > 2000))
      {
        if (Zelle3F > Zelle3maxi)
        {
          Zelle3maxi = Zelle3F;
        }
        if (Zelle3F < Zelle3mini)
        {
          Zelle3mini = Zelle3F;
        }
      }
      S3 = Z;
    }
    if (S3 == 'H') //zellspannung4
    {
      Zelle4 = Serial3.readString();
      Zelle4F = Zelle4.toFloat();
      if ((Zelle4F < 3700) && (Zelle4F > 2000))
      {
        if (Zelle4F > Zelle4maxi)
        {
          Zelle4maxi = Zelle4F;
        }
        if (Zelle4F < Zelle4mini)
        {
          Zelle4mini = Zelle4F;
        }
      }
      S3 = Z;
    }
    if (S3 == 'I') //zellspannung5
    {
      Zelle5 = Serial3.readString();
      Zelle5F = Zelle5.toFloat();
      if ((Zelle5F < 3700) && (Zelle5F > 2000))
      {
        if (Zelle5F > Zelle5maxi)
        {
          Zelle5maxi = Zelle5F;
        }
        if (Zelle5F < Zelle5mini)
        {
          Zelle5mini = Zelle5F;
        }
      }
      S3 = Z;
    }
    if (S3 == 'J') //zellspannung6
    {
      Zelle6 = Serial3.readString();
      Zelle6F = Zelle6.toFloat();
      if ((Zelle6F < 3700) && (Zelle6F > 2000))
      {
        if (Zelle6F > Zelle6maxi)
        {
          Zelle6maxi = Zelle6F;
        }
        if (Zelle6F < Zelle6mini)
        {
          Zelle6mini = Zelle6F;
        }
      }
      S3 = Z;
    }
    if (S3 == 'K') //zellspannung7
    {
      Zelle7 = Serial3.readString();
      Zelle7F = Zelle7.toFloat();
      if ((Zelle7F < 3700) && (Zelle7F > 2000))
      {
        if (Zelle7F > Zelle7maxi)
        {
          Zelle7maxi = Zelle7F;
        }
        if (Zelle7F < Zelle7mini)
        {
          Zelle7mini = Zelle7F;
        }
      }
      S3 = Z;
    }
    if (S3 == 'L') //zellspannung8
    {
      Zelle8 = Serial3.readString();
      Zelle8F = Zelle8.toFloat();
      if ((Zelle8F < 3700) && (Zelle8F > 2000))
      {
        if (Zelle8F > Zelle8maxi)
        {
          Zelle8maxi = Zelle8F;
        }
        if (Zelle8F < Zelle8mini)
        {
          Zelle8mini = Zelle8F;
        }
      }
      S3 = Z;
    }

    if (S3 == 'M') //zellemini
    {
      zellemini = Serial3.readString();
      S3 = Z;
    }
    if (S3 == 'N') //zellemaxi
    {
      zellemaxi = Serial3.readString();
      S3 = Z;
    }
    if (S3 == 'O') //AHREST
    {
      AHREST = Serial3.readString();
      S3 = Z;
    }
    if (S3 == 'U') //BMSVolt
    {
      BMSVolt = Serial3.readString();
      S3 = Z;
    }
    if (S3 == 'Q') //Batteriestrom
    {
      Batteriestrom = Serial3.readString();
      BatteriestromF = Batteriestrom.toFloat();
      S3 = Z;
    }
    if (S3 == 'R') //SOC
    {
      SOC = Serial3.readString();
      SOCF = SOC.toFloat();
      S3 = Z;
    }
    if (S3 == 'S') //bmsCycles
    {
      bmsCycles = Serial3.readString();
      BMSF = bmsCycles.toFloat();
      S3 = Z;
    }
    if (S3 == 'T') //Entlademosfet
    {
      Entlademosfet = Serial3.read();
      S3 = Z;
    }
    if (S3 == 'X') //lademosfet
    {
      lademosfet = Serial3.read();
      S3 = Z;
    }


    if (S3 == 'n') 
    {
      PinAON = false;
      digitalWrite(35, LOW);
      S3 = Z;
    }
    if (S3 == 'o') /
    {
      zahlLEDwahl = 0;
      while (P < 209)
      {
        P++;
        pixelHue = firstPixelHue + (P * 65536L / strip.numPixels());
        strip.setPixelColor(P, strip.gamma32(strip.ColorHSV(pixelHue)));
        strip.show();
      }
      P = 0;
      S3 = Z;
    }
  }

Sender
V3_2displays.ino (13.4 KB)

Hallo Und vielen dank.

Also zuerst mal ich bin mir der 3,3v zu 5 Volt Problematik bewusst und setzte da auf solche "Pegelwandler I2C 5V-3.3V Level Shifter" Teile welche so vermute ich auch das Problem sind.
Den bei reinen 3,3 zu 3,3 Volt Übertragungen welche zb zum PC gesendet werden, läuft seit Monaten alles Fehler frei ab.

So wie ich die kenne sind die nicht geeignet für Serial.

es gibt so habe ich rausgefunden 2 Versionen von den Platinen.
A ist direkt mit RX und TX gekennzeichnet. = geht bei mir gar nicht.
B sind unbeschriftet und haben einen leicht andern Aufbau laufen aber.

Hier ist einmal eine Simulation für eine Übertragung ohne delay.

Die Übertragung muss mit einem $ beginnen, dann eine SteuerCode A---Z und dann ein Wert 0..9. Als letztes ein /

Also z.B. $A1/.

Wenn der Wert mehr Stellen haben soll, muss case 2 erweitert werden.

In case 3 könnte dann eine Auswertefunktion aufgerufen werden, wenn die Nachricht gültig ist.

So kenne ich die auch

  1. 4 Transistor (MOSFET),
  2. Mit IC drauf.
    Kenne jedoch keine was hat auf dem Modul RX, TX Bezeichnung,
 Taste = Tastenfeld.getKey();  {
    if (Taste == 'A')
    {
      Serial3.println("a");
      tft2.fillScreen(BLACK);
      tft2.setTextColor(WHITE);
      tft2.setCursor(50, 0);
      tft2.print("A");
      delay(1000);
      Taste = 'p';
    }
    if (Taste == 'B')
    {
      Serial3.println("b");
      tft2.fillScreen(BLACK);
      tft2.setTextColor(WHITE);
      tft2.setCursor(50, 0);
      tft2.print("B");
      delay(1000);
      Taste = 'p';
    }
    if (Taste == 'C')
    {
      Serial3.println("c");
      tft2.fillScreen(BLACK);
      tft2.setTextColor(WHITE);

Ändere das doch mal in

    Taste = 'p';
    Taste = Tastenfeld.getKey();  
	switch (Taste){
	  case 'A':
	    Serial3.println("a");
        tft2.fillScreen(BLACK);
        tft2.setTextColor(WHITE);
        tft2.setCursor(50, 0);
        tft2.print("A");
		break;
	  case 'B':
	    Serial3.println("b");
        tft2.fillScreen(BLACK);
        tft2.setTextColor(WHITE);
        tft2.setCursor(50, 0);
        tft2.print("B");
		break;
      case 'B':
usw	.................................  
	} 

Du solltest dir einmal array und for Schleife ansehen. Damit kann man ganz viel Copy und Paste sparen.

Ok ja Sieht effizienter aus dem kann ich noch folgen.
break springt dann zu loop zurück nehme ich mal an?

Werde ich mal anpassen.

Danke wwerner für dein Empfänger Code. Teste ich morgen mal.

Aber eine frage hätte ich dazu noch, wie werden da Kommas (Ja punkte ich weis) behandelt also zb 1234,00 oder 1,00 ?

In meinem Beispiel noch gar nicht. Da wären es fehlerhafte Zeichen. Das muss dann noch erweitert werden

Hier mal eine Version mit mehrstelligen Zahlen. Float fehlt noch, die Stelle ist aber markiert

d.h. es geht jetzt auch z.B. $W123/ als String.

Du willst wahrscheinlich noch $E12,4/ haben?

Erstmal vielen dank für deine mühe aber ich kann dir in deinem aktuellen Code nicht ganz folgen will aber verhindern das du dir Zuviel Arbeit machst.
Das wegen noch mal kurz das kern Problem.

Ich lese einen wie du sicher gesehen in teil 1 nur ein Eingabe fehlt aus.
Da reicht ein einfachen übertragen und wieder erkennen des Buchstabens aus ohne wert.

in Teil 2 Werden Spannungswerte und später noch Temperaturen übertragen.

Brauche also einen Erkennungswert ZB ein Buchstabe der sauber erkannt wird und dann den wert und eine Erkennung das der wert zuende ist.

Und natürlich muss jeder wert auch fehlerfrei wieder zugeordnet werden.

Was ich bis zu letzt so um setzte:
`
Tastenfeld:
Sender

if (Taste == 'A')
    {
      Serial3.println("a");
      Taste = 'p';
    }

Empfänger:

if (Serial3.available())  {
    S3 = Serial3.read(); 
    if (S3 == 'a') 
    {
     Licht an ....
      S3 = Z;
    }

Und beim wert so ;

Sender
Serial3.println("E"); Das ln sollte ja eigentlich schon der End Befehl sein. wird aber zeitweise nicht richtig erkannt
delay(10); ( Um sicher zugehen das E Sicher übertragen/abgeschlossen ist / ja ist zu viel schon klar)
Serial3.println(Wert1);

Empfänger;

if (S3 == 'E') //Wert1
    {
      Wert1 = Serial3.readString();  /Alles einlesen was angekommen ist / Daten erfolgen alle 1-2 sek.
      Wert1F = Wert1.toFloat(); // Umwandlung vom String in float um sie Testen und verarbeiten zu können
      if ((Wert1F < 3700) && (Wert1F > 2000)) // Liegen die werten zwischen diesen werten welche unrealistische maximal werte sind ist alles ok und wird verarbeitet ansonsten verworfen.
      {
        if Wert1F > Wert1maxi)
        {
          Wert1maxi = Wert1F;
        }
        if (Wert1F < Wert1mini)
        {
          Wert1mini = Wert1F;
        }
      }
      S3 = Z;
    }

Ich habe deine Verbesserungen jetzt noch nicht umgesetzt,
Weil A: ich erst noch dein code verstehen möchte ehe ich alle meine Projekte auf den "Neue Standard" umbaue.

Und B Ich noch vermute das es auf die Übertragung selber keinen Einfluss hat ob If oder Case verwendet wird.

Ich habe mich auch dran versucht die werte Paket weise zu versenden.
Also zb 4x Spannung zu einen String zusammen zusetzten aber den bekomme ich nicht wieder sauber getrennt zur Verarbeitung.

Und Fehler anfälliger sind längere Übertragungen auch denke ich als viele kleine.

Senden Tute ich also eigentlich nur Buchstaben für Tastenfelder.
Dann 4 stellige werte OHNE Komma.
Und 1-3 Stellig werte mit Komma welche aber von -100 bis + 200 beliebig sind so das man nicht auf die länge schlissen kann.