Hallo liebes Forum! Bin 1001ste der nach dem Wie beim PWM fragt trotzdem hat irgendjemand ein kleines simples programm wo man sieht auf was alles zu achten ist ich weiss nur so, dass der counter1 raufzählt und mit dem OCR1A vergleicht und das Verhältnis auf den Pin OCR0 ausgibt oder jedenfalls so ähnlich äähh HILFE!! danke im vorraus
Hallo, ich habe den PWM (bei einem 90S2313) auch vor kurzem erst "entdeckt". Sagen wir, dass Du die Option des PWMs als "non-inverted PWM" gewählt hast, dh.: Hochzählen & Compare Match -> OC1=0 und umgedreht: Runterzählen & Compare Match löst OC1 Pin=1. Also dass der PWM Zähler hoch und runter zählt, ist klar? Nehmen wir an, Du hast die Option "9 Bit PWM" ausgewählt. Das heißt der Zähler pendelt von 0 bis 511. Im Compare Register muss dann also irgendein Wert zwischen 0 und 511 stehen. Wenn Du jetzt in das OCR1A Register den Wert 10 (dezimal!) eingibst, dann beim Hochzählen und dem 10ten Zähler-Schritt der OC1 Pin "0". Dann wird ohne Verzögerung weiter hochgezählt, bis 511 (auch dezimal!) erreicht ist. Danach wird wieder runtergezählt bis das Zählerregister den Wert 10 erneut erreicht; jetzt wird der OC1 Pin "1". Danach wird weiter bis zur 0 runtergezählt und danach geht es direkt wieder "hoch" und bei Zählerregister = 10 wird OC1 wieder gelöscht (0). Zusammengefasst sind also vom ersten mal, wo der OC1 Pin "0" ist bis zur nächsten "1" genau 2*501 Schritte vergangen (das ist die Low-Phase). Und umgekehrt von der "1" zur "0" genau 2*10 Schritte. Zusammengerechnet haben wir dann 2*501+2*10 = 1022 Schritte (das ist auch die Zahl, durch welche f(TC1) geteilt wird!). Den Vorteiler noch berücksichtigt gilt (für 9Bit PWM): (I): PWM_Frequenz = Systemfrequenz / (Vorteiler * 1022) Die ON-Zeit des OC1 Pins wird dann durch diese Formel ausgedrückt: (II): ON_Zeit = (Vorteiler 2 OCR1A) / Systemfrequenz Wenn man das jetzt noch etwas eleganter haben will und mit dem Duty Cycle rechnen möchte muss man erst folgende Formel aufstellen: (III): Duty_Cycle = ON_Zeit PWM_Frequenz 100% Jetzt (III) nach ON_Zeit umgestellt: (IV): ON_Zeit = Duty_Cycle / (PWM_Frequenz * 100%) (I) in (IV): (V): ON_Zeit = (Duty_Cycle Vorteiler 1022) / Systemfrequ. * 100% So...jetzt haben wir zwei Formeln, mit denen man die ON_Zeit bequem ausrechnen kann. Um es jetzt richtig einfach zu machen setzt man (II)=(V) und löst nach OCR1 auf...dann kürzen sich nämlich die Systemfrequenz weg und auch der Vorteiler. (VI): OCR1A = (Duty_Cycle * 1022) / 200% Formel (VI) kann man jetzt so wie sie ist in den Programmablauf einsetzen. zB: .EQU Duty_Cycle = 20 .DEF temph = r16 .DEF templ = r17 ..Code.. ldi temph,HIGH((Duty_Cycle * 1022)/200) ldi templ,LOW((Duty_Cycle * 1022)/200) ..und dann das ganze noch in das OCR1A Register kopieren Anstelle der "1022" in der sechsten Formel muss man natürlich den Wert eingeben, der in der jeweiligen PWM Option als Teiler eingesetzt werden muss. Bei 8Bit PWM wäre das dann 510. Zum besseren Verständnis eine kleine Graphik als Anhang - Paintbrush is cool, dass mir keiner was anderes behauptet! ;) Hannes
Hallo Hannes GRATULIERE ... ! mit Deinem Beitrag habe ich eine ausführliche und auch verständliche(!) Erklärung zu PWM gefunden; Vielen Dank also..! Jetzt aber noch eine Frage: Ich möchte mehrere LED mit PWM 'langsam !!' ein- und später ausschalten (= Vorbildgerechte Nachbildung von Lichtsignalen auf der Modelleisenbahn-Anlage) Ich benötige je Lichtsignal 3 Anschlüsse (rot/grün/gelb), die getrennt bzw. in Kombination miteinander geschaltet werden sollen - mit dem einen OC1-pin komme ich also nicht aus; - muß also über 'normale' pins anschalten; bei Deinem Know-how zum Thema PWM gibt's sicherlich auch hierfür einen Lösungs-Ansatz ??? Verwenden möchte ich den AVR 4433 (6 x 3 = 18 pins für 6 Lichtsignale) Auf eine positive Antwort freut sich Günter
Danke für die positive Wertung...ich habe eigentlich schon befürchtet, dass keiner was drauf schreibt, weil das Thema angeblich (ich hab die anderen Threads aber noch nicht gelesen) ja schon so oft durchgekaut wurde. Zu Deinem Problem...der 4433 ist doch ein Auslaufmodell, kann das sein? Als "recommended" wir der Mega8 angegeben. Wenn Du diesen nimmst, dann hast Du schonmal 3 PWMs. Aber ich glaube, dass Du bei so einem Problem mit den Leuchtsignalen bei der Eisenbahn eher eine andere Lösung als mit den PWM Kanälen versuchen solltest. ZB. verschiedene Zeitschleifen, die sich immer wiederholen. Damit kann man sehr lange Pausen erzielen. Oder musst Du diese drei Farben ineinander mischen, wie bei einer RGB-LED? Eine Hardware Lösung fällt mir jetzt spontan auch nicht ein...bis auf so eine Art Multiplex-Verfahren...aber ob sich das gut mit den PWM Signalen kombinieren lässt. Hannes
Hi! Bin ganz neu was µCs angeht, aber shcon mein erstes Projekt (bzw. der Grund warum ich mir überhaupt mal µCs angesehn hab ;)) setzt schon PWM (zum Leds dimmen) vorraus. Diese Seite: http://www.mc-project.de/Pages/pwm.html und der Thread hier hat mir schon sehr geholfen und so langsam beginne zu erahnen, dass der AtMega8 (und andere?) PWM schon von sich aus anbietet und man da nicht, wie ich dachte, selbst in einer endlosschlife mit counter pulse ausgeben muss usw. ich spar mir das lieber :D Was ich aber noch nicht so ganz verstehe: Wofür der prescaler bzw. Vorteiler ist. Auf de robigen Seite steht, das man damit Die Frequenz einstellen kann. Aber was das jetz genau bewirkt, offenbart sich mir nicht ganz. In den Beispielprogrammen: http://www.mc-project.de/Files/pwm_init.c und http://www.mc-project.de/Files/pwm_bsp.c Schaut das dann ja unglaublich komfortabel aus! Wenn ich das Programm richtig interpretiere, weise ich einer Variable (stellvertretend für den PWMoutput) einfach eine Wert zwischen 0 und 254 zu und den ganzen Rest erledigt der µC. Wie könnte man diese 254 Helligkeitsstufen (bzw. PWM-Verhältnisse) aufstocken? Ich habe Bedenken, ob man wenn ich das z.B. über 4 Sek dimme nicht sieht, sind dann ja nur 63Hz (254/4=63) oder denk ich völlig in die falsche Richtung? Vielen dank, jedem der sich die Mühe macht das alles zu lesen und mir vieleicht zu helfen ;D MfG, Simon Willmann.
Die Sache ist auch ziemlich komfortabel :-) Was du nicht ganz verstanden hast, ist, dass die eigentliche PWM-Frequenz wesentlich höher gewählt werden kann. Was du in 256 Schritten einstellen kannst, ist die Pulsweite! Wenn du eine LED hoch und runter dimmen möchtest (also kontinuierlich), dann achte darauf, die untere Grenze so zu wählen, dass du nur knapp unter der Flussspannung der Diode liegst. Ansonsten ist sie einen guten Teil der Zeit einfach nur aus. Gruss, Alex
an Günter, ich würde dir eine software PWM-erzeugung anraten wenn du so viele kanäle brauchst. ich hatte sowas mal für einen 80c32 geschrieben mit 16 kanälen. lieft bei 12Mhz sehr gut. sie lief im interupt und war recht kurz. man konnte also mit den µC "normal" weiterarbeiten :-). ich denke mal das sich das auch auf einen AVR übertragen läßt, zumal er ja schneller ist. da sollten dann auch locker 24 kanäle drin sein wenn denn genug pins frei sind. bei interesse kann ich ja mal das prinzip erklären wie ich das gemacht habe. CA
Hallo, eine Software PWM für mehrere Kanäle wurde mich auch sehr interressieren. Hat Jemand von euch mal ein Beispiel für ein AVR in Assembler? Hab darüber noch nichts weiteres gefunden, wie man sowas in Assembler erstellt. Gruß
Hi Alex! >>Was du in 256 Schritten einstellen kannst, ist die Pulsweite! Ja das meinte ich auch ungefähr ;) Wie könnte ich diesen Wert erhöhne? Also das ich die Pulsweite z.B. in einem Bereich von 512 Stufen einstellen könnte oder ist das nicht möglich? Wenn es geht, wassfür folgen hätte es auf die Geschwindigkeit? Rechnungen die 255 übersteigen muss ein 8bit AVR doch in 2 (oder mehr) Schritten machen. MfG, Simon!
Ich kenne keine Möglichkeit, den Bereich in dieser Form zu erhöhen. Es darf soundso bezweifelt werden, dass man mit blossem Auge eine Diskontinuität beim Dimmen feststellen kann. Rechnerisch belasten tut die ganze Sache den AVR nicht weiter, da alles parallel zur normalen Arbeit (also deiner Software) in Hardware abläuft. Den Bereich mittels Software zu erweitern sollte aber kein Problem darstellen, allerdings müsste dann die ganze PWM in Software geproggt werden und würde somit die Rechenleistung etwas drosseln. Gruss, Alex
hi, hier mal software beispiel fuer gcc. Dieses Beispiel benutzt den Timer2. Es laesst sich aber simpel auf Timer0 umschreiben. Timer2 ISR (34,72µs) OVERFLOW BETRIEB SIGNAL(SIG_OVERFLOW2) { if(z++ == 0) { cbi(PORTD,2); cbi(PORTD,3); } if(Ri++ == R) { sbi(PORTD,2); } if(Gi++ == G) { sbi(PORTD,3); } // hier koennten noch mehr kommen } void main(void) { unsigned char z; unsigend char R; unsigned char B; unsigned char G; TCCR2 = (1<<CS20)|(1<<TIOE2); // PRESCALER = 1 DDRD=0xFF; sei(); R = 150; G = 20; B = 255; for(;;){} } Mfg Dirk
Hallo, PWM in software zu realiesieren ist recht einfach. ich versuche es mal für 8 kanäle zu erklären um das prinzip zu verdeutlichen. wie man sicher schon merkt sind 8 kanäle genau 8 pins, also ein byte an den ausgängen des AVR. man bräuchte eigentlich nur die richtige bytefolge ausgeben und schon hätte man PWM erzeugt. und da es sich um eine bytefolge handelt, liegt es also nah eine tablle zu benutzten die z.b. 256 byte lang ist in der nacheinander die bytes in einer interuptroutine, die timer gesteuert ist, ausgebenen werden. dies ist recht einfach. das trickreiche ist eigentlich der inhalt der tablle. wenn man den aufbau verstanden hat sollte es einfach sein ein programm zu schreiben welches dies für jeden kanal berechnen kann. ich werde den aufbau mal mit hilfe von 8 bytes in einer tabelle klarmachen. bit | 01234567 --------+------------- 1. byte | 00000001 2. byte | 00000001 3. byte | 00010001 4. byte | 00010001 5. byte | 10010001 6. byte | 10010001 7. byte | 10010001 8. byte | 10010001 wenn man diese acht bytes nacheinander auf einen port wiederholtend ausgeben würde, dann hätte das bit 0 am port ein tastverhältnis von 4/4 also 50% ein und 50% aus und bit 3 2/6 also 75% ein und 25% aus und bit 7 0/8 also 100% ein und 0% aus. wie man sieht ist es eigentlich recht einfach. man kann die länge der tabelle auch verändern um einen höhere auflösung der PWM zu haben wobei die frequenz kleiner wird, oder verkleinern die länge der tabelle um eine höhere frequenz zu erhalten bei einer kleineren auflösung. das berechnen der tabelle sollte eigentlich kein problem sein für den geübten coder, genauso wie das erweitern auf 3 ports b.z.w. 24 pwmkanäle. ich werde versuchen in den nächsten tagen es von meinen 80c32 auf den avr zu übertragen. sollten noch fragen bestehen werde ich versuchen diese zu beantworten. CA
hiho, so hier mal die erste umsetzung von 80c32 nach AVR. im simulator ist es gelaufen. der code ist noch nicht perfekt und erst mal so hingezimmert. CA
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.