Hallo zusammen, ich hab hier ein Phänomen, welches ich nicht verstehe: ATmega328P mit 16 MHz (externer Quarz) Timer 0 mit Prescaler 1024 für SoftPWM Timer 0 läuft von 0..255, je nach Schwellwert (ebenfalls 0..255 also uint8) wird eine Display-Hintergrundbelechtung ein- oder ausgeschaltet. Funktioniert eigentlich super! Nun hab ich mit dem Oszi das PWM-Signal nach dem Schalttransistor angesehen, schaut eh gut aus, hat aber eine Periodendauer von 4 msec (und zwar nciht ungefähr 4 msec, sondern recht genau 4 msec) 4 msec => 250 Hz Allerdings: 16 MHz / 1024 (prescaler) = 15625 Hz Timer-Takt ein Volldruchlauf 0..255 => 15625 / 256 = 61 Hz also genau um den Faktor 4.096 daneben Wo ist mein Denkfehler?
Hellseher schrieb: > Definitionen des Timers posten Sorry, vergessen:
1 | #define BACKLIGHT_PORT PORTB
|
2 | #define BACKLIGHT_BIT _BV( 0 )
|
3 | #define BACKLIGHT_INIT DDRB |= BACKLIGHT_BIT
|
4 | #define BACKLIGHT_OFF BACKLIGHT_PORT &= ~BACKLIGHT_BIT
|
5 | #define BACKLIGHT_ON BACKLIGHT_PORT |= BACKLIGHT_BIT
|
6 | |
7 | static volatile uint8_t pwm_phase = 0; |
8 | static volatile uint8_t pwm_value = 0; |
9 | |
10 | |
11 | // init Timer 0
|
12 | static void timer_init(void) |
13 | {
|
14 | pwm_phase = 0; |
15 | pwm_value = 0; |
16 | |
17 | TCCR0A = 0; // normal operation |
18 | TCCR0B = _BV(CS02) || _BV(CS00); // prescaler 1024 |
19 | TIMSK0 = _BV(TOIE0); // enable overflow interrupt |
20 | }
|
21 | |
22 | |
23 | |
24 | // Timer 0 overflow handler
|
25 | ISR(TIMER0_OVF_vect) |
26 | {
|
27 | pwm_value++; |
28 | if (pwm_value < pwm_phase) { |
29 | BACKLIGHT_ON; |
30 | } else { |
31 | BACKLIGHT_OFF; |
32 | }
|
33 | }
|
Mit deinen WErten für pwm_phase dürfte sich an deinem Pin überhaupt nichts tun. Deine Berechnung stimmt an und für sich. Wenn die 16Mhz gesichert sind, bleibt nur noch die Möglichkeit, dass du dich vermessen hast oder nicht das misst was du denkst das du misst oder in deinem Programm ist noch an anderer Stelle was faul. PS: deine Beleuchtung müsste flackern wie Sau.
Karl Heinz Buchegger schrieb: > Mit deinen WErten für pwm_phase dürfte sich an deinem Pin überhaupt > nichts tun. Richtig. aber pwm_phase wird (an nicht sichtbarer Stelle) geändert. Zum Testen/Oszilloskopieren hab ichs auf 128 gesetzt (also 50%) > Deine Berechnung stimmt an und für sich. Wenn die 16Mhz gesichert sind, > bleibt nur noch die Möglichkeit, dass du dich vermessen hast oder nicht > das misst was du denkst das du misst oder in deinem Programm ist noch an > anderer Stelle was faul. Genau die 16 MHz zweifle ich ja auch an. Nur - wie prüf ich die? Am Quarz zu oszilloskopieren wird ja nicht funktionieren. Kanns an den Fuses liegen? eingestellt wären die auf lfuse:w:0xff:m hfuse:w:0xd6:m efuse:w:0x05:m Auch andere Stellen hääte ich geprüft, nur gibts nciht viel. Das ist der einzige Timer, sonst gibts nur diverse port-zugriffe...
> TCCR0B = _BV(CS02) || _BV(CS00); // prescaler 1024
Ach hier ist er.
Das ist kein Prescaler von 1024, sondern ein Prescaler von 1.
|| ist kein binäres Oder sondern ein logisches.
Und dann stimmt auch die Berechnung wieder. Mit einem Prescaler von 1
kommt man auf eine rechnerische PWM-Frequenz von 244Hz
D A N K E ! Sch%#!§.... Tippfehler (den Unterschied zwischen | und || kenn ich wohl...) den hätt ich noch ewig gesucht...
Karl Heinz Buchegger schrieb: > Und dann stimmt auch die Berechnung wieder. Mit einem Prescaler von 1 > kommt man auf eine rechnerische PWM-Frequenz von 244Hz Ähhhh... 16 MHz, prescaler 1 => 16 MHz 16 MHz / 256 = 62.5 kHz Wie kommst du auf 244 Hz?
Ich dnek ich habs: bei meinem Tippfehler
1 | TCCR0B = _BV(CS02) || _BV(CS00); // prescaler 1024 |
schlägt die "short circuit evaluation" zu, und TCCR0B wird auf _BV(CS02) gesetzt, das entspricht einem Prescaler von 256, und damit passt alles zusammen. Danke nochmal!
Michael Reinelt schrieb: > Karl Heinz Buchegger schrieb: > >> Und dann stimmt auch die Berechnung wieder. Mit einem Prescaler von 1 >> kommt man auf eine rechnerische PWM-Frequenz von 244Hz > > > Ähhhh... > > 16 MHz, prescaler 1 => 16 MHz > 16 MHz / 256 = 62.5 kHz > > Wie kommst du auf 244 Hz? Du brauchst 256 ISR Aufrufe, bis ein PWM Zyklus durch ist. 62kHz / 256 -> 244Hz
Michael Reinelt schrieb: > Ich dnek ich habs: bei meinem Tippfehler > >
1 | > TCCR0B = _BV(CS02) || _BV(CS00); // prescaler 1024 |
2 | >
|
> > schlägt die "short circuit evaluation" zu Nö. Das ist ein LOGISCHES Oder! Bei logischen Operationen kann das Ergebnis nur 0 oder 1 sein. Bei dir ist es 1, da sowowhl _BV(CS02) als auch _BV(CS00) ungleich 0 und damit logisch TRUE sind. Das Ergebnis ist also TRUE (1) und wenn man das zuweist, ergibt das einen Prescaler von 1 > gesetzt, das entspricht einem Prescaler von 256, und damit passt alles > zusammen. Du hast eine ISR Aufruffrequenz von 62kHz. Aber in der ISR teilst du das ja durch den Zähler nochmal weiter runter. Im Endeffekt landest du bei einer PWM Frequenz (steigende Flanke zu steigende Flanke am Portpin) von 244Hz.
Warum nutzt Du nicht einfach das Compare-Register des Timers? Dann brauchst Du keinen Softwarezähler und kannst viel höhere Frequenzen erreichen. Wenn Du die Hintergrundbeleuchtung an den passenden Pin anschließt, brauchst Du noch nicht mal die ISRs.
Fabian O. schrieb: > Wenn Du die Hintergrundbeleuchtung an den passenden Pin > anschließt, brauchst Du noch nicht mal die ISRs. Können vor Lachen :-) leider ist kein Output-Compare-Pin mehr frei.
Karl Heinz Buchegger schrieb: > Bei logischen Operationen kann das Ergebnis nur 0 oder 1 sein. > Bei dir ist es 1, da sowowhl _BV(CS02) als auch _BV(CS00) ungleich 0 und > damit logisch TRUE sind. Das Ergebnis ist also TRUE (1) und wenn man das > zuweist, ergibt das einen Prescaler von 1 > Du hast eine ISR Aufruffrequenz von 62kHz. > Aber in der ISR teilst du das > ja durch den Zähler nochmal weiter runter. Im Endeffekt landest du bei > einer PWM Frequenz (steigende Flanke zu steigende Flanke am Portpin) von > 244Hz. Du hast natürlich recht. meine "Soll-Berechnung" war schon komplett falsch. Ohne Tippfehler hätte ich eine PWM-Frequenz von 16 MHz / 1024 (prescaler) / 256 (overflow) / 256 (counter) = 0.2 Hz. jetzt versteh ich auch deine Aussage "deine beleuchtung muss flackern wie Sau" :-)
Hi
>Können vor Lachen :-) leider ist kein Output-Compare-Pin mehr frei.
Du kannst auch den Pin im Overflow-Interrupt setzen und im
Compare-Interrupt
löschen. Da ist keine Soft-PWM notwendig.
MfG Spess
spess53 schrieb: > Hi > >>Können vor Lachen :-) leider ist kein Output-Compare-Pin mehr frei. > > Du kannst auch den Pin im Overflow-Interrupt setzen und im > Compare-Interrupt > löschen. Da ist keine Soft-PWM notwendig. > > MfG Spess ja, so werd ich's eh machen müssen. Nachdem ich jetzt hoffentlich alle Denk- Tipp- und Rechenfehler elimiert habe, ist mir die PWM-Frequenz ohnehin zu niedrig.
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.