Forum: Mikrocontroller und Digitale Elektronik Drehzahlmessen mit Input Capture


von Micha (Gast)


Lesenswert?

Hallo!

Ich möchte einen Motor regeln (n=0..2000/min) und erhalte vom 
Tachogenerator entsprechend ein Signal mit f=0..2000Hz.

Programmiert ist noch nix, nur Vorüberlegung:
Tachogenerator an den ICP (ATMega644) und dann im ICP-Interrupt die 
Differenz zwischen den Timestamps errechnen = Dauer -> Drehzahl.
Unterhalb einer Schwellendrehzahl (~4-5 1/min) ist die Dauer zwischen 
den Tachoimpulsen nun aber länger als der 16bit Timer überstreicht, 
weshalb die Differenz unsinnige Werte annimmt. Diese würde ich gerne 
ausblenden bzw. auf die max. Periodendauer setzen, da ich diesen tiefen 
Drehzahlbereich nicht regeln will.

Die Beispiele, die ich hier im Forum schon entdeckt habe, gehen alle in 
die Richtung, durch den Overflow-Interrupt den Zähler auf mehr als 16bit 
aufzubohren, wobei ich diese zusätzliche Auflösung, wie gesagt, nicht 
benötige.

Mein Ansatz:
In der ICP-ISR den Timer auf 0 zurücksetzen und bei gesetztem Timer 
Overflow das Ergebnis verwerfen.
Vorteil: Differenzberechnung entfällt, ICP-Wert ist die Periodendauer
Nachteil: Timer lässt sich nicht mehr für andere Zwecke mitverwenden

Mein Bauchgefühl:
Funktioniert, ist aber unsauber wg. obigem Nachteil

Mein Wunsch:
Brett vor'm Kopf wegnehmen und damit zur Denkanregung einen leichten 
Schlag auf den Hinterkopf bekommen

Ich danke schonmal für den einen oder anderen Denkanstoß :-)

von Krapao (Gast)


Lesenswert?

> Unterhalb einer Schwellendrehzahl (~4-5 1/min) ist die Dauer zwischen
> den Tachoimpulsen nun aber länger als der 16bit Timer überstreicht,

Das hängt vom Prescaler des Timers ab.

von Ingo L. (Gast)


Lesenswert?

Grundsätzlich ist das alles kein Problem, man muss sich nur vorher über 
die Nötige Auflösung klar werden die man benötigt/anstrebt. Am 
Einfachsten ist natürlich die Periodendauermessung und dann über 10 
Perioden den Mittelwert bilden. Wenn du deinen Timer noch für andere 
Sachen benutzen willst, tu das, der µC kann die Periodendauermessung 
ganz easy nebenher laufen lassen.

Zu Beginn deiner Messung setzt du einen Overflow-zähler auf 0. Dann 
speicherst du den aktuellen Zählerstand. Beim Input Capture speicherst 
du dann den neuen Zählerwert. Anschließend errechnest du aus der 
Periodendauer die Frequenz. Die Timerüberläufe zählst du im 
Timeroverflow mit.

Insgesamte Timerincremente = (Overflowzähler * 2^16) +(Alter Wert-Neuer 
Wert)

Achtung, Alter Wert - Neuer Wert kann auch negativ werden, daher besser 
einen Cast auf (int) durchführen.



Ingo

von Micha (Gast)


Lesenswert?

Krapao schrieb:
> Das hängt vom Prescaler des Timers ab.

Der wird m.E. aber eher durch die Auflösung der oberen Drehzahlen 
vorgegeben. Außerdem will ich die ganz niedrigen Drehzahlen <5 1/min 
auch nicht messen.

von Ingo L. (Gast)


Lesenswert?

Ach so, zusätzlich startest du einen zweiten Timer (einfach Variable mit 
einem Wert laden und decremntieren), mit du deine Mindestfrequenz 
festlegst. Dieser wird bei jedem Input-Capture neu gestartet. Wenn in 
einer festen Zeit X kein IC auftaucht (die Variabvle wird runtergezählt 
und wenn sie 0 ist weißt du, dass die Zeit um ist), wird die Messung 
beendet und die Frequenz ist < als deine Mindestfrequenz.

Muss übrigens heißen:
Insgesamte Timerincremente = (Overflowzähler * 2^16) +(Neuer Wert- Alter
Wert)

Ingo

von Krapao (Gast)


Lesenswert?

> Der wird m.E. aber eher durch die Auflösung der oberen Drehzahlen
> vorgegeben. Außerdem will ich die ganz niedrigen Drehzahlen <5 1/min
> auch nicht messen.

Ich wollte dich nicht kritisieren, sondern einen Denkanstoß geben: Man 
kann den Prescaler passend zur Massaufgabe setzen - und innerhalb des 
Programms auch ändern, wenn sich die Messaufgabe ändert.

