PWM in SW ist ziemlich einfach... für jeden gewünschten PWM-Ausgang im SRAM des µC
eine 8 Bit Speicherstelle reservieren (pwm0, pwm1, pwm2, etc.); sowie einen 8 Bit
Zählerstand (pwm_act).
Timer aufsetzen (hat jeder anständige µC), der z.B. jede Millisekunde einen Interrupt
auslöst.
In der ISR (Interrupt Service Routine) für den Timer folgendes coden, in der Reihenfolge:
- pwm_act um 1 dekrementieren.
- Wenn pwm_act = 0, dann pwm_act mit 10 laden.
- pwm0 mit pwm_act vergleichen, wenn pwm0 >= pwm_act dann PWM0-Ausgang setzen,
ansonsten PWM0-Ausgang rücksetzen.
- pwm1 mit pwm_act vergleichen, wenn pwm1 >= pwm_act dann PWM1-Ausgang setzen,
ansonsten PWM1-Ausgang rücksetzen.
- usw. für jeden weiteren PWM-Ausgang.
Auf diese Art hast Du einen 100Hz-PWM-Ausgang (unterhalb der Trägheit des menschlichen
Auges), der 10 Helligkeitsstufen annehmen kann (0 = komplett aus, 10 = komplett an).
Mehr Helligkeitsstufen gehen auch, dann wird allerdings die PWM-Frequenz kleiner,
Abhilfe dann eine höhere Interruptfrequenz, das muss der µC dann allerdings noch packen
können.
Das Baseband (Hauptprogramm) führst Du als Endlosschleife aus, wo mit einem
Zufallsgenerator pwm0, pwm1, pwm2 etc. mit Werten zwischen 0 und 10 geladen werden.
Als Verzögerungsbasis zwischen den Werteänderungen bietet sich ein weiterer Timer mit
z.B. 100ms Verzögerung an, oder auch die Verzögerung wiederum durch einen Zufallsgenerator
bestimmen lassen. Pseudozufallsgeneratoren durch Schieberegister mit XOR-Feedback
an einigen Bits, dazu gibt es tausende Beispiele im Netz. Achtung, "Stuck at zero"
(Schieberegister komplett Null) muss gesondert abgefangen werden, sonst funktioniert
der Pseudozufallszahlengenerator nicht mehr.
So, das Prinzip sollte hiermit klar sein, mit dem Rest musst Du Dich alleine
auseinandersetzen...