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ß :-)
> 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.
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
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.
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
> 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.
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.
> 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.
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.
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"
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
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...
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.
> 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.
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.
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.
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.
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....
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.