Ich will die Geschwindigkeit eines Rades messen, wofür ich pro Umdrehung ein impuls bekomme. Ich benutze den 16bit Timer zusammen mit dem Input Capture Pin. Nur ich werd nicht so ganz schlau aus dem Datenblatt, ob man Overflow und ICP zusammen verwenden kann (würde ich gerne verwenden um zu detektieren ob das Rad "stillsteht") und ob der Counterwert bei einem IPC Event automatisch reseted wird. Als umrechnung für die Geschwindigkeit habe ich mir folgendes überlegt: X=36 * Counter_Stand_nach_1_sek*Radumfang_in_m (könnte man als Konstante Ablegen) kmh = ( X / ICP_Zählerstand) / 100 Sieht jemand in der Rechnung noch nen Denkfehler bzw Optimierungsmöglichkeit? hatte alternativ noch an: X=3600 * Counter_Stand_nach_1_sek*Radumfang_in_m kmh = X / ICP_Zählerstand gedacht dan muß ich aber wohl aufgrund der Größe der Zahl nen 32bit Wert für X vorsehen.
>ob man Overflow und ICP zusammen verwenden kann ja, geht. >ob der Counterwert bei einem IPC Event automatisch reseted Nein, wird er nicht. Du musst dir nur die beiden Timer-Werte merken und dann von einandern abziehen. OC kann man dabei auch noch machen (lassen)... Overflow ist dann natürlich etwas problematisch, da der auch so auftreten kann, ohne dass das Rad steht (2-3 Overflow müssten dann vielleicht auftreten, damit man das detektieren kann).
Naja, der Controller läuft mit 16mhz, vorteiler 1024, ergibt 4sek lang keine Impuls, das wären dann bei einem Umfang von 165cm, ne Geschwindikeit < 0.5kmh und ich wollte Minimal Geschwindikeit im Bereich ab 1kmh erfassen :) Könnte ich also bei einem ICP Event einfach Counter auf 0 setzen, ICP Register auslesen, und mit obiger Formel berechnen?
Um die Geschwindigkeit zu berechnen brauchst Du zwei Ereignisse bzw. die Zeitspanne dazwischen. Du brauchst also schon mal einen Capture-Interrupt um eine Messung zu starten und dann einen, der die Messung beendet und das Ergebnis ausspuckt.
Würde ich nicht machen. Nimm einfach den aktuellen ICP-Wert und addiere ihn zum OCA-Wert hinzu. Der erzeugt dann bei einem "virutellen" Überlauf einen Interrupt wenn kein neues ICP-Ereignis eingetreten ist.
@jonny.m: Hab ich ja Zeitpunkt 0 und Zeitpunkt 0+ICP Wert @Rahul: öm irgenwie versteh ich grad nicht ganz was genau du sagen willst... verwirrt
>Hab ich ja Zeitpunkt 0 und Zeitpunkt 0+ICP Wert
Du lässt den Timer konstant laufen.
Bei einem ICP-Interrupt sicherst du den ICP-Wert in einer Variablen
Beim folgenden ICP-Intrerupt sicherst du auch diesen Wert und ziehst du
den ersten von diesem ab. Damit hat du die Zeit zwischen zwei Impulsen.
Zu meinem "Watchdog":
Solange ein ICP-Interrupt auftritt, wird in das OC-Register ein
entsprechend höherer Wert geschrieben. Dieser Wert setzt sich aus dem
aktuellen ICP-Wert und einer Zeitkonstante zusammen, die du als
Überlauf definierst.
Sobald kein ICP-Interrupt mehr auftritt, weil das Rad steht, wird
irgendwann der OC-Wert erreicht und dessen Interrupt ausgelöst.
Damit hättest du dann dein "OVerflow-Interrupt"...
Jetzt klarer?
1. Capture-Ereignis: Timer starten (oder rücksetzen), 2. Capture: Wert einlesen und Ergebnis berechnen. Bei nem Überlauf -> Geschwindigkeit '0'. Wenn Du es so machst, sehe ich da keine Probleme, zumal in Deiner Anordnung die Frequenz der zu messenden Ereignisse sehr niedrig zu sein scheint. Da brauchste dann nicht die maximale Genauigkeit und der Aufruf der Capture-ISR fällt nicht störend ins Gewicht. Für Deine Anwendung sollte das tatsächlich ausreichen. Wenns allerdings in den Bereich höherer Geschwindigkeiten bzw. Genauigkeit geht, dann sollte die andere Methode benutzt werden. Ich würde den µC dann aber in Deinem Fall auch nicht mit vollen 16MHz betreiben, es sei denn, da hängen noch andere, zeitkritische Dinger dran... Gruß Johnny
Das mit der Zeit ist klar, dann muß ich aber ja noch prüfen welcher von beiden Werten größer ist sonst krieg ich ja negative Zahlen (bzw falsche) oder ist da jezt nen Denkfehler drinn? Das zweite ist klar, also soll ich den Output Compare Interupt noch verwenden, dachte ich soll ins Zählregister schreiben das wäre dan natürlich unsinnig. Da ich das ganze in Assembler programiere wäre mir natürlich am liebsten das ganze möglichst ohne zuviel 16bit Artimetik auskommt ;) Wenn ich es auf diese Weise mache, müßte allerdings das ganze Wohl am genausten sein und am besten anzupassen, würde den dann obige Formel funktionieren wenn ich erstmal die anzahl Takte zwischen zwei Interupts habe?
Also Geschwindikeit zwischen 1 und 180 km/h (maximal eher weniger) in 1km/h Auflösung hatte ich gedacht.
>Das mit der Zeit ist klar, dann muß ich aber ja noch prüfen welcher >von beiden Werten größer ist sonst krieg ich ja negative Zahlen (bzw >falsche) oder ist da jezt nen Denkfehler drinn? Nö, ist nicht wichtig. Probier es einfach mal auf dem Papier aus. Das dachte ich nämlich auch zuanfang. Solange du nicht auf die Idee kommst, den Zahlenbereich zu verringern (z.B. per CTC) und immer schön deine 8 oder 16 Bit durchtickern lässt, ist alles schön. Peter Dannegger hatte dazu mal was in irgendnem Beitrag geschrieben... Die Variante mit Timer-Start und -Stop ist nur empfehlenswert, wenn dieser explizit nur für diese Anwendung benutzt werden soll.
Wenn das so ist (ich glaub dir das mal) vereinfacht das die Sache natürlich erheblich. Ich wollte den Timer einfach stur laufen lassen auf seinen 16bit. Und der Vorteil ist natürlich der Timer kann noch für andere Anwendungen benuzt werden :) Danke schonmal für die Hilfe, kann den meine Umrechnung auf KMH so klappen? Habs zwar jezt shcon so zweimal überdacht aber im Prinzip ist mir kein Fehler aufgefallen.
So hier mal meine ISR: ICP_int: push temp in temp, SREG ;Timerwert einlesen in ICPL1, ICR1L in ICPH1, ICR1H ;Alten Wert abziehen sub ICPL2, ICPL1 sbc ICPH2, ICPH1 ;In Register speichern mov ICPL, ICPL2 mov ICPH, ICPH2 ;Alter Wert = neuer Wert mov ICPL2, ICPL1 mov ICPH2, ICPH2 ;Flag setzen für WertUpdate sbr Flags, (1<<F_CPM) out SREG, temp pop temp reti Im Hauptprogramm wird dann auf den geänderten Wert in ICPL/ICPH reagiert, der "alte" Wert wird vorerst mit 0 inistialisiert, da ich mit einer "falschen" Messung am Anfang leben kann. Wenn noch wer was sieht, das ich anders oder besser machen sollte...
> mov ICPH2, ICPH2 Da ist aber noch was faul... > push temp > in temp, SREG ... > out SREG, temp > pop temp ...und das macht so keinen Sinn. Wenn, dann andersrum. Du willst ja SREG sichern. Musst es also erst in temp laden und dann pushen bzw. am Ende erst poppen und dann in SREG schreiben...
Arg... hast recht da muß ne 1 hin in liest doch aber in das erste Register den Wert von Parameter 2 und umgekehrt, für out also sollte das so stimmen, temp braucht ja nicht nochmal gepusht werden da ich das innerhalb nicht verwende, aber die SUB Operation die Flags verändert.
> out SREG, temp
schreibt irgendwas undefiniertes (halt das, was zu dem Zeitpunkt in
temp steht) in SREG. Da kann alles Mögliche passieren. Wenn Du das
gesicherte SREG zurückschreiben willst, musst Du erst den Wert vom
Stack in temp laden (mit pop) und dann das was vorher drin war in
SREG schreiben. Und am Anfang natürlich genauso, nur andersrum. Du
sicherst ja nur temp. Da steht aber zu dem Zeitpunkt mit Sicherheit
nicht das drin, was DU eigentlich sichern willst!
Poste am besten mal den kompletten Code. An der ISR alleine kann man nicht sehen, ob das Konzept funktionieren kann.
> push temp temp wird gesichert (weil ggf. von einer Routine verwendet die durch die ISR unterbrochen wird) > in temp, SREG wert in temp wird durch den Wert in SREG überschrieben >... die ISR macht was (ändert aber am Wert von temp nix) > out SREG, temp der vorher in temp gespeicherte Wert wird ins SREG geschrieben > pop temp der Orginalzustand von temp wird wieder hergestellt >reti die ISR wird verlassen (SREG udn TEMP wie vor dem ientritt in die ISR)
Ah so! Sehr unübliche Methode. Normalerweise sichert man das SREG auf dem Stack und nicht im Registersatz (deshalb auch mein ungläubiges Kopfschütteln). Naja, Du musst es ja wissen... Aber wenn Du den Code nicht einstellst, kann Dir auch keiner weiter helfen:-( Ich mache jetzt Feierabend...
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.