Forum: Mikrocontroller und Digitale Elektronik Frequenz messen


von sammy (Gast)


Lesenswert?

Hi, ich moechte mit einem 2313 eine Frequenz messen und dann die mit
vordefinierten Werten vergleichen und dann die Abweichung eber LEDs
anzeigen.
Die Frequenz wird vor dem 2313 verstaerkt, so das sie als 0 und 1
erkannt wird, es muessen also diese Wechsel pro Zeit gezaehlt werden.
Wie schliesse ich das ganze am besten am Controller an?
Ueber Codeschnipsel wuerde ich mich auch freuen!

von Matthias (Gast)


Lesenswert?

Hi

was für eine Frequenz (welcher Größenordnung)?

Bei sehr kleinen Frequenzen (bis ein paar 100 Hz) kann man per Software
abtasten. Und aus der ermittleten Periodendauer dann die Frequenz
bestimmen.

Bei Frequenzen bis zu ein paar kHz arbeitet man mit der ICP-Funktion
eines Timers. Auch diese liefert dann die Periodendauer aus der man die
Frequenz berechnen kann.

Wenns noch mehr wird (bei AVR's <8MHz bei 50:50 Tastverhältnis direkt)
zählt man für eine bestimmte Zeitperiode die Anzahl der Pulse und hat
dann im Prinzip die Frequenz direkt vorliegen.

Wirds noch schneller muß man mit (einstellbaren) Vorteilern arbeiten.

Matthias

von sammy (Gast)


Lesenswert?

Die Frequenzen liegen zwischen ca 0Hz bis 8000Hz

von sammy (Gast)


Lesenswert?

ach ja, muss der Eingang zur Frequenzmessung an einem bestimmten I/O Pin
sein, oder ist das egal?

von crazy horse (Gast)


Lesenswert?

Frequenz 0Hz messen wird schwierig :-).
Zum groben Ablauf:
Ich würde den ICP benutzen, nehmen wir mal 8MHz Quarz und Vorteiler 8
für den Timer1, also 1µs Takt.
Damit kannst du ausreichend genau messen, allerdings läuft der Timer
bei niedrigen Eingangsfrequenzen über, muss also per Software erweitert
werden.
Dazu schreibst du dir eine T1OV-Interruptroutine, die bei jedem
Überlauf ein Register incrementiert, damit kommst du auf eine max.
Peridendauer von 1µs*65536 (Timer1)* 255 (zus. Register) 16,77s, das
entspricht ca. 0,06Hz.
Um aus dem 24bit-Ergebnis die Frequenz in Hz zu berechnen, brauchst du
nur noch eine Division 1.000.000/Messwert.
Willst du es genauer, kannst du den Timer1 ohne Vorteiler betreiben,
dann evtl. mit einem 16bit-OV-Zähler arbeiten.

von Mike (Gast)


Lesenswert?

Hi,

klappt das mit dem Frequenz messen auch wenn das Signal über eine
der ext. Interruptpins bekomme? Dann muß ich die Zeit zwischen zwei
Signalen doch einfach nur "per Hand" messen und dann genau so
rechnen.
Zum messen nehme ich einfach einen frei laufenden Counter und berechne

die Zeit zwischen zwei Signalen. Klappt das so oder sollte ich das
lieber doch anders machen?

Mike

von Matthias (Gast)


Lesenswert?

Hi

kannst du auch so machen. Bei 8kHz ghet das noch relativ gut.

Matthias

von Günther (Gast)


Lesenswert?

Ich will nicht extra noch ein Beitrag auf machen und erweiter diesen
mal.

Schafft ein Mega161 mit 16MHz es an PD2(INT0) etwa 17kHz zu messen?
Könnte ich die auch an anderen 'normalen' Eingängen messen?
Was passiert, wenn die F bis etwa 100kHz ansteigt? Ich denke mal worst
case gehen ein paar Takte verloren, oder?
Hintergrund: Wenn F über etwa 16kHz steigt soll ein Ausgang schalten.
Dabei ist es aber egal ob F dann 18kHz oder 200kHz hat. Hauptsache
alles über etwa 16kHz wird als mehr erkannt.
Die Frequenz die max. anliegen kann wird wohl 120kHz sein.
Eingangssignal ist Rechteck mit TTl-Level.

von Günther (Gast)


Lesenswert?

Keiner eine Antwort

von Hmm... (Gast)


Lesenswert?

