Forum: Mikrocontroller und Digitale Elektronik ATMega328P Frequenzmessen mit Timer. Welches Konzept?


von Frequenzmesser (Gast)


Lesenswert?

Hallo,

und zwar habe ich eine Frage bezüglich Frequenzmessung mit dem 
ATMega328P.
Bin mir total unschlüssig welches Konzept ich verweden soll.

Es sollen zwei Frequenzen mit folgenden Daten gemessen werden:
0 - 300Hz
0 - 200Hz

Da dies ja sehr niedrige Frequenzen sind, wäre doch ein 16Bit Timer mit 
einem Prescaler von 1024 am geeignetsten.

In der CPU Taktfrequenz habe ich micht noch nicht festgelegt endgültig 
festgelegt. 20 MHz, falls es mit dem Timer nicht passen sollte und es 
geschickter wäre eine niedrigere zu wählen sind auch 8 MHz ok.

Jetzt hab ich im Netz Ansätze gefunden wo jeder Pin einen Interrupt 
auslöst und dann den Zählerstand abfrägt. Habe auch aber das Problem 
gefunden, dass das nicht immer zuverlässig funktioniert. Der Controller 
soll auch einiges mehr machen als nur die zwei Frequenzen messen.

Oder wärs besser den ATMega328P durch einen ATMega328PB zu ersetzen und 
jede Frequenz auf einen ICP Eingang zu leiten (Der PB hat 3 16Bit 
Timer)?

Wie würdet ihr da ran gehen?

Vielen Dank

von THOR (Gast)


Lesenswert?

Frequenzmesser schrieb:
> Es sollen zwei Frequenzen mit folgenden Daten gemessen werden:
> 0 - 300Hz
> 0 - 200Hz

Welche Art von Signal? Rechteck?

Frequenzmesser schrieb:
> Jetzt hab ich im Netz Ansätze gefunden wo jeder Pin einen Interrupt
> auslöst und dann den Zählerstand abfrägt.

Joar, das geht.

Frequenzmesser schrieb:
> Habe auch aber das Problem
> gefunden, dass das nicht immer zuverlässig funktioniert.

Weil? Sehe ich keinen Grund für. Es sei denn, man programmiert das 
dämlich und irgendwann läuft der Zähler über.

Frequenzmesser schrieb:
> Oder wärs besser den ATMega328P durch einen ATMega328PB zu ersetzen und
> jede Frequenz auf einen ICP Eingang zu leiten (Der PB hat 3 16Bit
> Timer)?

ICP wäre die Hardwarevariante. Wenn der ATMega328PB auch tatsächlich 3 
Input capture pins hat, geht das.

von T. A. (wambly)


Lesenswert?

Hallo
Bei niederen Frequenzen geht man dazu über, die Periodendauer zu messen,
das dann 1/x die Freq ergibt.
Habe das bei einem Auto DZM so in Verwendung. Mit einem M8, da Du 2 
gleichzeitig brauchst bist Du mit dem 328 besser dran mit 2 ICP Pin's.

Mit Arduino Boards bekommst die meist an günstigsten mit Wartezeit.

Ciao

von Veit D. (devil-elec)


Lesenswert?

Hallo,

der Timercounter wird immer überlaufen. Man muss nur die Differenzen 
richtig ausrechnen. Ggf. noch einen Überlaufzähler vorsehen. Bei den 
niedrigen Takten wäre auch ein Pin Change Interrupt ausreichend, den hat 
jeder µC Pin. Ein einziger Timer läuft "nebenbei", der Zählerstand wird 
bei erkannten Change Interrupt immer ausgelesen und verrechnet.

von Frequenzmesser (Gast)


Lesenswert?

THOR schrieb:
> Frequenzmesser schrieb:
>> Es sollen zwei Frequenzen mit folgenden Daten gemessen werden:
>> 0 - 300Hz
>> 0 - 200Hz
>
> Welche Art von Signal? Rechteck?

Einmal eine Dreickspannung & das andere eine Rechteckspannung. Wird aber 
beides über einen OPV als Komparator in ein 5V TTL Signal umgewandelt.

