Guck mal hier:
http://evertdekker.com/Joomla/index....d=55&Itemid=84
Hallo AVR-Experten,
ich bin dabei mir ein Stimmungslicht zu bauen, dafür sehe ich eine 3W RGB-Led vor. um die verschiedenen Farbmischungen hinzubekommen benötige ich eine PWM erzeugung.
Nun da ich soweiso den ATmega8 nehme wollte und dieser laut Datenblatt auch 3 Kanäle beherscht habe ich mich für diesen entschieden.
Das hier ist erst mein 2. Projekt und ich muss mir die ganzen Fähigkeiten selber aneigenen. Habe also schon viel im Forum gelesen und auch auf diversen anderen Seiten.
Ich brauche eine PWM mit 3 Kanälen, das ganze sollte so schnell ablaufen das man auch die Helligkeit in vielen Stufen (ich sag mal >=100) einstellen kann um später auch sanfte Übergänge zu erzeigen.
Ich hatte eigentlich das ganze schon mit einer simplen Soft-PWM realisiert, dennoch wenn ich die nötige Daten für den anstehenden Wechsel der Farbe berechne flackert bzw. blitzen die LEDs auf also muss ne Hardware PMW her.
Das ganze ist im Datenblatt recht kompliziert angegeben, habe dieses Kapital auch schon 2 mal gelesen aber ich will es einfach nicht kapieren.
Herausgefunden habe ich bisher:
- Es ist Möglich eine feste Frequen, die bei allen 3 Kanälen gleich ist zu erzeugen und nur den Duty-Cycle zu ändern (genau sowas brauch ich!)
- Es können nur die Pins PB1 - PB3 verwedet werden.
- Timer 1 wird dafür benötigt (kein Problem hab ich noch frei)
Was muss in die ISR vom Timer1?
Wie änder ich den Duty-Cycle? Einfach die Register OC1A, OC1B und OC2 mit einem Wert zwischen 0...255 beschreiben?
16bit ist hier nicht möglich, da es nur geht wenn OC1A + OC1B zusammen sind.
Also wie man unscher erkennen kann bin ich noch sehr unerfahren hier. Würde mich um ein paar Denkanstöße freuen oder falls jemand ein Projekt hat, indem er auch 3 Kanäle mit Hardware PMW macht, und mir den entsprechenden Teil vom Source herauskopieren könnte wäre das auch ein großer Schritt für mich.
Zusammengefasst möchte ich eine PWM erzeugen, mit veränderbarem Duty-Cycle und einer festen Frequenz. Das ganze sollte noch relativ fein einstellbar sein, um eben weice Übergänge zu schaffen.
Btw: Ist es möglich den Duty-Cycle nur von 0...100 in 1% Schritten einzustellen oder ist es bei entsprechenden Takt auch möglich z.b. 0,5% Schritte zu machen?
Danke im Voraus.
mfg
Benny
Guck mal hier:
http://evertdekker.com/Joomla/index....d=55&Itemid=84
Ich würde sowas per Software PWM machen.
Dazu würde ich den Timer 0 oder 2 frei laufen lassen und zwar mit Prescaler /1 oder /8.
16MHz Taktfrequenz wären Empfehlenswert.
Im Timer Overflow Interrupt wird ein weiteres Register hochgezählt.
Wenn der Wert des Überlaufregister einen der 3 Timer Sollwerte ( = deine 3 Farben ) Überschreitet wird der entsprechende Ausgang low geschaltet.
Geht der Überlaufzähler wieder auf 0 werden alle Ausgänge deren Sollwert nicht 0 sind wieder eingeschaltet.
Die Vergleiche und das setzen der Ports, werden im Timer Overflow Interrupt gemacht.
Diese Art der PWM Erzeugung belastet den ATMEGA 8 ziemlich stark.
Bei Taktteiler /1 wird alle 256 Takte ein Timer Overflow Interrupt ausgelöst.
Die Interrupt Routine muss also so kurz wie möglich, am Besten in Assembler geschrieben sein. Bei Takteiler /8 entschärft sich die Lage etwas, es wird nur alle 2048 Prozessortakte ein Interrupt ausgelöst.
Bei /1 komm ich auf eine PWM Frequenz von 122 Hz. Bei /8 komm ich auf 15 Hz ( = eigentlich zu wenig ) bei einem 16MHz Quarz.
Die RGB Werte können in der Hauptroutine in die entsprechenden Register ( bzw. RAM Speicherplätze ) eingeschrieben werden.
Es sind dann die Werte 0...255 = 256 Werte möglich.
Weitere Interruptroutinen sollten auf jeden Fall vermieden werden.
Eine andere Stategie wäre die RGB Werte nach ihrem Wert zu sortieren und den nächsten Wert in das Comparematch Register einzutragen.
Dabei wären dann nur 4 Interrupts ( 3* Comparematch + 1*Overflow ) nötig.
Diese Art der PWM Erzeugung wäre meine erste Wahl, wenn ich noch andere Interrupts laufen habe.
Sind aber 2 Werte recht eng beieinander z.b. rot = 2, grün = 3, und der Controller hält sich zu lange in einer anderen Interruptroutine auf, kann der Comparematchinterrupt für grün verschluckt werden.
Das Setzen und Löschen der Ports findet auch hier auf Softwareebene statt.
Also auch hier sind die Interrupts so kurz wie nur irgend möglich zu halten.
Das Thema Software PWM wurde hier im Forum schon zig mal behandelt, schau halt mal mit der Suchfunktion noch ein wenig rum.
Der Timer 1 kann nur 2 Hardware PWM Kanäle erzeugen, dafür aber auch 16 Bit auflösung. Mit timer 2 kann man noch einen 8 BIT PWM Kanal erzeugen. Normalerweise sollen 8 Bits aber auch schon reichen. Wenn es mehr sein soll dann muss man halt doch Software PWM nehmen oder den 8 Bit PWM Wert selber modulieren, denn 16 bit PWM rein in Software wird etwas zu knapp.
Bei Hardware-PWM wird einmal der Timer in den entsprechenden Mode initialisiert und später einfach nur noch der PWM wert in das entsprechende Register geschrieben. Eine ISR routine braucht man dazu eigentlich nicht mehr.
Hallo,
danke für die ausführliche Erklärung. Muss das jetzt erstmal anders lösen, doch mit Soft PWM.
habe mir da doch sehr viel vorgenommen, da ich gleichzeitig ein RC5 Signal decoden möchte (Timer 0) und die Soft PWM (Timer 2) brauche und ebenso auch noch das Faden hinbekommen muss (Timmer 1).
Aber es funktioniert schon soweit ganz gut, flackern tut es nur in den untersten Helligkeitsstufen und ich denke mal wenn ich da einen 16MHz Quarz extern anschließe sollte das auch weg sein.
Allerdings ist mir völlig unklar wie Du nur 122 Hz bzw. 15 Hz kommst bei 16 MHz.
Eine Frage noch:
Wenn ich in der Funktion FadeGleichzeitig() bin, wird dann schon auf Interrupts reagiert (z.B. Timer 2 - Soft PWM)?Code:SIGNAL (SIG_OVERFLOW1) { // später Moduswahl // + Speed if (modus == 1) { FadeGleichzeitig(); } TCNT1 = speed_fade; }
Oder erst sobald die ISR vom Timer 1 beendet ist? Also müsste ich quasi in der FadeGleichzeitig() den Befehl sei() einfügen, oder?
mfg
Benny
cooming soon...
ich bastel ja gerade etwas sehr ähnliches (RGB-led mit RC5 und den 3 hardware PWMs), deshalb kann ich dir evtl helfen.
initialisierung der 3 PWMs:
gruesseCode:// set timers on PB1,2,3 used for PWM output (R,G,B) TCCR1A=(1<<COM1A1)|(1<<COM1B1)|(1<<WGM10); TCCR1B=(1<<CS10); TCCR2=(1<<WGM20)|(1<<COM21)|(1<<CS20); // initial PWM vals <-- hier die PWM werte zwischen 0 und 255 rein OCR1A=0; OCR1B=0; OCR2=0;
Lesezeichen