PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Frequenzmessung mit AVR



teslanikola
13.11.2005, 13:37
Servuz,
ich hab ja mal einen Post mit eine Frequenzzähler gemacht, der ja auch Funktioniert. Jetzt hab ich aber ein kleines Problem: Ich hab ein Signal das so aussieht:

So und jetzt möchte ich mit Hilfe von einem AVR die Frequen messen, wie ihr ja wisst liegt die schwirigkeit darin, das ich nur die Hohe messen will ( etwa so 200-400kHz ) ohne das die Nirdrige ( 100 -400 Hz ) mein ergebnis versaut. Wie kann ich das machen ??? Hilfe!!!

Danke schonmal für eure hilfe::

Rage_Empire
13.11.2005, 13:43
Hm, da wirst du wohl einen Hochpassd brauchen. Einen Filter, welcher nur die Hohen Signale zum AVR führt.

teslanikola
13.11.2005, 13:47
Ja, sowas hab ich mir schon gedacht, aber das prob ist ja das das "zwerhackt" kommt und nicht kontinuierlich

Rage_Empire
13.11.2005, 13:57
Kritische Anwendung, geb ich zu. Aber ich versteh den Hintergrund nicht.

teslanikola
13.11.2005, 15:02
Wenn ich dir das erklären soll, dann sistze ich morgen noch da!! Ist etwas für ein kompliziertes JuFo-Projekt.

Rage_Empire
13.11.2005, 15:06
Du könntest es mit triggern versuchen, aber ist sicherlich aufwendig

teslanikola
13.11.2005, 15:24
wie meinst du das?????

Rage_Empire
13.11.2005, 16:04
Na, auf den anfang der pulse triggern und dann zählen für eine bestimmte zeit.

SprinterSB
13.11.2005, 18:47
Du willst beides messen?
Die Frequenz der Bursts und die Frequenz, in der diese kommen?

teslanikola
13.11.2005, 20:59
nur die Frequen die in den Brust vorkommt

SprinterSB
13.11.2005, 21:38
Die Frequenz in deiner Brust liegt zwischen 1Hz und 3Hz. Falls nicht, schau besser mal bei Dr. Zook vorbei ;-)

Kennst du die Minimalzahl der Pulse?

prinzipiell mal so: Über externen Takt lässt du Timer1 hochzählen und startest Timer2 über externen INT. Im INT wird der INT deaktiviert.
Wenn die Minimalzahl der Bursts erreicht ist, lässt du einen OutCompare1 triggern. In der ISR schaust du dir möglichst schnell den Wert von Timer 2 an und berechnest die Frequenz oder merkst die relevanten Daten. Timer1 wird angehalten.
In der zweiten Phase lässt du die restlichen Bursts verstreichen und schaltest in der Tod-Phase wieder alles scharf

Wenn die Anzahl der Bursts immer gleich ist, wird's einfacher.

Du musst genau wissen, welche asm-Befehle ausgeführt werden, um das wieder rauszurechnen. Oder deine Ungenauigkeit wird so groß, daß du mit dem Ergebnis nix anfangen kannst.

Wenn du die untere Frequenz kennst, könntest du auch alles messen und die untere wieder rausrechnen?

Mit grösseren AVRs geht evtl auch folgendes: ein Timer zählt die Pulse über externen Takt und ein anderer merkt immer den Zählerstand via InputCapture. Das InputCapture überschreibt bei jedem Peak den ICRx-Wert, aber das stört nicht. Du brauchst ja nur den letzten. In der Todphase hast du massig Zeit, den zu lesen.

Abwandlungen gibt es da bestimmt mannigfaltig...

Ich hoffe mal, du hast nen AVR, auf dem genug Bandbreite frei ist bzw der während dessen sonst nix machen muss und auf mindestens 8MHz rennt?

Wie du siehst, braucht mein Vorschlag massig Resourcen (mehrere Pins, InputCapture, 2 Timer, externen INT, OutputCompare, Wissen über die ausgeführten asm-Instruktionen/Latenzen)

Xaver
14.11.2005, 12:22
Wie realisiert ihr die messung solch hoher Frequenzen?

Ich muss für ein schulprojekt ein Kapazitätsmessgerät bauen und habe nun auch den Teil zu Frequenzmessung geschrieben, doch er schafft nur frequenzen bis 25 khz richtig anzuzeigen, danach kommt nur noch schrott raus. Ich brauche aber 780khz, also noch über eine Stelle mehr.

