Frage:
Verlustfreie Komprimierungstechnik für digitale Signale in einem eingebetteten System
toasty
2020-07-29 02:24:07 UTC
view on stackexchange narkive permalink

Hier ist das Szenario:

Ich habe ein eingebettetes System, in dem ein ADC alle 2 Sekunden ein 16-Bit-Potentiostat-Beispiel protokolliert.Das System zeichnet weiterhin wochenlang Daten auf, was die Speichernutzung zu einem Problem macht.

Wie kann ich das Signal beim Protokollieren verlustfrei komprimieren, anstatt 16 Bit Speicher für jede der Millionen Samples zu verbrauchen?Idealerweise möchte ich das Signal in komprimierte 15-Minuten-Segmente aufteilen.Ich bin mir sicher, dass es dafür einen Standard gibt, aber ich kann ihn nicht finden.

Wenn es hilft, hat das Signal meistens sehr niedrige Deltas zwischen den Abtastwerten (niedrige Frequenz).

Speichern Sie unformatierte ADC-Werte oder konvertierte Werte (Gleitkomma mit einfacher / doppelter Genauigkeit)?Zeitstempel?Speichern Sie sie in Flash oder RAM?
Derzeit puffere ich 450 Roh-Samples im RAM und speichere dann alle 450 Samples, um mit einem Zeitstempel zu flashen.
@toasty Erzählen Sie uns viel mehr Details zu diesen Beispielen.Wirklich hilfreiche Ideen zur Komprimierung erfordern ein sehr detailliertes Verständnis dessen, womit Sie es zu tun haben.Wenn dies beispielsweise Daten von einem exponentiellen Abklingereignis mit einer bestimmten Art von Rauschen sind, würden bestimmte Ideen anderen vorgezogen.Es ist wie es ist.Je mehr wir wissen, desto besser können Sie eine Antwort erhalten.
Es ist ein Potentiostat.
und muss mehrere Analyten unterstützen
Ich wäre stark versucht, eine SD-Karte zu verwenden (Mikro oder nicht).Das kleinste, das Sie kaufen können, ist ungefähr 16G oder 32G, das Proben im Wert von ungefähr 544 oder 1088 Jahren mit 2 Bytes und 0,5 SPs enthält, ohne dass der Overhead des Dateisystems berücksichtigt wird.Wenn Sie ein kompatibles Dateisystem implementieren, kann es zur Analyse auf einen PC übertragen werden.
SD-Karte ist für das Projekt nicht zulässig :)
Reality Check: "Verwenden einer SD-Karte" ist für Ihr Projekt nicht möglich, aber "Entwickeln Sie eine neue, maßgeschneiderte Technik für die verlustfreie Komprimierung von Daten" nicht ???Sie erkennen, dass die Wirtschaftlichkeit hier völlig rückständig ist, wenn * überhaupt ein Wert * auf Ihre Zeit gelegt wird.Tun Sie es nicht, es sei denn, dies ist ein reines Leidenschaftsprojekt.
Haben Sie tatsächlich eine 16-Bit-Genauigkeit?Wenn die unteren 4 Bits nur zufälliges Rauschen sind, ist es nicht sinnvoll, sie zu protokollieren.
Sie können eine SD-Karte und einen Leser für <20 US-Dollar erwerben, die mehrere Gigabyte Daten aufnehmen können.Wenn Sie Arduino verwenden, gibt es sogar Bibliotheken, die alle Protokoll- und Dateisystemaufgaben für Sie erledigen. Sie können es also einfach anschließen und anweisen, Daten zu schreiben.
Herzlich willkommen!"Eingebettet" kann ein so breites Spektrum an Funktionen bedeuten ... Ich gehe davon aus, dass auf diesem System kein Linux oder ein gleichwertiges Betriebssystem ausgeführt werden kann, das zip, lzma usw. als einfache Antwort liefert.Wenn die Verwendung einer SD-Karte außerhalb des Anwendungsbereichs liegt, ist es hilfreich, wenn wir etwas mehr über die Funktionen Ihres Systems wissen.Das Entwickeln einer solchen Lösung ist ein Kompromiss, aber wir können nicht viel helfen, wenn wir nicht wissen, was Sie auszugleichen versuchen.Lebensdauer der Batterie?Kosten?Physische Größe?Wie viele Proben müssen Sie aufbewahren?
Das physikalische und elektrische Design ist fest und kann daher nicht erweitert werden.Es ist ein batteriebetriebenes System mit einem Mikrocontroller, auf dem ein Bare-Metal-Programm ausgeführt wird.Wenn ich Hilfe bei der Architektur des Systems und der Auswahl der Komponenten benötigt hätte, hätte ich stattdessen darum gebeten.Ich war neugierig, welche Signalkomprimierungslösungen es gibt, und die Antworten waren bisher angemessen und sehr hilfreich.
Verlustfreie Komprimierung ist eine statistische Modellierung, und Sie haben nicht viel von einem Modell bereitgestellt.Nach dem, was Sie uns gesagt haben, können Sie nicht viel besser machen als Huffman, der die Deltas codiert.Unabhängig davon scheint ein Potentiostat ein ziemlich lautes Gerät zu sein, und Sie können Rauschen nicht komprimieren. Ich stelle mir daher vor, dass Sie bestenfalls eine 2: 1-Komprimierung erhalten.
@toasty "Das Tolle an Standards ist, dass so viele zur Auswahl stehen."
Sechs antworten:
Dave Tweed
2020-07-29 03:47:03 UTC
view on stackexchange narkive permalink

