So ordnen Sie den 10-Bit-ADC-Wert einem Bereich mit Einschränkungen zu

Ich muss einen 10-Bit-ADC, dh [0-1023], einem Bereich [1-100] zuordnen. Die Abbildungsformel selbst ist das direkte „y=(xa)/(ba)*(dc)+c“, um x in [ab] auf y in [cd] abzubilden.

Eingang x wird als Durchschnitt von beispielsweise 1000 ADC-Messwerten berechnet.

Mein Problem ist folgendes. Der Eingang zum ADC ist ein Potentiometer und ich muss x NUR berechnen, wenn das Potentiometer stationär ist. Wie erkennt man das? Die Art und Weise, wie ich es derzeit mache, besteht darin, Sätze von 1000 ADC-Werten (auf einem Timer) zu lesen, ihren Durchschnitt zu berechnen und den "aktuellen Durchschnitt" mit dem "vorherigen Durchschnitt" zu vergleichen. Wenn "aktueller Durchschnitt - vorheriger Durchschnitt" etwas "+-Delta" ist, gehe ich davon aus, dass das Potentiometer stationär ist, und führe die Berechnung durch.

Gibt es einen besseren Weg, dies zu tun?

Bearbeiten: Um weitere Daten bereitzustellen;

  • Ich verwende eine C8051F850 MCU von SiLabs, die mit 24,5 MHz läuft
  • ADC-Proben werden alle 100 us gesammelt
  • Der Durchschnitt von 2500 Samples ~ 250 ms wird pro Satz berechnet. Somit werden alle 500 ms zwei Mittelwerte verglichen.
  • Mein "Delta" beträgt 10 Einheiten (ungefähr 1024/100)
  • Integer-Arithmetik also Rundungsfehler
Ich verstehe nicht, was der Bereich und die Gleichung mit dem Problem zu tun hat. Vielleicht sollten Sie es einfach entfernen und sich hier auf Ihr eigentliches Problem konzentrieren. Ich denke, das eigentliche Problem, mit dem Sie konfrontiert sind, ist jedoch eine Art XY-Problem .
@pipe - Ich habe das vollständige Problem und meine aktuelle Lösung dargestellt, damit der gesamte Kontext klar ist. Es funktioniert, aber ich bin nicht zufrieden damit und daher meine Frage. Gibt es etwas Bestimmtes, das Sie mir klarstellen möchten?
Verwenden Sie einen Software-Tiefpassfilter

Antworten (2)

Dies ist ein „Hypothesentest in Gegenwart von Rauschen“.

Wenn wir Hypothesen testen, definieren wir ein Paar von Bedingungen, zwischen denen wir unterscheiden wollen, und definieren dann einen Test, um dies am besten zu tun.

Sie haben eine Bedingung „ist stationär“ und einen Test |(aktueller_Durchschnitt – vorheriger_Durchschnitt)| definiert <Delta. In dieser Definition sind zwei weitere Bedingungen enthalten, die Bewegung nach oben und die Bewegung nach unten.

Während die Definition von „ist stationär“ nicht gut definiert ist, wenn wir den von Ihnen entwickelten Test zurückentwickeln, um herauszufinden, was das wirklich bedeutet, die Änderung der durchschnittlichen Position zwischen den ersten 1000 und den nächsten 1000 einer 2000 langen Stichprobe von Positionen, finden wir, dass es eine ziemlich vernünftige Sache ist.

Der Durchschnitt von 1000 Samples ist der beste Weg, um eine durchschnittliche Position zu berechnen, wenn wir davon ausgehen, dass das Rauschen bei jedem Sample unabhängig ist. Es ist auch schnell, verbraucht wenig Ressourcen, ist leicht verständlich und verbraucht wenig Speicher (muss nicht alle Eingaben speichern).

Die Differenz zwischen dem ersten und dem zweiten Satz gibt Ihnen die beste Schätzung der mittleren Geschwindigkeit des Pots über diese Zeit.

Betrachten Sie nun diesen Testfall. Bei den ersten 1000 Proben schwenkt der Topf schnell nach oben, bei den nächsten 1000 schwenkt er schnell nach unten. Die von Ihrem Schätzer berechnete mittlere Bewegung in diesem Zeitraum ist null.