Das ganze soll auf einem LCD ausgegeben werden, was die Sache etwas Zeitkitisch macht.

Ich habe, dass zu messende signal an Int0 angeschlossen und lasse bei fallender Flanke eine Variable Hochzählen. Ein interner Timer zählt eine Sekunde und gibt dann Die Variable am Display aus. Eigentlich ganz einfach

Hardware
-Mega 8 8Mhz
-27x4 LCD
-Bascom
-Funktionsgenerator der Schule



$regfile = "m8def.dat" 'Atmel MEGA 8 controller
$crystal = 8000000 'Quarz auf 8MHz


Ddrd.2 = 0 'PD2/INT0 als Eingang deklarieren
Portd.2 = 1 'Pullup Widerstand aktiveren



'27 x 4 LCD Display angeschlossen
'Festlegen der Verwendeten Ports
Ddrc = &B00111111 ' LCD ANzeige
Ddrd.6 = 1
Ddrd.7 = 1
Dim ___lcdno As Bit
Config Lcdpin = Pin , E = Portc.2 , E2 = Portc.3 , Rs = Portc.0 , Db4 = Portc.4 , Db5 = Portc.5 , Db6 = Portd.6 , Db7 = Portd.7
Config Lcd = 40 * 4


Dim Tasten_zaehler As Integer 'Variable für anzahl der Tastendrücke
Dim Frequenz As Integer 'Frequens den tastendrucks

Dim Timerprescale As Integer 'um timer auf 1 sec ztu stellen

On Int0 Taste0 'Interrupt Unterprogram für Taste 1 festlegen
On Timer0 Ontimer 'Interrupt Programm für Timer0 überlauf

Config Int0 = Falling 'Fallende Flake als Interrupt festlegen
Config Timer0 = Timer , Prescale = 1 'Timer als Timer Festlegen

Enable Int0 'Interruptlauscher Aktivieren
Enable Timer0 'Timer einschalten

Enable Interrupts 'Allgemein Interrupts erlauben


'--Hauptprogramm---------------------------------------------------------------
Tasten_zaehler = 0 'startwert festlegen
Timerprescale = 0 'startwert festlegen
Stop Timer0 'erstmal stop damit nicht schon jetzt interrupts kommen
___lcdno = 0 'Ober Displayhälfte initialisieren, wenn das Display zwei LCD-Controller besitzt
Initlcd
Cursor Off
Cls
___lcdno = 1 'untere Displayhälfte initialisieren, wenn das Display zwei LCD-Controller besitzt
Initlcd
Cursor On
Cls

___lcdno = 0
Home
Lcd "Das neue Frequenzmessgerät"
Locate 2 , 5
Lcd "***** MEGA 8 *****"

___lcdno = 1
Home
Locate 1 , 5
Lcd "(c) Boris Eskin"
Locate 2 , 5
Lcd "(c) Olaf Petersen"
Wait 2


'--jetzt kann es losgehen

___lcdno = 1
Cls
Home
Start Timer0

Do

If Timerprescale >= 31250 Then 'Sekundentakt auswerten der Tasten
Stop Timer0 'damit nicht heimlich weitergezählt wird ffals die Anzeige länger braucht
Disable Int0
Timerprescale = 0
Frequenz = Tasten_zaehler 'Anzahl der Impulse in Frequenz umrechnen (Periodendauer 1sec)
Tasten_zaehler = 0
Locate 1 , 10
Lcd Frequenz , " HZ" 'Ausgabe am LCD
nop
Enable Int0
Start Timer0
End If
Loop

End


'--Unterprogram--Interrupt an Taste 2-------------------------------------------
Taste0:
Incr Tasten_zaehler 'Impulse Zählen
Return

'--Unterprogramm Timer Überlauf 256 mal Quarztakt-------------------------------
Ontimer:
Incr Timerprescale 'Überlaufzähler um eins erhöhen#
Return

Xaver
14.11.2005, 12:27
Wie realisiert ihr die messung solch hoher Frequenzen?

Ich muss für ein schulprojekt ein Kapazitätsmessgerät bauen und habe nun auch den Teil zu Frequenzmessung geschrieben, doch er schafft nur frequenzen bis 25 khz richtig anzuzeigen, danach kommt nur noch schrott raus. Ich brauche aber 780khz, also noch über eine Stelle mehr.

