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
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.
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
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
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
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
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 :-)
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.
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?
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.
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
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%.
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
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.
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.
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
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.
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
> 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
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!
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.
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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.