Guten Tag,
ich habe ein kleines Problem mit der Sofware PWM, die hier in den
Artikeln beschrieben wird. Ich habe den Quellcode zur intelligenten
Lösung 1 zu 1 von hier übernommen.
http://www.mikrocontroller.net/articles/Soft-PWM
Klappt auch ansich ganz wunderbar. 0 ist wirklich Null und das Oszi
zeigt eine saubere Linie. Das andere extrem funktioniert leider nicht
richtig. Die PWM hat 8 Bit (256 Schritte), macht für mich als höchsten
einstellbaren Wert 255. Hier sollte das Oszi ja eigentlich eine glatte
Linie bei 5V zeigen. Jedoch hat man alle 10ms einen sehr kurzen Peak
Richtung Masse drin. An der Hardware liegt es nicht. Das manuelle Setzen
auf High- oder Low-Pegel klappt und auch eine einfachere Software PWM
funktioniert ohne diesen Fehler. Da ich zum einen diese Software auf 16
Kanäle und 10 Bit erweitern wollte, bin ich schon auf eine performante
Software PWM angewiesen. Zum anderen ist das anzusteuernde Element
Low-Aktiv, weshalb dieser Fehler nun wirklich störend ist. Wirklich
abschalten kann man so nicht. Auch verstehe ich die funktionsweise
dieser PWM noch nicht so ganz und bin somit auf euere Hilfe angewiesen.
MfG
Jürgen
Die PWM funktioniert absolut korrekt. Wenn du mal ins Atmel Datenblatt
schaust, wirst du sehen, dass die normalen PWM Ausgänge auch dieses
Phänomen haben (solang du die nicht im Glitch free Modus laufen lässt).
Du kannst ja einfach abfangen ob der Wert 255 ist und dann die Software
PWM "ausschalten". Sprich den Pin dauerhaft auf 1 setzen.
Eventuell reicht es aber auch den PWM Zähler nur von 0-254 zählen zu
lassen, Je nach Software (Hab oben in den Artikel nicht reingeguckt).
ich denke da verstehst du was falsch:
>> Das andere extrem funktioniert leider nicht richtig. Die PWM hat 8 Bit (256
Schritte), macht für mich als höchsten einstellbaren Wert 255. Hier sollte das
Oszi ja eigentlich eine glatte Linie bei 5V zeigen.
Ein PWM-Kanal ist kein "echter" DAC!
das sagt ja niemand, er hat das osci halt als logic-analyzer benutzt um
sich das PWM-Signal anzuschauen.
Das Problem ist halt, das man bei pwmwert==curStep abschaltet
das funtktioniert bei 0, bei 255 gibts da halt die lücke,
wenn man erst bei pwm-wert>curStep abschaltet gehts bei 0 nicht, dafür
schaltet er bei 255 nicht ab.
man kann das nur mit einer Speziallösung für den Wert 255 umgehen, indem
man bei 255 einfach gar nicht den Pin abschaltet.
Das brauch dann aber natürlich ein µ mehr rechenzeit
Ok,
das mit dem exkludieren von 255 als Wert aus der PWM ist sicherlich eine
Lösung. Ich kann mir aber immer noch nicht erklären, warum diese
Software dieses Verhalten aufweist. Einen Zusammenhang zwischen der
Hardware PWM und diesem Programm kann ich jedenfalls nicht erkennen.
Grüße Jürgen
Wenn du erreichen willst, dass eine PWM bei 0..255 zwischen "ganz aus"
und "ganz an" schwankt, dann muss die Periode 255 Takte betragen, nicht
256, sonst fehlt immer an einem Ende etwas. 255 von 256 Takten sind halt
einer zuwenig, wenn 0 für 0 Takte steht.
Merke: 0..256 sind 257 mögliche Werte.
Hardware-PWMs sind da auch nicht besser.
Ja, aber 256 klappt mit der Software nicht als Wert. Das gibt nur ein
wildes Geflacker. 255 ist der höchste einstellbare Wert. Stellt sich
natürlich die Frage ob man da irdenwo dran drehen kann. Muss ich mir
morgen mal in Ruhe anschauen.
Ok,
ich verstehe immer noch nicht wirklich, wie dieses Programm arbeitet
oder warum es zu diesen Spikes kommt. Hat sonst noch jemand eine Idee,
wie man das fixen könnte?
Grüße Jürgen
JayDee schrieb:
> Hat sonst noch jemand eine Idee,> wie man das fixen könnte?
Warum sollte man das?
Das ist ja nur in Deinem Kopf ein Problem.
Keiner merkt, daß die LED mit max 99,6% Helligkeit leuchtet.
Peter
if(pwm_cnt==pwm_cnt_max-1){// <-- HIER ÄNDERN!!! -1
15
pwm_sync=1;// Update jetzt möglich
16
pwm_cnt=0;
17
}
18
elsepwm_cnt++;
19
}
20
}
hAb den Code jetzt auch nicht 100 5ig durch, es könnte eber hier haken.
Kann aber auch sein, dass es dann gar nicht mehr geht. habs nicht
ausprobiert ;-)
Bernhard
Im Artikel stehen diverse Lösungen drin, welche du verwendet hast weiss
ich also nicht. Zur Illustration nehme ich mal die erste Variante
"Einfacher Lösungsansatz".
Da kommt raus:
für 0: 256x low, 0x high,
für 255: 1x low, 255x high.
Variante für
für 0: 255x low, 0x high,
für 255: 0x low, 255x high:
Magnus Müller schrieb:
> Bernhard Mayer schrieb:>> hAb den Code jetzt auch nicht 100 5ig durch, es könnte eber hier haken.>> Ich glaube, deine Shift Taste setzt aus ;)
Hoffentlich wars die Taste und nicht der Finger ;-)
Korrekter ist es natürlich, wenn PWM_STEPS nie grösser wird als 255.
Dann steht der Bereich 0..PWM_STEPS für ganzaus..ganzan und die Periode
passt auch wieder.
Der Kernfehler liegt darin, dass PWM_STEPS=256 zwar intuitiv nahe liegt,
aber mit diesem 8bit basierten Code nicht vollständig funktionieren
kann.
Also, ich habe die Version mit dem intelligenten Lösungsansatz aus dem
oben genannten Artikel verwendet. Mein Problem an der Sache ist, daß ich
einen Low-Aktiven Treiber damit ansteuern will. Wenn die PWM also nicht
permanent High-Pegel halten kann kriegt man den Treiber nie
abgeschaltet. Klar jetzt könnte man noch einen inverter davor setzen,
aber Softwarelösungen sind billiger.
Zurück zum Thema. Die Software bietet 256 Stufen für die PWM an. Das ist
eine 8-Bit Zahl. 0 ist alles aus 255 sollte alles an sein. Sind genau
256 Schritte. Gibt man 255 als Wert für die On-Time an, so hat man halt
alle 10ms kurze Peaks im Signal, obwohl ja jetzt permanente On-Time sein
sollte. 256 ist kein korrekter Wert für die PWM. Passt ja schon nicht
mehr in die 8Bit Zahl und das merkt man auch. Bei 256 gibt es auf allen
Ports nur noch wildes geflacker.
Mein Problem ist, daß ich die Funktionsweise dieser intelligenten Lösung
nicht völlig durchblicke und halt nicht weiß, wo ich eingreifen muss um
aus 255 als Wert für die On-Time ein permanentes High-Pegel Signal zu
erzeugen.
Ich habe jetzt mal den Vorschlag die ISR abzuändern durchprobiert.
Klappt aber bei der Version mit dem intelligenten Lösungsansatz alles
nicht. Danach klappt die ganze PWM nicht mehr richtig.
JayDee schrieb:
> 256 ist kein korrekter Wert für die PWM. Passt ja schon nicht> mehr in die 8Bit Zahl und das merkt man auch. Bei 256 gibt es auf allen> Ports nur noch wildes geflacker.
Du musst die Periode der PWM (PWM_STEPS) auf 255 reduzieren.
255 ist sowieso der Maximalwert mit dem ich die Software anspreche. 256
war nur ein Test der wie es zu erwarten ist auch nicht funktioniert, da
daß ja keine 8 Bit Zahl mehr ist.
Ok,
ich konnte das Problem jetzt auf die ISR Routine eingrenzen. Selbst wenn
ich den Port von Hand auf High-Pegel setze und nicht über die PWM setzen
lasse, habe ich diese kurzen Peaks Richtung Low-Pegel drin. Der Effekt
verschwindet, sobald ich die ISR auskommentiere. Jetzt muss ich mir mal
klarmachen, wieso das Programm den Else Teil der ISR Aufruft und wie man
es so umbauen kann, daß die Kanäle die permanente On-Time haben sollen
davon nicht betroffen sind.
Die IST sieht übrigens so aus
1
ISR(TIMER1_COMPA_vect){
2
staticuint16_tpwm_cnt;
3
uint16_ttmp;
4
5
OCR1A+=isr_ptr_time[pwm_cnt];
6
tmp=isr_ptr_mask[pwm_cnt];
7
8
if(pwm_cnt==0){
9
PWM_PORT=tmp&0x07;// Ports setzen zu Begin der PWM
10
PWM_PORT2=(tmp>>3)&0x3F;
11
PWM_PORT3=(tmp>>4)&0xE0;
12
pwm_cnt++;
13
}
14
else{
15
PWM_PORT&=tmp&0x07;// Ports löschen
16
PWM_PORT2&=(tmp>>3)&0x3F;
17
PWM_PORT3&=(tmp>>4)&0xE0;
18
if(pwm_cnt==pwm_cnt_max)
19
{
20
pwm_sync=1;// Update jetzt möglich
21
pwm_cnt=0;
22
}
23
elsepwm_cnt++;
24
}
25
26
}
Die oben vorgeschlagenen Lösung mit
if (pwm_cnt == pwm_cnt_max)
in
if (pwm_cnt == pwm_cnt_max-1)
zu ändern stoppte das Programm ja leider völlig.
Grüße Jürgen