Bei der Komprimierung geht es darum, die Redundanzen in den Daten zu finden und zu entfernen. Da Sie uns anscheinend nicht viel über Ihre tatsächlichen Datensätze erzählen können, muss diese Antwort sehr allgemein gehalten sein.

Ich stelle fest, dass "Potentiostat" -Daten kontinuierlich sind, im Allgemeinen langsam variieren, aber von Probe zu Probe geringfügige Abweichungen aufweisen können. Eine gute Möglichkeit, dies in 15-Minuten-Blöcken (450 Stichproben) zu codieren, besteht darin, ein Polynom erster Ordnung (oder mehr, je nach allgemeiner Art Ihrer Daten) anzupassen zu dem Datenblock, um seine Gesamtform zu erfassen. 1 sup>

Der Block würde dann als Parameter für dieses Polynom (möglicherweise vier 16-Bit-Zahlen) plus die einzelnen Stichprobenabweichungen von diesem Polynom codiert, bei denen es sich vermutlich um viel kleinere Zahlen handeln kann - möglicherweise 450 3- oder 4-Bit-Zahlen für insgesamt 1414 oder 1864 Bit anstelle der ursprünglichen 7200 Bit - ein Komprimierungsverhältnis von ungefähr 4 oder 5 zu 1.

Wenn Sie feststellen, dass Sie für die Beispieldeltas keine feste Breite verwenden können, sollten Sie die Huffman-Codierung verwenden, um sie darzustellen. Kleine Werte erhalten Kurzcodes, während die vermutlich selteneren großen Werte längere Codes erhalten . Abhängig von Ihren Daten sollten Sie immer noch in der Lage sein, ein Komprimierungsverhältnis von 3 zu 1 zu erhalten.

1 sup> Wenn sich herausstellt, dass die Daten eine zyklische Komponente haben, kann es sinnvoller sein, die wichtigsten periodischen Komponenten (Frequenz, Phase und Amplitude) mithilfe der Autoregression oder Fourier-Analyse zu identifizieren Notieren Sie die einzelnen Probendeltas aus der durch diese Parameter definierten Funktion.

jpa
2020-07-29 12:56:21 UTC
view on stackexchange narkive permalink

Ihre Daten bestehen wahrscheinlich aus zwei Komponenten:

  • Niedrige Geschwindigkeitsänderungen der tatsächlichen Spannung
  • Zufällige Abweichung aufgrund von ADC-Rauschen

Es ist wahrscheinlich, dass die zufällige Variation den größten Teil der Entropie in den Daten darstellt. Sie können es durch Oversampling reduzieren: Wenn Sie beispielsweise 4 Samples gleichzeitig nehmen und das Ergebnis durch 4 teilen, wird das Rauschen halbiert.

Es gibt kein weit verbreitetes Komprimierungsformat für die verlustfreie Komprimierung von ADC-Samples. Free Lossless Audio Codec wird manchmal verwendet, ist jedoch recht rechenintensiv und möglicherweise nicht für Ihr System geeignet. Generische verlustfreie Komprimierungsformate wie DEFLATE und LZ4 benötigen weniger Rechenressourcen, aber das Komprimierungsverhältnis ist nur dann sehr gut, wenn Sie benutzerdefinierte Vorverarbeitungsschritte hinzufügen. Daher ist es möglicherweise am besten, ein benutzerdefiniertes Komprimierungsschema zu entwerfen.

Die generische Struktur für Komprimierungsmethoden besteht normalerweise aus zwei Teilen:

  1. Vorverarbeitung zur Verbesserung der Kompressibilität: Nehmen Sie beispielsweise die Differenz zweier aufeinanderfolgender Werte oder wenden Sie eine Polynomvorhersage an.
  2. Entropiecodierung zur Darstellung jedes Symbols mit der geringsten Anzahl von benötigten Bits. Eine gängige Methode sind Huffman-Codes, bei denen entweder konstante oder dynamisch erstellte Tabellen verwendet werden.
  3. ol>

    Ein benutzerdefiniertes Format, das ich mit Erfolg verwendet habe, ist die Berechnung des Deltas zwischen aufeinanderfolgenden Samples und die Codierung der Differenz mithilfe der Elias-Gammakodierung. Es hat den Vorteil, dass es einfach zu implementieren ist und weniger als 1 Byte pro Abtastcodierung für sich langsam ändernde Signale erreicht.

