Zeitmessung am Arduino UNO über Interrupt

Programmierung und Hardwaredesign mit Arduino, AVR, PIC und Konsorten.

Moderatoren: MaxZ, ebastler, SeriousD

Antworten
Benutzeravatar

Thread-Ersteller
L_B_S
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

Beitrag von L_B_S »

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
interrupt.jpg
... 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
Benutzeravatar

Alexander470815
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

Beitrag von Alexander470815 »

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.
Benutzeravatar

VDX
Beiträge: 2323
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

Beitrag von VDX »

... 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
Benutzeravatar

gamerpaddy
Beiträge: 2824
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

Beitrag von gamerpaddy »

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

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
:wurst:
Benutzeravatar

Thunderbolt
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

Beitrag von Thunderbolt »

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.
haben die AVRs nicht auch Input Capture für die Timer, um den Zählerwert bei 'ne flanke in 'n register zu packen?

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
Benutzeravatar

Thread-Ersteller
L_B_S
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

Beitrag von L_B_S »

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
Benutzeravatar

Alexander470815
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

Beitrag von Alexander470815 »

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?
Stimm das wäre auch eine gute Variante.
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.
L_B_S hat geschrieben: Sa 26. Apr 2025, 12:51 TCCR1A und TCCR1B ist das der Vorteiler ?
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.
L_B_S hat geschrieben: Sa 26. Apr 2025, 12:51 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.
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.
Benutzeravatar

Thread-Ersteller
L_B_S
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

Beitrag von L_B_S »

@Alexander470815
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
Das kann ich so nicht nachvollziehen. Ist warscheinlich ein Missverständnis. Ich benutze die Zeit zwischen 2 Impulsen (= eine Umdr.) als Torzeit.
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.
der Wert schwankt oder die Auswertung sehr lange dauert.
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.
Antworten