Forum: Mikrocontroller und Digitale Elektronik PWM Frequenz um Faktor 4 zu niedrig


von Michael R. (Firma: Brainit GmbH) (fisa)


Lesenswert?

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?

von Hellseher (Gast)


Lesenswert?

Definitionen des Timers posten

von Michael R. (Firma: Brainit GmbH) (fisa)


Lesenswert?

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
}

von Karl H. (kbuchegg)


Lesenswert?

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.

von Michael R. (Firma: Brainit GmbH) (fisa)


Lesenswert?

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...

von Karl H. (kbuchegg)


Lesenswert?

>     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

von Michael R. (Firma: Brainit GmbH) (fisa)


Lesenswert?

D A N K E !

Sch%#!§.... Tippfehler (den Unterschied zwischen | und  || kenn ich 
wohl...)

den hätt ich noch ewig gesucht...

von Michael R. (Firma: Brainit GmbH) (fisa)


Lesenswert?

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?

von Michael R. (Firma: Brainit GmbH) (fisa)


Lesenswert?

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!

von Karl H. (kbuchegg)


Lesenswert?

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

von Karl H. (kbuchegg)


Lesenswert?

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.

von Fabian O. (xfr)


Lesenswert?

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.

von Michael R. (Firma: Brainit GmbH) (fisa)


Lesenswert?

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.

von Michael R. (Firma: Brainit GmbH) (fisa)


Lesenswert?

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" :-)

von spess53 (Gast)


Lesenswert?

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

von Michael R. (Firma: Brainit GmbH) (fisa)


Lesenswert?

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
Noch kein Account? Hier anmelden.