Forum: Mikrocontroller und Digitale Elektronik Zeit zwischen zwei Pulsen messen


von 007 (Gast)


Lesenswert?

Hallo,
Ich baue eine Drehzahlmessung. Ein Hallsensor sendet bei jeder Umdrehung 
einen Puls an meinen Atmega2560.

Habe mir überlegt, einen Timer immer von 0 an hochzählen zu lassen. Bei 
einem Puls wird ein Interrupt ausgelöst und der Timer gestoppt sowie die 
Zeit ausgewertet.

Passt das so, oder gibt es einen eleganteren Weg? Das ganze soll 
möglichst nicht die CPU belasten.

Grüsse, 007

von Karl H. (kbuchegg)


Lesenswert?

Dein Stichwort lautet "Input Capture"

such im Forum nach Frequenzmesser bzw Drehzahlmesser.
Du bist beileibe nicht der Erste der so etwas baut.

Alle Lösungen, die keinen Input Capture verwenden, sondern Timer 
starten, stoppen und loeschen , kannst du getrost ignorieren.

von sakul237 (Gast)


Lesenswert?

Da werden sie geholfen:
High-Speed capture mit ATmega Timer

von Michael R. (Firma: Brainit GmbH) (fisa)


Lesenswert?

Karl Heinz schrieb:

> Alle Lösungen, die keinen Input Capture verwenden, sondern Timer
> starten, stoppen und loeschen , kannst du getrost ignorieren.

Naja... grundsätzlich hast du recht, aber: sobald der ICP-Pin 
anderweitig fest vergeben ist, oder mehr als ein Signal (bzw. mehr als 
ICP-Eingänge vorhanden) gemessen werden muss, kommt man um eine 
Alternative nicht herum... soviel Unterschied zwischen ICP und 
"normalem" PinChange-Int mit Timer auslesen ist dann auch nicht. 
natürlich ist ICP einfacher, sauberer und genauer.

: Bearbeitet durch User
von 007 (Gast)


Lesenswert?

Ok, hört sich gut an. Danke für die Hinweise. Ich route momentan noch 
das Layout, deshalb kommt es mir vorallem darauf an, den richtigen Pin 
auszuwählen.

Für den High Speed Capture Modus muss ich einen ICP Pin nutzen, richtig?

Laut Datenblatt des ATmega2560 bieten sich an:
PD4(ICP1)
PE6(ICP3)
PL0(ICP4)
PL1(ICP5)

Ist einer zu bevorzugen? So wie ich das verstanden habe, gehört jeder zu 
einem eigenen baugleichen 16-bit Timer. Daher dürfte es wohl egal sein?

007

von spess53 (Gast)


Lesenswert?

Hi

>Für den High Speed Capture Modus muss ich einen ICP Pin nutzen, richtig?

Jain. Alternativ zu den ICP-Pins kann Input Capture auch vom Analog 
Comparator getriggert werden. Und wenn du den ADC nicht benutzt stehen 
dir dadurch auch noch die Pins ADC0...ADC15 zur Verfügung.

MfG Spess

von spess53 (Gast)


Lesenswert?

Hi

>Alternativ zu den ICP-Pins kann Input Capture auch vom Analog
>Comparator getriggert werden.

->Alternativ zu den ICP-Pins kann Input Capture von Timer1 auch vom 
Analog
Comparator getriggert werden.

MfG Spess

von m.n. (Gast)


Lesenswert?

spess53 schrieb:
> Alternativ zu den ICP-Pins

kann man auch jeden Pin-Change-Eingang verwenden, den aktuelle AVRs 
überall haben.
Beitrag "4-Kanal Drehzahlmessung mit ATmega88"
oder für nur einen Kanal
Beitrag "Frequenz / Drehzahl, 4-stell. 7-Segm.-LCD, ATtiny45"

Eine Belastung der CPU findet in der Regel nur dann statt, wenn 
Universalfunktionen wie delay_ms(100) aufgerufen werden :-)

von Rolf Magnus (Gast)


Lesenswert?

007 schrieb:
> Habe mir überlegt, einen Timer immer von 0 an hochzählen zu lassen. Bei
> einem Puls wird ein Interrupt ausgelöst und der Timer gestoppt sowie die
> Zeit ausgewertet.

Wozu den Timer stoppen?
ICP ist sicher die beste Lösung, aber es geht auch ohne. Dann aber den 
Timer laufen lassen und lediglich in der ISR den Wert auslesen.

