Höchst mögliche Timer-Auflösung erreichen

Thema: Präzisions-Zeitmessung

Wahrscheinlich schon zig Mal durchgekaut, und ich habe mit mehreren Such-Versuchen auch einiges dazu gefunden. Aber eines ist mir nicht klar geworden: Was ist die maximale Auflösung bei der Zeitmessung?

Wenn ich einen Nano mit 16MHz betreibe, und die steigende und die fallende Flanke eines Signals auf den richtigen Interrupt-Pin lege, dann müsste nach meinem Verständnis per Capture der Wert des entsprechenden Counters gespeichert werden (die korrekte Konfiguration der Register mal vorausgesetzt).

Ich denke dabei an Timer1.

Frage: Habe ich das richtig verstanden, dass ich diesen Timer mit voller Clock, also 16MHZ, laufen lassen kann?
Wenn ja: Müsste dann die maximale mögliche Auflösung nicht bei 1/16000000 Sekunden liegen, also 1/16 µs ?

So konkret konnte ich das bisher nirgendwo herauslesen.

Natürlich wird man für die kritische Dauer alle anderen Interrupts anhalten und ggf. auch die Überläufe mit zählen müssen, wenn es zu lange dauert. Und auch der Overhead der Interrupt-Routinen ist zu verrechnen. Aber das sind erst mal Nebenkriegsschauplätze.

Mich interessiert zunächst vor allem, ob ich mit meiner Annahme richtig liege: Kann ich auf diese Art eine Auflösung von 1/16 µs erreichen?

Hallo,

wenn der Timer mit Prescaler 1 läuft, damit mit 16MHz, dann ist die Auflösung dessen 62,5ns, also ein Takt. Die Annahme ist also richtig. Man wird es nur praktisch nicht hinbekommen, ein Signalwechsel mit einem Abstand von 62,5ns auch mit diesem zeitlichen Abstand zu messen. Auf Grund des bedingten Overheads. Das wäre dann die Messgenauigkeit.

Die Timer haben einstellbare Vorteiler (Prescaler). Wenn der Teiler auf 1 steht, läuft der Timer mit dem Prozessortakt

Der Interrupt zum Auswerten ist halt das Problem. Die minimale Zeit die du wirklich messen kannst ist glaube ich die Zeit die zu braucht um in die Interrupt-Routine zu springen und das Capture-Register in eine Variable zu kopieren. Das Zähler-Register wird zwar in das Capture-Register kopiert, aber wenn das zu schnell passiert wird der Wert immer wieder überschrieben bevor du was damit machen kannst.
Das lässt sich evtl. optimieren durch nackte Interrupt Routinen bei denen du selbst für das sichern benötigter Register verantwortlich bist (also der Compiler keine Push Anweisungen am Anfang macht). Aber so oder so dauert das ein klein wenig. Es liegt auch mindestens ein Takt zwischen zwei ISR-Aufrufen.

Außerdem willst du sehr wahrscheinlich sonst noch Dinge erledigen also kannst du nicht die ganze Zeit nur Interrupts ausführen :slight_smile:

hi,

hier war doch vor kurzem was über einen hardware-zähler, ich glaube auf D8?

ich weiß nicht genau, was der TO will, aber vielleicht hilft der ja.

gruß stefan

emax_:
Was ist die maximale Auflösung bei der Zeitmessung?...
Natürlich wird man für die kritische Dauer alle anderen Interrupts anhalten und ggf. auch die Überläufe mit zählen müssen, wenn es zu lange dauert. Und auch der Overhead der Interrupt-Routinen ist zu verrechnen. .

Du musst hier unterscheiden zwischen der Auflösung deiner Zeitmessung, und der kleinsten Zeitspanne, die Du messen kannst. Die Auflösung ist in der Tat 62,5ns, wenn Du mit dem Capture-Register arbeitest. Dass ist unabhängig von der Dauer der ISR-Routine und da muss auch keine Overhead verrechnet werden.
Etwas anderes ist die kleinste messbare Zeitspanne. Die hängt schon von Verzögerungen und den Laufzeiten der ISR-Routinen ab. Da kann man aber nichts verrechenen. Wenn das Capture-Register schon wieder überschrieben wurde, weil die ISR-Routine zu langsam war ist der Wert halt weg. Ist die Zeitspanne bis zum nächsten Capture-Ereignis groß genug, ist es egal wie lange die ISR-Routine zum Auslesen braucht. Der erfasste Wert hat sich ja nicht verändert.

P.S. ich glaube nicht dass der Timer als HW-Zähler hilft. Da werden Ereignisse gezählt, aber die Zeit dazwischen wird nicht erfasst. Aber vielleicht sollte mal tatsächlich mal das genaue Problem geschildert werden.

Danke allen, und die Anmerkungen zum kleinstmöglichen Intervall stimmen natürlich.

Aber das ist nicht das Problem, weil es nicht um die Genauigkeit im kurzen Bereich geht, sondern und die Auflösung, mehr dazu weiter unten.

Hier nun der Hintergrund:

