Hallo, ich nutze momentan einen µC als Frequenzteiler. Die Frequenz wird reziprok gemessen und wieder ausgegeben. Die Frequenzteilung erfolgt in Software, durch rundung etc ist der Wert oft nicht ganz genau. Wäre der Wert Rund (2 oder 4 etc) würde ich einfach einen Zähler nehmen, aber 4.5?? Frequenz mit 9 multiplizieren und dann durch 2 Teilen? aber da wird der Aufwand ziemlich hoch, oder? Oder mit einem zweiten zähler immer jeden zweiten takt 4 bzw 5 teilen?
Früher (tm) hätte man dafür eine PLL mit passenden Teilern drumrum verwendet und den µC ganz raus gelassen. Um welchen Frequenzbereich geht es überhaupt. http://www.ti.com/lit/an/swra029/swra029.pdf Basti schrieb: > Frequenz mit 9 multiplizieren und dann durch 2 Teilen? Willst du nun durch 4.5 teilen oder mit 4.5 multiplizieren.
Wie misst du die Frequenz, und wie gibst du sie wieder aus? Ist die Frequenz so gering, dass du die einzelnen high-low und low-high Flanken am Eingang detektieren kannst? Soll das Ausgangssignal symmetrisch sein (50%/50% Tastverhältnis), oder kann es unsymmetrisch und synchron zu den Eingangsflanken sein?
Stimmt. Das wäre multiplizieren. Ich will durch 4.5 teilen also Fin=4.5 Fout=1 Frequenzbereich Fin = 0Hz-1.5Khz Im Prinzip geht es mit dem Controller ganz gut - ich habe aber bedenken das die Berechnung mit den Kommastellen so evtl zu unregelmäßigkeiten führt.
Joe: Ja, ich messe die zeit zwischen zwei high flanken, und berechne die Ausgangsfrequenz und Timersettings zum generieren der Ausgangsfrequenz
Joe F. schrieb: > Soll das Ausgangssignal symmetrisch sein (50%/50% Tastverhältnis), oder > kann es unsymmetrisch und synchron zu den Eingangsflanken sein?
Definiere doch einfach, dass das Eingangssignal ebenfalls ein Tastverhältnis von 50:50 haben muss. Dann ist das einfach mit einem Flankeninterrupt zu erledigen...
@ Basti Ist doch erst einmal eine gute Methode. Wo hakt es denn bei der Genauigkeit?
Also bei 1.5KHz sollte das noch locker so zu erledigen sein:
1 | uint8_t in_port_state; |
2 | uint8_t in_port_state_buf; |
3 | uint8_t clk_cnt; |
4 | uint8_t out_port_state = 0; |
5 | |
6 | while(1) |
7 | {
|
8 | in_port_state = get_input_port(); |
9 | |
10 | if (in_port_state ^ in_port_state_buf) // edge detected |
11 | {
|
12 | clk_cnt++; |
13 | if (clk_cnt == 9) |
14 | {
|
15 | set_output_port(out_port_state); |
16 | out_port_state ^= 1; |
17 | clk_cnt = 0; |
18 | }
|
19 | in_port_state_buf = in_port_state; |
20 | }
|
21 | }
|
get_input_port() und set_output_port() musst du natürlich entsprechend anpassen. Das Ausgangssignal ist dann ebenfalls 50%/50%, der Vorteil gegenüber der Methode die Frequenz zu messen und einen Timer zu setzen ist, dass die obige Methode dem Eingangssignal in Echtzeit folgt, demzufolge keine Glitches entstehen können.
Basti schrieb: > Ich will durch 4.5 teilen also Fin=4.5 Fout=1 > Frequenzbereich Fin = 0Hz-1.5Khz Wie schnell kann sich die Frequenz am Eingang aendern? Ist es schlimm, wenn erst die naechste Periode die Eingangsfrequenz/4.5 hat? Dann koenntest Du die Zeit fuer die Periode messen und dann eine passend berechnete wieder ausgeben. aswx
Basti schrieb: > ich nutze momentan einen µC als Frequenzteiler. Warum nicht einfach mit einem XOR verdoppeln und dann durch 9 teilen? Alternativ nen Swallow-Teiler nehmen? In PLL-Gefilden ist das sehr üblich. W.S.
W.S. schrieb: > Warum nicht einfach mit einem XOR verdoppeln und dann durch 9 teilen? > Alternativ nen Swallow-Teiler nehmen? In PLL-Gefilden ist das sehr > üblich. Bei 0 Hz aber ganz schön schwierig ;-) Basti schrieb: > ich nutze momentan einen µC als Frequenzteiler. Konnte ich Dich noch nicht vom STM32 überzeugen? ;-) Beim F407 beträgt die Auflösung der Messung bzw. Signalerzeugung typ. 6 ns. In Deinem Frequenzbereich (0 Hz ausgenommen) lassen sich damit Auflösungen < 10 ppm erreichen. Das sollte doch reichen.
m.n. schrieb: > Bei 0 Hz aber ganz schön schwierig ;-) Bei 0 Hz wird die Frequenzbestimmung durch Messung der Periodendauer mit dem µC auch nicht einfacher. Und ob das mit den Timersettings hinzukriegen ist, hängt auch sehr davon ab, wie genau 0 Hz wirklich 0 Hz ist.
Dumdi D. schrieb: > W.S. schrieb: >> mit einem XOR verdoppeln > > wie geht das genau? Auch wenn ich nicht W.S. bin: Eingangstaktsignal auf einen Eingang XOR, das selbe Signal zeitverzögert auf den zweiten Eingang des XOR geben, das Ergebnis: Ausgangsfrequenz = 2 * Eingangsfrequenz mit Pulsdauer der Zeit mit der verzögert der zweite Eingang des XOR beaufschlagt wurde. ==> bei dieser Frequenzverdopplung entstehen Frequenzen mit Nadelimplusen, die "unabhängig" vom Puls-Pauseverhältnis der Eingangsfrequenz ist, solange die Zeitverzögerung kürzer als die Pulszeit der Eingangsfrequenz ist !
Ralph S. schrieb: > ==> bei dieser Frequenzverdopplung entstehen Frequenzen mit > Nadelimplusen, die "unabhängig" vom Puls-Pauseverhältnis der > Eingangsfrequenz ist Spätestens wenn man diese Nadelimpulse auf einen Teiler mit ungeradem Teilerverhältnis gibt, sieht man, wie das Puls-Pausenverhältnis vom Originalsignal einen Jitter der Flankenlage beim Ausgangssignal erzeugt.
Basti schrieb: > Frequenz mit 9 multiplizieren und dann durch 2 Teilen? Was kommt denn da raus? Mal nachgedacht? Eilst Du auch dem Freitag voraus?
also 0hz erkenne ich mit dem watchdog :-P @n.m: Eval Board ist unterwegs, aber so genau braucht die Auflösung nicht zu sein. Haben mit 1hz getestet, reicht völlig -> mit den ca 0.1hz auflösung sollte es sich mit nem avr lösen lassen @aswx: die ändert sich ständig, weil die drehzahl einer maschine gemessen wird die nicht ganz konstant läuft -> wir warten aber nach der ausgabe eines geänderten wertes 100ms. ausgegeben wird nur, wenn sich die eingangsfrequenz 0.25hz ändert. wenn sich die frequenz nicht ändert wird sofort neu eingelesen @ludwig: ich hatte heute den eindruck das die ausgangsfrequenz ein bisschen "zappelt" ich werde das morgen nochmal mit dem frequenzgenerator prüfen. ich vermute, das bei manchen frequenzen ein rechenfehler passiert, weil ich die variable auf zwei nachkommastellen begrenzt habe.
Ich werfe nochmal die Idee in die Runde das Ausgangssignal direkt aus den Flanken des Inputsignals zu erzeugen. Um ein 50%/50% Verhältnis des Ausgangssignals zu erreichen müsstest du allerdings beide Flanken (falling/rising) detektieren und nach jeweils 9 Flanken den Pegel des Ausgangs ändern. Wenn dir das Port-polling nicht gefällt, kann man das auch in einem Interrupt erledigen, wenn dein uC auf beide Flanken Interrupts auslösen kann. Ansonsten wäre die Alternative nur eine Flanke (rising oder falling) zu detektieren, und dann abwechselnd nach 4, 5, 4, 5, 4... Flanken den Ausgang zu toggeln. Dann hast du aber ein Puls-Pause-Verhältnis von 4:5 am Ausgang. Wie gesagt, der Vorteil dieser Methode ist, das Eingang und Ausgang absolut synchron sind und keine seltsamen Glitches auftreten.
:
Bearbeitet durch User
Ich halte die Vorgabe: "0 bis" schlicht und einfach für unsinnig. Nicht nur dass die Null selber ein paar Eigenheiten mit sich bringt, auch Frequenzen knapp oberhalb sind erst nach längerer Zeit synchronisierbar. Interessant find ich auch den Ansatz, mittels eines Wachhundes, nichts festzustellen;-)
Joe F. schrieb: > Wie gesagt, der Vorteil dieser Methode ist, das Eingang und Ausgang > absolut synchron sind und keine seltsamen Glitches auftreten. Und der Logikpegel am Ausgang beim umschalten genau umgekehrt ist, weil Flankenanzahl ungerade ist. Sollte aber nicht von Bedeutung sein.
Basti schrieb: > ich hatte heute den eindruck das die ausgangsfrequenz ein > bisschen "zappelt" ich werde das morgen nochmal mit dem > frequenzgenerator prüfen. ich vermute, das bei manchen frequenzen ein > rechenfehler passiert, weil ich die variable auf zwei nachkommastellen > begrenzt habe. Vielleicht probierst Du mein Programm für einen ATmega48. Da sollte nichts zappeln: http://mino-elektronik.de/Generator/takte_impulse.htm#bsp4 Die untere Eingangsfrequenz kannst Du ja niedriger wählen als die eingestellten 10 Hz.
Eingangssignal mittels Input Capture Funktion messen (Periodendauer) und parallel dazu mittels Umrechung und Output Compare Funktion ausgeben. Trivial, kann man beliebig genau machen. https://www.mikrocontroller.net/articles/AVR_-_Die_genaue_Sekunde_/_RTC#Verbesserte_Version_mit_durchlaufendem_Hardwarez.C3.A4hler Wer's old school mag, nimmt zwei 4 Bit Zähler und teile synchron durch 9, einer taktet auf der steigenden, einer auf der fallenden Flanke. Die Aufänge werden passend kombiniert, meist per ODER.
Falk B. schrieb: > Wer's old school mag, nimmt zwei 4 Bit Zähler und teile synchron durch > 9, einer taktet auf der steigenden, einer auf der fallenden Flanke. Die > Aufänge werden passend kombiniert, meist per ODER. und hofft, dass es keine Runts gibt ...
m.n. schrieb: > Bei 0 Hz aber ganz schön schwierig ;-) Hä? Was ist daran schwierig? Null rein, Null wieder raus. Stimmt doch. Ich würde eher Probleme bei sehr großer Frequenzvariation sehen, weil man das RC-Glied ja wenigstens eine bissel nach der zu erwartenden Inputfrequenz dimensionieren muß, aber 10:1 sollte allemal drin sein. W.S.
W.S. schrieb: > Hä? > Was ist daran schwierig? > Null rein, Null wieder raus. Stimmt doch. Schon, aber es kann sehr lange dauern festzustellen, dass die Eingangsfrequenz kleiner als x Hz ist - etwas mehr Nachdenken ist doch nicht ganz falsch, wenn auch mühsam. Georg
Hallo alle, also es läuft. Das Problem war die Meßtoleranz beim Messen er Eingangsfrequenz. Ich lasse den Timer0 hochzählen und starte/stoppe ihn per software, weil ich den Timer1 für die Frequenzerzeugung nutze. Ist im Bereich von zweir Nachkommastellen bei der Eingangsfrquenz stabil Jetzt läuft es: - Reziproke Eingangsfrequenzmessung (Zeit zwischen zwei high flanken) - Periodendauer mit 4.5 Multiplizieren - Ausgabe Ich habe die Ausgabe so gestaltet, das die Frequenz um mind. 0.5Hz variieren muss damit der Timer verändert wird, das bringt mehr Ruhe in die Ausgangsfrequenz. Ich überlege das noch zu ändern, zB bei 100Hz ist es dann für die Zielanwendung egal ob es 100 oder 100.5 hz sind, da reichen auch 1Hz Auflösung. Aber bei 4 Hz ausgangsfrequenz ist 4.5hz schon ein merkbarer Unterschied Da sich in der Zielanwendung auch die Anforderung geändert hat, überlege ich zu dem die Rechnerei zu lassen, und mit einer Lookup-Table zu arbeiten. 1ms Verzögerung für alle berechnungen sind doch ganz schön satt.
Basti schrieb: > Da sich in der Zielanwendung auch die Anforderung geändert hat, überlege > ich zu dem die Rechnerei zu lassen, und mit einer Lookup-Table zu > arbeiten. 1ms Verzögerung für alle berechnungen sind doch ganz schön > satt. Und warum machst du es dann nicht in Echtzeit? Also Flanken detektieren, und Ausgangssignal direkt aus Eingangssignal erzeugen? Dann gibts auch keine Probleme mit 0Hz, und es ist auch egal, ob sich die Eingangsfrequenz um nur 0.001Hz verändert, der Ausgang geht absolut latenzfrei mit.
:
Bearbeitet durch User
Basti schrieb: > Da sich in der Zielanwendung auch die Anforderung geändert hat, überlege > ich zu dem die Rechnerei zu lassen, und mit einer Lookup-Table zu > arbeiten. 1ms Verzögerung für alle berechnungen sind doch ganz schön > satt. Ja. Manche Leute kapieren das nie. Aber warum einfach, wenn es auch kompliziert geht... Joe F. hat dir doch die beste Lösung geschickt, du kannst es natürlich auch mit Tabellen, Logarithmen und ähnlichem machen... Joe F. schrieb: > Das Ausgangssignal ist dann ebenfalls 50%/50%, der Vorteil gegenüber der > Methode die Frequenz zu messen und einen Timer zu setzen ist, dass die > obige Methode dem Eingangssignal in Echtzeit folgt, demzufolge keine > Glitches entstehen können.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.