Forum: Mikrocontroller und Digitale Elektronik Nutzbare PWM Ausgänge bei verschiedenen Modi?


von Stephan S. (outsider)


Lesenswert?

Ich nutze im Moment einen Mega88 und versuche mich mit den PWM Modi 
vertraut zu machen.

Kann es sein dass der Simulator total falsch simuliert bei solchen 
Sachen? Wenn ich den Fast PWM nutze zählt der Zähler im Simulator bis 
zum TOP Wert und dann wieder zurück. Eigentlich dürfte er ja immer nur 
hoch zählen. Wenn ich mein Programm in den Baustein schreibe und mir das 
Ergebnis mit dem Oszi ansehe, scheint es aber genauso zu stimmen wie es 
im Datenblatt beschrieben ist und nicht so wie es der Simulator anzeigt.

Was ich aber teilweise nicht verstehe: In welchem Modus kann ich welche 
OCx Pins nutzen um ein PWM Signal abzugreifen und mit welchen Registern 
muss ich den MAX Wert und den Compare Wert einstellen? Das Beispiel im 
Tutorial mit Fast PWM, ICR1 als MAX Wert und OC1A als Vergleichswert 
funktioniert. Jedoch kann ich scheinbar OC1B nicht als zweites PWM 
Signal nutzen, warum? Ist das wirklich so?

Und was geschieht wenn ich WGM13:0 = 15 setze, also in den Modus wo der 
Zähler bis zum OCR1A Wert zählt, wo kommt dann der Vergleichswert hin? 
Und wo kann ich ein PWM Signal abgreifen?

Irgendwie wäre da mal so etwas wie eine Matrix fürs Tutorial nicht 
schlecht wo die Modi gelistet sind mit Untermodi und dann Spalten "wo 
kommt das Signal raus", "wo wird der Vergleichswert hingeschrieben", 
"welche Pins sind nutzbar".

von Michael K. (mmike)


Lesenswert?

Hi,

im Datenblatt ist Tabelle 14-4 (Seite 132) eigentlich sehr 
aussagekräftig !


Stephan S. wrote:
> Ich nutze im Moment einen Mega88 und versuche mich mit den PWM Modi
> vertraut zu machen.

Fein.

> Kann es sein dass der Simulator total falsch simuliert bei solchen
> Sachen? Wenn ich den Fast PWM nutze zählt der Zähler im Simulator bis
> zum TOP Wert und dann wieder zurück. Eigentlich dürfte er ja immer nur
> hoch zählen. Wenn ich mein Programm in den Baustein schreibe und mir das
> Ergebnis mit dem Oszi ansehe, scheint es aber genauso zu stimmen wie es
> im Datenblatt beschrieben ist und nicht so wie es der Simulator anzeigt.

Der Simulator macht das manchmal seltsame Sachen. Also nicht darauf 
verlassen !

> Was ich aber teilweise nicht verstehe: In welchem Modus kann ich welche
> OCx Pins nutzen um ein PWM Signal abzugreifen und mit welchen Registern
> muss ich den MAX Wert und den Compare Wert einstellen? Das Beispiel im
> Tutorial mit Fast PWM, ICR1 als MAX Wert und OC1A als Vergleichswert
> funktioniert. Jedoch kann ich scheinbar OC1B nicht als zweites PWM
> Signal nutzen, warum? Ist das wirklich so?

Siehe Tabelle 14-4 (s.o.). Bei FastPWM Mode 14 kannst du den MAX Wert 
über OCR1 einstellen und OC1A und OC1B nutzen! Das geht auf alle Fälle!

Hier nen kleines Beispiel für die Konfiguration:

// Timer1, Mode 14, Fast PWM, Prescaler 1, OCP A (clear), OCP B (clear)
TCCR1A   = (1 << WGM11) | (1 << COM1A1) | (1 << COM1B1);
TCCR1B   = (1 << WGM13) | (1 << WGM12) | (1 << CS10);

oder mit Interrupts:

// Timer 1 overflow ISR
ISR (TIMER1_OVF_vect)
{
}

// Timer 1 compare A ISR
ISR (TIMER1_COMPA_vect)
{
}

// Timer 1 compare B ISR
ISR (TIMER1_COMPB_vect)
{
}

// Timer1, Mode 14, Fast PWM, Prescaler 1, OCP A (clear), OCP B (clear)
TCCR1A   = (1 << WGM11) | (1 << COM1A1) | (1 << COM1B1);
TCCR1B   = (1 << WGM13) | (1 << WGM12) | (1 << CS10);
TIMSK  |= (1 << TOIE1) | (1 << OCIE1A) | (1 << OCIE1B);



> Und was geschieht wenn ich WGM13:0 = 15 setze, also in den Modus wo der
> Zähler bis zum OCR1A Wert zählt, wo kommt dann der Vergleichswert hin?
> Und wo kann ich ein PWM Signal abgreifen?

In dem Modus kannst Du nur noch OC1B als PWM Kanal nutzen ! Raus kommts 
dann an PB2 (OC1B)

>
> Irgendwie wäre da mal so etwas wie eine Matrix fürs Tutorial nicht
> schlecht wo die Modi gelistet sind mit Untermodi und dann Spalten "wo
> kommt das Signal raus", "wo wird der Vergleichswert hingeschrieben",
> "welche Pins sind nutzbar".

siehe Tabelle !

Grüße,
Michael

von Michael K. (mmike)


Lesenswert?

