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