Go Down

Topic: serielle Daten kontrolliert zerlegen (Read 2268 times) previous topic - next topic

SkobyMobil

Hallo,
ich habe das mal mehr als 4Std. laufen lassen.
Sender ist ein Mega mit XBee, Empfänger ein Uno mit XBee.
Ich sende 3x9 verschiedene Werte, alle 20Sek 9 Werte.
Also 00-9 Werte, 20-9 andere Werte und 40-wieder 9 andere Werte.
Die int Werte liegen in einem Bereich von -60 bis 10858.

Die Werte werden in einer bestimmten Reihenfolge gesendet und in ein
EmpfangsArray geschrieben.
Der Index des Array ändert sich mit einem '\n'-Zähler. Er zählt also immer
von 0 bis 8. Da ich auch '\n'-Gesamt zähle, kann ich einfach mit Modulo
feststellen ob ein '\n' verloren gegangen ist. Ist Modulo nicht 0 zählt
ein Fehlerzähler einen hoch.

Weiter sind die Summen der Pakete bekannt, 4819, 23584 und 942.
Stimmt eine Summe nicht mit dem Vergleich, dann zählt ein Fehlerzähler
einen hoch.

In 4Std habe ich so 720 mal ein Paket von 9 Werten gesendet und empfangen.
Die Fehlerzähler stehen auf 0.
Real werde ich alle 15Min senden. Legt man nun die 720 zu Grunde, also
720 mal 15 min dann komme ich auf eine Fehlerfreie Übertragung von
7,5 Tagen. Ja, ja, alles Theorie.
Ich- halte das schon für verdammt gut…
Ohne eure Tips und Anregungen wäre ich bei weitem noch nicht so weit.
Also mal ein großes DANKE SCHÖN an euch!

So wie es jetzt läuft, werde ich es mal 24Std laufen lassen, mal sehen was die
Fehlerzähler dann bringen.

Hier habe ich nur 9 Werte übertragen, mal sehen wie es bei 48 Werten läuft.

"Woran kann der Empfänger die zwei Paket-Formate unterscheiden? Bei Text am '\n' Zeichen, aber im Binär-Fall ?"

Da haben wird uns wohl falsch verstanden. Die Pakete haben alle das gleiche
Format, nur ein Paket enthält 9 Werte, das andere 48 Werte.
Die 9 Werte werden automatisch gesendet, die 48 manuell- wenn Taster, dann…

Bei den 48 Werten werde ich einmal den Sketch von Whandall probieren.
Das scheine ich begriffen zu haben. Glaube ich…

"Beim großen Paket musst du auf jedenn Fall sicherstellen"
"Problem ist, dass wenn der Empfänger erstmal zu lesen angefangen hat"

Da muß ich mich bei den XBee´s mal schlaulesen, vielleicht können die da
etwas abnehmen.

Wenn ich jetzt auf das Display des Uno schaue, dann fällt mit vor Freude
"ein Ei aus der Hose"

Vor der seriellen Kommunikation habe ich einen riesen Bammel gehabt, aber Dank
eurer Hilfe habe ich vieles verfeinern und sicherer machne können…
Man muß sich da nur mal mit beschäftigen, dann begreift man das auch.
Ich melde mich bestimmt wieder.
Also nochmals, Danke schön.
Gruß und Spaß
Andreas

die zweite Maus bekommt den Speck...

Serenifly

#16
Apr 08, 2017, 08:04 pm Last Edit: Apr 08, 2017, 08:08 pm by Serenifly
Quote
Die int Werte liegen in einem Bereich von -60 bis 10858.
Wenn du Summierungs-Variante verwendest dann passe auch auf dass du das Vorzeichen abfragst und behandelst. Also abspeichern ob ein '-' da ist und wenn ja am Ende mit -1 multiplizieren

Wenn man erst mal einen String bis zum Komma einliest und dann mit atoi() konvertiert hat man das Problem nicht. Und kostet nur ein paar Byte für den Puffer.