von Michael R. (Firma: Brainit GmbH) (fisa)


Lesenswert?

m.n. schrieb:
> spess53 schrieb:
>> Alternativ zu den ICP-Pins
>
> kann man auch jeden Pin-Change-Eingang verwenden, den aktuelle AVRs
> überall haben.

Ja, aber das ist dann streng genommen kein ICP mehr, oder?

von Stefan F. (Gast)


Lesenswert?

Genau. Denn dann must Du den Zählerstand per Software auslesen, und die 
kann sich wegen gesperrter Interrupts beliebig verzögern.

Der Input Capture Eingang hingegen ist ein hardware Feature, der 
funktioniert auch, wenn Interrupts global gesperrt sind. Also kann 
dessen Capturing nicht verzögert werden.

von Karl H. (kbuchegg)


Lesenswert?

Michael Reinelt schrieb:

> "normalem" PinChange-Int mit Timer auslesen ist dann auch nicht.
> natürlich ist ICP einfacher, sauberer und genauer.

Selbst dann lässt man den Timer einfach durchlaufen und macht nicht 
diese start/stop/0-Setzen Orgie.

: Bearbeitet durch User
von m.n. (Gast)


Lesenswert?

Michael Reinelt schrieb:
> Ja, aber das ist dann streng genommen kein ICP mehr, oder?

Richtig. Aber um zum Beispiel ein 4-stelliges Ergebnis bei 10 
Messungen/s zu erhalten, reicht eine Auflösung der Zeit von <=10µs. ICP 
wird dann notwendig, wenn die Zeit auf <100ns aufgelöst gemessen werden 
muß.

In jedem Fall muß beim ICP- oder PC-Interrupt eine ISR aufgerufen 
werden, die die Ereignisse zählt.
Nimmt man beispielsweise eine Drehzahl von 6000Upm, so sind das 100Hz 
und die ISR wird alle 10ms aufgerufen. Selbst bei suboptimaler 
Programmierung dauert diese ISR <5µs. Die µC-Belastung liegt somit bei 
ca. 0,05%.

von spess53 (Gast)


Lesenswert?

Hi

>In jedem Fall muß beim ICP- oder PC-Interrupt eine ISR aufgerufen
>werden, die die Ereignisse zählt.

Das sind aber zwei paar Schuhe. Bei ICP wird der Zeitpunkt beim 
Eintreffen des Ereignisses gespeichert. Wann die ISR das Ergebnis abholt 
ist irrelevant solange es vor dem nächsten Ereignis erfolgt.

Wenn per PC gemessen wird zählt nicht das Ereignis sondern der 
Zeitpunkt, an dem die ISR aufgerufen wird. Also nur wirklich nutzbar, 
wenn der PC-Interrupt
ständig freie Bahn hat.

MfG Spess

von m.n. (Gast)


Lesenswert?

spess53 schrieb:
> Also nur wirklich nutzbar,
> wenn der PC-Interrupt
> ständig freie Bahn hat.

Man kann dem PCI ja freie Bahn schaffen, indem andere ISRs ihm den Platz 
einräumen.
Auch der ICP-Interrupt muß für jedes Ereignis freie Bahn haben, sonst 
gehen Ereignisse verloren.
Falls Jemand ISRs nicht richtig programmiert, geht es immer schief. Auch 
ICP geht schief, wenn man die Anforderungen (virtuell) immer weiter 
hochschraubt, dass keine Lösung mehr möglich ist. Soll der TO seine 
Anforderungen kundtun, dann kann man sehen, was notwendig und was 
überflüssig ist.

von Rolf Magnus (Gast)


Lesenswert?

Stefan us schrieb:
> Genau. Denn dann must Du den Zählerstand per Software auslesen, und die
> kann sich wegen gesperrter Interrupts beliebig verzögern.

Ja. Aber wenn man den Timer weiterlaufen läßt, geht nichts verloren. 
Eine Messung ergibt dann eine minimal längere Zeit, dafür ist sie bei 
der nächsten Messung wieder entsprechend kürzer. Das spielt bei einer 
Drehzahlmessung aber keine große Rolle, da sich die Drehzahlen nicht so 
wahnsinnig schnell ändern. Wenn man einen gleitenden Mittelwert bildet, 
rechnet man damit den Jitter wieder raus - vorausgesetzt, man stoppt den 
Timer nicht.

von 007 (Gast)


Lesenswert?

m.n. schrieb:
> Soll der TO seine
> Anforderungen kundtun, dann kann man sehen, was notwendig und was
> überflüssig ist.

