Genauigkeit micros()

Hallo,
Wie bekomme ich heraus, wie genau mein Arduini Pro mini mit 328 die micros() zählt? Ich habe eine Schaltung, die einen durchschirttenen Winkel seit letzter Anfrage ausgibt, und will damit die Rate bestimmen, also die wieviel Grad pro Minute. Dazu triggere ich meinen Sensor an und messe die Zeit zwischen zwei Triggern. Leider weicht der Wert immer wieder von einem Vergleichswert ab, ich habe Temparaturschwankungen im Quarz als Ursache im Hinterkopf. Kann mir einer was dazu sagen?
Danke!

Sketch? Unnötige Delays?
Sollte sich nicht auf die micros() auswirken. Fehlerquote liegt bei 30-50 Millionstel.

Fehlerquote liegt bei 30-50 Millionstel.

Verstehe ich nicht.
micros() springt in 4er Schritten und das passiert sicher nicht exakt alle 4000 ns. Zumal bei 16MHz ein Takt 62,5 ns beträgt.
Bis du micros() abgefragt hast, ist schon fast / ungefähr eine µs rum. :wink:

sschultewolter:
Sollte sich nicht auf die micros() auswirken. Fehlerquote liegt bei 30-50 Millionstel.

Ich verstehe das als Genauigkeit 30-50 µsec..

Dein Messaufbau wäre bestimmt auch interessant. Es klingt so, als ob du eine zu hohe Genauigkeit von einem Ultraschallentfernungssensor erwartest.

Der Sensor ist ein faseroptischer Kreisel, der ist hochgenau.
Er gibt mir nach dem Antriggern den WErt der druchschrittenen Winkel seit dem letzten Trigger aus. Wenn ich also triggere, und den Sensor um 45° drehe, dann wieder triggere, dann gibt er mit 45° raus. Das klappt auch sehr gut. Ich kann ihn drehen wie ich will, wenn ich die Messwerte aufsummiere, komme ich immer wieder bei 0° an, wenn ich ihn in die Ausgangslage bringe.
Wenn ich die Zeit messe, die zwischen zwei Werten vergangen ist, kann ich sagen, x° sind in yMinuten vergangen. Aber genau der Wert passt eben nicht.

// rot := Drehrate [°/min]
  // RLV := Real Life Value, Messwert mit Skalierungsfaktor und BIAS
  //invervalDur := Dauer zwischen zwei Abfragen
  rot = (60e6 * RLV / intervalDur);

Achso, 60e6 nur, um von gemessenen Microsekunden auf Minuten zu kommen [°/min]...

Hallo,

könnte da die geringe Rechengenauigkeit des Arduinos reinspielen? Und wie genau sind die Werte deines Sensors aufgelöst? Du fragst vermutlich in sehr kurzen Abständen ab um auf Grad/Minute hochzurechnen. Da reichen schon minimale Rechenungenauigketen und Auflösungsschwächen um größere Abweichungen zu produzieren, wenn du den Wert mit einer Million multiplizierst.

leclerke:
Wenn ich die Zeit messe, die zwischen zwei Werten vergangen ist, kann ich sagen, x° sind in yMinuten vergangen. Aber genau der Wert passt eben nicht.

Der micros() Zähler auf dem Arduino zählt in Schritten von je 4 weiter, also 4, 8, 12, 16 etc., die absolute Genauigkeit liegt bei Resonatoren als Taktgeber auf dem Board bei etwa 1000 ppm (bei Schwingquarz-Taktgenerierung etwa 10 mal genauer) und der Zähler läuft ungefähr alle 70 Minuten einmal über.