Und ja, serielle Kommunikation ist recht trivial wenn man es gleich richtig macht. Da lagst du auch schon von Anfang an richtig mit Trennzeichen und Endzeichen. Statt irgendwelche Delays zu verwenden um zu warten dass alles da ist.
Es gibt auch mehrere Wege das zu lösen. Was am vernünftigsten ist hängt von der Anwendung ab. Strings sind nicht das effizienteste dabei, aber sehr flexibel, da man einfach die Auswertung ändern kann ohne den Einlese-Code zu ändern.

ElEspanol

Binärübertragung:
Habe es zwar auch noch nicht gemacht, aber mal drüber gelesen, dass man das Endezeichen mit byte stuffing machen kann. D.h., man legt ein Zeichen als Endezeichen fest, und, falls das Zeichen im Datenstrom vorkommt, wird es mit mit byte stuffing codiert. Ich glaube wenigstens, dass es so hieß, musst mal googeln

michael_x

Quote
Da haben wird uns wohl falsch verstanden. Die Pakete haben alle das gleiche Format, nur ein Paket enthält 9 Werte, das andere 48 Werte.
Ja, da haben wir uns wohl falsch verstanden: Das meinte ich mit "zwei verschiedene Formate"
Oder willst du jedesmal 48 Werte senden, wobei meist nur die ersten 9 interessieren ?

Bei Binär gibt es erstmal keine Sonderzeichen. Das '\n' ist eine dezimal-Zehn ( 0x0A ) und kann ohne weiteres das erste Byte eines int - Wertes sein. Das gleiche gilt für alle anderen übertragenen Werte.

Lösungen:
- Wie ElEspanol vorgeschlagen hat: einem Zeichen Sonderbedeutung geben ( "Achtung" ) und dann (mindestens) zwei Extras definieren: "Nachricht-Ende" und "Achtung als Datenbyte auffassen" (Eins der beiden kann natürlich das gleiche Zeichen wie <achtung> sein.

- Wie ich angedeutet habe: Länge als erstes voranschicken. Da wir max 48 Werte haben, reicht dafür ein Byte

- Sonderfall, hier möglich: nur Kennung vorausschicken: es kommt ein  Lang- oder Kurz-Paket.

- Warten, ob noch mehr kommt. Das findet nicht nur Serenifly nicht so gut. Aber was passiert im Fehlerfall? Ich kenne die xBees nicht gut genug: stellt diese Übertragung sicher, dass immer eine ganze Nachricht fehlerfrei ankommt?  Oder wird da nur jedes Byte einzeln gesichert?

Dass so etwas 4 Stunden fehlerfrei läuft, ist ja schonmal gut. ( Glückwunsch ;) )
Aber erst wenn Fehler passiert sind, kann man abschätzen, wie wahrscheinlich sie sind.
Was passiert, wenn Sender und Empfänger sehr weit auseinander sind?
Und wenn du dann mit einem passenden  (anderes XBee?) oder unpassendem Störsender dazwischenfunkst ?

Dass mal garnix kommt, lässt sich nicht verhindern.
Dass auch mal was falsches oder unvollständiges kommt, wäre die nächste Schwierigkeit.
Dass nach einem unvollständigen Paket sich alles aufhängt, sollte man jedenfalls versuchen in den Griff zu kriegen.
Bei Textübertragung kein Problem: Wenn was kommt, kommt irgendwann auch ein '\n'.
Bei Binär wäre ElEspanols Lösung  ( auf <Achtung><Ende> warten ), genauso gut.

Serenifly