Sind Sie froh, dass dieser Zustand als stationär erkannt wird? Wenn nein, dann müssen wir unsere Definition von stationär ändern. Laut Ihrem Kommentar sind Sie mit etwas nicht zufrieden. Aber was?

Wie Sie sehen, liegt das Problem nicht beim Test selbst, sondern bei (a) Ihrer schlechten Definition dessen, was „stationär“ bedeutet, und (b) Ihrer schlechten Definition dessen, was Sie an der Leistung des vorliegenden Tests unbefriedigend finden.

Der von Ihnen definierte Test ist der vernünftigste Test, den es gibt, um die Durchschnittsgeschwindigkeit in Gegenwart von Rauschen zu erkennen. Ob dies mit Ihrer realen Physik und Ihrem Benutzerverhalten gut funktioniert, ist eine andere Frage.

Wenn Sie feststellen, dass Sie die Beschleunigung tatsächlich erkennen müssen, um sie in Ihrem Fall zu verbessern, ist es ganz einfach, drei aufeinanderfolgende gemittelte Abtastungen zu nehmen, beide Deltas zu berechnen und dann das Delta-Delta zu berechnen.

Wenn Sie feststellen, dass eine Änderung der durchschnittlichen Größe, um die Rate zu ändern, mit der Änderungen erkannt werden können, besser funktioniert, dann tun Sie dies.

Es gibt andere Alternativen, die andere Hypothesen testen. Die erste wäre, zwei laufende Mittelwerte mit unterschiedlichen Zeitkonstanten zu berechnen. Dies ist ein gebräuchlicher Filter, der als Kantendetektor in der Bildverarbeitung verwendet wird, erkennt aber auch "Kanten" in eindimensionalen Daten. Da die Filter rekursiv sind, ist dies recht günstig zu implementieren. Allerdings müssten Sie die beiden Zeitkonstanten auf Ihre Situation abstimmen, also wie würden Sie sie besser abstimmen als die eine Zeitkonstante Ihres aktuellen Testers?

Die zweite besteht darin, eine FFT Ihrer Proben durchzuführen. Sie können dann die Energie im DC-Bin (Menge an Stillstand) mit der Energie in den Niederfrequenz-Bins (Bewegungsbetrag, Beschleunigung, Beschleunigungsänderung ...) vergleichen, während Sie die Energie in den Hochfrequenz-Bins (Leserauschen) verwerfen. . Aber das braucht viel Speicher und Rechenleistung und scheint übertrieben zu sein.

Ein drittes, basierend auf Ihrem Kommentar, dass die Latenz das Problem ist, wäre die gleichzeitige Schätzung der Position unddie Steigung der Geraden durch lineare Regression. Dafür gibt es eine rekursive Formel, daher ist es für Sie relativ effizient, ohne zusätzlichen Speicher in Echtzeit zu rechnen. Dies würde es Ihnen ermöglichen, die Verzögerung beim Sammeln der Daten zu „korrigieren“, indem Sie beide Schätzungen nach vorne extrapolieren, um die gemittelte Position „jetzt“ zu erhalten. Beachten Sie, dass die lineare Regression Probleme mit dem dynamischen Bereich haben kann, wenn sie für große Datensätze durchgeführt wird, und da Sie ganzzahlige Arithmetik verwenden, müssen Sie sorgfältig über die Implementierung nachdenken. Eine Möglichkeit, die Dinge zu verbessern, wäre, die lineare Regression zu dezimieren und mit einer viel niedrigeren Abtastrate auszuführen, die besser mit der Geschwindigkeit übereinstimmt, mit der Ihr Topf in der realen Welt bewegt wird, und mit der Reaktionszeit, die das Programm haben soll.

