Hi Leute, ich möchte eine Impulsbreite von max. 10ms mit dem Timer1 vom Mega48 messen, mit möglichst wenig Prozessorbelastung (also z.B. "wie lange war die Leitung auf "H"). Vorüberlegung: Takt = 1MHz, also sollte der Timer erst nach gut 20ms überlaufen, wenn der CTC-Mode 12 verwendet wird und timer1 ohne prescaler läuft? Ist es so richtig / am einfachsten, oder gibt es etwas Einfacheres, was ich übersehen habe? 1) ICES (edge detector) auf L->H einstellen, Interrupt abwarten (steigende Flanke) 2) in der ISR: Timer1 auf 0 stellen, ICES auf H->L umstellen 3) Interrupt abwarten (fallende Flanke) 4) in der ISR: Timer auslesen = Impulsbreite; ICES (edge detector) wieder auf auf L->H einstellen (dann wieder weiter bei 2)
Rainer Unsinn schrieb: > > Ist es so richtig / am einfachsten, oder gibt es etwas Einfacheres, was > ich übersehen habe? Hat der Mega48 am Timer 1 keinen Input Capture?
Grundsätzlich funktioniert das. Ich habe auf die Art und Weise mal ein PWM Signal ausgewertet. Das hatte, soweit ich mich erinnern kann, 10 kHz. Problematisch wird es, wenn du nebenbei noch andere Interrupts laufen hast. Außerdem kann es bei kurzen Peaks, beispielsweise ein PWM von 0,1% oder 99,9% passieren, dass das Setzen der Register und das Umschalten der Flankenerkennung so lange dauert, dass du erst die nächste Flanke wieder erkennst, dann also statt 0,1% 100,1% gemessen werden. Viel Erfolg.
Im Prinzip geht es so. ICES dürft sich schon auf die Input capture Einheit beziehen. Man sollte aber den Timer nicht zurücksetzen, sondern die Zeit nur Auslesen und die Differenz einfach berechnen. Den Überlauf kriegt man automatisch richtig hin, wenn man die Differenz mit word (16 Bit unsigned) berechnet.
Rainer Unsinn schrieb: > Hi Leute, ich möchte eine Impulsbreite von max. 10ms mit dem Timer1 vom > Mega48 messen, mit möglichst wenig Prozessorbelastung (also z.B. "wie > lange war die Leitung auf "H"). Wie genau muss es denn sein? Wenn du deinen Systemtimer (den du hoffentlich hast) auf 10KHz einstellst, kannst du dein Signal im 100us Raster abtasten. Ansonsten, wie bereits erwähnt, den ICP des AVRs nehmen.
Karl Heinz schrieb: > Rainer Unsinn schrieb: >> >> Ist es so richtig / am einfachsten, oder gibt es etwas Einfacheres, was >> ich übersehen habe? > > Hat der Mega48 am Timer 1 keinen Input Capture? Doch, hat er (B0 istICP1) - da will ich ja das Signal auch anschließen - geht es damit einfacher, ggf. wie?
Marcel V. schrieb: > Außerdem kann es bei kurzen Peaks, beispielsweise ein PWM > von 0,1% oder 99,9% passieren Man sollte beachten, dass es doch eine merkliche Latenz von ~2us gibt, vom ICP bis zum betreten der dazughörigen ISR, sodass die Flankenumschaltung bei kleinen Pulsweiten nicht schnell genug erfolgt. Also Pulse < 2us würde ich sein lassen.
Lurchi schrieb: > Im Prinzip geht es so. > > ICES dürft sich schon auf die Input capture Einheit beziehen. > > Man sollte aber den Timer nicht zurücksetzen, sondern die Zeit nur > Auslesen und die Differenz einfach berechnen. Den Überlauf kriegt man > automatisch richtig hin, wenn man die Differenz mit word (16 Bit > unsigned) berechnet. stimmt, ich lass das 0-stellen weg. Aber ich seh schon, ich habe eine bessere Möglichkeit übersehen - schon 2 Hinweise auf den ICP.. ?
Ach ja und an Genauigkeit nehme ich gerne was da ist, also der Timer zählt ja dann bei mir mit Mikrosekundenschritten..
Rainer Unsinn schrieb: > Doch, hat er (B0 istICP1) - da will ich ja das Signal auch anschließen - > geht es damit einfacher, ggf. wie?
1 | ISR (INPUT_CAPTURE) |
2 | {
|
3 | static uint16_t NewTimerValue, OldValue, Difference; |
4 | NewTimerValue = ICP1; |
5 | |
6 | if (NewTimerValue < OldValue){ |
7 | Difference = 0xFFFF - OldValue + NewTimerValue; |
8 | }else{ |
9 | Difference = NewTimerValue - OldValue; |
10 | }
|
11 | // Differenz auswerten
|
12 | // ...
|
13 | |
14 | OldValue = NewTimerValue; |
15 | }
|
Rainer Unsinn schrieb: > Karl Heinz schrieb: >> Rainer Unsinn schrieb: >>> >>> Ist es so richtig / am einfachsten, oder gibt es etwas Einfacheres, was >>> ich übersehen habe? >> >> Hat der Mega48 am Timer 1 keinen Input Capture? > > Doch, hat er (B0 istICP1) - da will ich ja das Signal auch anschließen Und warum fummelst du dann am TCNT1 Register rum? Das braucht kein Mensch. Das ist ja das geniale am Input Capture, dass einen der TCNT überhaupt nicht mehr interessieren braucht. D.h. solange die zu messenden Ticks den maximalen Zählumfang des Timers nicht überschreiten. Der Timer 1 ist ein 16 Bit Timer. D.h. du kannst damit bis zu 65535 Ticks ganz einfach so im Capture INterrupt 'ausmessen'
1 | volatile uint16_t Differenz; |
2 | |
3 | ISR( ... ) |
4 | {
|
5 | static uint16_t Start; |
6 | uint16_t Now = Capture_Register; |
7 | |
8 | Differenz = Now - Start; |
9 | Start = Now; |
10 | }
|
bei dir kommt dann noch die Flankenumschaltung dazu, aber vom Prinzip her wars das. Die Pulsbreite kann bis zu 65535 Timerticks lang sein und du wirst immer das richtige Ergebnis erhalten. Und zwar auf den Timertakt genau.
Ingo Less schrieb: ... > Difference = 0xFFFF - OldValue + NewTimerValue; > }else{ > Difference = NewTimerValue - OldValue; > } > // Differenz auswerten > // ... ... Damit bekomme ich aber - meiner Meinung nach - NUR den Abstand zwischen 2 steigenden Flanken, oder?
Ingo Less schrieb: > if (NewTimerValue < OldValue){ > Difference = 0xFFFF - OldValue + NewTimerValue; > }else{ > Difference = NewTimerValue - OldValue; > } Braucht kein Mensch. Solange unsigned gerechnet wird, kommt da immer das richtige Ergebnis raus, wenn man einfach nur Ende - Anfang rechnet.
Rainer Unsinn schrieb: > Ingo Less schrieb: > ... >> Difference = 0xFFFF - OldValue + NewTimerValue; >> }else{ >> Difference = NewTimerValue - OldValue; >> } >> // Differenz auswerten >> // ... > ... > > Damit bekomme ich aber - meiner Meinung nach - NUR den Abstand zwischen > 2 steigenden Flanken, oder? Das kann man so nicht sagen. Er hat ja nicht gezeigt, wie die Einstellung der Flankendetektion ist :-)
Rainer Unsinn schrieb: > Damit bekomme ich aber - meiner Meinung nach - NUR den Abstand zwischen > 2 steigenden Flanken, oder? Ja, das musst du noch per Hand umschalten Karl Heinz schrieb: > Solange unsigned gerechnet wird, kommt da immer das richtige Ergebnis > raus, wenn man einfach nur Ende - Anfang rechnet. Sicher?
Ingo Less schrieb: > Karl Heinz schrieb: >> Solange unsigned gerechnet wird, kommt da immer das richtige Ergebnis >> raus, wenn man einfach nur Ende - Anfang rechnet. > Sicher? Ja, sicher. Geht nicht anders. Es gibt ja bei unsigned kein negatives Ergebnis. Probiers aus, wenn du mir nicht traust. Was ergibt 5 - 65530?
Karl Heinz schrieb: > bei dir kommt dann noch die Flankenumschaltung dazu, aber vom Prinzip > her wars das. Na gut, so wird's gehen (Flankenumschaltung direkt nach dem Auslesen). Ein paar Zeilen kommen wohl noch dazu, damit ich mit der richtigen Flanke anfange, aber so ist es schön einfach. Danke an Alle!
Karl Heinz schrieb: > Ja, sicher. > Geht nicht anders. Es gibt ja bei unsigned kein negatives Ergebnis. > Probiers aus, wenn du mir nicht traust. Läuft ;)
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.