Geschrieben am

Nicht konstante Poti-Werte am Arduino ausgleichen Tutorial

Wenn dein Arduino keine konstanten Werte von den Potis liefert sondern diese leicht schwanken oder zittern, kannst du dies mit einem einfachen Programmier-Trick glätten und die Schwankungen am Poti beseitigen. In diesem kurzen Tutorial zeige ich dir wie’s geht.

So geht’s:

Und so kann man die Zeitverzögerung durch die Glättung umgehen:

int potiWert = 0;
int smoothWert = 0;

int potiWertAlt = 0;
int quickSmooth = 0;
int differenz = 0;
boolean quickAktiv = false;
int x = 0;

void setup() {
 Serial.begin(9600);
}

void loop() {
 
 potiWert = analogRead(A0);
 
 smoothWert = 0.6 * smoothWert + 0.4 * analogRead(A0);
 
 differenz = abs(potiWert - potiWertAlt);
 
 if (differenz <= 5 && quickAktiv == false) {
 quickSmooth = 0.6 * smoothWert + 0.4 * analogRead(A0);
 }
 else if (differenz <= 5 && quickAktiv == true){
 quickSmooth = analogRead(A0);
 x++;
 }
 else {
 quickSmooth = analogRead(A0);
 quickAktiv = true;
 };
 
 if (x >= 10) {
 x = 0;
 quickAktiv = false;
 };
 
 potiWertAlt = potiWert;
 
 Serial.print("\t");
 Serial.print(potiWert);
 Serial.print("\t");
 Serial.print(smoothWert);
 Serial.print("\t");
 Serial.print(differenz);
 Serial.print("\t");
 Serial.print(quickSmooth);
 Serial.print("\t");
 Serial.println(quickAktiv);
}

Ein Gedanke zu „Nicht konstante Poti-Werte am Arduino ausgleichen Tutorial

  1. Im Gegensatz zu zum Beispiel Desktop-CPUs haben die meisten AVRs, die das Herzstück der Arduinos darstellen, keinen Floating-Point-Support in Hardware. Das heißt, der Compiler muss alles in Software nachbauen, wenn man Fließkommarechnungen verwendet. Das macht die Geschichte natürlich langsam. Daher verwendet man – wo möglich – besser nur Integer-Operationen. Eine sehr gute und ausführliche Betrachtung dazu findet Ihr hier: http://bleaklow.com/2012/06/20/sensor_smoothing_and_optimised_maths_on_the_arduino.html

    Wer keine Lust hat, unter dem Link alles nachzulesen und/oder Assembler scheut, kann diese zwei Zeilen hier verwenden, diese ist ca. 6x schneller als die Floating-Point-Lösung. Wenn es für eure Anwendung egal ist, dass es länger dauert, könnt Ihr bei der Version von Götz bleiben.

    smoothWert = (smoothWert * 10) + (analogRead(A0) * 6);
    smoothWert = (smoothWert + 8) >> 4;

    Kurz zur Erklärung: Statt mit Floating-Point-Arithmetik wird mit Fixed-Point-Arithmetik gearbeitet, hier mit 4 Bit nach dem Komma.
    Möchte man jetzt ganz allgemein a = x * k + y * l berechnen, muss man dafür Folgendes tun:

    a = (x * j) + (y * i);
    a = (a + 8) >> 4;

    Um den Integer-Wert j zu erhalten, muss man k = j / 2^4 für j lösen, also j = k * 2^4. Den Wert i kann man dann so berechnen: i = 2^4 – j.

    Am Beispiel:
    j = 0.6 * 2^4 = 9.6, also rund 10.
    i = 16 – 10 = 6.

    Die zweite Zeile sorgt für die Rundung (via +0.5 und abschneiden der Nachkommastellen) und skaliert das Ergebnis wieder zurück in die „normale“ Skala, denn zuvor haben wir ja mit dem jeweiligen Bruchteil von 2^4 die Zahlen größer gemacht. Die +8 sind die oben genannten +0.5, denn 2^4 / 2 = 8.

    Die Genauigkeit kann erhöht werden, indem man überall statt 2^4 z.B. 2^6 verwendet. Aber Achtung: Gerade 8-Bit-AVRs kommen schnell an die Grenze des Wertebereichs, selbst wenn man uint16_t statt int o.Ä. verwendet. Bei 16 Bit für eine uint16_t-Variable und Poti-Werten von 0 – 255 (8 Bit) sind so maximal 8 Bit nach dem Komma möglich, denn es muss gelten: (255 * 2^8) + (2^8 / 2) <= 2^16 – 1. D.h. hier wäre sogar 2^8 statt 2^4 noch in Ordnung.

Kommentar verfassen