Bei der Genauigkeit aufgrund der spezifischen technischen Ausführung des Arduino kommen also drei Problemfelder in Betracht:

  1. Genauigkeit zwischen zwei Auslesungen: 4 µs
    Die zeitliche Auflösung des Timers ist nicht größer, also können zwischen zwei Auslesungen Fehlauslesungen von 4µs auftreten.

  2. Absolute Genauigkeit des Taktsignals
    Bei 1000 ppm Ganggenauigkeit sind das 1000 µs Ungenauigkeit bei tatschlich 1 Million vergangener µs, D.h. tatsächliche 1000µs könnten auf dem Arduino auch entweder 999 oder 1001 µs sein, bzw. wegen der Zählung in Viererschritten: Wenn tatsächlich 4000 µs vergehen, könnte der Arduino entweder 3996 µs oder auch 4004µs zählen, je nachdem ob der Taktgenerator zu schnell oder zu langsam tickt.

  3. Beim Überlauf des 32-Bit Zählers springt der Zählerstand wieder auf 0 und beginnt von vorne zu zählen
    Auswerteroutinen müssen daher so programmiert werden, dass der Zählerüberlauf alle 70 Minuten nicht zu Fehlmessungen führt (falls das Programm länger als 70 Minuten am Stück laufen soll).

Von diesen Problemfeldern abgesehen scheint Dein Messaufbau auch Ungenauigkeiten durch die Asynchronität der internen Messungen Deines Sensors und die Abfrage zu beliebigen Zeitpunkten durch die Triggerung vom Arduino zu leiden. Beispiel: Man stelle sich ein Rad vor, dass ca. 1,5 Umdrehungen pro Sekunde ausführt und einmal pro Radumdrehung einen Impuls abgibt. Von außen kann man zu beliebigen Zeitpunkten die Anzahl der Impulse seit der letzten Abfrage abfragen. Was passiert nun, wenn man mit einer Rate von 1 pro Sekunde die Drehzahl des Rades abfragt, wenn es mit 1,5 pro Sekunde dreht? Ergebnis; Man bekommt Messungen, die mal 1 sind und mal 2. Obwohl sich das Rad stets gleichbleibend mit 1,5 pro Sekunde dreht, erhält man durch das Sampling mit anschließender Berechnung mal die Drehzahl 1 pro Sekunde und mal 2 pro Sekunde. Die Geschwindigkeit scheint heftig zu schwanken, obwohl sie konstant ist.

Wieso das?
1,5 Umdrehungen pro Sekunde bedeuten ca. 667 ms pro Radumdrehung.

Wenn nun der erste Impuls nach 100 ms und dann wieder nach 767 ms Sekunden gezählt wird, hat man zwei Impulse in einer Sekunde.

Kommt aber der erste Impuls erst nach 500 ms, dann würde der nächste Impuls erst nach 1167 ms kommen, also nicht mehr in derselben Sekunde, man zählt nur 1 Impuls pro Sekunde.

Und das passiert bei Deiner Messung auch, wenn Du die Samplingrate durch den Arduino und die interne Messrate des Sensors nicht perfekt synchronisieren kannst.

Falls Du also Dein Messverfahren nicht verbessern kannst, und wenn die Anzahl der Messungen sehr viel schneller aufeinander folgen als Geschwindigkeitsänderungen auftreten, könnte Dir die "exponentielle Glättung" der Messwerte im zeitlichen Verlauf helfen. Da Du zeitlich veränderlich und prinzipbedingt mal zu hohe und mal zu niedrige Werte ermittelst, ergibt sich der richtige Wert durch exponentielle Glättung. Sehr schnelle Geschwindigkeitsänderungen werden dabei allerdings ebenso geglättet wie Dein prinzipbedingter Messfehler durch unterschiedliche Samplingraten von Arduino und Sensor: D.h. um Änderungen der Geschwindigkeit nicht mit zu großer zeitlicher Verzögerung festzustellen, muss der Glättungsfaktor angemessen gewählt werden.

Und falls die Änderungsgeschwindigkeit des Messwertes sehr hoch ist im Vergleich zur Samplingrate, kannst Du Dein asynchrones Messprinzip, bei dem die Samplings des Sensors mit den Samplings des Arduino asynchron laufen, vergessen. Dann würdest Du stattdessen synchron messen müssen, d.h. der Sensor gibt immer dann einen neuen Wert aus, wenn er intern ein neues Sample selbst gemessen hat. So dass der Arduino aufgrund derselben Zeitbasis rechnen kann wie der Sensor tatsächlich mißt.