Werte von Variablen verschieben sich

Hi, ich verscuhe jetzt schon seit einigen Tagen ein wahrscheinlich recht einfaches Problem zu lösen. Und zwar will ich mit einem HC12 Funkmodul Werte von einem Arduino zu einem anderen senden um von dort aus zu einem Nextion Display Befehle zu senden. Es funktioniert auch einwandfrei (so scheint es zumindest). Nach ungefähr 5 Minuten verschieben sich jedoch die Werte irgendwie und der Wert von w1 ist nicht mehr der Wert von w1 sondern von w5. Ebenso bei allen anderen Variablen. Hat hier jemand einen Lösungsvorschlag? Anbei der Code für Sender (Code2.4_4 Nano_copy....) und Empfänger (HC12 Empfänger nano2).

SENDER CODE:

#include <SoftwareSerial.h>
#include <Wire.h>
SoftwareSerial HC12(10,11);
//SoftwareSerial nextion(11,12);

long unsigned int start;
long unsigned int intervall=400;

int w1=2;
int w2=3;
int w3=4;
int w4=5;
int w5=6;
int w6=7;
int w7=8;

int x1;
int x2;
int x3;
int x4;
int x5;
int x6;
int x7;

void setup() {
  Serial.begin(115200);
  Serial.println("Let's start!");
  HC12.begin(2400);
  pinMode(2, INPUT);
  pinMode(3, INPUT);
  pinMode(4, INPUT);
  pinMode(5, INPUT);
  pinMode(6, INPUT);
  pinMode(7, INPUT);
  pinMode(8, INPUT);

  int w1;
  int w2;
  int w3;
  int w4;
  int w5;
  int w6;
  int w7;
}

void loop() 
{
  String requestString = "";
  if (HC12.available()) 
  {
    requestString = HC12.readString();
    Serial.println(requestString);    
  }
    String dataString = "";
    createDataString(dataString);
    //Serial.println(dataString);
    HC12.print(dataString);

    Serial.println(x1);
    Serial.println(x2);
    Serial.println(x3);
    Serial.println(x4);
    Serial.println(x5);
    Serial.println(x6);
    Serial.println(x7);
}

void createDataString(String &data)
{  
  w1=digitalRead(2);
  w2=digitalRead(3);
  w3=digitalRead(4);
  w4=digitalRead(5);
  w5=digitalRead(6);
  w6=digitalRead(7);
  w7=digitalRead(8);

    //PUNT A
  if(w1==LOW)
  {
    x1=0;
  }
  if(w1==HIGH)
  {
    x1=1;
  }

  //PUNKT B
  if(w2==LOW)
  {
    x2=0;
  }
  if(w2==HIGH)
  {
    x2=1;
  }

  //MODUS
  if(w3==LOW)
  {
    x3=0;
  }
  if(w3==HIGH)
  {
    x3=1;
  }

  //BREMSE
  if(w4==LOW)
  {
    x4=0;
  }
  if(w4==HIGH)
  {
    x4=1;
  }

  //RICHTUNG 1
  if(w5==LOW)
  {
    x5=0;
  }
  if(w5==HIGH)
  {
    x5=1;
  }

  //RICHTUNG 2
  if(w6==LOW)
  {
    x6=0;
  }
  if(w6==HIGH)
  {
    x6=1;
  }

  //SIGNAL
  if(w7==LOW)
  {
    x7=1;
  }
  if(w7==HIGH)
  {
    x7=0;
  }
 
if(millis()-start >= 400)
{
data = "*" + String(x1) + "*" + String(x2) + "*" + String(x3) + "*" + String(x4) + "*" + String(x5) + "*" + String(x6) + "*" + String(x7); 
//delay(200);
Serial.println("");

start = millis();
}
}

EMPFÄNGER CODE:

#include <SoftwareSerial.h>
#include <Wire.h>

long unsigned int start;
long unsigned int intervall=400;

SoftwareSerial HC12(10,11);

void setup() 
{
  //pinMode(requestPin, INPUT);
  Serial.begin(115200);
  HC12.begin(2400);

  Serial.println("Let's start!");
}

