PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Pulsfrequenzmodulation (PFM) einlesen



FHKoeln_FSII
09.06.2007, 19:00
Hallo zusammen,

ich bin neu hier und arbeite im Rahmen meines Fahrzeugtechnik-Studiums gerade mit dem Board RN-Mega128Funk (ist mit einem ATMega128 bestückt).

Das einlesen von einer Pulsfrequenzmodulation bereitet mir Kopfschmerzen ](*,)
Kann ich für das einlesen eines solchen Signals auf igrendwelche Bibliotheken etc. zurückgreifen, oder muss ich mir das selbst mit einem Timer und deren Interrupts programmieren?

Für jegliche Hilfe wäre ich dankar!

Gruß
Knut

wkrug
09.06.2007, 19:29
Wie schaut denn so ein PFM Signal aus?

Vieleicht kenn ich sowas unter anderem Namen.

FHKoeln_FSII
10.06.2007, 12:20
Hallo wkrug,

danke für Deine Antwort. Mit dem PFM Signal meine ich ein Signal, welches nicht wie bei einem PWM durch das Tastverhältnis die Information überträgt, sondern allein die Frequenz ausschlaggebend ist (hier ist eine nette Grafik dazu http://www.elektronik-kompendium.de/sites/kom/0401131.htm).
Hintergrund: Ein Teammitglied hat einen Sensor mit zwei Lichtschranken gebaut, welcher mittels einer Lochscheibe ein Geschwindigkeitssignal des Fahrzeugs liefern soll. Die beiden Lichtschranken sind leicht versetzt, sodass die zweite Lichtschranke dafür verwendet werden soll, um zu identifizieren, in welche Richtung sich das Fahrzeug bewegt.

Gruß
Knut

wkrug
10.06.2007, 20:49
Was für dich funktionieren sollte wäre eine Servoimpuls Auswerteroutine.
In dieser Routine wird auf eine positive Flanke eines Signals gewartet.
Tritt diese auf wird auf den Abfall dieses Signals gewartet und die Zeit (Timer) gemessen.
Du lässt die Umschaltung "warten auf die negative Flanke weg" und hast deine Auswertung.

Was ebenso funktionieren sollte wäre eine Drehzahlmesser Routine.
Allerdings dann eine, die nicht mit einer fixen Torzeit, sondern mit der Erfassung der Umlaufzeit arbeitet (Das zu messende Signal arbeitet als Torzeitquelle).

Eine Ausnahme wäre, wenn deine Frequenzen sehr hoch wären.
Da würde die fix Torzeitmethode eine wesentlich geringere Belastung des Controllers bedeuten.
Ich hab so mit Assembler eine Routine hingekriegt die bis zu 13kHz fehlerfrei arbeitet (Läuft über INT0).
Wenn Du dein Signal als externe Taktquelle konfigurierst wären noch wesentlich höhere Frequenzen möglich.

In welchem Frequenzbereich bewegt sich denn dein Signal ?
3...4 kHz sollte so ein ATMEL AVR in der Periodendauermethode locker packen.

Periodendauermessung:
Wenn Du die Routine selber schreiben willst lässt Du den Timer 1 frei laufen und schliesst dein Signal an den ICP Pin an.
Bei jeder positivern Flanke wird ein Interrupt getriggert der das Input Capture Register (und eventuelle Überlaufregister) ausliest und die Werte der vorhergehenden Messung abzieht.
Das Ergebnis ist die Periodendauer deiner Eingabefrequenz.

Wenn Du den Controller mit 8MHz laufen lässt und den Prescaler auf 8 einstellst kriegst Du deine Timerwerte gleich in µs aus dem Timer raus - ist doch praktisch, oder.
Wenn es bei Dir um sehr niedrige Frequenzen geht kannst Du den Prescaler natürlich auch auf größere Teilerfaktoren einstellen.

Der Hauptaufand ist es die richtigen Bits in den Registern des Timers 1 einzustellen, die Interruptroutine selber ist Pipifax:
1.Register sichern
2.Das ICR auslesen.
3.Die Werte des vorherigen Interrupts abziehen.
4.Die aktuellen Werte in einem Puffer ablegen (für den nächsten Interrupt)
5.Den berechneten Zeitwert zur weiteren Verarbeitung zwischenspeichern.
6.Eventuell ein Flag setzen, das es neue Werte gibt (ich mach das immer so)
7.Die Register zurücksichern
8.Interrupt verlassen.

Der Rest der Verarbeitung passiert im Hauptprogramm, gesteuert durch das Flag aus der Interruptroutine.
Wenn Dir die 16Bit des Timers 1 nicht reichen, kannst Du noch einen Timer1Overflow Interrupt aktivieren, in dem Du ein, zwei, drei, weitere Register hochzählen lässt.

Ich würde für deine Anwendung mindestens einen ATMEGA8 einsetzen, da der sehr preisgünstig ist und trotzdem schon vollwertige Timer hat - im Gegensatz zur Tiny Serie.

Ich bastel zur Zeit an einer Telemetrieübertragung mit Drehzahlmesser.
Das Programm ist in "C" mit Codevision AVR geschrieben, die für Dich relevanten Programmteile sind in Assembler.
Ab einer bestimmten Drehzahl wird zwischen den beiden Meßmethoden umgeschaltet. Wenn Du magst kann ich Dir den Code als PN mal schicken.

peterfido
10.06.2007, 21:40
Sieht wohl nach "Handarbeit" aus.


do
if a>b then 'Richtung= rückwärts
a=a*-1
end if
v=a*...... 'je nach Takt und Timer....
lcd v ;
lcd "km/h"

loop

on int0:

a=timer1 'Geschwindigkeit (Erste Lichtschranke)
b=timer1-2 'Hilfsvariable für die Richtung-Zeit, die dieser Befehl benötigt wird abgezogen, evtl anpassen (2. Lichtschranke)
timer1=0

FHKoeln_FSII
10.06.2007, 22:15
Danke für die Antworten, dass muss ich mir erst einmal auf der Zunge zergehen lassen :-s

Vielleicht nochmal kurz zu den Randbedingungen. Ich verwende ein ATMega128 der mit 16MHz rennt. Hinzu kommt, dass der Timer0 für die Ansteuerung der Servos draufgeht (ich nutze die Servobibliothek). Timer1 und Timer2 bleiben, um einmal die Geschwindigkeit (PFM Signal) und den Lenkwinkel (PWM Signal) einzulesen. Jetzt aber zu Deiner ausgiebigen Antwort.

Interessant wäre glaube ich die von Dir angesprochende Periodendauermessung. Die maximal Frquenz, die ich von dem Team-Mitglied, der den Sensor eingebaut hat, bekommen habe ist nur 344Hz. Das wäre Deiner Erfahrung nach ja kein Problem. Nachvollziehen kann ich Deine Ausführungen hierzu, aber hättest Du vielleicht ein in Bascom programmiertes Beispiel? Ich arbeite erst seit ein paar Wochen mit dieser gasamten Microcontroller-Materie.

@peterfido
Wie kann ich diese Zeile aus Deinem Code verstehen?

b=timer1-2
Um zwischen Vorwärts und Rückwärtsfahrt zu unterscheiden hatte ich mir folgendes Gedacht. Wenn das Signal der ersten Gabellichtschranke von LOW auf HIGH wechselt, dann ist das Signal von der 2. Gabellichtschranke je nach Fahrtrichtung entweder noch LOW oder bereits HIGH. Ich weiß nur nicht, ob ich dies in der kurzen Zeit überprüfen kann.

Gruß
Knut

peterfido
10.06.2007, 22:29
Da der Timer weiterläuft, kann es sein, dass bis zum b=timer1 dieser schon wieder um 2 Punkte gestiegen ist, deswegen werden diese wieder abgezogen.

wkrug
11.06.2007, 09:12
Da der Timer weiterläuft, kann es sein, dass bis zum b=timer1 dieser schon wieder um 2 Punkte gestiegen ist, deswegen werden diese wieder abgezogen.
Genau aus diesem Grund hab ich dem Themenstarter auch den ICP Pin (Interrupt) empfohlen, weil man sich hier die Nachrechnerei sparen kann.
Tritt ein ICP Interrupt auf wird sofort der aktuelle Zählerinhalt von TCNT in das ICR geschrieben und kann dort, während des ICP Interrupt, in aller Ruhe ausgelesen werden.
Du kannst natürlich in dieser Routine auch gleich den 2 ten Port deiner Lichtschranke abrufen und damit die Richtungsinformation gewinnen.
Das sollte so ähnlich funktionieren wie bei einem Drehimpulsgeber.
Das abziehen eines fixen Wertes, wie von Peterfido vorgeschlagen, kann zu Problemen führen, wenn man Teiler (Prescaler) einsetzt, weil Du ja nie weisst an welcher Stelle der Prescaler gerade steht. Also müssten dann manchmal 1, manchmal 2, oder manchmal 3 abgezogen werden. Da man den Zählerstand des Prescalers nicht auslesen kann ist das ein reines Ratespiel.
Ein weiteres Problem das dabei entstehen kann ist das was ich "Overtaking Effekt" nenne.

Der kann passieren wenn man zusätzliche Register mit einem Timer Overflow Interrupt hochzählt.

Dein Zähler hat einen Wert knapp vor dem Timer Overflow erreicht.
Nun tritt ein Signal Interrupt auf. Der Timer erreicht nun den Wert 0 und würde den Timer Overflow Interrupt triggern.
Das funktioniert aber nicht, da der Controller ja schon einen Interrupt abarbeitet. Es fehlt Dir also in deinem Überlaufregister 1 Count. Du liest also in deinem Signal Interrupt den Überlauf Zähler aus und das TCNT Register, das ja wieder auf 0 steht. Somit machst Du in deiner Berechnung einen Fehler von 255 Counts (Bei einem 8 Bit Zähler).

Ich hab mich mal bei einem 220V Dimmer mit so einem Problem schon mal 3 Tage rumgeschlagen (hat immer geflackert) bevor ich auf diesen blöden Effekt gestoßen bin und die Timer Routine komplett umschreiben musste.

@Knut
Mit "Bascom" Quelltext kann ich Dir leider nicht dienen, ich progge zur Zeit in "C" und Assembler.
Ein ATMEGA 128 mit 16MHz langweilt sich bei deiner Aufgabenstellung.
Die Prescaler einstellungen sind auch von der gewünschten Präzision abhängig.
Je kleiner der Teilerfaktor umso genauer die Messung, allerdings verbunden mit erhöhter Controllerbelastung.