Guten Tag
Ich suche nach einer Möglichkeit kurze Datenpakete zu komprimieren.
Im konkreten Fall ist es eine Übertragung von 10Byte Binärdaten.
(4x 2Byte und 2x 1Byte große Variabeln)
Die Komprimierverfahren, die ich bis jetzt gefunden habe, sind nur für
größere Datenmengen.
Kennt jemand ein Komprimier-Verfahren, dass man auch auf einem AVR
verwenden kann?
Die ersten 8 Byte sind Sensordaten, die über ADC eingelesen werden. Die
letzten beiden Byte sind Daten von einer Schalter-/Taster-Matrix.
Die ersten 8 Byte ändern sich also nicht sprunghaft, sondern folgen
einer (vorher unbekannten) Kurve.
Barny schrieb:> Die ersten 8 Byte ändern sich also nicht sprunghaft, sondern folgen> einer (vorher unbekannten) Kurve.
Da bietet sich eine Huffman-Codierung mit fest definierter
Wahrscheinlichkeitsverteilung und Codierung an. Kleine Differenzen in
wenig Bits, grosse Differenzen in viel Bits codieren. Naturgemäss wird
die Länge der entstehenden Messages variabel, häufige sind kürzer,
seltene länger.
Allerdings musst du vmtl. damit rechnen, das auch mal eine Message über
die Wupper geht, und dass der Empfänger irgenwann mal einen Anfang
braucht.
> letzten beiden Byte sind Daten von einer Schalter-/Taster-Matrix.
Und da wird wohl der Normalzustand der Matrix "inaktiv" sein, was sich
ggf. in nur einem Bit codieren lässt.
Bei 10 Byte Daten kannst du die Daten selber so gut wie nicht mehr
kompremieren. Im Einzelfall mag das gehen (wenn die aktuellen Datenwerte
günstig sind), aber meistens ist das "Kompremierte" danach länger als
die Urdaten. Aber eines der üblichen Kompremiervorgänge wirst du da
knicken können, da geht nicht viel.
Was ich an deiner Stelle versuchen würde:
Nur die Veränderungen übertragen.
Da sich deine ADC Werte nicht sprunghaft ändern, würde es unter
Umständen genügen, nur die Änderung (+-127) in nur 1 Byte zu übertragen.
Der Empfänger rechnet den Wert zu seinem letzten bekannten Wert hinzu
und hat so wieder seinen aktuellen Wert.
Das wären dann 4 Byte Einsparung. Der Grund warum ich oben nur +-127
genannt habe und nicht die Asymetrie -128/+127 ausgenutzt habe, liegt
darin, dass ich mir den Wert 0x81 als Sonderfall reservieren würde. Ist
das erste Byte der Nachricht 0x81 dann handelt es sich nicht um
Differenzwerte, sondern die übertragenen Sensordaten sind die
Absolutwerte (also 4 mal 2 Byte). Die würde ich ab und zu einstreuen,
damit der Empfänger mit Sicherheit wieder einen aktuellen Stand hat.
Das könnte man überhaupt für alle 4 Sensorwerte einzeln vereinbaren:
grundsätzlich wird nur die Differenz übertragen, es sei denn diese
Differenz sei -128 (also 0x81). Dann folgt auf diese 0x81 noch 2 Bytes
mit dem absoluten Messer in 2 Bytes. Damit bist du dann in der Lage,
dass der Sender dann auch tatsächliche Sprünge in den Messdaten
übertrageb kann. (denn einer Aussage "Das kommt in meinen Messwerten
nicht vor" traue ich grundsätzlich nicht über den Weg)
Bei den Schaltern kannst du nicht mehr viel machen. 2 Byte, da lässt
sich nichts mehr kompremieren. Ausser vielleicht ein spezieller erster
Bytewert (welcher in den Schalterstellungen nicht vorkommen kann), der
aussagt: keine Veränderung. Wenn du aber alle 16 Bits für Schalter
brauchst, dann geht da nichts mehr.
Man kann da zig Varianten vorschlagen, aber alles hängt davon ab, wie
häufig/schnell sich die Daten ändern. Wenn sich die ADC-Daten alle
ungefähr mit der gleichen Frequenz/Amplitude ändern ist eine andere
Codierung sinnvoller, als wenn sich nur einer davon häufig ändert, die
anderen selten oder nur sehr gering (Rauschen ggf. vorher ausfiltern).
Wenn sich i.d.R. nur einer davon häufiger ändert, dann kann man den als
Differenz mit Tag übertragen, d.h. die Message heisst sinngemäss "ADC#0
+15" und überträgt bei den anderen Kanälen schlicht garnichts.
Diesem Schema folgend muss man bei den Schaltern/Tastern normalerweise
nichts übertragen, weil sich da in den meisten Messages gegenüber der
vorherigen nichts geändert hat. Man muss nur einen Code, ein Tag oder
ein Bit reservieren, um im Fall einer Änderung ebendiese übertragen zu
können.
Mit solchen Methoden kommt man je nach Daten u.U. auf eine mittlere
Länge von 2-3 Bytes pro Sample.
Danke für eure Tipps
Noch ein paar Details mehr.
Normalerweise werden die Daten im Sekundentakt übertragen.
Es ist ein hochauflösender Modus geplant, bei dem zwischen 5 und 50 mal
in der Sekunde die Daten übertragen werden.
Genau desswegen möchte ich die Daten komprimieren.
Da sich die Daten innerhalb dieses Zeitraums nur sehr wenig ändern, wird
die Methode nur die Änderungen zu übertragen sicher die Besste sein.
Außer euch fällt etwas besseres ein.
Barny schrieb:> Nicht die Geschwindigkeit, sondern die Datenmenge ist das Problem.> Ich sende mit 868MHz> Bei nur 6 Minuten Sendezeit wird es etwas eng.
Ich würde mal sage die Baudrate ist dein Problem.
Und im Moment sehe ich noch nicht, warum du die nicht soweit hochsetzen
kannst, dass du 500 Bytes in der Sekunde rüberblasen kannst. 500 Bytes /
Sekunde sind nicht allzuviel.
Kurzer check mit Google ergibt, dass da Baudraten bis rauf zu knapp
40kBit/s möglich sind. Das sind über den Daumen gerechnet 40000 / 10 =
4000 Bytes pro Sekunde. Da bist du mit 500 Bytes noch weit weg.
A. K. schrieb:> Bei Funk wäre zudem zu bedenken, dass Differenzcodierung bei verlorenen> Daten ein Problem kriegt und man bei Funk damit rechnen muss.
Aus dem gleichen Grund ist es auch dringend angeraten, sich bei Funk ein
anderes Protokoll als "Alle Datenbytes einfach so rüberblasen und darauf
hoffen, dass der Empfänger synchron die Bytes wieder richtig
auseinanderpfriemelt" sich auszudenken.
Bei Funk MUSST du damit rechnen, dass Bytes verloren gehen. Mit allen
Konsequenzen.
Karl heinz Buchegger schrieb:> Bei Funk MUSST du damit rechnen, dass Bytes verloren gehen. Mit allen> Konsequenzen.
Also mindestens noch einen CRC16 dazu. Dann fehlt aber immer noch eine
Mimik daß der Empfänger verlorene (kaputte) Pakete noch mal nachfordern
kann.
Wenn die Daten im Absender nicht leidlich tief gepuffert und
anschliessend gebündelt übertragen werden, dann sollte man überlegen, ob
man nicht eher mit teilweise verlorenen Daten leben will, als sich bei
teilweise gestörtem Funk die Leitung und das Übertragungsprotokoll noch
mit Retries zuzustopfen und so ggf. ganz zu blockieren.
Wenn das nicht in Frage kommt, dann ist eine ausreichend tiefe
Speicherung im Absendersystem unbedingt ratsam.
Also
Es muss sofort gesendet werden, ich brauche die Daten live.
Aktuell verwende ich eigentlich kein Protokoll.
Ich sende die Daten einfach so und hänge einen Kontrollwert hinten dran.
(8 Bit Checksumme -> Dass eine Byte, dass ich vorher versehentlich zu
den Schaltern gezählt habe.)
Bei fehlerhaften Daten wird dass Datenpaket verworfen und auf dass
Nächste gewartet.
Da die Sensordaten immer wieder neu kommen, macht es nichts aus wenn
dass ein oder andere Paket verlohren geht.
Bezüglich Datenrate.
Das X-Bee schafft wenn ich mich richtig erinnere eine Datenrate von
24kBit/s.
Beim Übertragen genemigt sich das X-Bee im günstigsten Fall ca. 2/3 des
möglichen Datenvolumens als Overhead. Wenn man noch zusätzliche Dinge
wie mehrfachsenden der Daten, Adressen,... verwendet, schaut das Ganze
noch schlimmer aus.
Dass bedeutet ich habe 2400 Byte/s 60s 6min = 864000Byte an Rohdaten.
864000 / 3 = 288000 Byte an Nutzdaten
Und bei 500 Byte die Sekunde brauche ich 30000 Byte.
Dass bedeutet dass sich das Ganze mit den Modulen, die ich verwende
nicht ganz ausgeht.
Barny schrieb:> Aktuell verwende ich eigentlich kein Protokoll.> Ich sende die Daten einfach so und hänge einen Kontrollwert hinten dran.> (8 Bit Checksumme -> Dass eine Byte, dass ich vorher versehentlich zu> den Schaltern gezählt habe.)> Bei fehlerhaften Daten wird dass Datenpaket verworfen und auf dass> Nächste gewartet.> Da die Sensordaten immer wieder neu kommen, macht es nichts aus wenn> dass ein oder andere Paket verlohren geht.
Dann ist eine Differenzkodierung aber schlecht, denn die funktioniert ja
nur, wenn die vorangegangenen Pakete auch angekommen sind.
> Beim Übertragen genemigt sich das X-Bee im günstigsten Fall ca. 2/3 des> möglichen Datenvolumens als Overhead. Wenn man noch zusätzliche Dinge> wie mehrfachsenden der Daten, Adressen,... verwendet, schaut das Ganze> noch schlimmer aus.>> Dass bedeutet ich habe 2400 Byte/s 60s 6min = 864000Byte an Rohdaten.> 864000 / 3 = 288000 Byte an Nutzdaten>> Und bei 500 Byte die Sekunde brauche ich 30000 Byte.
Wie kommst du auf diesen Wert? Und warum rechnest du es auf 6 Minuten
hoch und dann wieder zurück?
Du hast 2400 Byte/s an Rohdaten. Ein Drittel davon sind 800 Byte/s. Du
brauchst aber nur 500 Byte/s.
Rolf Magnus schrieb:> Wie kommst du auf diesen Wert? Und warum rechnest du es auf 6 Minuten> hoch und dann wieder zurück?
Ich rechne auf 6Minuten auf weil nur 6 Minuten in einer Stunde gesendet
werden darf. -> 10% dudy cycle
Runter rechne ich nicht mehr.
Dass mit den 6 Minuten ist eine gesetzliche Angelegenheit.
Dass bedeutet ich habe 2400 Byte/s * 60s = 144000 Bytes/min
144000 Bytes/min * 6min/h = 864000Byte an Rohdaten.
864000Byte / 3 = 288000 Byte an Nutzdaten
Dass ist leider eine Tatsache.
> Ich rechne auf 6Minuten auf weil nur 6 Minuten in einer Stunde gesendet> werden darf.
Jetzt wird vieles klarer.
Müssen das 6 zusammenhängende Minuten sein und dann darfst du wieder
54min nichts senden?
Dann musst du ja sowieso viel speichern und hast viele Daten zu
komprimieren.
Die 6 Minuten kann ich aufteilen wie ich will.
Und da ich nicht so lange auf die Daten warten will und kann, möchte ich
die Daten nicht bündeln, sondern live senden.
Rolf Magnus schrieb:> Dann ist eine Differenzkodierung aber schlecht, denn die funktioniert ja> nur, wenn die vorangegangenen Pakete auch angekommen sind.
Da hast du recht, da werde ich mir etwas überlegen.
...bei mir sind jetzt folgende Vorgaben des TE hängen geblieben:
- 288000 Bytes pro Stunde zur Datenübertragung nutzbar
- 10 Bytes pro Sample
- 8 Bytes des Samples folgen einer unbekannten Kurve
- gewünschte Samplerate: 5 bis 50 Samples pro Sekunde
- Daten sollen ungepuffert (Live) zur Verfügung stehen
- Der Verlust einzelner Datenpakete (Samples) ist unkritisch
...für mich hieße das jetzt im einfachsten Fall 7 Samples pro Sekunde
unkomprimiert zu senden. Erweitern wäre bei 7 Samples/s noch auf 11
Bytes möglich um mit einer Checksumme korrupte Datenpakete zu verwerfen.
Für jegliche Gedanken bzgl. Komprimierung müsste näheres zur Kurvenform
der 8 Datenpakete bekannt sein. Da könnte sich vielleicht etwas in
Richtung ADPCM eignen.
Tom schrieb:> Für jegliche Gedanken bzgl. Komprimierung müsste näheres zur Kurvenform> der 8 Datenpakete bekannt sein. Da könnte sich vielleicht etwas in> Richtung ADPCM eignen.
Nachtrag: Ich meinte natürlich nicht 8 Datenpakete, sondern 8 Bytes.
Habe jetzt auch im nachhinein erst gesehen, dass es eigentlich nicht 8
Bytes sondern 4x2Bytes sind, also vermutlich 4 voneinander unabhängige
Sensoren. Sprich, auch 4 voneinander unabhängige Kurven. Das schränkt
das Potenzial zum Komprimieren schon verdammt ein.
Die Anzahl der Samples pro Sekunde zu verdoppeln halte ich selbst mit
geeigneter Komprimierung schon für unrealistisch.
Es wird vermutlich für die Anwendung auch keinen großen Unterschied
machen ob 7 Samples pro Sekunde oder (geschätzt komprimiert) 10 Samples
pro Sekunde übertragen werden können.
Mein Fazit: Unkomprimiert 7 Samples (10 bytes + 1byte) pro Sekunde mit
einer Checksumme übertragen um die Integrität der Daten sicherzustellen.
Jeglicher sonstiger Aufwand erscheint mir bei unveränderten technischen
Vorgaben für nicht sinnvoll.
Tom schrieb:> Habe jetzt auch im nachhinein erst gesehen, dass es eigentlich nicht 8> Bytes sondern 4x2Bytes sind, also vermutlich 4 voneinander unabhängige> Sensoren. Sprich, auch 4 voneinander unabhängige Kurven.
Es sind 4 Sensoren.
Nach einwenig Nachdenken sind mir noch weitere Einspahrungsmöglichkeiten
eingefallen.
Bei den 2 x 1 Byte für die Schalter kann ich auf 1 Byte verzichten, wenn
ich anstatt jedesmal alle Zustände zu übertragen sondern nur den Taster,
der sich geändert hat sende. -> 7Bit Adresse + 1 Bit für Zustand ein/aus
Da die Sensoren über einen 10Bit ADC eingelesen werden, sind 6 Bit pro
Wert ungenutzt. Man kann also schachteln.
Dass bedeutet ich kann 4 Sensoren und ein Byte für Schalter/Taster in
6Byte unterbringen. Dass macht 7 Byte mit Konntrollwert.
Dass bedeutet, dass ich 11Pakete/s senden kann.
Wenn ich bedenke, dass das 1. Bit der Sensordaten meißtens sowiso nur
wild herumläuft, kann man da auch noch weiter einsparen.
Aber solange keiner eine geniale Lösung hat wie man die Daten
komprimieren kann, mussich einsehen, dass nicht mehr Pakete / s gesendet
werden können.