void loop() 
{
  int w1 ;
  int w2 ;
  int w3 ;
  int w4 ;
  int w5 ;
  int w6 ;
  int w7 ;

if (HC12.available())
  {
    w1 = HC12.parseInt();
    w2 = HC12.parseInt();
    w3 = HC12.parseInt();
    w4 = HC12.parseInt();
    w5 = HC12.parseInt();
    w6 = HC12.parseInt();
    w7 = HC12.parseInt();

/*
    Serial.print("Wert 1: ");
    Serial.println(w1);
    Serial.print("Wert 2: ");
    Serial.println(w2);
    Serial.print("Wert 3: ");
    Serial.println(w3);  
    Serial.print("Wert 4: ");
    Serial.println(w4);
    Serial.print("Wert 5: ");
    Serial.println(w5);  
    Serial.print("Wert 6: ");
    Serial.println(w6);
    Serial.print("Wert 7: ");
    Serial.println(w7);  
    Serial.println("");
*/
  }

  else
  {
    Serial.write(0xFF);
    Serial.write(0xFF);
    Serial.write(0xFF);
    Serial.print("tDirection.tx= \"NIX\" ");
    Serial.write(0xFF);
    Serial.write(0xFF);
    Serial.write(0xFF); 
  }

  String cmd;
cmd += "\"";

//PUNKT A SETZEN
if(w1 ==1)
{
Serial.write(0xFF);
Serial.write(0xFF);
Serial.write(0xFF);
Serial.print("tPA.bco=0");
Serial.write(0xFF);
Serial.write(0xFF);
Serial.write(0xFF);
}
if(w1 ==0)
{
Serial.write(0xFF);
Serial.write(0xFF);
Serial.write(0xFF);
Serial.print("tPA.bco=63488");
Serial.write(0xFF);
Serial.write(0xFF);
Serial.write(0xFF);
}

//PUNKT B SETZEN
if(w2 ==1)
{
Serial.write(0xFF);
Serial.write(0xFF);
Serial.write(0xFF);
Serial.print("tPB.bco=0");
Serial.write(0xFF);
Serial.write(0xFF);
Serial.write(0xFF);
}
if(w2 ==0)
{
Serial.write(0xFF);
Serial.write(0xFF);
Serial.write(0xFF);
Serial.print("tPB.bco=63488");
Serial.write(0xFF);
Serial.write(0xFF);
Serial.write(0xFF);
}

//MODUS SETZEN
if(w3 ==0)
{
Serial.write(0xFF);
Serial.write(0xFF);
Serial.write(0xFF);
Serial.print("pb_Mode.pic=7");
Serial.write(0xFF);
Serial.write(0xFF);
Serial.write(0xFF);
}
if(w3 ==1)
{
Serial.write(0xFF);
Serial.write(0xFF);
Serial.write(0xFF);
Serial.print("pb_Mode.pic=11");
Serial.write(0xFF);
Serial.write(0xFF);
Serial.write(0xFF);
}

//BREMSE SETZEN
if(w4 ==0)
{
Serial.write(0xFF);
Serial.write(0xFF);
Serial.write(0xFF);
Serial.print("pb_Brake.pic=10");
Serial.write(0xFF);
Serial.write(0xFF);
Serial.write(0xFF);
}
if(w4 ==1)
{
Serial.write(0xFF);
Serial.write(0xFF);
Serial.write(0xFF);
Serial.print("pb_Brake.pic=3");
Serial.write(0xFF);
Serial.write(0xFF);
Serial.write(0xFF);
}

//Richtung 1
if(w5&w6 ==0)
{
Serial.write(0xFF);
Serial.write(0xFF);
Serial.write(0xFF);
Serial.print("tDirection.tx= \"NIX\" ");
Serial.write(0xFF);
Serial.write(0xFF);
Serial.write(0xFF);
}
if(w5 ==1)
{
Serial.write(0xFF);
Serial.write(0xFF);
Serial.write(0xFF);
Serial.print("t3.txt=1");
Serial.write(0xFF);
Serial.write(0xFF);
Serial.write(0xFF);
}

//RICHTUNG 2
if(w6 ==1)
{
Serial.write(0xFF);
Serial.write(0xFF);
Serial.write(0xFF);
Serial.print("tDirection.txt= \"2\ ");
Serial.write(0xFF);
Serial.write(0xFF);
Serial.write(0xFF);
}

//SIGNAL
if(w7 ==1)
{
Serial.write(0xFF);
Serial.write(0xFF);
Serial.write(0xFF);
//SIGNAL HIER
Serial.print("tDirection.txt= \"2\ ");
Serial.write(0xFF);
Serial.write(0xFF);
Serial.write(0xFF);
}
if(w7 ==0)
{
Serial.write(0xFF);
Serial.write(0xFF);
Serial.write(0xFF);
//KEIN SIGNAL HIER
Serial.print("tDirection.txt= \"2\ ");
Serial.write(0xFF);
Serial.write(0xFF);
Serial.write(0xFF);
}

/*
Serial.write(0xFF);
Serial.write(0xFF);
Serial.write(0xFF);
Serial.print("pb_Mode.pic=\" " +  String(w3) + "\"");
Serial.write(0xFF);
Serial.write(0xFF);
Serial.write(0xFF);
Serial.print("tPA.bco=" + cmd + String(w5) + cmd);
Serial.write(0xFF);
Serial.write(0xFF);
Serial.write(0xFF);
Serial.print("tPB.bco=" + cmd + String(w6) + cmd);
Serial.write(0xFF);
Serial.write(0xFF);
Serial.write(0xFF);
Serial.print("vb_Standort.val=" + cmd + String(w7) + cmd);
Serial.write(0xFF);
Serial.write(0xFF);
Serial.write(0xFF);
Serial.println("");
*/
  delay(100);
}