Die Projekte, die ich in Sachen Ultraschall-Entfernungsmessung bisher verfolgt habe, bedienen sich meist der gängigen Timer-Unterstützung im Arduino-System, was ja auch ok ist. Ich möchte aber genauer messen, als ich es dort gesehen habe.

Was zu messen ist: Der Heizöl-Stand in einer Batterie von vier Tanks a 2000 Ltr = 8000 Ltr Gesamtvolumen. Jeder Einzeltank ist 168 cm hoch. Das heisst, je Millimeter Pegel entspricht das (etwa) 2000Ltr/1680mm = 1,19 Liter je 1mm Pegelhöhe (die Tankrundungen oben und unten mal vernachlässigt).

Da es vier solcher Tanks sind, und diese verbunden sind, komme ich auf 4x1,19 Liter je mm Pegel = 4,76 Liter.

Nun erreichen die mir bekannten Projekte nie mehr als 3mm Genauigkeit, ich könnte mit einer Messung so also nie genauer als gut 14 Liter sein. Das liegt m.E. daran, dass nicht die volle Leistungsfähigkeit der ATMega-Hardware genutzt wird.

Das Ganze funktioniert so, dass z.B. ein US-100 Sensor für die Laufzeit des Signals einen High-Pegel ausgibt.

Wenn man nun einen maximal schnellen Timer im Capture Mode laufen lässt, und mit der steigenden und dann der fallenden Flanke misst, ließe sich -rechnerisch- eine Auflösung von etwa 0,02 mm erreichen. Lässt sich nachrechnen: 331,4 m/s * 1/16 µs.

Da es sich dabei um die Hin- und die Rückstrecke handelt, wäre die Genauigkeit sogar doppelt so hoch.

Im Optimalfall wäre für die Verbrauchsmessung also eine Auflösung von 0,01* 4,71 Liter = 47ml möglich. (Ich glaubs grad selber nicht).

Wenn ich mich in meiner Begeisterung nicht irgendwo blöd verrechnet habe, wäre das - bei einem 8000 Liter Tank (!) - sensationell !

Ok, Praxis schlägt natürlich immer Theorie. Man muss die Lufttemperatur berücksichtigen, und auch die des Öls, es dehnt sich bei Wärme ja aus. Und dann hat der Sensor sicher auch so seine Wiederhol-Ungenauigkeiten.

Aber die Luft/Öl-Temperatur kann ich mit einem Lookup-Table berücksichtigen, ebenso die Rundungen des Tanks. Und mit den Sensor-Abweichungen muss ich leben. Der Mittelwert aus 10 oder 100 Messungen hintereinander sollte das lindern.

Es müsste jedenfalls genauer gehen, als das, was ich bisher gesehen habe.

Der Nano hat weiter nichts zu tun, als drei oder vier mal am Tag, oder von mir aus auch stündlich diese Messung zu machen, und per NRF24L01 weiter zu geben.

Und nun ist auch klar, warum ich keine Kurzeit-Genauigkeit brauche, sondern Auflösung. Die Mindeststrecke wird bei 15-20 cm liegen, das sind gut 450 Mikrosekunden. Danach ist dann unendlich viel Zeit, in der ich ich die summierten Overhead-Aufwendungen abziehen Temperaturkompensationen und Tanksymmetrien berechnen kann.

Vielen Dank noch mal allen, und wenns Anregungen, Einwände oder Tipps zur Idee gibt, freu ich mich natürlich drüber. :slight_smile:

PS: MicroBahners und mein Beitrag haben sich überlappt. Wie ich sehe, genau den Punkt getroffen. Und Du hast natürlich Recht: Overhead ist nicht, ist ja Capture. :blush:

MicroBahner:
Ich glaube nicht dass der Timer als HW-Zähler hilft. Da werden Ereignisse gezählt, aber die Zeit dazwischen wird nicht erfasst.

Er meint den Interrupt Capture Modus. Der misst in der Tat die Zeit zwischen zwei Flanken. Der Zähler zählt und wenn das Ereignis eintritt wird der Zähler in das Capture-Register kopiert und ein Interrupt ausgelöst.

Die Mindeststrecke wird bei 15-20 cm liegen, das sind gut 450 Mikrosekunden

450us sind massig Zeit. Das ist nicht so extrem wie du anfangs angedeutet hast

Ja stimmt, die Thread-Überschrift war unkorrekt.

Habs geändert.

Serenifly:
Er meint den Interrupt Capture Modus. Der misst in der Tat die Zeit zwischen zwei Flanken. Der Zähler zählt und wenn das Ereignis eintritt wird der Zähler in das Capture-Register kopiert und ein Interrupt ausgelöst.

Mein Einwand bezügl. des HW-Zählers bezog sich auf den Vorschlag von Stefan (Eisebaer). Da hate ich den Eindruck, dass er den externen Zählermode uind nicht den Capture meinte.

Der meint das gleiche. D8 ist der Interrupt Capture Pin (ICP1) von Timer1. Ja, der Timer rein als Zähler ist genaugenommen was anderes, aber letztlich zählt man die Zeit auch in Hardware

@emax_: Hast Du mal ermittelt, was so pro Tag verbraucht wird? Wenn Du nur 4 mal am Tag messen willst, könnte das den möglichen Spielraum noch erweitern.