Das ganze soll auf einem LCD ausgegeben werden, was die Sache etwas Zeitkitisch macht.

Ich habe, dass zu messende signal an Int0 angeschlossen und lasse bei fallender Flanke eine Variable Hochzählen. Ein interner Timer zählt eine Sekunde und gibt dann Die Variable am Display aus. Eigentlich ganz einfach

Hardware
-Mega 8 8Mhz
-27x4 LCD
-Bascom
-Funktionsgenerator der Schule



$regfile = "m8def.dat" 'Atmel MEGA 8 controller
$crystal = 8000000 'Quarz auf 8MHz


Ddrd.2 = 0 'PD2/INT0 als Eingang deklarieren
Portd.2 = 1 'Pullup Widerstand aktiveren



'27 x 4 LCD Display angeschlossen
'Festlegen der Verwendeten Ports
Ddrc = &B00111111 ' LCD ANzeige
Ddrd.6 = 1
Ddrd.7 = 1
Dim ___lcdno As Bit
Config Lcdpin = Pin , E = Portc.2 , E2 = Portc.3 , Rs = Portc.0 , Db4 = Portc.4 , Db5 = Portc.5 , Db6 = Portd.6 , Db7 = Portd.7
Config Lcd = 40 * 4


Dim Tasten_zaehler As Integer 'Variable für anzahl der Tastendrücke
Dim Frequenz As Integer 'Frequens den tastendrucks

Dim Timerprescale As Integer 'um timer auf 1 sec ztu stellen

On Int0 Taste0 'Interrupt Unterprogram für Taste 1 festlegen
On Timer0 Ontimer 'Interrupt Programm für Timer0 überlauf

Config Int0 = Falling 'Fallende Flake als Interrupt festlegen
Config Timer0 = Timer , Prescale = 1 'Timer als Timer Festlegen

Enable Int0 'Interruptlauscher Aktivieren
Enable Timer0 'Timer einschalten

Enable Interrupts 'Allgemein Interrupts erlauben


'--Hauptprogramm---------------------------------------------------------------
Tasten_zaehler = 0 'startwert festlegen
Timerprescale = 0 'startwert festlegen
Stop Timer0 'erstmal stop damit nicht schon jetzt interrupts kommen
___lcdno = 0 'Ober Displayhälfte initialisieren, wenn das Display zwei LCD-Controller besitzt
Initlcd
Cursor Off
Cls
___lcdno = 1 'untere Displayhälfte initialisieren, wenn das Display zwei LCD-Controller besitzt
Initlcd
Cursor On
Cls

___lcdno = 0
Home
Lcd "Das neue Frequenzmessgerät"
Locate 2 , 5
Lcd "***** MEGA 8 *****"

___lcdno = 1
Home
Locate 1 , 5
Lcd "(c) Boris Eskin"
Locate 2 , 5
Lcd "(c) Olaf Petersen"
Wait 2


'--jetzt kann es losgehen

___lcdno = 1
Cls
Home
Start Timer0

Do

If Timerprescale >= 31250 Then 'Sekundentakt auswerten der Tasten
Stop Timer0 'damit nicht heimlich weitergezählt wird ffals die Anzeige länger braucht
Disable Int0
Timerprescale = 0
Frequenz = Tasten_zaehler 'Anzahl der Impulse in Frequenz umrechnen (Periodendauer 1sec)
Tasten_zaehler = 0
Locate 1 , 10
Lcd Frequenz , " HZ" 'Ausgabe am LCD
nop
Enable Int0
Start Timer0
End If
Loop

End


'--Unterprogram--Interrupt an Taste 2-------------------------------------------
Taste0:
Incr Tasten_zaehler 'Impulse Zählen
Return

'--Unterprogramm Timer Überlauf 256 mal Quarztakt-------------------------------
Ontimer:
Incr Timerprescale 'Überlaufzähler um eins erhöhen#
Return

SprinterSB
14.11.2005, 12:51
Ich muss für ein schulprojekt ein Kapazitätsmessgerät bauen und habe nun auch den Teil zu Frequenzmessung geschrieben [...]