Wenn du mit einer Änderung der Specs von (n=0..2000/min) auf 
(n=5..2000/min) alle Probleme umschiffen kannst, mach es.

von Micha (Gast)


Lesenswert?

Krapao schrieb:
> Wenn du mit einer Änderung der Specs von (n=0..2000/min) auf
> (n=5..2000/min) alle Probleme umschiffen kannst, mach es.

Ok, vielleicht habe ich mich bei den Specs unsauber ausgedrückt. Gibt es 
eine einfache Möglichkeit, bei durchlaufendem Timer zu erkennen, dass 
ein Überlauf  von Timer_Alt -> Timer_neu stattgefunden hat? Das Timer 
Overflow Flag hilft mir erstmal ja nur, wenn ich den Timer jedesmal 
zurücksetze.

von Krapao (Gast)


Lesenswert?

> Das Timer Overflow Flag hilft mir erstmal ja nur, wenn ich den Timer
> jedesmal zurücksetze.

Üblich ist es, dass man die Anzahl der Overflows in einer ISR mit zählt.

Bei einem durchlaufenden Timer kannst du dir aus "Anzahl der Overflows 
* Timerbreite (Shiften statt Multiplizieren!) + akt. Timerstand" ständig 
einen eindeutigen Timestamp errechnen. Dabei aufpassen, dass du Anzahl 
der Overflows und akt. Timerstand atomar  (=> Artikel Interrupt) 
liest.

von Micha (Gast)


Lesenswert?

Krapao schrieb:
> Bei einem durchlaufenden Timer kannst du dir aus "Anzahl der Overflows
> * Timerbreite (Shiften statt Multiplizieren!) + akt. Timerstand" ständig
> einen eindeutigen Timestamp errechnen. Dabei aufpassen, dass du Anzahl
> der Overflows und akt. Timerstand atomar  (=> Artikel Interrupt)
> liest.

Damit erweitere ich aber bloss den Timer.
Damit löse nicht ich die ursprüngliche Problemstellung, dass mich eine 
Periodendauer, die größer ist, als die max. Spannweite von 16bit, nicht 
interessiert und verworfen werden kann.

von Krapao (Gast)


Lesenswert?

Das ist keine Problemstellung sondern ein Verfahren. Wenn das Verfahren 
bei deinem Projekt funktioniert benutze es. Du kennst die Nachteile und 
die Vorteile.

Und wenn du bei deinem Verfahren Timeroverflows vermeiden willst, dann 
Beitrag "Re: Drehzahlmessen mit Input Capture"

Dein "Brett vorm Kopf" ist die Denke "Differenz unsinnige Werte 
annimmt".
Genau deswegen benutzen andere Leute die Overflows.

Wenn du mit Overflows umgehen kannst oder die Nachteile des 
overflow-freien Verfahrens nicht tragbar sind, weil du z.B. den 
durchlaufenden Timer noch für anderes brauchst, dann 
Beitrag "Re: Drehzahlmessen mit Input Capture"

von Ingo (Gast)


Lesenswert?

Micha schrieb:
> Damit erweitere ich aber bloss den Timer.
> Damit löse nicht ich die ursprüngliche Problemstellung, dass mich eine
> Periodendauer, die größer ist, als die max. Spannweite von 16bit, nicht
> interessiert und verworfen werden kann.
Hallo?

Ingo L. schrieb:
> Ach so, zusätzlich startest du einen zweiten Timer (einfach Variable mit
> einem Wert laden und decremntieren), mit du deine Mindestfrequenz
> festlegst. Dieser wird bei jedem Input-Capture neu gestartet. Wenn in
> einer festen Zeit X kein IC auftaucht (die Variabvle wird runtergezählt
> und wenn sie 0 ist weißt du, dass die Zeit um ist), wird die Messung
> beendet und die Frequenz ist < als deine Mindestfrequenz.
Einfach mal lesen


Ingo

von Johannes G. (gutenberg)


Lesenswert?

Micha schrieb:
> Das Timer
> Overflow Flag hilft mir erstmal ja nur, wenn ich den Timer jedesmal
> zurücksetze.

Ist echt ein dickes Brett ;)

Musst ja nicht die Overflows zählen, wenn dich das nicht interessiert. 
Du musst bloss merken, DASS ein Overflow stattfand.

Also wenn dein Tachosignal kommt, checkst du erst ob Overflow passierte, 
falls ja ist der Timerwert Schrott, Timer = 0, Overflow = 0, fertig.

Falls kein Overflow war, ist deine aktuelle Timerzeit brauchbar, 
rechne...

von Micha (Gast)


Lesenswert?

Johannes G. schrieb:
> Ist echt ein dickes Brett ;)

Kiefer, druckkesselimprägniert :)

Deinen Ansatz verfolge ich gerade anhand der Sägezahnbilder aus dem 
AVR-Datenblatt, allerdings komme ich wohl nicht umher, mehr als einen 
Overflow zu zählen wenn ich die gesamten 16bit Timerbreite nutzen 
möchte.

