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.
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
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.
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.
> 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
voaltileuint16_tdifference;
2
volatileuint8_tnewValue;
3
4
ISR(...)
5
{
6
uint16_tnow=ICR1;
7
staticuint16_tlast;
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.
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.
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!