Tolle Erklärung! Danke schön. Mein Problem ist, dass wenn sich der Topf nach unten bewegt (dh ich erhalte Werte von 1023 nach unten) vs. wenn sich der Topf nach oben bewegt (dh ich erhalte Werte von 0 aufwärts), der Durchschnitt zu den oberen oder unteren Enden hin verzerrt wird. Dies wird verstärkt, wenn die Person den Topf sehr schnell dreht. Wie entferne ich diese Schräglage? Ein Ansatz besteht darin, den obigen Test zu verwenden, um "stationär" zu erkennen, beide Mittelwerte wegzuwerfen, einen neuen Satz von Mittelwerten zu sammeln und zu verwenden (z. B. über 100 ms) und diesen als Eingabe x zu verwenden. Dies fügt meiner Reaktionszeit offensichtlich mehr Latenz hinzu, die ich nach Möglichkeit vermeiden möchte.
Ich habe meinen ursprünglichen Beitrag mit einigen weiteren Daten bearbeitet.
@RamanathanR Ihre OP-Bearbeitung scheint nichts Relevantes hinzuzufügen, aber Ihr Kommentar oben deutet darauf hin, dass Latenz das Problem ist. Ich habe meine Frage aktualisiert, um dies im letzten Absatz anzusprechen. Sie können auch in Betracht ziehen, die Abtastrate mit einem linearen Filter auf etwas zu dezimieren, das Ihren gewünschten Reaktionszeiten besser entspricht, und "intelligentes" Zeug mit einer viel niedrigeren Abtastrate zu machen. Dies wird das Problem gut aufteilen und zu einer besseren Implementierung führen. Die Details gehen über eine Diskussion in diesem Forum hinaus, aber wir können uns offline unterhalten, wenn Sie detaillierte Hilfe wünschen.

Mittelung macht ein paar Dinge; und es gibt bessere Wege.

  1. Fügt Latenz = n * Abtastintervall hinzu
  2. Reduziert zufälligen Jitter um Vpp/ N
  3. Fungiert als erster Tiefpassfilter, wobei ein gewichteter Filter die gleiche Rausch-BW mit steileren Rändern und geringerer Gruppenverzögerung (Latenz) haben kann, genau wie aktive Filter.

  4. Kann Aliasing-Fehler verursachen, wenn Signale die Nyquist-Frequenz vor der Mittelwertbildung überschreiten, daher ist eine gewisse Filterung erforderlich, aber ein Brick-Wall-Filter >= 5. Ordnung ist besser für niedrige Latenzzeiten, die im Wesentlichen Werte für die Mittelwertbildung gewichten.

  5. Wenn Sie auf den Leerlauf warten und der Topf Zittergeräusche durch Vibrationen hat, wird dies zu einer übermäßigen Latenz führen.

  6. Wenn Sie einen anderen kontinuierlichen gewichteten Mittelwert entwerfen, können Sie die Gruppenverzögerung und den Bewegungsfehler mithilfe von Parametern wie einem Kalman-Filter optimieren. Dies wird in GPS und anderen Bewegungspositions-, Geschwindigkeits- und Beschleunigungssensoren verwendet.

6b. ... wie @Neil_UK vorgeschlagen hat, können Sie eine FFT an den Werten durchführen (oder exportieren und analysieren), dann kann ich der Reihe nach einen angepassten Filter für das Grundsignal verwenden (Anstiegsrate 10 ~ 90% = tR = 0,35 / f-3dB). um das Rauschen unter Verwendung von Gewichtungswerten auf gleitenden Durchschnitten zurückzuweisen.

  1. Sie können eine Geschwindigkeitsgewichtung anhand der mittleren Differenz der Werte verwenden, um die Position aufgrund der Latenz vorherzusagen und mit weniger Verzögerung zu einem glatten Ergebnis zu gelangen. Dann können Sie die Anzahl der zum Dezimieren erforderlichen Samples (Auflösung reduzieren) auf 1%-Werte (0 ~ 99) reduzieren.

Ich überlasse es anderen, den Dezimierungsalgorithmus zu skizzieren, was grundlegende Algebra ist.

ps Ich würde für diese Anwendung, wie sie in modernen Systemen verwendet wird, einen Inkremental-Quadratur-Encoder mit Arretierungen anstelle eines Potentiometers verwenden.

Vielen Dank für all die Ideen. Ich habe viel zu denken (und zu lesen) :-)