Forum: Mikrocontroller und Digitale Elektronik Problem Signalfrequenz ermitteln mit Mega32


von Rolf (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,

habe folgendes Problem:

Möchte mit einem AVR Mega32 (16Mhz Quarz) die Frequenz 2er
Rechtecksignale (3 bis 500 Hz, Puls/Pause = 1:1) ermitteln.

Verwende folgenden Lösungsansatz:
die 2 Signale gehen je auf einen externen Int. 0/1 (die ext. Int.
reagieren auf jeden Flankenwechsel), mit dem Timer 0 und 2 messe ich
die Puls bzw. Pausendauer (Prescaler 250kHz = 4 us/Zähltakt)
Beim 1. Flankenwechsel der z.B am Int 0 erkannt wird, wird Timer1
zurück gesetzt. Da es nur ein 8Bit Timer ist muß ich in der Timer
OverFlow Int. eine Variable für die Überläufe hochzählen.

Wird nun der 2. Flankenwechsel erkannt, lese ich den Überlaufzähler,
sowie das Timerregister aus und ermittle dadurch die Frequenz.
-> Anschließend wird wieder für eine Puls bzw Pausendauer gewartet und
dann erfolgt eine neue Messung.

Das ganze funktioniert im Prinzip schon, allerdings erhalte ich bei
bestimmten Signalfrequenzen einen "Messfehler".
Das ganze liegt vermutlich daran: Wenn während ich in der Int.Routine
des Ext.Int. bin ein erneuter TimerOverflow auftritt so erfolgt die
Inkrementierung der Überlaufvariable erst wenn die Ext.Int Routine
abgearbeitet ist -> somit ist die ermittelte Zeitdauer um den Wert 256
zu klein.
Deshalb dacht ich mir ich halte zu Beginn der ext.Int Routine den Timer
an, lese das Overflow Flag des Timers aus und wenn dies auf "1" ist
nehm ich die Inkrementierung der Überlaufvariable in der ext.int
Routine vor und lösche das Bit für den TimerOverflow Interrupt.

Doch das ganze funktioniert leider noch immer nicht... Kann mir jemand
sagen was ich da falsch mach ?? Oder wie ich es besser lösen kann ??
(Bei einer Eingangsfrequenz von 248 Hz, beträgt die ermittelte Frequenz
mal 248Hz und mal 164Hz. Erhöhe oder veringere ich die Eingangsfrequenz
um 1, dann ist die ermittelte Frequenz immer korrekt).


Vielen Dank

Gruß, Rolf

von Bernhard S. (bernhard)


Lesenswert?

Hallo Rolf,

ich habe mich auch schon mit dieser Materie beschäftigt und hier zwei
grundlegende Verfahren vorgestellt:

http://www.mikrocontroller.net/forum/read-4-230466.html


>die 2 Signale gehen je auf einen externen Int. 0/1 (die ext. Int.
>reagieren auf jeden Flankenwechsel), mit dem Timer 0 und 2 messe ich
>die Puls bzw. Pausendauer

Warum wertest Du jeden Flankenwechsel aus? Es würde genügen, wenn Du
nur einen Wechsel (z.B. fallende Flanke) auswertest.

Warumm zählst Du nicht einfach die Anzahl der Impulse pro Zeit, wäre
doch einfacher und genauer? Bei einer Messung der Periodendauer erfolgt
doch anschließend die Umrechnung f=1/T,
wobei T fehlerbehaftet ist.

Bernhard

von Rolf (Gast)


Lesenswert?

Hallo Bernhard,

danke für Deine Hinweise.
Bei den Signalen handelt es sich um das Drehzahl und
Geschwindigkeitssignal eines Motorrads.
Die Variante mit "nur" 1 Sekunde lang die anliegenden Impulse
hochzählen hatte ich anfangs versucht. Das hat auch super funktioniert.
Der Haken daran: ich aktualisiere alle 250ms das Display mit der
Drehzahl / Geschwindigkeitsanzeige. Da ich ja erst 1 Sekunde die
Impulse sammeln muß war die Anzeige des Drehzahlmessers viel zu langsam
und ist immer hinterher gelaufen.
Darum hab ich dann auch versucht den Interrupt auf fallende und
steigende Flanke zu triggern -> somit muß ich nur 500ms die Pulse
zählen um die Frequenz zu bekommen. (war leider immer noch etwas zu
träge am Display)
Wenn ich nur 250ms die Pulse zähle und dann mal 2 rechne, dann wirds zu
ungenau, da ich dan ja die Frequenz nur in 2er Schritten ermittle.

Die Variante mit dem Timer wäre von der Aktualisierungs-geschwindigkeit
echt super, wenn die blöden Fehler nicht drin wären... Zumal könnt ich
die anliegende Frequenz sogar aufs 1/10 genau bestimmen und nicht nur
auf 1 Hz genau wie bei der "Interrupt Zähl-Variante"


Hab ja bei meinem ersten Beitrag nen kleinen Programmausschnitt
angehängt, mach ich da vielleicht beim Abfragen des TimerOverflow
Interrupt oder bei dessen Rücksetzung nen Fehler ???


Gruß Rolf.

von Bernhard S. (bernhard)


Lesenswert?

Hallo Rolf,

jetzt habe ich's verstanden, warum Du die Periodendauer messen
möchtest ;)

Da hast Du natürlich Recht, mit diesem Prinzip kann man sehr schnell
eine Drehzahl ermitteln.

>Hab ja bei meinem ersten Beitrag nen kleinen Programmausschnitt
>angehängt, mach ich da vielleicht beim Abfragen des TimerOverflow
>Interrupt oder bei dessen Rücksetzung nen Fehler ???

Kann ich leider nicht beurteilen, da ich bei zeitkritischen Problemen
lieber in Assembler programmiere, denn da weiß man genau, was der µC
bei jedem Takt gerade macht, meistens zumindest ;)

Bernhard

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
Noch kein Account? Hier anmelden.