Zeitmessung am Arduino UNO über Interrupt
Moderatoren: MaxZ, ebastler, SeriousD
-
- Beiträge: 554
- Registriert: Fr 24. Jul 2015, 10:13
- Schule/Uni/Arbeit: KFZ-Elktr.
- Hat sich bedankt: 24 Mal
- Danksagung erhalten: 23 Mal
Zeitmessung am Arduino UNO über Interrupt
Es gibt ja nun genug Beispiele im Netz wie man zB. eine Stoppuhr mit dem UNO realisieren kann.
Ich möchte aber Zeiten messen, die im µs-Bereich , so etwa ab 50 µs, liegen. Der Messvorgang startet sporadisch und es sind recht kurze Zeiten
Daher kann und will ich den ProgCode nicht in die "void loop()" - Schleife packen, sondern die beiden Interrupt's am UNO verwenden.
So soll das dann ablaufen :
beim "Vorbeigang" eines Objektes erzeugt die 1. Lichtschranke einen Impuls der durch einen nicht retriggerbaren Monostab. Multivibrator
zu einem definierten LOW - HIGH - LOW Impuls mit einer Breite von 2 µs geformt wird.
Dieser Impuls löst am UNO-Pin 2 den Interrupt (Ext Int) 0 aus.
Die ISR dafür sieht so aus
void ISR_Ext0()
{
Startzeit = micros();
}
der Zähler für die micros sollte dort auch weiterlaufen lt. Arduino-Referenz ... unvorhersehbar verhalten... was auch immer das bedeuten mag
Die ISR ist recht kurz und wird, schhätze ich, weniger als 1 - 2 ms dauern
Danach Rücksprung in die "void loop()" - Schleife und .... der Zähler für die micros zählt ja derweil weiter ....
nach einiger Zeit... beim "Vorbeigang" des Objektes an der 2. Lichtschranke wird auch wieder ein Impuls (wie an der 1. Lichtschranke) erzeugt der
am UNO-Pin 3 den Interrupt (Ext Int) 1 auslöst. Die ISR dafür sieht so aus
void ISR_Ext1()
{
Stopzeit = micros();
}
Danach Rücksprung in die "void loop()" - Schleife , die Start- und Stopzeit auswerten und zB. auf einem LCD anzeigen lassen.
Bei einen einmaligen Durchlauf sollte das eigentlich so funktionieren. Auch bei mehrmaligen Durchlauf sollte es klappen. Ich muß nur sicherstellen,
daß während der Auswertezeit und der Anzeige die Interrupt's gesperrt sind.
Das ist jetzt nur erst einmal ein Entwurf und ich wollte diesen Entwurf auch noch weiterentwickeln (zB. Dauermessung) oder hat jemand eine andere/bessere Idee ?
Gruß
Ludwig
Ich möchte aber Zeiten messen, die im µs-Bereich , so etwa ab 50 µs, liegen. Der Messvorgang startet sporadisch und es sind recht kurze Zeiten
Daher kann und will ich den ProgCode nicht in die "void loop()" - Schleife packen, sondern die beiden Interrupt's am UNO verwenden.
So soll das dann ablaufen :
beim "Vorbeigang" eines Objektes erzeugt die 1. Lichtschranke einen Impuls der durch einen nicht retriggerbaren Monostab. Multivibrator
zu einem definierten LOW - HIGH - LOW Impuls mit einer Breite von 2 µs geformt wird.
Dieser Impuls löst am UNO-Pin 2 den Interrupt (Ext Int) 0 aus.
Die ISR dafür sieht so aus
void ISR_Ext0()
{
Startzeit = micros();
}
der Zähler für die micros sollte dort auch weiterlaufen lt. Arduino-Referenz ... unvorhersehbar verhalten... was auch immer das bedeuten mag
Die ISR ist recht kurz und wird, schhätze ich, weniger als 1 - 2 ms dauern
Danach Rücksprung in die "void loop()" - Schleife und .... der Zähler für die micros zählt ja derweil weiter ....
nach einiger Zeit... beim "Vorbeigang" des Objektes an der 2. Lichtschranke wird auch wieder ein Impuls (wie an der 1. Lichtschranke) erzeugt der
am UNO-Pin 3 den Interrupt (Ext Int) 1 auslöst. Die ISR dafür sieht so aus
void ISR_Ext1()
{
Stopzeit = micros();
}
Danach Rücksprung in die "void loop()" - Schleife , die Start- und Stopzeit auswerten und zB. auf einem LCD anzeigen lassen.
Bei einen einmaligen Durchlauf sollte das eigentlich so funktionieren. Auch bei mehrmaligen Durchlauf sollte es klappen. Ich muß nur sicherstellen,
daß während der Auswertezeit und der Anzeige die Interrupt's gesperrt sind.
Das ist jetzt nur erst einmal ein Entwurf und ich wollte diesen Entwurf auch noch weiterentwickeln (zB. Dauermessung) oder hat jemand eine andere/bessere Idee ?
Gruß
Ludwig
-
- Beiträge: 2035
- Registriert: Mi 14. Jul 2010, 22:00
- Spezialgebiet: Kältetechnik, Frequenzumrichter, E-bikes
- Wohnort: D:\Hessen\Gießen
- Hat sich bedankt: 33 Mal
- Danksagung erhalten: 149 Mal
Re: Zeitmessung am Arduino UNO über Interrupt
Zweckmäßig wäre wohl kein Macro dafür zu verwenden sondern das "zu Fuß" zu programmieren.
Sprich man sucht sich einen Hardware Timer aus des Microcontrollers aus stellt für diesen einen passenden Teiler ein so das sich die gewünschte Zeit gut messen lässt.
Wie lange der Impuls am Interrupt Eingang anliegt ist im Prinzip egal wenn man nur auf eine Flanke trigert, auf einen Pegel triggern geht zwar auch, würde ich aber nicht empfehlen.
Beim ersten interrupt stellt man dann das Timer Zählerregister auf Null und beim zweiten interrupt liest man den Wert aus und speichert den in einer beliebigen Variable.
Wenn man den 16 Bit Timer 1 mit 16MHz laufen lässt dann hat man eine Auflösung von 1/16MHz = 63ns.
Der Zähler läuft über nach 4,096ms (wenn man längere Intervalle messen möchte kann man auch einen interrupt stellen der beim Überlauf ausgeführt wird um die Überläufe mitzuzählen).
Wenn das wirklich genau werden soll dann ist noch zu beachten das der Keramik Oszillator "Quarz" nicht sonderlich genau ist, damit kann die Messung also schonmal ein paar Prozent daneben liegen.
Der Timer 1 wird aber glaube ich von der Arduino library selber verwendet.
Im idealfall nimmt man also einen Controller der mehrere 16 bit Timer hat.
Die meisten Arduino Nano Klone haben mittlerweile einen Mega 328 PB drauf, der hat dann noch Timer3,4 und 5 die alle 16 Bit Timer sind.
Sprich man sucht sich einen Hardware Timer aus des Microcontrollers aus stellt für diesen einen passenden Teiler ein so das sich die gewünschte Zeit gut messen lässt.
Wie lange der Impuls am Interrupt Eingang anliegt ist im Prinzip egal wenn man nur auf eine Flanke trigert, auf einen Pegel triggern geht zwar auch, würde ich aber nicht empfehlen.
Beim ersten interrupt stellt man dann das Timer Zählerregister auf Null und beim zweiten interrupt liest man den Wert aus und speichert den in einer beliebigen Variable.
Wenn man den 16 Bit Timer 1 mit 16MHz laufen lässt dann hat man eine Auflösung von 1/16MHz = 63ns.
Der Zähler läuft über nach 4,096ms (wenn man längere Intervalle messen möchte kann man auch einen interrupt stellen der beim Überlauf ausgeführt wird um die Überläufe mitzuzählen).
Wenn das wirklich genau werden soll dann ist noch zu beachten das der Keramik Oszillator "Quarz" nicht sonderlich genau ist, damit kann die Messung also schonmal ein paar Prozent daneben liegen.
Der Timer 1 wird aber glaube ich von der Arduino library selber verwendet.
Im idealfall nimmt man also einen Controller der mehrere 16 bit Timer hat.
Die meisten Arduino Nano Klone haben mittlerweile einen Mega 328 PB drauf, der hat dann noch Timer3,4 und 5 die alle 16 Bit Timer sind.
-
- Beiträge: 2322
- Registriert: Fr 13. Jul 2018, 18:23
- Spezialgebiet: Laser und Mikro-/Nanotechnik
- Hat sich bedankt: 21 Mal
- Danksagung erhalten: 270 Mal
Re: Zeitmessung am Arduino UNO über Interrupt
... sollte ein "kleiner" Arduino zu langsam sein, dann ggf. einen schnelleren ESP32 nehmen -- die "großen" Arduinos sind da deutlich teurer ...
Aufruf zum Projekt "Müll-freie Meere" - https://reprap.org/forum/list.php?426 -- Facebook-Gruppe - https://www.facebook.com/groups/383822522290730
Call for the project "garbage-free seas" - https://reprap.org/forum/list.php?425
Call for the project "garbage-free seas" - https://reprap.org/forum/list.php?425
-
- Beiträge: 2823
- Registriert: Mo 13. Aug 2012, 09:03
- Spezialgebiet: Spezialgebiet
- Schule/Uni/Arbeit: Schule/Uni/Arbeit
- Wohnort: Mannheim
- Hat sich bedankt: 40 Mal
- Danksagung erhalten: 358 Mal
- Kontaktdaten:
Re: Zeitmessung am Arduino UNO über Interrupt
Du könntest ein internen Timer benutzen der auf dem 16mhz clock läuft und beim start resetten und stop den zähler auslesen.
die sind aber nur 16bit groß, je nach prescaler läuft der dir halt relativ schnell voll.
bei 1:1 (16mhz) ist der nach 4ms voll du hast aber 63ns auflösung, bei 1:1024 erst nach 4.1s aber du hast nur 64µs auflösung
mit einem esp32 hast du sogar ein 64bit timer wenn man tief genug in den code gräbt.
bei 80mhz sind das 12.5ns auflösung (cpu rennt zwar auf 240 aber timer nur auf 80)...
und überlaufen wird der dir in absehbarer zeit auch nicht... 2^64 x 80MHz sind 7300 jahre...
und mit dem esp32 hat man helperfunktionen damit man nicht diesen unlesbaren, unflexible TCCR mist raussuchen muss. und kann interrupts auch an pins verteilen wie man lustig ist.
zb. timerStart, timerBegin, timerWrite timerRead etc.
oder du nimmst hardware dafür
der TDC-GP22 kann unterschiede bis 65ps messen...aber nur für ein paar ms bis der timer volläuft
https://www.mouser.de/ProductDetail/Sci ... wpBw%3D%3D
die sind aber nur 16bit groß, je nach prescaler läuft der dir halt relativ schnell voll.
bei 1:1 (16mhz) ist der nach 4ms voll du hast aber 63ns auflösung, bei 1:1024 erst nach 4.1s aber du hast nur 64µs auflösung
Code: Alles auswählen
//setup
attachInterrupt(digitalPinToInterrupt(2), startisr, RISING); // Start
attachInterrupt(digitalPinToInterrupt(3), stopisr, RISING); // Stop
TCCR1A = 0;
TCCR1B = 0;
TCCR1B |= (1 << CS10); //ohne prescaler, 62.5ns
TCNT1 = 0;
//setup
void startisr() {
TCNT1 = 0;
}
void stopisr() {
ende = TCNT1;
}
mit einem esp32 hast du sogar ein 64bit timer wenn man tief genug in den code gräbt.
bei 80mhz sind das 12.5ns auflösung (cpu rennt zwar auf 240 aber timer nur auf 80)...
und überlaufen wird der dir in absehbarer zeit auch nicht... 2^64 x 80MHz sind 7300 jahre...
und mit dem esp32 hat man helperfunktionen damit man nicht diesen unlesbaren, unflexible TCCR mist raussuchen muss. und kann interrupts auch an pins verteilen wie man lustig ist.
zb. timerStart, timerBegin, timerWrite timerRead etc.
oder du nimmst hardware dafür
der TDC-GP22 kann unterschiede bis 65ps messen...aber nur für ein paar ms bis der timer volläuft
https://www.mouser.de/ProductDetail/Sci ... wpBw%3D%3D