THOR schrieb:
> Frequenzmesser schrieb:
>> Habe auch aber das Problem
>> gefunden, dass das nicht immer zuverlässig funktioniert.
>
> Weil? Sehe ich keinen Grund für. Es sei denn, man programmiert das
> dämlich und irgendwann läuft der Zähler über.

Der Grund war falls die Interrupts zu knapp aneinander kommen.

THOR schrieb:
> ICP wäre die Hardwarevariante. Wenn der ATMega328PB auch tatsächlich 3
> Input capture pins hat, geht das.

Ja hat 3 auf jeweils einem 16Bit Timer.

T. A. schrieb:
> Habe das bei einem Auto DZM so in Verwendung.

Bei mir ebenfalls. Drehzahl und Geschwindigkeit.

von m.n. (Gast)


Lesenswert?

Frequenzmesser schrieb:
> Oder wärs besser den ATMega328P durch einen ATMega328PB zu ersetzen und
> jede Frequenz auf einen ICP Eingang zu leiten (Der PB hat 3 16Bit
> Timer)?

Kannst Du machen, muß aber nicht sein. Mit Hilfe des ADC-Multiplexers 
kann man auch die ADC-Eingänge per ICP nacheinander messen.
Kleiner Nachteil: bei 0 Hz können ewige Wartezeiten auftreten.

von Frequenzmesser (Gast)


Lesenswert?

Ein ATMega328P wäre mir natürlich lieber. Wie meinst Du dass mit den 
Wartezeiten? Also Praktisch ein Timeout programmieren? Dann dauerts 
X-Sekunden bis 0Hz erkannt werden?

von Peter D. (peda)


Lesenswert?

Man kann das alles ausrechnen.
Wie oft sollen neue Messungen angezeigt werden und welcher Fehler ist 
zulässig.
Einen Interrupt könnte man in 50 CPU-Zyklen ausführen. D.h. wenn beide 
gleichzeitig auftreten, ist ein Jitter von 50 Zyklen möglich.

Muß die Messung genauer sein, gibt es aber auch Möglichkeiten. Z.B. 
einen Eingang auf den ICP und den als ISR_NOBLOCK, da der ja keinen 
Jitter hat.

von m.n. (Gast)


Lesenswert?

Frequenzmesser schrieb:
> Ein ATMega328P wäre mir natürlich lieber. Wie meinst Du dass mit den
> Wartezeiten? Also Praktisch ein Timeout programmieren?

Ja, ein Timeout was den Eingangsfrequenzbereich auf >= 1 Hz - 2 Hz 
begrenzt. Alles, was darunter liegt, erzeugt eine Anzeige 0.00.

Welche Auflösung, Genauigkeit und Meßrate brauchst Du überhaupt? Sofern 
es nur 3 - 4 Stellen bei 2 - 3 Messungen/s sind, kann man auch die 
Eingänge zyklisch mit 10 - 30 kHz abtasten und Signaländerungen per 
Software auswerten. Dafür reicht schon ein µC mit 8 Bit Timer.

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Frequenzmesser schrieb:
>> Weil? Sehe ich keinen Grund für. Es sei denn, man programmiert das
>> dämlich und irgendwann läuft der Zähler über.
>
> Der Grund war falls die Interrupts zu knapp aneinander kommen.

Kann passieren, wenn man PC Interrupts nimmt und die in der gleichen 
PCINT Gruppe sind. Ganz blöd könnte man INT0 und INT1 verwenden, die 
werden auf jeden Fall hintereinander abgearbeitet und verlieren keine 
Pulse oder man kann auch Timer mit dem Messsignal takten (T0, T1) und 
mit einer internen Uhr auslesen.
Da gibts so viele Möglichkeiten, das einem schon fast schwindlig wird 
:-)

: Bearbeitet durch User
von Manfred (Gast)


Lesenswert?

Frequenzmesser schrieb:
> Bin mir total unschlüssig welches Konzept ich verweden soll.
Arbeite mal den durch:
http://shelvin.de/ein-frequenzzaehler-fuer-niedrige-frequenzen-mit-dem-arduino-uno-und-der-pulslaengenmessung/

Dort wird etwas erwähnt, was ich noch nicht gehört habe:
"Der Arduino bietet hierzu die Funktion pulseIn(pin, signal) an."

von Wolfgang (Gast)


Lesenswert?