Glenn Willen
2020-07-29 11:51:13 UTC
view on stackexchange narkive permalink

Die beste Codierung hängt stark von der Verteilung Ihrer Samples ab. Sie haben uns gesagt, dass die Deltas größtenteils recht klein sind, was bedeutet, dass Ihr erster Schritt mit ziemlicher Sicherheit die Delta-Codierung sein wird (wobei jeder Wert in seine Differenz zum vorherigen Wert umgewandelt wird).

Eine weitere Einschränkung ist das System, auf dem Sie die Codierung durchführen. Sie haben gesagt, es ist "eingebettet", aber das umfasst eine ganze Reihe von Funktionen. Sie haben auch gesagt, dass SD-Karten außerhalb des Gültigkeitsbereichs liegen und dass Sie jeweils nur 450 Samples im RAM puffern, was auf ein sehr kleines System hindeutet. In diesem Fall erscheint eine Optimierung zur Vereinfachung und Erhaltung von CPU / RAM angebracht.

Wenn der häufigste Delta-Wert genau 0 ist - das heißt, viele Stichproben sind dieselben wie im vorherigen Beispiel -, ist es wahrscheinlich eine gute Idee, diese Läufe mit 0-Werten zuerst "in Lauflänge zu codieren". (Das heißt, nur speichern, wie viele in einer Reihe waren.)

Der Rest hängt weiter davon ab, wie die Werteverteilung aussieht. Ich werde aus Übungsgründen davon ausgehen, dass sie fast alle im Bereich von -64 < x < 63 (d. H. Eine 7-Bit-Ganzzahl mit Vorzeichen) liegen. Ich gehe auch davon aus, dass es am einfachsten ist, mit Bytes anstatt mit Bits zu arbeiten (was wahrscheinlich zutrifft, wenn Sie beispielsweise C schreiben). Wenn dies nicht zutrifft, finden Sie ein bitweises Schema ganz unten in der Antwort. Eine sehr einfache byteweise Codierung könnte ungefähr so ​​aussehen:

0b0xxxxxxx - Ein Literalwert (Delta), der im Teil "xxxxxxx" als 7-Bit-Ganzzahl mit Vorzeichen dargestellt wird. (Werte von -64 bis 63.)

0b10xxxxxx - eine Folge von Nullen (Deltas), deren Länge durch "xxxxxx" dargestellt wird (6 vorzeichenlose Bits können bis zu 63 ausdrücken, und wenn wir mehr benötigen, können wir einfach einen weiteren Eintrag hinzufügen.)

0b110xxxxx 0byyyyyyyy - Ein Literalwert (Delta), der im Teil "xxxxxyyyyyyyy" als 13-Bit-Ganzzahl mit Vorzeichen dargestellt wird.

0b11111111 0bxxxxxxxx 0byyyyyyyy - ein Literalwert (Delta), der als 16-Bit-Ganzzahl mit Vorzeichen dargestellt wird. Dies ist (offensichtlich) eine sehr ineffiziente Codierung, da ein 16-Bit-Wert in eine 3-Byte-Darstellung umgewandelt wird. Es verschwendet unnötig Speicherplatz, um die Ausgabebytes ausgerichtet zu halten. Dieses Schema ist nur dann sinnvoll, wenn so große Deltas sehr selten sind. (Jedes nichttriviale Komprimierungsschema hat einige Eingaben, für die die resultierende Ausgabe tatsächlich größer ist; dies ist ein Satz der Informationstheorie.)

(Das obige Schema ist leicht von der UTF-8-Codierung von Unicode inspiriert.)

Im Gegensatz zu Huffman-Codes (in einer anderen Antwort erwähnt) wird die angenommene Werteverteilung im Voraus festgelegt. Dies ist eine Tugend, weil es die Dinge einfach hält und es vermeidet, den Anfang jedes Probenblocks mit Overhead zu belasten. Dies ist ein Laster, da für ein adaptiveres Schema keine Handabstimmung der Verteilung erforderlich wäre.

Wenn Deltas üblich sind, die viel kleiner als -64 bis 63 sind, muss eine bessere byteweise Codierung als die oben genannte mehr als ein Sample gleichzeitig verarbeiten, um eine bessere Komprimierung als 2: 1 zu erzielen (d. h. mehr als ein Abtastwert pro Ausgangsbyte.)

