Hallo Ich möchte gern einen einfachen Frequenzgenerator (Rechteck) bauen mit variablem Duty-Cycle. Ich habe das heute schon programmiert mit einem Attiny25: PWM im CTC Modus Lässt sich mit verschiedenen Prescalern in einem weitem Frequenzbereich einstellen. Nun stellt sich mir die Frage, bekommt man die Auflösung genauer hin? sowohl von Duty als auch von der Frequenz? (denn je höher die Frequenz in einem Prescalerbereich, desto schlechter die Duty-Auflösung) konkret möchte ich einen Blitzer machen, welcher GENAU! 50hz macht (und noch andere Sachen) Ich habe hier leider nur Quarze mit 4,8,12,16Mhz Mit einem 16Mhz Quarz, einem Prescaler von 2048 bekomme ich 50,08Hz hin, genauer wirds nicht, weil immer krumme Zahlen rauskommen. Selbst wenn ich den Systemtakt massiv runternehmen würde, komme ich nicht hin. Ich hatte mal irgendwo eine Lösung mit 16bit Auflösung gefunden, weiß aber nichtmehr ob duty oder frequenz. gibt es hier noch andere Lösungsansätze?
Markus B. schrieb: > Mit einem 16Mhz Quarz, einem Prescaler von 2048 bekomme ich 50,08Hz Versuch es mal mit einem Vorteiler von 512. Wie genau soll dein "GENAU!" sein? Markus B. schrieb: > gibt es hier noch andere Lösungsansätze? 3,2768 MHz http://www.reichelt.de/Quarze/3-2768-HC18/3//index.html?ACTION=3&GROUPID=3173&ARTICLE=2376&SEARCH=3%2C2768&OFFSET=16&WKID=0& 6,5536 MHz http://www.reichelt.de/Quarze/6-5536-HC18/3//index.html?ACTION=3&GROUPID=3173&ARTICLE=2646&SEARCH=6%2C5536%0A&OFFSET=16&WKID=0&
genau heist genau, also dass ich mit einem geraden zahlenwert draufkomme. 3,2768 MHz funktioniert mit 512 prescaler, hab ich aber nicht da und das ganze soll eigentlich morgen fertig sein. ich dachte es würde irgendwie elegant mit software gehen.
John schrieb: > Versuch es mal mit einem Vorteiler von 512. Und dann noch ein 16bit Timer der bis 625 Zählt.
Markus B. schrieb: > konkret möchte ich einen Blitzer machen, welcher GENAU! 50hz macht (und > noch andere Sachen) Naja, GENAU! wird man das mit einem Quarz ohnehin nicht so ohne weiteres hinbekommen, soo furchtbar präzise sind die Dinger ja net. > gibt es hier noch andere Lösungsansätze? Wenn's um die Größenordnung von 50 Hz geht kann man das auch locker mithilfe von Timerinterrupts "von Hand" erledigen. Dazu müsste man halt in jedem Interrupt den Timer für den folgenden Interrupt neu setzen; dadurch könnte man (bei einem Systemtakt von 10 MHz) prinzipiell auf 0,0000001 Hz genau werden - soweit der Quarz das zulässt... Sicher, die Flanke würde mal 1/10 Mikrosekunde zu früh und mal 1/10 Mikrosekunde zu spät erfolgen, aber es wäre allemal besser als 50,08 Hz. Wenn ich mich richtig erinnere, dann wird genau dieses Thema in dem Artikel "Die genaue Sekunde" behandelt: http://www.mikrocontroller.net/articles/AVR_-_Die_genaue_Sekunde_/_RTC
Markus B. schrieb: > ich dachte es würde irgendwie elegant mit software gehen. So geht es mit Steuerspannungen (Poti) http://www.mino-elektronik.de/Generator/takte_impulse.htm#bsp1 und so, wenn man lange Zeiten braucht, die man per Terminal eingibt http://www.mino-elektronik.de/Generator/takte_impulse.htm#bsp2 Es sollte nicht schwer fallen, beide Möglichkeiten nach Bedarf zu kombinieren. Falls man höhere Frequenzen oder Auflösung braucht, bietet sich ein STM32F4xx an, der seine Timer mit 168MHz laufen lassen kann. Bei der Auflösung kommt man damit auf ca. 6 ns. Soll ich Dir noch ein Programm dafür machen? ;-)
Markus B. schrieb: > Mit einem 16Mhz Quarz, einem Prescaler von 2048 bekomme ich 50,08Hz hin, > genauer wirds nicht, weil immer krumme Zahlen rauskommen. Ohne Abgleich wird der Oszillator aber auch nicht sehr viel genauer sein. Kannst du die Oszillatorfrequnz wenigstens genau messen? Dann kannst du einen Interrupthandler bauen, der mit viel geringerem Vorteiler z.B. 64 auskommt. Diesen 250kHz Interrupt lässt du eine 4 Byte Addition so machen, dass die Summe alle 20ms überläuft. Das MSB kopierts du einfach auf den Output-Pin. Z.B. sind bei 250kHz 250000/50 = 5000 Additionen pro Periode erforderlich. Bei einer 4-Byte Addition sollte jedes Mal 4294967296 / 5000 = 858993,4592 addiert werden. Nächste Näherung für den Summanden ist 858993 und somit passiert der Überlauf tatsächlich nach 5000,0026728972180215671140509876 Interrupts. Das bedeutet dass die Ausgangsfrequenz meist bei genau 16E+6/(5000*64)= 50Hz liegt und gelegentlich ein 4µs längerer Zyklus von 16E+6/(5001*64)= 49,99Hz stattfindet. Der Vorteil ist, dass man auch bei ungenauen Quarzfrequenzen die Ausgangsfrequenz sehr präzise einstellen kann, indem man nur den Wert 858993 etwas ändert.
Thomas Eckmann schrieb: > Entweder PWM oder CTC. Das ist Quatsch. Es gibt bei einigen µCs die Möglichkeit, den Max-Count festzulegen (CTC) und innerhalb dieses Zählablaufs PWM-Aufgaben zu erledigen. Jetzt aber zum Wunsch von Markus B. (scrap): > konkret möchte ich einen Blitzer machen, welcher GENAU! 50hz macht (und noch andere Sachen) Da möchte jemand ALLES und zwar SOFORT, aber kann nicht mal mitteilen, was da nun an Frequenz- und PWM-Auflösung feht. Und das alles nur mit einem Tiny25 und Software, wobei die Software aber nicht zu viel Gehirnschmalz kosten darf... Grundsätzlich (wenn der Tiny25 sonst nicht viel zu tun hat), ist das möglich, kostet aber Gehirnschmalz... Man könnte einen kleineren Vorteilerfaktor nehmen, das erhöht die Frequenzauflösung. Z.B. 16.000.000 Hz / 256 = 62.500 Hz 62.500 Hz / 1250 = 50,000 Hz Das sind 5 Zählerdurchläufe (CTC) von 0...249 Wenn der Blitz nur 0...3,9 ms lang sein soll, musst du die Durchläufe mitzählen und bei jeden 5. Durchlauf die PWM aktivieren (Auflösung = 16 µs). Oder geschickt mit Compare-Match-Interrupts arbeiten.
danke oldi, auf so eine idee bin ich noch garnicht gekommen. ich sehe aber schon ich komme für "einfach" wohl um ein "krummes" quarz wohl nicht drumrum. die quarzgenauigkeit ist mir hinreichend genau. jetzt noch toeranzen und temperaturabhänigkeiten ins spiel zu bringen ist overkill. aber wenn ich feststelle dass ich schon rein rechnerisch keine chance hab mein ziel zu erreichen ist es eben unbefriedigend.
Oldie schrieb: > Das ist Quatsch. Es gibt bei einigen µCs die Möglichkeit, den > Max-Count festzulegen (CTC) und innerhalb dieses Zählablaufs > PWM-Aufgaben zu erledigen. Der einzige Quatsch ist das, was du hier erzählst. Im CTC gibt es Clear, Set und Toggle. Das ist kein PWM, da der Ausgang nicht am Anfang des Zyklus gesetzt oder je nach Mode gelöscht wird. Mag sein, dass es Controller gibt, die das können. AVRs gehören nicht dazu. Der Maxcount für PWM wird nicht im CTC-Mode festgelegt, sondern im entsprechenden PWM-Mode. Das, was du oben vorschlägst, ist ganz normale Software-PWM. mfg.
Markus B. schrieb: > ich sehe aber schon ich komme für "einfach" wohl um ein "krummes" quarz > wohl nicht drumrum. Wie kommst Du darauf? Weiter oben hatte ich doch auf Programme verwiesen, die bestens ein genaues Timing erzeugen, auch mit einem ATtiny25 mit 8-Bit Timer. Hast Du das garnicht gelesen oder hat Dich die Lektüre überfordert?
1 | #define MAX F_CPU / 1000 / 50
|
2 | unsigned int nDuty = 10; |
3 | |
4 | void InitTimer(void) |
5 | {
|
6 | TCCR0B = (1 << CS01); |
7 | TCCR0A = (1 << WGM01); |
8 | OCR0A = 124; |
9 | TIMSK |= (1 << OCIE0A); |
10 | DDRB |= (1 << 0); |
11 | }
|
12 | ISR(TIMER0_COMPA_vect) |
13 | {
|
14 | static unsigned int nCount = 0; |
15 | nCount++; |
16 | if(nCount == MAX - nDuty) |
17 | {
|
18 | TCCR0A |= (1 << COM0A1) | (1 << COM0A0); |
19 | }
|
20 | else if(nCount == MAX) |
21 | {
|
22 | PORTB &= ~(1 << 0); |
23 | TCCR0A &= ~((1 << COM0A1) | (1 << COM0A0)); |
24 | nCount = 0; |
25 | }
|
26 | }
|
Auflösung 62,5 µs bei 16 MHz. mfg.
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.