So trivial wie die Realisierung einer PWM mittels eines Mikrocontroller auf den ersten Blick scheinen mag, so kompliziert wird das Ganze, wenn man mehrere unabhängige Signale erzeugen will. Hier erweist sich die sonst so flexible 8051 Architektur als ziemlich hinderlich. Bessere Ergebnisse erhält man wahrscheinlich bei Verwendung eines DSPs, CPLDs/FPGAs oder natürlich eines PWM ICs. Das trotzdem nur ein 8051 kompatibler Flash Controller zum Einsatz kommt, liegt wohl hauptsächlich daran, weil ich etwas gegen IC Verschwendung habe, :). Einen Controller braucht man für die serielle Kommunikation mit dem PC sowieso. Also kann dieser doch auch gleich die Erzeugung der PWM Signale übernehmen. Dieser Gedanke führte zu drei Lösungsansätzen, von denen erst der dritte ein zufriedenstellendes Ergebnis erbrachte. Nachfolgend werde ich meine 3 Ideen kurz erläutern. Die Assemblerprogramme sind in der Syntax des MCS51 Assemblers (siehe Linkpage ) angeben.
Erste Idee: Pattern Tabelle
Wenn man die Rasterung des PWM Signals hinreichend grob wählt, kann man das Bitmuster für
jeden PWM Zustand in einer Tabelle abspeichern. Jedem Kanal kann man eine Zeile in dieser
Tabelle zuweisen und nun Spaltenweise die so gewählten Werte auf einem Port des Controllers
im Zeittakt ausgeben.
Das Hauptproblem: Das Zusammenstellen des Ausgabewertes verbraucht zuviel Rechenzeit um auf eine
vernünftige PWM Frequenz zu kommen.
Zweites Problem: Die Tabelle mit den PWM Mustern belegt ziemlich viel Speicher. Bei höheren
Auflösungen kann dieser bei einem nicht so gut bestückten Controller schnell knapp werden.
Programm
Zweite Idee: Duty Counter
Hier wird die Länge des Duty Cycles für jeden PWM Kanal heruntergezählt und anschliessend geprüft, ob
dieser schon abgelaufen ist. So kann der Ausgabewert für jeden Kanal und sukzessive
die Gesamtausgabe zusammengestellt werden. Nach Ablauf von 32 Ausgabeschritten (der PWM Auflösung)
werden die Duty Zähler neu geladen.
Dies funktioniert bis auf einige Ungenauigkeiten schon recht gut, ist bloss schrecklich langsam.
Zu langsam, für eine PWM.
Programm
Dritte Idee: Quasiparallelität
Da bis jetzt die zu niedrige PWM Frequenz der Grund für das Scheitern der beiden ersten Ansätze
war, musste ein anders Konzept her. Diese Version arbeitet mit Differenzählern. Das funktioniert
folgendermassen: Zuerst werden alle Kanäle gleichzeitig eingeschaltet. Dann wird der Kanal mit
dem kürzesten Duty Cycle ermittelt. Dieser Wert bildet
den ersten Zähler. Nach dessen Ablauf kann dieser Kanal mit der kürzesten An-Dauer abgeschaltet
werden. Der Wert des zweiten Zählers ergibt sich aus der Differenz des 2. kürzesten Duty Cycles
mit Zähler 1. Ist Zähler 2 abgelaufen, wird dieser Kanal abgeschaltet. Dies wird fortgeführt bis
alle Kanäle aus sind und die gesamte PWM Period abgelaufen ist.
Da die Berechungen der Zähler etwas komplizierter sind, werden diese schon im
PC Programm ausgeführt.
Mit dieser Methode erreicht man eine PWM Frequenz abhängig von der Auflösung und dem verwendeten
Quarz von bis zu 8 kHz.
Einige Ungenauigkeiten und Einschränkungen gibt es leider trotzdem. So ist es unmöglich, zwei
Kanälen die gleiche Länge des Duty Cycles zuzuweisen. Das Dekrementieren der Differenzcounter
und der Test auf Null verbraucht schon mehrer Zeitschritte. Aus dem gleichen Grund ist auch kein
Duty Cycle mit dem Wert 0 möglich.
Diese Version wird zur Zeit eingesetzt. Deshalb auch Download als A51 File (MCS51 Assembler),
List File und Intel Hex Format.
Programm | 4_channel_pwm.a51 | 4_channel_pwm.l51 | 4_channel_pwm.hex |