Frequenzmesser schrieb:
> Dann dauerts X-Sekunden bis 0Hz erkannt werden?

Löse dich von der Vorstellung, jemals in deinem Leben 0Hz messen zu 
können. Eine halbe Schwingung, die deine Lebensdauer ziemlich sicher 
übersteigt, hat immer noch eine Frequenz von 0,3nHz ;-)

Du solltest eine sinnvolle untere Grenzen festlegen und daran dein 
Timeout orientieren.

von m.n. (Gast)


Lesenswert?

Manfred schrieb:
> Dort wird etwas erwähnt, was ich noch nicht gehört habe:
> "Der Arduino bietet hierzu die Funktion pulseIn(pin, signal) an."

Der Arduino ist ja ein Alleskönner! Einfach eine Funktion aufrufen und 
schon sind alle Probleme beseitigt.
Aber wäre es nicht besser, die Probleme zu lösen?

Das Suchwort für die Problemlösung heißt "reziproke Frequenzmessung". 
Alles andere kann man bei diesen tiefen Frequenzen getrost vergessen.

von Axel S. (a-za-z0-9)


Lesenswert?

m.n. schrieb:
> Das Suchwort für die Problemlösung heißt "reziproke Frequenzmessung".
> Alles andere kann man bei diesen tiefen Frequenzen getrost vergessen.

Jein. Bei Frequenzen von maximal 300Hz, einer Referenzfrequenz von bis 
zu 20MHz und vermutlich gar keinen Anforderungen an die Meßgenauigkeit 
wird aus der reziproken Frequenzmessung von ganz allein eine schlichte 
Periodendauermessung. Zweckmäßigerweise erledigt mit der 
Capture-Funktion eines Timers, für mehrere Kanäle dann halt mit mehreren 
solchen.

Der Punkt mit der unteren Frequenzgrenze wurde ja schon besprochen. Wenn 
der TE (Troll Editor?) weiterhin auf einer Grenze von 0 Hz beharrt, ist 
das Thema ja ohnehin durch, oder?

von Wolfgang (Gast)


Lesenswert?

Vielleicht hat der TO inzwischen den Artikel Frequenzzählermodul 
entdeckt.

von m.n. (Gast)


Lesenswert?

Axel S. schrieb:
> wird aus der reziproken Frequenzmessung von ganz allein eine schlichte
> Periodendauermessung.

Und da der TO keine Periodendauer, sondern eine Frequenz angezeigt 
bekommen möchte, wird aus der Periodendauermessung wieder eine reziproke 
Frequenzmessung.

Wolfgang schrieb:
> Vielleicht hat der TO inzwischen den Artikel Frequenzzählermodul
> entdeckt.

Und dabei festgestellt, daß diese Schaltung nur für einen Kanal geeignet 
ist. Mit bis zu 4 Kanälen ist das dann besser geeignet: 
Beitrag "4-Kanal Drehzahlmessung mit ATmega88"

von Frequenzmesser (Gast)


Lesenswert?

Ja ihr habt recht. 0Hz ist Unsinn. Wollte damit nur sagen, dass der 
Zustand auftritt und erkannt werden soll. Der Frequenzbereich lautet:

20Hz - 300Hz
14Hz - 200Hz

mindestens auf ein 1Hz genau, besser 0.5Hz. Ist diese Anforderung 
möglich?

Manfred schrieb:
> Arbeite mal den durch:
> 
http://shelvin.de/ein-frequenzzaehler-fuer-niedrige-frequenzen-mit-dem-arduino-uno-und-der-pulslaengenmessung/

Ich verwende keinen Arduino. Programmiere in C.

m.n. schrieb:
> Das Suchwort für die Problemlösung heißt "reziproke Frequenzmessung".

Schau ich mir an.

von Manfred (Gast)


Lesenswert?

m.n. schrieb:
> Der Arduino ist ja ein Alleskönner! Einfach eine Funktion aufrufen und
> schon sind alle Probleme beseitigt.
Du bist dusselig. Schön hoch die Nase und bloß nicht über das eigene 
Tellerchen gucken!

Frequenzmesser schrieb:
> Ich verwende keinen Arduino. Programmiere in C.
Welche Sprache verwendet Arduino?