Kapazitätsmessung geht ganz gut mit CaptureCompare-Einheit: Aufladen, und über nen R-entladen, dabei die Zeit messen. Schaltbeispiel C-Messung (https://www.roboternetz.de/phpBB2/zeigebeitrag.php?p=117048#117048)

felack
14.11.2005, 13:33
@Xaver

schau mal bei elektor.de :

http://www.elektor.de/Portals/0/Magazine/Downloads/2005/030045-11.zip

da gibt es als Gratissoftware ein gutes BASCOM-Programm für einen 1MHz Frequenzzähler. Ist zwar für den AT90S2313 mit 2x16 LCD, aber mit einigen kleinen Ändereungen läuft es auch auf dem ATMEGA8 mit 27x4 LCD.

felack

Werner_Just
14.11.2005, 14:39
Hallo Nikola,

> Wie kann ich das machen ??? Hilfe!!!

Den Rowalt hast Du ja.

Die Frequenzmessung würde ich über den Capture Interrupt realisieren,
da die eigentliche Zeitmessung bei 200 - 400 kHz kaum Zeit verbrauchen darf.

Prinzip:
Während einer definierten Messzeit speicherst Du in der Capture Interrupt die Timerwerte z.B. der Low-Flanken.

Nach Ablauf der "Messzeit" wertest Du die gespeicherten Timerwerte aus.
Du ziehst dabei aufeinanderfolgende Timerwerte voneinander ab und erhältst so die Periodenzeiten.
Die Periodenzeitwerte die über einem Schwellenwert (**) liegen verwirfst Du, die anderen mittelst Du (*).

Aus den gemittelten Werten bestimmst Du anschließend Deine Frequenz.

Ciao,
Werner

(*) die Mittelung wird nötig, da Deine einzelnen Frequenzwerte heftig streuen werden. Bei 400 kHz Burst und 16MHz Takt hast Du gerade mal
eine Timeränderung um 40 Werte / Periode.

(**) den Schwellenwert würde ich erstmal fest vorgeben. In späteren Versionen kannst Du den Schwellenwert immer noch automatisch erzeugen.

(***) Nochwas, bei 40 Takten, die Du für den Interrupt zu Verfügung hast, musst Du den Capture Interrupt zwangsläufig in Assembler programmieren. In Bascom braucht alleine schon das Sichern der Register mehr Zeit. Der Rest kann in Bascom sein. Den Interrupt mit Nosave declarieren!

SprinterSB
14.11.2005, 14:52
Bei dem Ansatz geht es vielleicht sogar besser, nicht über Interrupts zu gehen, sondern auf das Input-Capture Flag zu pollen. Den Overhead, den eine Schleife mitbringt, dürfte kleiner sein als der Overhead in einer ISR.

Werner_Just
14.11.2005, 15:33
Hallo,

stimmt, man kann auf das Capture-Flag auch pollen. Würde sinn machen.

Ciao,
Werner

SprinterSB
14.11.2005, 15:41
Zudem braucht man die einzelnen IC-Werte nicht; nur den ersten und den lezten. Nen RAM-Zugriff während der Messung kann man also vermeiden. Ein Register merkt den IC-Startwert und eines zählt die Pulse, ein leztes nimmt den aktuellen IC-Wert auf, der immer wieder überschrieben wird.

Werner_Just
14.11.2005, 15:50
Hallo Georg-Johann,

und wie detektierst Du dabei das Du im Burst misst?

Ciao,
Werner

SprinterSB
14.11.2005, 16:14
Hoi Werner,

stimmt, da war noch was....

In der Schleife immer nen Timer rücksetzen und dessen Overflow verwenden (wohl wieder via poll). Wenn man zu wenig Takte hat wird das Ergebnis verworfen, weil die Messung währens eines Bursts startete.

*grübel* oder besser mit Vorlauf-Schleife, erst wenn man nen Overlow hat, macht man scharf für die Messung. Beim nächsten Overflow speichert man die Werte bzw Taktzahl und IC-Differenz, dann weiter, bis man so viel Samples hat wie man möchte. Falls man einen Overflow hat und 0 Takte, ist der Burst ausgeblieben.

Bei den Randbedingungen wird man IMHO um einen 2ten Timer schwerlich rumkommen...

Für den IC-Timer bietet sich Timer 1 an und für den OVL ein 8-Bit-Timer

...oder hab ich was übersehen 8-[

teslanikola
14.11.2005, 22:43
Danke ich schau dann mal was ich machen kann