#19
Apr 09, 2017, 12:25 pm Last Edit: Apr 09, 2017, 12:26 pm by Serenifly
- Wie ElEspanol vorgeschlagen hat: einem Zeichen Sonderbedeutung geben ( "Achtung" ) und dann (mindestens) zwei Extras definieren: "Nachricht-Ende" und "Achtung als Datenbyte auffassen" (Eins der beiden kann natürlich das gleiche Zeichen wie <achtung> sein.
Das ist nicht was vorgeschlagen wurde. Bei Byte Stuffing wird Null als Endzeichen genommen. Und wenn wenn im Datenstrom eine Null vorkommt wird es durch den Abstand zur nächsten Null ersetzt. Außerdem gibt das erste Byte die Position der ersten Null an. So weiß man immer wo Daten-Nullen sind.
Der Code dafür ist nicht ganz trivial, aber gibt es fertig.


Wenn alle Pakete immer die gleiche Länge haben braucht man das aber nicht. Dass mal ein Byte vollkommen verloren geht kommt eigentlich nicht vor. Vielleicht wenn die Gegenseite die Übertragung ganz abbricht. Aber das kann man mit Timeouts abfangen.

SkobyMobil

#20
Apr 09, 2017, 06:53 pm Last Edit: Apr 09, 2017, 06:58 pm by SkobyMobil
Hallo,
die Regeln sind:

-alle 15min 1mal, 9 Werte (Wert0…Wert8) zu übertragen

- max. 48 Werte (Wert0…Wert47) nur auf Anforderung (wenn Taster, dann) zu übertragen
(
Ich habe auf dem Nextion ein Diagramm, das mit diesen 48 Werten beliefert wird. Sie
werden dort in Variablen abgelegt. Kommt es auf dem Nextion zu einem Spannungsverlust
gehen diese Werte verloren. Mit der Anforderung (wenn Taste, dann) kann ich die Werte
wieder herstellen.
Kommt es auf dem Mega zu einem Spannungsverlust, werden mit der Anforderung (wenn Buttom, dann) 48 Werte vom Nextion zum Mega übertragen.
Kommt es auf dem Mega gleichzeitig mit dem Nextion zu einem Spannungsverlust, mache ich
dicke Backen.

- 1 Wert nur auf Anforderung (wenn Taster, dann) zu übertragen.

Der Wertebereich liegt zwischen int -60 bis 10858

Das sind die Regeln…

Stand der Dinge ist,
der mega hat über Nacht- bis in die späten Morgenstunden gesendet
und der Uno empfangen. Dabei ist es zu 7 Summenfehlern gekommen- kein
"Modulo '\n' Fehler.
Bei der Menge der Werte halte ich das schon für ziemlich gut. Über diese 7 Fehler
mache ich mir noch keine Gedanken. Zum einem ist es so, das die Anzahl zu gering ist,
zum anderem- die lassen sich ziemlich leicht unter Kontrolle bringen.
Ich kann hier sagen, das funktioniert.
D.h. für mich- wenn der Mega es an den Uno sendet, dann kann er es auch an das Nextion
senden. Wenn der Mega es an den Uno sendet, dann kann der Uno/das Nextion, es auch an
den Mega senden. In diesen Fällen, komme ich- da auf alle Fälle mit klar.


"byte stuffing"
Habe ich noch nie gehört, also in der Wiki mal einen Überblick verschafft. Wenn ich es
richtig verstanden habe, dann nutzt man es dazu- eine Datenverbindung, in Bezug auf die
Prüfung der Daten, richtig sicher zu machen.
Da ich hier keine Aktoren schalte, benötige ich das nicht. Auch das Handling der Geschichte
kommt mir als richtig schwerer Stoff vor.


XBee´s
Meine funken im 868MHz Band. Eingestellt habe ich nur die Id´s, die Adressen und das es
eine Point to Point Verbindung ist.
Betrieben werden die mit "echten" 868MHz-Antennen. Die Sendeleistung habe ich auf
2mW eingestellt.
Den Kanal habe ich fest auf Kanal 26 (868,35MHz) eingestellt.
Ich habe einen Reset-Taster konfiguriert, und einen Sende/EmpfangsTaster zu Prüfung
konfiguriert. Die Verschlüsselung habe ich ausgeschaltet. Dann habe ich noch eine
Status-LED konfiguriert. Diese gibt Auskunft über senden/empfangen und Fehler.
Der Rest steht auf Werkseinstellungen.

Man kann diese XBee´s so konfigurieren, das sie den gesamten Datenverkehr unter sich
selbst verwalten. Das fängt bei einer Fehlermeldung an, und hört auf mit- wie lange,
soll ich, in welchen Abständen, auf welchen Kanälen- versuchen etwas zu senden oder zu
empfangen. Diese XBee´s sind richtig fähig.


Nun bin ich dazu gekommen, die Sache mal mit 48 Werten zu probieren. Auf der Mega-
Seite habe ich mit:

Code: [Select]
  Serial3.print(Wert0);
  Serial3.print('\n');



Serial3.print(Wert47);
  Serial3.print('\n');
delay(30000);


versucht aus Whandall´s Sketch etwas zu holen. Das ging erwartungsgemäß schief.
Zum einem weil ich keine reine Ziffer liefer, zum anderem weil im Sketch festgelegt
ist (mit, if (isdigit(got))) das nur Ziffern akzeptiert werden.
Ich habe aber auch Ziffer die < 0 sind, also Vorzeichen belastet.
Nun könnte man ja über die "Arduino String Character Analysis" etwas anderes definieren,
müßte dann aber in seinen Funktionen wahrscheinlich auch etwas ändern.

Also habe ich das erst einmal gelassen. Der Sketch gefällt mir aber besser als die jetzige
Lösung. Da bin ich noch nicht von ab.

Also habe ich wieder die alte Lösung genommen.
Code: [Select]

(char c = stream.read();)
 
Hier werden jetzt die Werte wieder mit ihrem Index (Wert23 in Werte[23]) geschrieben und
dann verarbeitet.
Das funktionierte selbstverständlich auch nicht, weil- dieses dreck´s TFT den ganzen
Uno ausbremst.

Gesendet wird so:
Code: [Select]
  Serial3.print(Wert0);
  Serial3.print('\n');



Serial3.print(Wert47);
  Serial3.print('\n');
delay(30000);


Also den ganzen Sketch auf serielle Ausgabe umgestellt.
Das- hat aber auch nicht funktioniert. Der kommt bis Wert16, dann ist Schluss.
Dann die nächsten 16. Ist er einmal durch geht es bei 0 wieder weiter.
Der Zähler von '\n' läuft einwandfrei durch.
Der Inhalt von Wert x, ist aber nicht der eigentliche- MüllWerte.
Da scheint etwas mit dem Speicher, der Zeit, dem Arduino oder den XBee´s nicht zu
stimmen.

Wie michael_x schon sagte, was passiert wenn…

Dann habe ich probiert:

Code: [Select]
  Serial3.print(Wert0);
  Serial3.print('\n');
  delay(50);



Serial3.print(Wert47);
  Serial3.print('\n');
  delay(30000);


Das funktioniert seid mehr als 2Std fehlerfrei. AAAber delay()- das geht nicht!

Ich weiß:
Wenn ich mit dem Mega an das Nextion 48 Werte sende, es zu keinen Problemen kommt.
Der Mega sendet das:

Code: [Select]
Serial2.print("WertLuft.val=");//Luft
  Serial2.print(NexLuft);
  Serial2.write(NexT,3);
  Serial2.print("click Uebersicht,1");
  Serial2.write(NexT,3);


aus einer Schleife.
Der Mega ist hier also raus. Bleiben XBee und Uno.

Beim XBee wüßte ich noch nicht, an was es liegen könnte. Es hat einen Speicher, ich
weiß aber noch nicht, ob dieser als Buffer auch genutzt wird.

Bleibt der Uno mit seiner "SoftwareSerial". Die habe ich gefressen.
Keine Ahnung, so richtig tickt es nicht.

An den Xbee´s möchte ich noch nicht fummel, ist gut möglich das ich mir dann die
nächste Baustelle aufmache.
Ich werde mir zu Ostern mal einen 2.ten Mega gönnen. Da habe ich wenigstens echte
Schnittstellen.
Dieser "SoftwareSerial" traue ich nicht übern Weg.
Es läuft erst einmal so tra,la,la- geht so. Wenn ich den Mega habe, melde ich mich
wieder.
Gruß und Dank
Andreas
;;;
die zweite Maus bekommt den Speck...

Serenifly

#21
Apr 09, 2017, 07:44 pm Last Edit: Apr 09, 2017, 07:45 pm by Serenifly
Quote
Ich habe aber auch Ziffer die < 0 sind, also Vorzeichen belastet.
Die hast Zahlen die < 0 sind. Nicht Ziffern.

Bei dem Code von Whandall musst wie gesagt abfragen ob du ein Minus-Zeichen empfängst und diesen Zustand abspeichern. Wenn ja musst am Ende das Ergebnis mit -1 multiplizieren. Das ist alles.



Habe ich noch nie gehört, also in der Wiki mal einen Überblick verschafft. Wenn ich es
richtig verstanden habe, dann nutzt man es dazu- eine Datenverbindung, in Bezug auf die
Prüfung der Daten, richtig sicher zu machen.
Falsch. Es geht darum bei der Übertragung von Binärdaten ein bestimmtes Endzeichen zu haben aber es zu ermöglichen dass dieses Endzeichen auch im Datenstrom vorkommen kann. Mit Fehlererkennung hat das nichts zu tun.

In der englischen Wikipedia gibt es einen eigenen Artikel dazu. Wobei man den Code da allerdings nicht direkt verwenden sollte.

SkobyMobil

Hallo,
vielen Dank für die Erklärungen…

Mir ist bei der allgemeine seriellen Kommunikation aber noch etwas
aufgefallen.

Ich drücke eine Taste
dann- einmal:
Code: [Select]
Serialx.print(Wert);
Beim Empfänger kommt aber beim ersten Tastendruck nichts an.
Drücke ich die Taste ein zweites mal, ist der Wert sofort da.
Muß man die serielle Übertragung anschubsen- oder an was liegt das?
Gruß und Dank
Andreas
die zweite Maus bekommt den Speck...

michael_x

Quote
Beim Empfänger kommt aber beim ersten Tastendruck nichts an.
Nichts?
Oder kein ',' und kein '\n' ?

Bei deinem missglückten 48-Werte - Versuch geht auch --nach meinem Verständnis-- was durcheinander:
Whandall's Sketch erwartet bis zu 49 Werte durch ',' getrennt und dann ein '\n'.

Was print liefert, hängt am Datentyp der Variablen:

Code: [Select]
int Wert;
Serial.print(Wert); // sendet evtl. am Anfang ein '-' oder auch nicht, dann min. 1 bis max. 5 Zeichen im Bereich '0' ... '9' und sonst nichts.

ElEspanol

Hadt du auch einen Timeout eingebaut?

SkobyMobil

Hallo,
Whandall´s Sketch werde ich ganz sicher zum laufen bekommen.

"Hast du auch einen Timeout eingebaut?"

Nein, was die FlussKontrolle angeht habe ich noch nichts gemacht.
Da kümmer ich mich drum, wenn ich den zweiten Mega hier habe.
Gruß und Dank
Andreas
die zweite Maus bekommt den Speck...

SkobyMobil

Hallo,
"Beim Empfänger kommt aber beim ersten Tastendruck nichts an."

Eine -1, d.h. keine Daten

So als wenn erst einmal der serielle, leere Speicher gelesen wird.

"Bei deinem missglückten 48-Werte - Versuch"

Ich habe nun den Uno mit SoftwareSerial gegen einen echten Mega 2560 R3
getauscht. 48 Werte nach dieser Methode:

(char c = stream.read();)

Das funktioniert mit dem Mega ohne Probleme, selbst das nebenher zählen
von '\n'.
Wird wohl die SoftwareSerial gewesen sein, die da ins spucken gekommen ist.

Die XBee regeln den Datenverkehr unter sich. Die gesammte serielle
Kommunikation läuft ohne Lib´s mit zwei Mega einwandfrei über die XBee.

Ich weiß jetzt, das ich 48 Werte in eins einfach so rüberschieben kann.
Das ist sehr gut.

Nun werde ich mal mit Whandall's Sketch probieren wie weit ich komme.

Dann brauche ich noch ein Protokoll, kann ja sein, das doch etwas mal
schiefläuft. Die XBee berechnen sich eine Prüfsumme, diese kann man lesen.
Mal sehen, vielleicht kann ich die weiter verwenden.
Das sind aber andere Bohnen.
Dank eurer Hilfe bin ich schon richtig weit gekommen.
Gruß und Spaß
Andreas
die zweite Maus bekommt den Speck...

Go Up