Forum: Mikrocontroller und Digitale Elektronik wiedereinmal PWM


von rebs (Gast)


Lesenswert?

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

von Hannes N (Gast)


Angehängte Dateien:

Lesenswert?

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

von günter (Gast)


Lesenswert?

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

von Hannes N (Gast)


Lesenswert?

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

von Simon Willmann (Gast)


Lesenswert?

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.

von Alex (Gast)


Lesenswert?

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

von Dirk Broßwick (Gast)


Lesenswert?

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

von PatrickHH (Gast)


Lesenswert?

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ß

von Simon Willmann (Gast)


Lesenswert?

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!

von Alex (Gast)


Lesenswert?

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

von Dirk (Gast)


Lesenswert?

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

von Dirk Broßwick (Gast)


Lesenswert?

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

von Dirk Broßwick (Gast)


Angehängte Dateien:

Lesenswert?

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
Noch kein Account? Hier anmelden.