-
- Beiträge: 2934
- Registriert: Fr 7. Apr 2006, 14:05
- Spezialgebiet: Physik,Elektronik,Blender
- Schule/Uni/Arbeit: M.Sc ET, Hardwareentwickler
- Wohnort: 65366 Geisenheim (Hessen)
- Hat sich bedankt: 1 Mal
- Danksagung erhalten: 90 Mal
- Kontaktdaten:
Re: Zeitmessung am Arduino UNO über Interrupt
haben die AVRs nicht auch Input Capture für die Timer, um den Zählerwert bei 'ne flanke in 'n register zu packen?Alexander470815 hat geschrieben: ↑Fr 25. Apr 2025, 15:50 Zweckmäßig wäre wohl kein Macro dafür zu verwenden sondern das "zu Fuß" zu programmieren.
Sprich man sucht sich einen Hardware Timer aus des Microcontrollers aus stellt für diesen einen passenden Teiler ein so das sich die gewünschte Zeit gut messen lässt.
Wie lange der Impuls am Interrupt Eingang anliegt ist im Prinzip egal wenn man nur auf eine Flanke trigert, auf einen Pegel triggern geht zwar auch, würde ich aber nicht empfehlen.
Beim ersten interrupt stellt man dann das Timer Zählerregister auf Null und beim zweiten interrupt liest man den Wert aus und speichert den in einer beliebigen Variable.
Wenn man den 16 Bit Timer 1 mit 16MHz laufen lässt dann hat man eine Auflösung von 1/16MHz = 63ns.
Der Zähler läuft über nach 4,096ms (wenn man längere Intervalle messen möchte kann man auch einen interrupt stellen der beim Überlauf ausgeführt wird um die Überläufe mitzuzählen).
Wenn das wirklich genau werden soll dann ist noch zu beachten das der Keramik Oszillator "Quarz" nicht sonderlich genau ist, damit kann die Messung also schonmal ein paar Prozent daneben liegen.
Der Timer 1 wird aber glaube ich von der Arduino library selber verwendet.
Im idealfall nimmt man also einen Controller der mehrere 16 bit Timer hat.
Die meisten Arduino Nano Klone haben mittlerweile einen Mega 328 PB drauf, der hat dann noch Timer3,4 und 5 die alle 16 Bit Timer sind.
Dann könnte man das Start und Stoppuls über Dioden zusammen auf den Input-Capture legen, und jeweils getrennt auf INT0 und INT1
in den Interrupts für INT0 und INT1 fischt man dann jeweils den wert aus dem Input-Capture register
dann ist die Messung unabhängig von eventueller interrupt-latenz
-
- Beiträge: 554
- Registriert: Fr 24. Jul 2015, 10:13
- Schule/Uni/Arbeit: KFZ-Elktr.
- Hat sich bedankt: 24 Mal
- Danksagung erhalten: 23 Mal
Re: Zeitmessung am Arduino UNO über Interrupt
Danke erst einmal an alle für die Antworten und Hinweise
@gamerpaddy
Dein Hinweis ist interresant. Ich muß allerdings vorher sagen, daß ich mich erst in diese Materie einarbeiten muß. Hab quasi von Null
angefangen und Schritt für Schritt autodidaktisch vorgearbeitet. Daher dazu einige Fragen.
TCNT1 ist das Register, in dem der aktuelle Zählerstand steht und auch gelesen werden kann, richtig ?
TCCR1A und TCCR1B ist das der Vorteiler ?
der Rest ist mir klar
Ich habe damit kein konkretes Projekt im Auge. Das Ganze dient im Momemt erst einmal der Wissenserweiterung.
Was ich vielleicht mittelfristig damit vorhabe, ist eine Drehzahlmessung an rotierenden Objekten mit Hilfe einer Reflexlichtschranke.
Max. 60000 Umdr. / min) wären das 1ms zwischen den Impulsen.
Ich vermute aber, daß die Reaktionszeit der Lichtschranke dort die Grenze vorgibt. Ich glaube nicht, daß die so schnell reagieren, muß ich erst herausfinden.
Da ich auch gern mit Hardware experimentiere, wäre die Alternative dann eine Torschaltung und eine zusätzliche Hardware (ein über Quarz getakteter Binärzähler),
die die Impulse in einer vorbestimmten Zeil zählt , sinnvoller. Die logische Steuerung der Hardware und die Auswertung und Anzeige könnte dann ein Microcontrollers erledigen.
Trotzdem werde ich auch einmal mit der esp32 beschäftigen... kann ja nix schaden.
Gruß
Ludwig
....ohhh... sehe gerade Reflex-Optokoppler ITR20001/T hat eine Rise Time tR - 25 - μs und Time Fall Time 25 - μs. Sind doch schnell genug
@gamerpaddy
Dein Hinweis ist interresant. Ich muß allerdings vorher sagen, daß ich mich erst in diese Materie einarbeiten muß. Hab quasi von Null
angefangen und Schritt für Schritt autodidaktisch vorgearbeitet. Daher dazu einige Fragen.
TCNT1 ist das Register, in dem der aktuelle Zählerstand steht und auch gelesen werden kann, richtig ?
TCCR1A und TCCR1B ist das der Vorteiler ?
der Rest ist mir klar
Ich habe damit kein konkretes Projekt im Auge. Das Ganze dient im Momemt erst einmal der Wissenserweiterung.
Was ich vielleicht mittelfristig damit vorhabe, ist eine Drehzahlmessung an rotierenden Objekten mit Hilfe einer Reflexlichtschranke.
Max. 60000 Umdr. / min) wären das 1ms zwischen den Impulsen.
Ich vermute aber, daß die Reaktionszeit der Lichtschranke dort die Grenze vorgibt. Ich glaube nicht, daß die so schnell reagieren, muß ich erst herausfinden.
Da ich auch gern mit Hardware experimentiere, wäre die Alternative dann eine Torschaltung und eine zusätzliche Hardware (ein über Quarz getakteter Binärzähler),
die die Impulse in einer vorbestimmten Zeil zählt , sinnvoller. Die logische Steuerung der Hardware und die Auswertung und Anzeige könnte dann ein Microcontrollers erledigen.
Trotzdem werde ich auch einmal mit der esp32 beschäftigen... kann ja nix schaden.
Gruß
Ludwig
....ohhh... sehe gerade Reflex-Optokoppler ITR20001/T hat eine Rise Time tR - 25 - μs und Time Fall Time 25 - μs. Sind doch schnell genug
-
- Beiträge: 2035
- Registriert: Mi 14. Jul 2010, 22:00
- Spezialgebiet: Kältetechnik, Frequenzumrichter, E-bikes
- Wohnort: D:\Hessen\Gießen
- Hat sich bedankt: 33 Mal
- Danksagung erhalten: 149 Mal
Re: Zeitmessung am Arduino UNO über Interrupt
Stimm das wäre auch eine gute Variante.Thunderbolt hat geschrieben: ↑Fr 25. Apr 2025, 20:18 haben die AVRs nicht auch Input Capture für die Timer, um den Zählerwert bei 'ne flanke in 'n register zu packen?
Man kann auch einen interrupt auslösen wenn es einen capture gab um die Daten zu verarbeiten.
Da muss man sich dann ja immer nur den letzten Wert des Timers in eine Variable schreiben so das man ihn im nächsten Durchgang wieder hat.
Nein das sind die Register mit denen man den Timer konfiguriert, der Vorteiler sind nur Bit 0,1,2 von TCCR1B.
Dazu einfach im Datenblatt von deinem Controller schauen, die Atmel Datenblätter sind da ziemlich ausführlich.
Wenn man die Überläufe zählen will muss man ggf. auch noch den overflow interrupt aktivieren, das passiert mit dem TIMSK1 Register.
Für sehr hohe Drehzahlen ja.
Für kleine Drehzahlen eher nein da die Auflösung dann extrem leidet, der Wert schwankt oder die Auswertung sehr lange dauert.
Wenn man über eine Sekunde misst und die Drehzahl 90 U/min beträgt dann schwankt der Wert der dabei rauskommt die ganze Zeit zwischen 60 und 120 U/min.
-
- Beiträge: 554
- Registriert: Fr 24. Jul 2015, 10:13
- Schule/Uni/Arbeit: KFZ-Elktr.
- Hat sich bedankt: 24 Mal
- Danksagung erhalten: 23 Mal
Re: Zeitmessung am Arduino UNO über Interrupt
@Alexander470815
Der ext. Zähler wird mit einer festen Frequenz getaktet.
Um bei deinem Beispiel zu bleiben: 90 U/min sind 1,5 U/sec = 666 ms je Umdrehung. bzw. Zeit zwischen 2 Impulsen.
Wenn ich den ext. Binärzähler zB. mit 1 KHz takten würde, würde dieser an seinen Ausgängen 666 in binär codierter Form anzeigen.
Das kann ich so nicht nachvollziehen. Ist warscheinlich ein Missverständnis. Ich benutze die Zeit zwischen 2 Impulsen (= eine Umdr.) als Torzeit.Für sehr hohe Drehzahlen ja.
Für kleine Drehzahlen eher nein da die Auflösung dann extrem leidet, der Wert schwankt oder die Auswertung sehr lange dauert.
Wenn man über eine Sekunde misst und die Drehzahl 90 U/min beträgt dann schwankt der Wert der dabei rauskommt die ganze Zeit zwischen 60 und 120 U/min.
Nach oben
Der ext. Zähler wird mit einer festen Frequenz getaktet.
Um bei deinem Beispiel zu bleiben: 90 U/min sind 1,5 U/sec = 666 ms je Umdrehung. bzw. Zeit zwischen 2 Impulsen.
Wenn ich den ext. Binärzähler zB. mit 1 KHz takten würde, würde dieser an seinen Ausgängen 666 in binär codierter Form anzeigen.
Die Messung dauert dann immer eine Umdrehung oder wenn man diee Lesemarke für den Reflexkoppler verkürzt (zB. auf eine halbe Umdr.) entsprechend weniger.der Wert schwankt oder die Auswertung sehr lange dauert.