Ich möchte Messdaten eines oder mehrerer Datenlogger per nRF24L01+ Module übertragen. Kommunikation funktioniert soweit. Nun hat der nRF24 ja nur 32 Bytes Payload. In den Tutorials mit nur einem Sensor am Arduino ist das kein Problem, das passt immer in die Payload. Ich habe aber mehrere Sensoren (Temp, RH, Licht, ADC1..6), die verschiedene Werte (Ganzzahl, Festkommazahl) in unterschiedlicher Skalierung (16bit, 32bit) erzeugen. Wenn ich die in einem Rutsch übertrage, werden die 32 Bytes der Payload überschritten. Jetzt überlege ich, wie ich die Daten möglichst einfach und dennoch zuverlässig übertrage. 1. Binär hintereinander, etwa wie RTC-MODBUS Vorteil: Es spart enorm Bytes Nachteil: Ich übertrage keine Information über das Datenformat, Kommastelle, Anzahl der Bytes pro Wert. Das muss alles in Sender und Empfänger exakt übereinstimmen. Der nRF24 scheint Probleme mit langen Payloads ohne Pegelwechsel zu haben, eine Übertragung von mehreren Werten mit Nullen könnte also fehlerhaft empfangen werden. 2. Hex-Codiert hintereinander, etwa wie ASCII-MODBUS Vorteil: immer noch kürzer als ASCII-Strings, keine reinen Nullbytes in der Payload Nachteil: wie 1., keine Info über Datenformat 3. ASCII, je ein Wert pro Payload Beispiel: Dtemp1[-15.55°C] Vorteil: Ich kann beliebige Werte senden, inklusive Kennung, Einheit und würde die 32Bytes doch nicht ausreizen. Geht ein Paket verloren (max. Retransmits überschritten), sind die anderen Werte dennoch gültig. Nachteil: Es müssten sehr viele Datenpakete gesendet werden, um einen Datensatz zu übertragen. 4. ASCII, mehrere Werte pro Payload Beispiel: Data1[-15.55,33.3,1023.0] Vorteil: wie 3., und es würden weniger Pakete benötigt Nachteil: Die Pakete wären nicht "schön" aufgebaut. Z.B. gehen 3 Werte eines Sensors (Temp, RH, Druck) in ein Paket, 6 Werte vom ADC müssten aber auf 2 Pakete aufgeteilt werden. 5. ASCII, alle Werte als Stream Alle Werte hintereinander in einen Sendebuffer, dieser wird dann paketweise gesendet. Vorteil: keine Probleme mit Payload-Länge Nachteil: geht ein Paket verloren, ist der gesamte Datensatz unbrauchbar. Und ich muss irgendwie (zusätzliche Prüfsumme) feststellen können, ob alle Pakete angekommen sind. 6. ASCII, alle Werte als JSON Stream Die Werte als JSON Stream ausgeben, sonst wie 5. Vorteil: wie 5., aber willkürliche Anordnung der Daten möglich, Einheiten werden mit übertragen Nachteil: wie 5., und erheblicher Overhead durch die JSON Formatierung Welche Art der Datenübertragung hat sich in dem Bereich bewährt? Der nRF24 nimmt einem ja schon Vieles ab (AutoRetransmit, Enhanced ShockBurst Mode, CRC Validation (eines Paketes).
Karl K. schrieb: > Nun hat der nRF24 ja nur 32 Bytes Payload. Dann definierst du verschiedene Datenpakettypen und überträgst in einem Byte den Typ. > Der nRF24 scheint Probleme mit langen Payloads ohne Pegelwechsel zu > haben, eine Übertragung von mehreren Werten mit Nullen könnte also > fehlerhaft empfangen werden. Dann sorge in deinen Payloads dafür, dass das nicht passiert. Stichwort "Bit Stuffing". Bei längeren Sequenzen von 1en oder 0en fügst du nach einer bestimmten Anzahl ein gegenpoliges Bit zusätzlich ein. Der Empfänger weiß das und sortiert es wieder aus.
Naja, andererseits haben wir 2019 und der nRF24 bringt ja schon einige Eigenintelligenz mit. Muss man sich da wirklich noch mit so Kram wie Bitstuffing beschäftigen? Der nRF selbst arbeitet ja mit GFSK und entsprechenden Filtern zur Fehlerreduzierung, plus zuschaltbarem CRC.
Karl K. schrieb: > Der nRF selbst arbeitet ja mit GFSK und entsprechenden Filtern zur > Fehlerreduzierung, plus zuschaltbarem CRC. GFSK ist eine Modulationsart. Mit der Kodierung deines Datenstromes hat das nun wirklich nichts zu tun. Du willst nicht wirklich bei der Datenkodierung/-dekodierung schlampen, um deine Fehleralgorithmen herauszufordern. Sonst geht hinterher die Jammerei wegen der geringen Reichweite los und/oder dir bricht die Datenrate ein, weil du auf Grund von deiner CRC immer feststellst, dass die Daten nicht heil ankommen.
Wolfgang schrieb: > GFSK ist eine Modulationsart. Mit der Kodierung deines Datenstromes hat > das nun wirklich nichts zu tun. Insofern schon, da FSK wahrscheinlich doch anfällig bei Daten ohne längeren Bitwechsel ist, weil dann keine Flanke zur Synchronisation da ist. Wolfgang schrieb: > Du willst nicht wirklich bei der Datenkodierung/-dekodierung schlampen, > um deine Fehleralgorithmen herauszufordern. Deswegen würde mich halt mal interessieren, wie andere sowas umsetzen und was sie für Erfahrungen damit haben. Wie gesagt, es gibt unzählige Tuts wo mit dem nRF24 und nem Arduino oder Raspberry ein einzelner Sensorwert übertragen wird. Und wie das mit Tuts so ist: Wenn es spannend wird, hören sie auf. Also wie übertrage ich damit größere Datenmengen? (Wobei größere hier immer noch im Bereich wenige hundert Byte sind.) Meine Überlegungen: Wenn ich mit ASCII arbeite, habe ich in einem Byte immer wechselnde Bits drin, auch wenn ich 000.0 übertrage. Wenn ich mit ASCII-Hex arbeite auch. Wenn ich mit Packed-BCD oder Binärdaten arbeite, können längere Folgen nur Null auftreten, die müsste ich dann mit Bitstuffing oder Manchestercodierung auflockern, allerdings würde meine Payload dadurch um 20% bei Bitstuffing oder 100% bei Manchestercodierung länger - aber immer noch kürzer als die Zeichen als ASCII-String zu übertragen. Was immer noch nicht das Problem löst: Was mache ich wenn die Bytefolge nicht mehr in meine Payload passt?
Karl K. schrieb: > Wenn ich mit Packed-BCD oder Binärdaten arbeite, können längere Folgen > nur Null auftreten, die müsste ich dann mit Bitstuffing oder > Manchestercodierung auflockern, allerdings würde meine Payload dadurch > um 20% bei Bitstuffing oder 100% bei Manchestercodierung länger - aber > immer noch kürzer als die Zeichen als ASCII-String zu übertragen. Ich bin da auch noch nicht drauf gekommen, daß der nRF24 keine interne Codierungseinheit bzw. Modem besitzt. Will demnächst was mit dem machen, insofern erstmal danke für den Tip und die Überlegung. Normalerweise hat selbst ein älterer Transceiver wie der CC1101 sowas wie eine Manchester-Engine mit drin, die man nur benutzen muß. Der NRF ist eben viel billiger und hat deshalb andere Einsatzbereiche. Ich würde hier erstmal zu einem Leitungscode, naheliegend Manchester Code, greifen. Halbiert zwar die Datenrate, macht aber Sinn bei längeren Folgen. Gibts auch schon Libs dazu, z.B.: https://github.com/silentbicycle/spooky Oder eben was anderes implementierbares: https://de.wikipedia.org/wiki/Leitungscode Oder im einfachsten Fall einen Scrambler implementieren, um die Gleichanteile zu eliminieren, mit dem schönen Nebeneffekt, daß die Datenrate nicht halbiert wird. https://de.wikipedia.org/wiki/Scrambler_(Telekommunikation) > Was immer noch nicht das Problem löst: Was mache ich wenn die Bytefolge > nicht mehr in meine Payload passt? Im einfachsten Fall mit lookup table bekannte und häufige Bytefolgen codieren. Besser würde ich aber zu Quellcodierung wie Shannon-Fano oder Huffman greifen. https://de.wikipedia.org/wiki/Datenkompression#W%C3%B6rterbuchmethode https://de.wikipedia.org/wiki/Datenkompression#Entropiekodierung https://en.wikipedia.org/wiki/Shannon%E2%80%93Fano_coding Habe nur das als beispielhafte Implementierung auf die Schnelle gefunden: https://github.com/GENiEBEN/fanohuff Das ist doch mal eine schöne nachrichtentechnische Aufgabe. Da werde ich gleich richtig sentimental, wenn mir meine Studienzeit wieder in Erinnerung kommt :-)
:
Bearbeitet durch User
Karl K. schrieb: > Naja, andererseits haben wir 2019 und der nRF24 bringt ja schon einige > Eigenintelligenz mit. Muss man sich da wirklich noch mit so Kram wie > Bitstuffing beschäftigen? Das Manual vom Chip, das man so findet, ist übrigens von 2008. Und wie gesagt, war der Chip wohl für irgendwas Billiges vorgesehen.
Karl K. schrieb: > Deswegen würde mich halt mal interessieren, wie andere sowas umsetzen > und was sie für Erfahrungen damit haben. Die verwenden Bit Stuffing (z.B. max. 5 gleiche Bits hintereinander) und übertragen ihre Daten nicht per ASCII, sondern verwenden z.B. einen Code mit einem Hamming-Abstand von drei, so dass sich einzelne Bitfehler im Datenwort korrigieren lassen. Besser noch ist ein Blockcode.
Rico W. schrieb: > Ich würde hier erstmal zu einem Leitungscode, naheliegend Manchester > Code, greifen. Andererseits bietet mir der nRF24 ja schon OSI-Layer 1 und 2 an. Da will ich eigentlich nicht mehr mit Manchester oder Scrambling rummachen müssen. Und zumindest mit ASCII läuft die Übertragung erstaunlich zuverlässig. Wenn Bytes falsch angekommen sind, dann lags an der Software. (Tipp: Man kann zwar eine Payload mit 34 Byte senden, es kommen trotzdem nur 32 an, nur wird halt die Länge falsch übermittelt.) Allerdings ist meine Überlegung zu 5. unzureichend: Wenn eine Payload nicht übermittelt wird, gibts kein Ackn und die Übertragung wird abgebrochen. Damit ist der Datensatz eh unvollständig und wird vom Empfänger komplett verworfen. Dann hab ich zwar keine falschen Daten, aber das ändert leider nichts dran, dass ich für den Datensatz gar keine Daten habe. Und im Sinne von "der Datalogger soll mit Akku laufen" will ich dann auch nicht ständig versuchen den Datensatz erneut zu senden.
Karl K. schrieb: > Rico W. schrieb: >> Ich würde hier erstmal zu einem Leitungscode, naheliegend Manchester >> Code, greifen. > > Andererseits bietet mir der nRF24 ja schon OSI-Layer 1 und 2 an. Da will > ich eigentlich nicht mehr mit Manchester oder Scrambling rummachen > müssen. Layer 1 (Sicherung) ist im Chip eben nur unzureichend für deine Anwendung umgesetzt. Dann mußt du dich entweder mit der Implementierung auseinandersetzen oder mit den Gegebenheiten abfinden. Übrigens alles schonmal dagewesen: Beitrag "Scrambler für Funkstrecke" Guck dir mal das Packet Modem und den Scrambler nach G3RUH an. Hat sich lange Zeit bewährt, bis heute. Code gibt es auch: https://gist.github.com/andresv/4589178 Oder ein App Note: https://www.silabs.com/documents/public/application-notes/AN592.pdf
Rico W. schrieb: > Layer 1 (Sicherung) ist im Chip eben nur unzureichend für deine > Anwendung umgesetzt. Nun, offenbar nicht. Hab gerade mal ein paar Bitpattern ausprobiert: Es ist völlig egal, ob da Nullen oder ASCII oder 1010 Wechsel oder $FF durchgeschoben wird, auch mit 32 Bytes an Nullen ergeben sich weder Fehler im Datenstream noch eine merklich erhöhte Retransmit-Rate wegen fehlerhafter Pakete. Insofern würde ich durch irgendwelches Bitstuffing oder Scrambling nichts gewinnen. Dass man lange Folgen von Nullen / Einsen vermeiden soll bezieht sich offenbar wirklich nur auf die Adresse. Es kommt dann zu erhöhten Empfangsfehlern, weil der nRF glaubt was zu empfangen was zur Adresse passt. Das wird dann zwar sowieso spätestens bei der Checksumme verworfen, aber erhöht halt den Fehlercounter. Und 1010 Bitwechsel in der Adresse ($55 und $AA) soll man vermeiden, weil das die Preampel zur Synchro fortsetzt und auch zu falschen Adresserkennungen führen kann. Für die Übertragung ist also offenbar egal ob Binärdaten oder ASCII-Strings. Jetzt muss ich nur sehen, ob die Einsparung mit Binär wirklich so viel mehr bringt, um die Nachteile gegenüber ASCII auszugleichen.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.