Es kommt ja vor allem darauf an, was Du erreichen willst. Eine Verbrauchsmessung über diesen Weg (zur Abrechnung) wird Dir keiner abnehmen.
Wenn es um die Vorratsmenge geht, ist die Genauigkeit nicht notwendig.

Alter Messgrundsatz: So genau wie nötig, nicht so genau wie möglich.

Die Anwendung ist uns aber nicht bekannt.

Gruß Tommy

Serenifly:
Der meint das gleiche. D8 ist der Interrupt Capture Pin (ICP1) von Timer1. Ja, der Timer rein als Zähler ist genaugenommen was anderes, aber letztlich zählt man die Zeit auch in Hardware

Ok, sorry mein Fehler, irgendwo gab's hier vor einiger Zeit mal was wo es um die externen Takteingänge ging. Aber das wäre D5 gewesen :-[

Hallo Tommy,

nein, keine Verbrauchsmessung für Abrechnungszwecke.

Mein alter Herr (90 Jahre) schafft den Weg in den Keller nicht mehr, und hat ständig Angst, dass das Öl alle ist. Also möchte ich ihm eine Anzeige bereitstellen, wo er aufs Knöpfchen drückt, das Nokia-5110 Display geht an, und zeigt ihm den Restbestand an.

Die Daten gehen auf eine SD-Karte im Anzeigemodul (wird auch ein Nano), so dass der Messzyklus unabhängig von den Anfragen immer gleich ablaufen kann.

Dazu noch eine nette Grafik über den Wochen-, Monats-, Quartals- und Jahresverbrauch. Das ist alles.

Die Genauigkeit, das ist mein eigener Spleen, möchte ich ans Limit bringen. Ist so ein schönes, kleines, unkritisches Projekt, wo man mal das Machbare bis zum Abwinken durchexerzieren kann. Am Ende wird es dann vermutlich doch wieder 'unerklärliche' Abweichungen geben, kennt man ja.

Aber es ist Hobby, gepaart mit Spieltrieb und beruflicher Vorbelastung (Entwickler).

Wird eine Weile dauern. Aber wenn was dabei herausgekommen ist, stelle ich es hier mal vor - wenn ich es nicht vergesse oder die üblichen Katastrophen dazwischen kommen. :wink:

Ok. Wenn die Genauigkeit nur Dir geschuldet ist, solltest auch nur Du mit den daraus resultierenden Problemen leben müssen :wink:

Gruß Tommy

emax_:
Die Projekte, die ich in Sachen Ultraschall-Entfernungsmessung bisher verfolgt habe, bedienen sich meist der gängigen Timer-Unterstützung im Arduino-System, was ja auch ok ist. Ich möchte aber genauer messen, als ich es dort gesehen habe.

Was zu messen ist: Der Heizöl-Stand in einer Batterie von vier Tanks a 2000 Ltr = 8000 Ltr Gesamtvolumen. Jeder Einzeltank ist 168 cm hoch. Das heisst, je Millimeter Pegel entspricht das (etwa) 2000Ltr/1680mm = 1,19 Liter je 1mm Pegelhöhe (die Tankrundungen oben und unten mal vernachlässigt).

Du willst wirklich in einen Heizöltank Elektronik einbauen? Soll's eine Hobbybombe werden? Vergiß es schnellstens.

Laß Dir Flußmesser am Abfluß und am Rückfluß einbauen und errechne mit diesen den Verbrauch bzw wieviel noch in den Tanks ist.

Alternativ konntest Du einfach die Zeit messen wo der Brenner eingeschaltet ist. Der hat auch einen konstanten Verbrauch und darum eine Messung des Verbrauchs. Dann kannste ja einmal die Woche den Heizölstand nachmessen und so korrigieren bzw den Verbrauch genauer berechnen.

Dein Alter Herr wird sicher auch zufrieden sein, wenn die Anzeige um einige 100 l falsch anzeigt. Hauptsache sie zeigt keine negativen Werte an oder Werte nahe bei Null.

Du machst Dir gedanken wie Du die Zeitdauer des Signals des Ultraschallsensors messen kannst, bedenkst aber nicht daß auf dem Sensor ein Kontroller verbaut ist, von dem Du nicht im geringsten die Programmierung kennst und darum auch nicht wie lange und wie konstant die Verarbeitungszeit des Empfangssignal das Mikrofons ist.

Kann ein Ultraschallsensor eigentlich Distanzen unter der Periode der Ultraschallschwingung (wellenlänge) messen?

Wenn's Du sehr genau haben willst kannst Du ja einen dikreten Zähler mit Taktgenerator bauen, der mit dem Signal des Ultraschallwandlers gestartet/ gestoppt wird und mittels Arduino ausgelesen wird. So ist das unabhängig von der Programmierung des Arduinos aber immernoch abhängig von der Signalauswertung im Sensor.
Grüße Uwe

uwefed:
Du willst wirklich in einen Heizöltank Elektronik einbauen?

Ach...
Vielleicht, kann man ja mit einer Berstscheibe das Problem noch weiter optimieren...