Hab hierfür mal nen Codegenerator geschrieben für Mega 8, 16, 32

Beitrag "Codegenerator Timer1 für Mega 8, 16, 32"

für Mega88 musst die Registernamen wahrscheinlich ein wenig anpassen !

Grüße,
Michael

von Stephan S. (outsider)


Lesenswert?

Vielen Dank! Da hab ich den Wald vor lauter Bäumen mal wieder nicht 
gesehen. Wenn ich natürlich die COM1B nicht konfiguriere kommt 
logischerweise auch nichts raus, auch wenn ich PB2 auf Ausgang schalte.

In welchem Datenblatt soll die besagte Tabelle eigentlich sein? In 
meinem mega88 Datenblatt 09/07 kann ich weder bei dem genannten Bild, 
noch auf genannter Seite sowas finden.

Den Generator find ich übrigens echt gut. Wenn da jetzt noch stehen 
würde welche Ausgänge nutzbar sind und in welche Register ich die 
Vergleichswerte schreiben müsste wäre er perfekt!

Grund für die Ganze Aktion ist übrigens net konkrekte Aufgabenstellung: 
Ich brauche 2 PWM-Signale. Das zweite ist genau invertiert zum ersten. 
Das Problem an der Sache ist allerdings dass ich eine einstellbare 
Totzeit brauche, sprich wenn das erste Signal low geht soll das andere 
nicht sofort auf high gehen, sondern erst nach einer definierbaren Zeit. 
Dazu hab ich bis jetzt noch keine so einfache Lösung gefunden.

von Michael K. (mmike)


Lesenswert?

Hallo Stephan,

in diesem Datenblatt:

http://www.atmel.com/dyn/resources/prod_documents/doc2545.pdf

ists Seite 133 Tabelle 15-4 (sorry hatte geschrieben 14-4 da mein 
Datenblatt ein wenig älter 11/06).

> Den Generator find ich übrigens echt gut. Wenn da jetzt noch stehen
> würde welche Ausgänge nutzbar sind und in welche Register ich die
> Vergleichswerte schreiben müsste wäre er perfekt!

Danke. Nutzbar sind natürlich die Ausgänge die Du konfigurierst. Also in 
Deinem Beispiel OC1A und OC1B. Welche Pins das sind sagt uns das 
Datenblatt. In Deinem Falle also PB1 und PB2. Für den Pin OC1A (PB1) ist 
das Register OCR1A zuständig und für Pin OC1B (PB2) eben OCR1B.

> Ich brauche 2 PWM-Signale. Das zweite ist genau invertiert zum ersten.

Fein Timer 1 hat genau 2 "Ausgangspins". Die Invertierung kannst auch 
schon "reinbauen". Je nach dem wie Du COM1A1/COM1A0 bzw. COM1B1/COM1B0 
setzt.

> Das Problem an der Sache ist allerdings dass ich eine einstellbare
> Totzeit brauche, sprich wenn das erste Signal low geht soll das andere
> nicht sofort auf high gehen, sondern erst nach einer definierbaren Zeit.
> Dazu hab ich bis jetzt noch keine so einfache Lösung gefunden.

Das klingt nicht zu wild.

Ich habs so verstanden:

Kanal A:
1
   _______                   ___
2
__|       |_________________|   
3
4
          xxxx
5
__             ____________
6
  |___________|            |___
Kanal B:


Der Bereich markiert mit den xxxx ist der Totzeitbereich. Kanal A ist 
high und Kanal B soll nach Kanal A + Totzeit auf high gehen. Richtig ?

Kannst Du folgendermassen machen:

OCR1A bestimmt das Tastverhältnis für Kanal A, Bsp. Wert = 200

OCR1B bestimmt das Tastverhältnis für Kanal B, und kann einfach 
berechnet werden, mit OCR1B = Totzeitwert + OCR1A. Musst nur darauf 
achten, dass der Wert von OCR1B nicht größer als ICR1 wird !


Grüße,
Michael

von Stephan S. (outsider)


Lesenswert?

So in etwa wars richtig, nur dass ich bei beiden Wechseln die Totzeit 
brauche. Eigentlich dachte ich auch dass ich jetzt die Lösung habe, aber 
irgendwas haut nicht bei der Berechnung hin. Folgendermaßen sieht mein 
Programm aus:

#include <avr/io.h>
#define TCLK 0.0000001

int main()
{
uint16_t f=10000;
uint16_t t_tot=0;
ICR1 = 1/(f*2*TCLK);
OCR1A = ((ICR1)/2) - (t_tot/(2*TCLK));

// OC1A und OC1B auf Ausgang
DDRB = (1 << PB1 ) | (1 << PB2 );

// Timer1, Mode 14, Fast PWM, Prescaler 1, OCP A (clear), OCP B (set)
TCCR1A   = (1 << WGM11) | (1 << COM1A1) | (1 << COM1B1) | (1 << COM1B0);
TCCR1B   = (1 << WGM13) | (1 << CS10);

OCR1B = (ICR1 - OCR1A);

  while( 1 )
  ;
}


Jetzt gibts folgendes Problem:

Bei "ICR1 = 1/(f*2*TCLK);" kommt wenn f gleich 10000 ist nicht 500, 
sondern fälschlicherweise 499 raus. bei f gleich 1000 und f gleich 
100000 ist das Ergebnis richtig. Ich kann es nicht nachvollziehen was da 
passiert. Rundungsfehler?

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.