Mit den vielen unnötigen Leerzeilen ist der Code im Forum schlecht lesbar. Bitte entferne diese. Warum deklarierst Du die ganzen int am Ende vom setup?

Gruß Tommy

Ich sehe kein Protokoll!

Somit auch keinen Schutz gegen "Verschiebungen" oder sonstige Fehler.

jetzt sollte es besser zum lesen gehen. Du hast recht, macht nicht viel Sinn die int nochmal zu deklarieren.

Wie genau würde dieses Aussehen? Kenn mich leider beim Programmieren nicht all zu gut aus, bin noch relativ neu.

Mache dir keine Sorgen, das habe ich auch ohne deine Ansage ganz klar erkannt!

So dass der Daten Transport gesichert ist!
(und nicht wie bei dir die Synchronisierung verliert)
Das "OSI Schichtenmodell" könntest du dir ansehen, da wird erklärt worum es sich dreht.

Hier ist mal ein recht schlankes Protokoll implementiert, vielleicht kannste dir da ja was von abschauen.

Hallo @stevewib,

neben der fehlenden Synchronisierung Deiner Nutzdaten gibt es noch mindestens ein weiteres Problem Deines Sendeprogramms: Wenn ich mich nicht sehr täusche, wird die SoftSerial-Schnittstelle im aktuellen Sketch blitzschnell in den Überlauf gebracht ...

Wenn ich Deinen Sketch im Wokwi-Online-Simulator auf einem Arduino Uno starte, durchläuft der Sketch die Loop() über 200 mal pro Sekunde. Jedesmal wird dabei dataString über HC12 (SoftSerial) ausgegeben.

  • dataString besteht aus 14 Zeichen (7 Nullen bzw. Einsen und 7 Asterisk)
  • HC12 kann maximal 2400 /10 = 240 Zeichen pro Sekunde "loswerden"
  • HC12 verfügt standardmässig über einen Puffer von 64 Byte
  • 200 x 14 Zeichen/Sekunde = 2800 Zeichen

Es werden also mit dem Code aus Post #1 mehr als 10mal so viele Daten gesendet, als die Schnittstelle übertragen kann.

Interessanterweise ändert sich der Sendeinhalt jedoch nur alle 400 ms. Siehe

if(millis()-start >= 400)

in createDataString().

Würde nur der aktuelle String gesendet, wären es zwei bis drei Übertragungen pro Sekunde, und damit kein Überlaufproblem. Dies ließe sich am schnellsten lösen, indem die Zeile

HC12.print(dataString);

aus der loop() in die Funktion createDataString() hinter die Zeile data = ... verschoben wird:

if(millis()-start >= 400)
{
data = "*" + String(x1) + "*" + String(x2) + "*" + String(x3) + "*" + String(x4) + "*" + String(x5) + "*" + String(x6) + "*" + String(x7); 
//delay(200);
 HC12.print(dataString);
Serial.println("");

start = millis();
}

Damit sollte das Problem verscheucht, die fehlende Synchronisation aber nicht gelöst sein.

Eine einfache Lösung zur Synchronisation besteht darin, jeden Transfer von dataString mit einem chr(13) abzuschließen. Das Empfangsprogramm kann dann solange Daten sammeln, bis ein chr(13) gelesen wird. Der bis dahin empfangene String muss 14 Zeichen beinhalten, sonst fehlt etwas und der Eingangsstring wird verworfen (ggf. plus Fehlermeldung).

Insgesamt könnte man die Übertragung von letztlich 7 Bit Information anstatt mit 14 Zeichen natürlich wesentlich "schlanker" umsetzen.