Der AVR kann schon recht kurze Pulse am Eingang erkennen, sofern sie an 
einen  interruptfähigen Pin ankommen. Problematischer wird es dann, noch 
eine Anwendung laufen zu lassen.

Beispiel:

120 kHz Signal an AVR mit 10 MHz Takt macht alle 83 Befehle einen 
Interrupt. Da bleibt nicht viel Zeit um noch groß anderes zu rechnen. Um 
allerdings nur eine Frequenz zu errechnen und auf die UART zu packen 
sollte es reichen ;)

von Kai G. (runtimeterror)


Lesenswert?

Sollte locker gehen... um mal den Grenzfall zu betrachten: 16 MHz / 200 
kHz gibt 80 Taktzyklen pro Messung (deckt sich etwa mit  Hmm...s 
Rechenbeispiel).

Kann jetzt gerade nur für Assembler sprechen, aber C sollte da auch noch 
locker drin sein:
Für jeden edge rise/fall
- Interrupt-Jump
- Timer-Reset
- Messwert ablegen
- bedingter Sprung, wenn Messreihe voll
- return
Sollte in unter 20 Taktzyklen zu schaffen sein.

Dein Programm hat also noch mindestens 1 - 20/80 = 75% Rechenzeit für 
nicht zeitkritische Sachen übrig (wenn ich nicht grob fahrlässig 
verrechnet habe :) ). Für die Übermittlung, Berechnung und/oder Ausgabe 
der Messergebnisse kannst du auch kurz die Messung anhalten und 
anschließend wieder starten - kann aber bei niedrigen Frequenzen die 
Messung verfälschen, wenn man nicht aufpasst.

Wenn du alle Nulldurchgänge messen willst und nicht nur rising/falling 
edge, verdoppelt sich logischer Weise die Anzahl der Interruptaufrufe.

Ab Frequenzen wo die Interrupts zu viel Rechenzeit verbrauchen kannst du 
ein einfaches Polling verwenden - dann macht der Mikrocontroller aber 
nichts mehr nebenher. Ich würde hier aber spätestens auch anfangen nach 
anderen Lösungen zu suchen.

Sollte die Frequenz deutlich höher als dein Limit werden macht sich das 
vielzitierte Nyquist-Shannon-Abtasttheorem 
(http://de.wikipedia.org/wiki/Nyquist-Shannon-Abtasttheorem) wieder 
bemerkbar und die Messergebnisse stimmen nicht mehr.

von Stephan (Gast)


Lesenswert?

@Günther
Sorry, jetzt hast du drei Jahre am selben Problem rumgebastelt und immer 
noch keine eigene Lösung? Anstatt nochmal drei Jahre auf eine Lösung zu 
warten beginn doch ein Studium oder arbeite dich sonst tiefer in die 
Materie ein.
Getreu dem Motto:
"Hilf dir selbst, dann hilft dir Gott"

von THM (Gast)


Lesenswert?

Input-Capture-INT enabled, die Überläufe zählen und die Start- und 
Stopzeit (Zählerstände des Timers beim ICP-INT) merken, dann mit der 
Taktfrequenz verrechnen. Z.B. mega32 bei 16MHz so:
1
Frequenz = (ICP_OVF * 65536) + stoptime - starttime;  // Zählerstand ermitteln
2
Frequenz = (16000000/Frequenz);// SYSCLK*32 wegen PWM-Mode,
3
Status &= ~_BV(ST_ICP);    // Frequenz berechnen
4
TIFR |= _BV(ICF1);
Auf dem Tiny2313 dürfte das einige Resourcen fressen.

Siehe auch in der Codesammlung (nach 'Frequenz' suchen).

von THM (Gast)


Lesenswert?

Input-Capture-INT enabled, die Überläufe zählen und die Start- und 
Stopzeit (Zählerstände des Timers beim ICP-INT) merken, dann mit der 
Taktfrequenz verrechnen. Z.B. mega32 bei 16MHz so:

1
Frequenz = (ICP_OVF * 65536) + stoptime - starttime;  // Zählerstand ermitteln
2
Frequenz = (16000000/Frequenz);
3
Status &= ~_BV(ST_ICP);    // Frequenz berechnen
4
TIFR |= _BV(ICF1);
Auf dem Tiny2313 dürfte das einige Resourcen fressen.

Siehe auch in der Codesammlung (nach 'Frequenz' suchen).

So isses besser ;)

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.