Forum: Compiler & IDEs Komprimieren von kleinen Datenmengen.


von Barny (Gast)


Lesenswert?

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?

von Peter (Gast)


Lesenswert?

es kommt auf die Daten an, wenn sie wirklich zufällig sind, dann kann 
man nichts komprimieren.

von Barny (Gast)


Lesenswert?

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.

von Peter (Gast)


Lesenswert?

dann könnte man auch die differenz nur übertragen

von (prx) A. K. (prx)


Lesenswert?

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.

von Karl H. (kbuchegg)


Lesenswert?

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.

von (prx) A. K. (prx)


Lesenswert?

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.

von Barny (Gast)


Lesenswert?

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.

von ich (Gast)


Lesenswert?

Nur mal so ne Frage, wo ist das Problem mit 50-500Byte pro Sekunde, da 
ist doch fast alles schnell genug.

von Barny (Gast)


Lesenswert?

Nicht die Geschwindigkeit, sondern die Datenmenge ist das Problem.
Ich sende mit 868MHz
Bei nur 6 Minuten Sendezeit wird es etwas eng.

von Karl H. (kbuchegg)


Lesenswert?

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.

von (prx) A. K. (prx)


Lesenswert?

Bei Funk wäre zudem zu bedenken, dass Differenzcodierung bei verlorenen 
Daten ein Problem kriegt und man bei Funk damit rechnen muss.

von Karl H. (kbuchegg)


Lesenswert?

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.

von U.R.Schmitt (Gast)


Lesenswert?

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.

von Simon K. (simon) Benutzerseite


Lesenswert?

Am besten sind Ack und Sequenznummern, wie bei TCP.

von Peter (Gast)


Lesenswert?

muss es denn sofort gesendet werden? Wenn nicht kann man auch sammeln 
und dann komprimieren, das ganze das als ein etas größere Packet 
abschicken.

von (prx) A. K. (prx)


Lesenswert?

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.

von Barny (Gast)


Lesenswert?

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.

von Rolf Magnus (Gast)


Lesenswert?

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.

von Barny (Gast)


Lesenswert?

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.

von sebastians (Gast)


Lesenswert?

> 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.

von Barny (Gast)


Lesenswert?

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.

von Tom (Gast)


Lesenswert?

...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.

von Tom (Gast)


Lesenswert?

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.

von Barny (Gast)


Lesenswert?

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.

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
Noch kein Account? Hier anmelden.