Hast Du Dir die Beschreibungen angeschaut? Der Matthias Busse hat da 
durchaus qualifiziert beschrieben, wie er das angeht. Ich denke, dass 
man auf dieser Basis vorwärts kommt.

von Axel S. (a-za-z0-9)


Lesenswert?

Frequenzmesser schrieb:
> Ja ihr habt recht. 0Hz ist Unsinn. Wollte damit nur sagen, dass
> der Zustand auftritt und erkannt werden soll. Der Frequenzbereich
> lautet:
>
> 20Hz - 300Hz
> 14Hz - 200Hz
>
> mindestens auf ein 1Hz genau, besser 0.5Hz. Ist diese Anforderung
> möglich?

Ja, das ist Pillepalle. Wenn 0.5Hz Fehler auf 300Hz erlaubt sind, dann 
geht das auch ohne ICP, per Pinchange-Interrupt [1].

Das Grundprinzip ist ganz einfach: du läßt einen Timer mit konstanter 
Frequenz durchlaufen, sagen wir einfach mit 1MHz (8MHz mit Prescaler=8). 
Bei jedem Interrupt liest du den Timerwert aus und merkst ihn dir. Dann 
ziehst du den zuletzt gemerkten Wert ab und erhältst direkt die Zeit 
zwischen zwei Interrupts in µs. Der Kehrwert ist die Frequenz [2].

Jetzt müssen wir noch schauen, ob es ein Problem mit Überläufen geben 
kann: bei 1MHz läuft ein 16-Bit Timer über mit f = 1MHz/2^16 ~= 15Hz. 
Das ist blöd, denn es bedeutet, daß du 14Hz nicht mehr messen kannst. Du 
kannst jetzt entweder den Timer langsamer betreiben, z.B. mit 500kHz 
oder - besser - du erweiterst den Timer auf 32 Bit indem du den 
Überlauf-Interrupt aktivierst und bei jedem Überlauf einen uint16_t 
inkrementierst [3]. Diese Variable ergibt dann zusammen mit dem TCNT 
Register einen 32-Bit Timer. Die Timestamps, mit denen du im Interrupt 
rechnest, sind dann halt 32-Bit Werte.

Die Erkennung einer niedrigen Eingangsfrequenz ist auch einfach. Dazu 
brauchst du zwei weitere Variablen, z.B. uint8_t. Jedes Mal, wenn der 
PC-Interrupt eine Flanke des jeweiligen Signals erkannt hat, setzt er 
die Variable auf 0. Im Timerüberlauf inkrementierst beide Variablen und 
prüfst ihren Wert. Ein Wert von 15 bedeutet, daß eine Sekunde lang kein 
Signal gezählt wurde.

[1] wenn dein µC genügend ICP-Einheiten hat, dann solltest du die 
natürlich verwenden. Oder du kannst auch für ein Signal ICP verwenden 
und für das anderen einen Pinchange-Interrupt.

[2] Wenn du 10.000.000 / T rechnest (wobei T die Periodendauer im µs 
ist), dann kriegst du die Frequenz in 10-tel Hz raus und kannst alles 
mit Integer rechnen. Noch besser ist (10.000.000 + T/2) / T. Das rundet 
gleich noch.

[3] hier kann es eine race condition geben, wenn Überlauf und 
Capture-Event gleichzeitig auftreten. Das mußt du in Software abfangen. 
Das Problem wurde hier mehrfach durchdekliniert, u.a. im 
Beitrag "AVR Timer mit 32 Bit"

von m.n. (Gast)


Lesenswert?

Manfred schrieb:
> Du bist dusselig.

Aber nicht so beschränkt, daß ich Frequenzen mit pulseIn() messen würde. 
Diese Funktion hat ja die Eleganz von delay(10000).

von Wolfgang (Gast)


Lesenswert?

Frequenzmesser schrieb:
> 20Hz - 300Hz
> 14Hz - 200Hz
>
> mindestens auf ein 1Hz genau, besser 0.5Hz. Ist diese Anforderung
> möglich?

Dann zäume das Pferd doch mal anders rum auf und rechne aus, mit welcher 
Auflösung die Periodendauer gemessen werden muss, damit die von dir 
gewünschte Frequenzauflösung in deinem Bereich erreicht wird.

Das kriegst du fast noch mit einer Stopuhr hin ;-)

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.