0 Overflow -> Zulässig, da innerhalb 16bit
1 Overflow & Neu > Alt -> Verwerfen, da 16bit überlauf
1 Overflow & Neu < Alt -> Zulässig, da innerhalb 16bit
2 Overflows -> Verwerfen, da 16bit Überlauf

Overflows werden in der zugehörigen ISR inkrementiert und in der ICP-ISR 
zurückgesetzt. Dachte nur, vielleicht gibt es eine Lösung, die ohne 
zusätzliche Overflow-ISR oder ohne zusätzlichen Timer auskommt.

von Krapao (Gast)


Lesenswert?

> Dachte nur, vielleicht gibt es eine Lösung, die ohne
> zusätzliche Overflow-ISR oder ohne zusätzlichen Timer auskommt.

Du braucht keinen zusätzlichen Timer! Du kannst den ICP Interrupt und 
den Overflow Interrupt bei dem gleichen Timer enablen.

von Ulrich (Gast)


Lesenswert?

Man könnte auch den Timer weiter laufen lassen, und statt dem overflow 
interrupt einen output compare Interrupt nutzen. Also einfach eines der 
OCR Register passend (z.B. timerstand +60000) setzen.  Wenn das passende 
Interrupt-Flag gesetzt ist, war die Zeit zu lang.

Ein Overflow beim Timer zwischen den 2 ICP Events ist noch keine 
Problem, wenn man die Rechnung mit word Variablen, also 16 Bit unsigned 
macht. Der Cast nach Int ist als genau falsch. Das Ergebnis ist auch 
immer Positiv - sind doch keine Neutrinos.

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Hier ist noch ein anderer Ansatz: Triggere mit dem Indexpuls eine IRQ 
und zähle da drin eine Variable um 1 hoch.
Ein Timerinterupt liest jede Sekunde die Variable, speichert sie als 
Messergebnis und setzt sie danach zurück. Gibt auch noch bei 0 U/sec 
richtige Ergebnisse.

von Micha (Gast)


Lesenswert?

Ulrich schrieb:
> Man könnte auch den Timer weiter laufen lassen, und statt dem overflow
> interrupt einen output compare Interrupt nutzen. Also einfach eines der
> OCR Register passend (z.B. timerstand +60000) setzen.  Wenn das passende
> Interrupt-Flag gesetzt ist, war die Zeit zu lang.

Da kann ich aber auch das Overflow-Flag auswerten und verwerfe die 
einfach Ergebnisse, die einen Überlauf hatten. Vielleicht gar keine so 
schlechte Idee: Gibt bei niedrigen Drehzahlen dann ggf. eine schlechtere 
Zeitauflösung, aber verschmerzbar, da ich den Bereich nur beim Anfahren 
und Anhalten durchlaufe. Werd ich versuchsweise mal implementieren.

> Ein Overflow beim Timer zwischen den 2 ICP Events ist noch keine
> Problem, wenn man die Rechnung mit word Variablen, also 16 Bit unsigned
> macht. Der Cast nach Int ist als genau falsch. Das Ergebnis ist auch
> immer Positiv - sind doch keine Neutrinos.

Ich rechne bei sowas immer nur mit 16bit unsigned.

Krapao schrieb:
> Du braucht keinen zusätzlichen Timer! Du kannst den ICP Interrupt und
> den Overflow Interrupt bei dem gleichen Timer enablen.

Ja, ich weiß. Auf den Overflow Interrupt wollte ich als ewiger 
Minimalist halt verzichten.

von Tim (Gast)


Lesenswert?

Bitte auch die Interrupt Priorität und die Latenz berücksichtigen.
Wenn der ICP im Interrupt auf 0 gesetzt wird kannst du einige Schritte 
verlieren wenn der µC noch andere Interrupts bearbeiten muss.

nb: Der Motor macht 60 Impulse Pro Umdrehung?
Sonst sind es nur 33,3Hz....

von Micha (Gast)


Lesenswert?

Tim schrieb:
> Bitte auch die Interrupt Priorität und die Latenz berücksichtigen.
> Wenn der ICP im Interrupt auf 0 gesetzt wird kannst du einige Schritte
> verlieren wenn der µC noch andere Interrupts bearbeiten muss.

Deshalb wollte ich auch eine Lösung finden, auf der ich den Timer 
durchlaufen lassen kann.

> nb: Der Motor macht 60 Impulse Pro Umdrehung?
> Sonst sind es nur 33,3Hz....

Welche Motoren meinst Du mit "Sonst sind es nur 33,3Hz"? Meiner hier - 
Herkunft unbekannt, Universalmotor mit schätzungsweise ~300W - macht 
über den Tachogenerator ~60 Impulse/Umdrehung.

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.