Es geht um eine Drehzahlmessung für ein Regelung. Es treten Werte im 
Bereich von ca. 1 bis 100 Hz auf. Das ganze soll aber möglichst im 
Hintergrund ablaufen und nicht die CPU belasten. Sobald ein neuer Wert 
erfasst wird, möchte ich einen Interrupt haben, der dann kurz rechnet 
und die Stellgröße des Regelkreises ändert.

007

von m.n. (Gast)


Lesenswert?

007 schrieb:
> Es treten Werte im
> Bereich von ca. 1 bis 100 Hz auf. Das ganze soll aber möglichst im
> Hintergrund ablaufen und nicht die CPU belasten.

Ich habe Dir ja eine Hausnummer (0,05% @ 100Hz) genannt. Für meine 
Begriffe belastet das die CPU nur unwesentlich. Da die untere Frequenz 
bei 1Hz liegt, kann die Regelung auch nicht besonders schnell ausfallen, 
sodass die zeitliche Auflösung Drehzahlerfassung rel. unkritisch ist.

von Karl H. (kbuchegg)


Lesenswert?

Worum gehts jetzt eigentlich?

Ob man das auf Biegen und Brechen mit einem Pin Change Interrupt löst 
oder ganz einfach das Feature des Timers einsetzt (Input Capture), 
welches Atmel genau zu diesem Zwecke dem Timer mitgegeben hat, selbst 
wenn man damit auf einen bestimmten Pin festgenagelt ist.

Bitte sagt mir, dass das jetzt nicht das Thema ist.

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

> Auch der ICP-Interrupt muß für jedes Ereignis freie Bahn haben, sonst gehen 
Ereignisse verloren.

Ja.
Das ist aber ein ganz anderer Fall als der, bei dem der Pin Change 
Interrupt verzögert kommt, weil ein anderer Timerinterrupt gerade das 
Multiplexing einer 7-Segment Anzeige gemacht hat.

Das der Input Capture ...
1
voaltile uint16_t difference;
2
volatile uint8_t newValue;
3
4
ISR( ... )
5
{
6
  uint16_t now = ICR1;
7
  static uint16_t last;
8
9
  difference = last - now;
10
  newValue = TRUE;
11
}
... auch irgendwann an seine Grenzen kommt, ist klar. Sobald die 1/f der 
zu messenden Schwingung in die Nähe der Ausführungszeit irgendeiner ISR 
kommt, beginnt die Sache haarig zu werden. Aber das ist kein Grund, dass 
ich mir ein Messergebnis von einem anderen Interrupt versauen lasse, in 
dem ich den ICP nicht benutze, weil Pin Change cool ist.

: Bearbeitet durch User
von m.n. (Gast)


Lesenswert?

Karl Heinz schrieb:
> Das ist aber ein ganz anderer Fall als der, bei dem der Pin Change
> Interrupt verzögert kommt, weil ein anderer Timerinterrupt gerade das
> Multiplexing einer 7-Segment Anzeige gemacht hat.

Ich weiß ja, dass Du meine Programmierkünste nicht zu schätzen weiß. Das 
ist aber nicht mein Problem :-)

Sieh Dir mal das Multiplexen einer 7-Segementanzeige an.
Beitrag "Frequenz, Drehzahl, 4x7-Segment LED, Multiplex-Betrieb"

Ich habe die ISR fürs Multiplexen einmal extrahiert:

ISR(TIMER1_COMPB_vect)   // wird mit MPX_FREQUENZ aufgerufen
{
static uint8_t digit_nr;
  OCR1B += MPX_TEILER;   // Intervall nachladen
  sei();                 // und gleich wieder freigeben

Wie man sieht, wird der globale Interrupt wieder zugelassen, sobald 
OCR1B nachgeladen ist. Abhängig vom Compiler, wieviele Register er 
retten muß, sollte der Interrupt bei 16MHz Taktfrequenz nach 1-2µs 
wieder verfügbar sein. Das weitere Multiplexen kann in Ruhe abgearbeitet 
werden.
Mit den von mir genannten 10µs sind wir (ich zumindest) noch weit 
entfernt!

von Ulrich (Gast)


Lesenswert?

Die Lösung mit ICP ist die bessere, weil genauer und auch von der CPU 
Belastung klein. Wenn die Anforderungen nicht so hoch sind oder kein ICP 
Pin zur Verfügung steht, geht es auch mit einem Interrupt (z.B. Pin 
Change oder Int0,Int1) - allerdings gibt es da eine Ungenauigkeit durch 
die nicht immer gleiche Reaktionszeit auf den Interrupt. Je nachdem was 
sonst noch an Interrupts läuft können das 10 oder auch 100 Zyklen werden 
- wenn man es schlecht macht natürlich auch mehr.

von Karl H. (kbuchegg)


Lesenswert?

m.n. schrieb:
> Karl Heinz schrieb:
>> Das ist aber ein ganz anderer Fall als der, bei dem der Pin Change
>> Interrupt verzögert kommt, weil ein anderer Timerinterrupt gerade das
>> Multiplexing einer 7-Segment Anzeige gemacht hat.
>
> Ich weiß ja, dass Du meine Programmierkünste nicht zu schätzen weiß. Das
> ist aber nicht mein Problem :-)
>
> Sieh Dir mal das Multiplexen einer 7-Segementanzeige an.
> Beitrag "Frequenz, Drehzahl, 4x7-Segment LED, Multiplex-Betrieb"
>
> Ich habe die ISR fürs Multiplexen einmal extrahiert:

Oh geh, bitte.
Ich hab hier im Forum zig 7-Segment Multiplex Routinen geschrieben. 
Denkst du echt, ich wüsste nicht wie das geht?

> > Ich weiß ja, dass Du meine Programmierkünste nicht zu schätzen weiß.

Oh, nein.
Was ich an dir nicht schätze, das ist, dass du alles anders machen 
musst, aus keinem wirklich guten Grund heraus. Du machst es anders und 
du schlägst was anderes vor, nur damit es anders ist. Und dagegen hab 
ich was.
Solange sich das Problem überhaupt nicht stellt, dass alle 4 ICP Pins 
besetzt sind und man das auch hardwaremässig nicht ändern kann, gibt es 
keinen Grund, dem TO einen Pin Change Interrupt schmackhaft zu machen. 
Es ist die einfachste Lösung, die keine Probleme aufwirft (ausser dem 
fast gleichzeitigem Auftreten von Capture und Overflow) und sich auch 
gut in ein nahezu beliebiges Gesamtprogramm einfügt, solange das nur 
einigermassen nach den Regeln der Kunst gebaut ist. Bis jetzt hab ich an 
einer Pin Change Lösung nichts, aber auch gar nichts gesehen, inwiefern 
sie einer Capture Lösung überlegen wäre - ausser der Möglichkeit 
beliebige Pins hernehmen zu können, was ich allerdings als nicht 
wirklich wesentlich erachte wenn 4 mögliche Pins zur Verfügung stehen.

Ich hab nichts gegen 'anders machen'. Aber 'anders machen' nur um des 
'anders machen' Willens, ist mir zu wenig. Es gibt erprobte und gute 
Lösungen, deren Verhalten und Nebenwirkungen gut bekannt sind.

: Bearbeitet durch User
von m.n. (Gast)


Lesenswert?

Karl Heinz schrieb:
> Alle Lösungen, die keinen Input Capture verwenden, ... , kannst du
> getrost ignorieren.

Was ich nicht mag, sind genau diese pauschalen Falschaussagen!
Dabei geht es mir nicht darum, mich mit Unbelehrbaren zu streiten, 
sondern unerfahrenen Personen Mut zu machen, anderer Leute Vorurteile 
nicht  ungeprüft fürs eigene Handeln zu übernehmen.
Für diese Erkenntnis muß man leider erst alt werden, aber besser spät 
als nie :-)

Ulrich schrieb:
> Die Lösung mit ICP ist die bessere, weil genauer und auch von der CPU
> Belastung klein.

Keine Frage! Aber die Praxis zeigt doch, dass man nicht immer einen für 
alle Belange völlig freien Controller zur Verfügung hat. Wenn, wie beim 
ATmega2560, noch viele freie ICPs zur Verfügung stehen, nimmt man sie 
natürlich. (Den ICP vom 90S2313 nutze ich seit 15 Jahren; er kam damals 
wie für mein Problem geschaffen im pinkompatiblen 89C2051 Gehäuse.)

Bei Interrupts kann man natürlich auch viel falsch machen - auf der 
anderen Seite aber auch gut lernen, die Prioritäten im Programm 
sorgfältig zu setzen. Da muß man seine eigenen Erfahrungen machen und 
diese immer wieder neu an neuerer Hardware überprüfen.
Mit "Das machen wir immer so" bleibt man im Kopf stehen!

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.