Wenn die bitweise Codierung in Ordnung ist, lautet das viel einfacher zu beschreibende Schema wie folgt: Immer noch zuerst Delta-Codierung, dann Codierung wie folgt. Auf ein 0-Bit folgt eine positive Ganzzahl variabler Länge, die die Anzahl der folgenden Nullen codiert. Auf ein 1-Bit folgt ein Vorzeichenbit, dann eine positive Ganzzahl variabler Länge, die zusammen den nächsten (Delta) Wert codiert. Die positiven Ganzzahlen variabler Länge können mit einem der Codes von https://en.wikipedia.org/wiki/Universal_code_(data_compression) wie einem der Elias-Codes codiert werden. (Welche Codierung am besten ist, hängt wiederum von der Verteilung der Daten ab, aber wahrscheinlich ist jede davon großartig.)

Die Art und Weise, wie Sie Ihren Denkprozess hier abgebrochen haben, ist äußerst hilfreich.Vielen Dank!
@toasty Gern geschehen, ich bin froh, dass dies hilfreich war!
Hinweis: Einige andere Personen haben kommentiert, dass den Samples zufälliges ADC-Rauschen überlagert wird, was zu zufälligem Jitter zwischen den Samples führt.Wenn dies zutrifft (es sei denn, Sie möchten das Rauschen zuerst herausfiltern, bevor Sie es komprimieren, was es verlustbehaftet machen würde), macht das von mir beschriebene Codierungsmaterial für die Lauflänge keinen Sinn, da bei Vorhandensein von Rauschen, das jedes Sample ändert,es wird niemals helfen.
Vegard
2020-07-29 11:29:47 UTC
view on stackexchange narkive permalink

Um Daves Idee zu erweitern, besteht eine andere Möglichkeit, einen 15-Minuten-Block zu speichern, wenn sich der Wert im Laufe der Zeit langsam ändert, darin, nur die Änderungen zu speichern.

Sie beginnen mit der vollständigen 16-Bit-Nummer und bestimmen dann, wie viele Bits Sie benötigen, um die größte Änderung zwischen zwei Abtastwerten zu speichern.Wenn beispielsweise die größte Änderung von 1050 auf 1013 erfolgt, beträgt die Differenz -37 oder 1011011 in der Zweierkompliment-Binärdatei.Dies erfordert 7 Bytes pro Abtastung anstelle von 16.

Dies schränkt natürlich Ihre Fähigkeit ein, Temperatursprünge zu protokollieren.Sie können ein Bit hinzufügen, das Sie auffordert, die nächsten 16 Bits zu nehmen und sie als vollständige Stichprobe zu interpretieren (bei großen Änderungen) oder nur die nächsten n Bits zu nehmen und sie als Delta zu interpretieren.
Michael
2020-07-29 15:46:52 UTC
view on stackexchange narkive permalink

Schreiben Sie nicht alle zwei Sekunden Daten.

Schreiben Sie Daten nur, wenn die Änderung über einem bestimmten Schwellenwert liegt und einen Zeitstempel enthält.

Sowohl für Daten als auch für den Zeitstempel können Sie Deltas (Unterschied zum vorherigen Beispiel) mit weniger Bits protokollieren und nur dann die volle Breite verwenden, wenn die Änderung die für Deltas definierte Breite überschreitet.

Brian Drummond
2020-07-29 22:51:38 UTC
view on stackexchange narkive permalink

Zwei Möglichkeiten:

  1. Rollen Sie Ihr eigenes Komprimierungsschema.Fangen Sie einfach an: Wenn beispielsweise mehrere Proben nacheinander denselben Wert haben, verwenden Sie die RLL-Codierung.Die Verfeinerung des Systems kann Forschungs- und Entwicklungsanstrengungen erfordern.Die Antworten von Dave Tweed und Glenn Willen legen gute Ansätze nahe.

  2. Wählen Sie ein vorhandenes Schema aus.Laut der Antwort von jpa fällt FLAC sofort ein (obwohl es auf Audio-Sampleraten abzielt).Wenn Sie über eine relativ leistungsfähige CPU verfügen und eine benutzerfreundliche Softwarebibliothek finden, können Sie Ihre Arbeit mit viel weniger Aufwand erledigen.

  3. ol>

    Wenn Sie nicht an Hochfrequenzrauschen interessiert sind, hilft ein Tiefpassfilter vor der Komprimierung wahrscheinlich dem Komprimierungsverhältnis in beide Richtungen.



Diese Fragen und Antworten wurden automatisch aus der englischen Sprache übersetzt.Der ursprüngliche Inhalt ist auf stackexchange verfügbar. Wir danken ihm für die cc by-sa 4.0-Lizenz, unter der er vertrieben wird.
Loading...