Forum: Compiler & IDEs Atmega88: Fast-PWM-Ausgabe von Non-Inverting auf Inverting umstellen


von Lars L. (Gast)


Lesenswert?

Hallo,
ich will auf einem Atmega88 die Fast PWM Ausgabe für OCR0A und OCR0B vom 
Non-Inverting-Mode auf den Inverting Mode umstellen.
Non-Inverting funktioniert einwandfrei.
Zum Umstellen auf Inverting muss WGM02 in Register TCCR0B ja von 0 auf 1 
gesetzt werden.
Das alleine funktioniert aber nicht.
Weiß jemand, was hier noch umgestellt werden muss oder wo der Fehler 
liegen könnte?

Kann auch gerne die anderen Registereinstellungen und Werte posten, wenn 
das weiterhilft.

von Oliver S. (oliverso)


Lesenswert?

Lars L. schrieb:
> Kann auch gerne die anderen Registereinstellungen und Werte posten, wenn
> das weiterhilft.

Nee, die allermeisten üben sich lieber im Glaskugelesen. Echter 
compilierbarer Code (hier rein kopiert oder noch besser als Anhang) ist 
ja sowas von spießig.

Oliver

von Lars L (Gast)


Lesenswert?

1
DDRD |= (1<<PD5) | (1<<PD6);    //OCR0x Pins auf Ausgang
2
3
4
TCNT0 = 255;// PWM-Max.-Wert 
5
6
7
TCCR0A |= (1<< WGM01)|(1<<WGM00);
8
TCCR0B |= (0<< WGM02); // 0 = non-inv. fast PWM; 1 = inv. fast PWM
9
TCCR0B |= (1<< CS00); // prescaler = 1   
10
11
  
12
OCR0A = 99; //Startwert OCR0A
13
OCR0B = 99; //Startwert OCR0B
14
15
16
TCCR0A |= (1<<COM0A1)|(0<<COM0A0); // Einschalten Ausgabe 0A
17
TCCR0A |= (1<<COM0B1)|(0<<COM0B0); // Einschalten Ausgabe 0B

So wie abgebildet funktioniert der Code im Programm im 
Non-Inverting-Fast-PWM-Modus.
Für eine Non-Inverting-Fast-PWM-Ausgabe habe ich Zeile 8 so geändert:
TCCR0B |= (1<< WGM02);

Diese Änderung alleine scheint aber nicht zu reichen, um in den 
Inverting-Fast-PWM-Modus zu kommen.

von Georg M. (g_m)


Lesenswert?

DS40002074A
Table 15-3
Table 15-6

von Lars L. (Gast)


Lesenswert?

Kann man es vielleicht ein bisschen konkretisieren?

von OMG (Gast)


Lesenswert?

Lars L. schrieb:
> Kann man es vielleicht ein bisschen konkretisieren?

Ganz konkret: lies die Worte in den erwähnten Tabellen,
suche den Text "inverting" und  "non-inverting" und ziehe
deine Schlüsse daraus.

von Lars L. (Gast)


Lesenswert?

Habe es mittlerweile gesehen, COM0A0 und COM0B0 müssen neben WGM02 auch 
auf 1 gesetzt werden:
1
DDRD |= (1<<PD5) | (1<<PD6);    //OCR0x Pins auf Ausgang
2
3
TCNT0 = 254;// PWM-"Max."-Wert 
4
5
TCCR0A |= (1<< WGM01)|(1<<WGM00);
6
7
TCCR0B |= (1<< WGM02); // 0 = non-inv. fast PWM; 1 = inv. fast PWM
8
9
TCCR0B |= (1<< CS00); // prescaler = 1   
10
11
  
12
13
OCR0A = 255; //Startwert OCR0A = Pin auf Lo (kein Nadelpuls)
14
15
OCR0B = 255; //Startwert OCR0B = Pin auf Lo (kein Nadelpuls)
16
17
TCCR0A |= (1<<COM0A1)|(1<<COM0A0); // Einschalten Ausgabe 0A
18
19
TCCR0A |= (1<<COM0B1)|(1<<COM0B0); // Einschalten Ausgabe 0B

Es klappt aber trotzdem nicht so richtig.
Ich möchte den inverting Mode benutzen, um bei OCR0A = 255 bzw. OCR0B = 
255 jeweils auf eine Ausgabespannung von 0 kommen zu können (das geht ja 
im noninverting Modus nicht).
Aber mit den Einstellungen wie hier gezeigt kommt man trotzdem mit 
beiden nicht auf 0 runter.
Die Einstellungen aus Table 15-3 und Table 15-6 sollten aber stimmen.


Weiß jemand, woran das liegt? TCNT0 = 254 müsste doch stimmen.

von Carsten-Peter C. (carsten-p)


Lesenswert?

Lars L. schrieb:
> jeweils auf eine Ausgabespannung von 0 kommen zu können (das geht ja
> im noninverting Modus nicht)

Hallo, ich mach das so:  Wenn der Ausgang 0 sein soll, setze ich im 
Register TCCR1A COM1A1/COM1B1 und COM1A0/COM1B0 je nach Port auf 0. Ist 
der Ausgabewert nicht 0, setze ich den entsprechenden Wert wieder im 
TCCR1A. Bei der Initialisierung habe ich vorher die beiden Ports auf 
Ausgang und 0 gesetzt. Somit lassen sich Pulslängen von 0 bis 100% 
einstellen. Das funktioniert zumindest beim ATTiny4313 ganz gut.
Gruß Carsten

