mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Geschwindigkeit Mittels ICP messen


Autor: Laeubi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Rahul (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>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).

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert

Autor: Laeubi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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?

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Rahul (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Laeubi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@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

Autor: Rahul (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>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?

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Laeubi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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?

Autor: Laeubi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also Geschwindikeit zwischen 1 und 180 km/h (maximal eher weniger) in
1km/h Auflösung hatte ich gedacht.

Autor: Rahul (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>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.

Autor: Laeubi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Laeubi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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...

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> 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...

Autor: Laeubi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> 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!

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Poste am besten mal den kompletten Code. An der ISR alleine kann man
nicht sehen, ob das Konzept funktionieren kann.

Autor: Laeubi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> 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)

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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...

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.