Wenn Du bei dem jetzigen Verfahren bleiben willst, könntest Du anstatt der "*" ein signifikantes Zeichen vor der jeweiligen Null/Eins verwenden:

Anstatt *0*0*0*1*0*0*0 schreibe A0B0C0D1E0F0G0

So lässt sich prüfen, ob der String der erwarteten Syntax entspricht.

Aus den Werten der einzelnen Daten könnte man zusätzlich auch noch einen oder mehrere Prüfcharakter erzeugen und mit übertragen. Eine lesbare Form wäre beispielsweise, die zusätzliche (aber eigentlich schon mehr als ausreichende) hexadezimale Übertragung der Daten einzuführen. Dazu einfach die Daten vorne um eine Null erweitern, so dass aus

000 1111 

ein

0000 1111  -> $0F

wird. Dann die Zeichen 0F am Ende des Strings mit übertragen.

Hier ein bzgl. der Sendehäufigkeit (und etwas bzgl. der Übersichtlichkeit) veränderter Sketch zum Ausprobieren (ohne Synchronisation, das überlasse ich Dir; Du musst dann ja auch das Empfangsprogramm entsprechend ändern):

#include <SoftwareSerial.h>
#include <Wire.h>
SoftwareSerial HC12(10, 11);
//SoftwareSerial nextion(11,12);

long unsigned int start     = 0;
long unsigned int intervall = 400;

int x1;
int x2;
int x3;
int x4;
int x5;
int x6;
int x7;

void setup() {
  Serial.begin(115200);
  Serial.println("Let's start!");
  HC12.begin(2400);
  pinMode(2, INPUT);
  pinMode(3, INPUT);
  pinMode(4, INPUT);
  pinMode(5, INPUT);
  pinMode(6, INPUT);
  pinMode(7, INPUT);
  pinMode(8, INPUT);
}

String requestString = "";
String dataString = "";
 
void loop()
{
   if (HC12.available())
  {
    requestString = HC12.readString();
    Serial.println(requestString);
  }
  

 if (millis() - start >= intervall)
  {
    createDataString(dataString);
    HC12.print(dataString);
    Serial.println(dataString);
    start = millis();
  }
}

void createDataString(String &data)
{
  //PUNKT A
  x1 = (digitalRead(2)) ? 1 : 0;
  //PUNKT B
  x2 = (digitalRead(3)) ? 1 : 0;
  //MODUS
  x3 = (digitalRead(4)) ? 1 : 0;
  //BREMSE
  x4 = (digitalRead(5)) ? 1 : 0;
  //RICHTUNG 1
  x5 = (digitalRead(6)) ? 1 : 0;
  //RICHTUNG 2
  x6 = (digitalRead(7)) ? 1 : 0;
  //SIGNAL
  x7 = (digitalRead(8)) ? 1 : 0;
  // Output String
  data = "*" + String(x1) + "*" + String(x2) + "*" + String(x3) + "*" + String(x4) + "*" + String(x5) + "*" + String(x6) + "*" + String(x7);
  String HexData = String((x1 << 6) +(x2 << 5) + (x3 << 4) + (x4 << 3) + (x5 << 2) +(x6 << 1) + x7, HEX);
  Serial.print("Hex = ");
  Serial.println(HexData);
}

Ich danke dir Vielmals!!!! Habe es jetzt seit über einer halben Stunde am laufen und es funktioniert! Vielen Dank

Freut mich!

Aber so wie im Post #9, also nur zeitlich entzerrt, ohne weitere Absicherung der Übertragung, korrekt?

Ich würde im Minimum entweder jede Übertragung mit einem CR ( char(13) ) abschließen oder das erste Sternchen durch z.B. Hashtag # ersetzen. Dann kann man auf Empfängerseite mit einfachen Mitteln auch wieder aufsynchronisieren, wenn es mal ein kurzfristiges Übertragungsproblem gab.

Eigentlich genügt es, den String, der im Sketch als "HexData" deklariert ist, mit ggf. einem $-Zeichen davor zu senden ... Bedingt nur, dass man ihn auf der Empfangsseite wieder in die binären Zustände der digitalen Inputs rückübersetzt; das ist aber keine besonders schwierige Aufgabe.

Gruß

ec2021

P.S.: Ansonsten kannst Du den Thread auch gerne als "Gelöst" markieren ...

hab jetzt nur die Zeile verändert an dem die Werte mit HC12.print an den HC12 gesendet werden. das mit den Absichern muss ich erst noch machen aber es funktioniert.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.