von Joachim B. (jar)


Lesenswert?

Carsten-Peter C. schrieb:
> Hallo, ich mach das so:  Wenn der Ausgang 0 sein soll, setze ich im
> Register TCCR1A COM1A1/COM1B1 und COM1A0/COM1B0 je nach Port auf 0

ja weil es bei Inverting kein 0 gibt

Ich wunderte mich bei Nokia5110 LCD am ESP32 da war die 
Hintergrundbeleuchtung bei einer Displaysorte genau invers zum AVR
Es gab verschiedene Lieferungen und Designs so musste ich auch noch 
verschiedene Wege probieren
Am AVR fing es an Module die 5V tolerant waren!
1
// der Plan aus LED Fading Stufen von 0-100%
2
const uint8_t pwmtable_11C[] PROGMEM = {0, 2, 4, 7, 11, 19, 32, 54, 90, 152, 255};
3
4
//dann kamen die vom anderen Lieferanten für ESP32 3,3V und invers!
5
const uint8_t pwmtable_11C[] PROGMEM = {255, 152, 90, 54, 32, 19, 11, 7, 4, 2, 0};
6
7
// anderer Lieferant anderes Display
8
// hier führte die NULL zu volle Helligkeit deswegen die 1 am Ende
9
const uint8_t pwmtable_11C[] PROGMEM = {255, 253, 251, 248, 244, 236, 223, 201, 164, 103,   1};

nicht perfekt aber mir genügte es!

von Georg M. (g_m)


Lesenswert?

Ich habe keinen Atmega88 und kann es nicht prüfen, aber mit dem 
ATtiny13A funktioniert die inverted PWM so dass wenn OCR0A = 255 dann 
bleibt die LED ausgeschaltet.
1
// ATtiny13A inverted PWM test
2
3
#define F_CPU 1200000UL
4
#include <avr/io.h>
5
#include <util/delay.h>
6
7
int main(void)
8
{
9
  DDRB |= (1<<DDB0);                        // set PB0 as output (OC0A)
10
  TCCR0B |= (1<<CS01);                      // set PWM frequency
11
  TCCR0A |= (1 << WGM01) | (1 << WGM00);    // set to Fast PWM Mode
12
  TCCR0A |= (1 << COM0A1) | (1 << COM0A0);  // set OC0A on compare match, clear OC0A at top
13
14
  while(1)
15
  {
16
    OCR0A = 253;
17
    _delay_ms(2000);
18
    OCR0A = 254;
19
    _delay_ms(2000);
20
    OCR0A = 255;            // LED off
21
    _delay_ms(2000);
22
  }
23
}

: Bearbeitet durch User
von Joachim B. (jar)


Lesenswert?

Georg M. schrieb:
> funktioniert die inverted PWM

kommt vermutlich drauf an ob man die LED nach GND oder nach +VCC 
verschaltet!

Mir scheint es gibt mehrere Inverted Definitionen, inverted bezüglich 
der PWM und inverted bezüglich der Verschaltung sowie einer Kombination 
beider.

: Bearbeitet durch User
von Ach Achim (Gast)


Lesenswert?

Mir dagegen erscheint es, als ob es immer die gleichen Nasen sind, die
dem manischen Zwang, IRGENDETWAS zu antworten erliegen. Egal was, egal
welches Thema: Antworten und dabei der Erste sein!

von c-hater (Gast)


Lesenswert?

Lars L. schrieb:

> Aber mit den Einstellungen wie hier gezeigt kommt man trotzdem mit
> beiden nicht auf 0 runter.

Das ist normal für den FastPWM-Modus. Invertiert kommst du "oben" nicht 
ganz auf VCC, sondern nur auf 255/256 VCC, und im nichtinvertiert kommst 
du "unten" nicht ganz auf 0, sondern nur auf 1/256 VCC.

Das gilt natürlich für die 8Bit-Timer, bei 16Bit-Timern ist es halt 
analog 65535/65536 bzw. 1/65536.

Um wirklich den ganzen Bereich von 0 bis VCC überstreiben zu können, muß 
man für einen der Endwerte den Invertier-Modus wechseln oder man 
verwendet den PhaseCorrect-Modus, der aber wiederum andere Nachteile 
hat.

von Joachim B. (jar)


Lesenswert?

c-hater schrieb:
> Das ist normal für den FastPWM-Modus. Invertiert kommst du "oben" nicht
> ganz auf VCC, sondern nur auf 255/256 VCC, und im nichtinvertiert kommst
> du "unten" nicht ganz auf 0, sondern nur auf 1/256 VCC.

wusste ich es doch, mal so mal so, je nach dem wie LED verschaltet sind, 
nach VCC oder nach GND
Das ist sogar bei Module unterschiedlich die gleich aussehen

von Georg M. (g_m)


Lesenswert?

DS40002074A:
The extreme values for the OCR0A Register represents special cases when 
generating a PWM waveform output in the fast PWM mode.
If the OCR0A is set equal to BOTTOM, the output will be a narrow spike 
for each MAX+1 timer clock cycle.
Setting the OCR0A equal to MAX will result in a constantly high or low 
output (depending on the polarity of the output set by the COM0A1:0 
bits.)

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.