So, jetzt hab' ich da auch mal ein Problem - ein sehr merkwürdiges mit ner Software-PWM...
hab' das jetzt mal nicht bei "Anfänger" geschreiben, weil: 1. Ich bin kein "wirklicher Anfänger" mehr, was µC betrifft, 2. es handelt sich nicht um ein Anfänger-Problem wie "Timer läuft nicht", "Was sind Fuse-Bits" o.ä., sondern um ein echt komisches Phänomen, 3. ich würde gerne auf Anfänger-Kommentare á la "schau' mal bei Microcontroller.net" etc. verzichten...
Zur Sache: ich habe, um meine Dimmerkurve mal zu überprüfen, das Ganze (Beschreibung im anderen Thread) schnell umgebaut: noch ne grüne LED statt der roten hin, diese fadet ohne, die andere mit Dimmerkurve - zum Vergleich.
Da ist mir dann aufgefallen: im unteren Bereich flackert das Ganze gewaltig - komisch! - dachte mir zuerst, vielleicht ist das bei dem Rainbow-Fader nur nicht aufgefallen, weil da ja immer eine LED zusätzlich voll an war...
Habe dann mal (weil ich mir irgendwie dachte, vielleicht sieht man die 244 HZ PWM-Frequenz bei ganz kleinen Helligkeiten ja doch noch?!?!) die erste LED auf nen kleinen Wert (2) festgesetzt. Folgendes Ergebnis: das Ganze flackert nicht mehr, nur wenn die fadende LED ganz "unten ist", "stolpert" sie irgendwie, und die andere (die auf einen festen Wert gesetzt ist, das Register wird für nix anderes benutzt) flackert mal kurz...
Da ich dachte, dass das was mit der Dimmerkurve zu tun haben könnte, hab' ich die rausgeschmissen, Programm immer weiter vereinfacht, ist jetzt nur noch ne PWM-Routine, ein Register fest auf "5", das andere fadet (ganz langsam, damit man's sieht) von 0 auf 9 und wieder zurück - siehe hier:
[code:1]
.include "m8515def.inc"
;-------------------------------------------------------------------------------
; Register etc. definieren
;-------------------------------------------------------------------------------
.def temp0 = R16
.def temp1 = R17
.def temp2 = R18
.def temp_ZL = R1
.def temp_ZH = R2
.def LED1 = R20
.def LED2 = R21
.def PWM_Count = R23
;-------------------------------------------------------------------------------
; Interrupt-Vektor-Tabelle Mega 8515
;-------------------------------------------------------------------------------
.CSEG
.org 0x0000
rjmp Start ; Reset Handler
reti ; External Interrupt Request 0
reti ; External Interrupt Request 1
reti ; Timer/Counter1 Capture Event
reti ; Timer/Counter1 Compare Match A
reti ; Timer/Counter1 Compare Match B
reti ; Timer/Counter1 Overflow
rjmp ISR_PWM ; Timer/Counter0 Overflow --> PWM-Routine
reti ; Serial Transfer Complete
reti ; Rx Complete
reti ; Data Register Empty
reti ; Tx Complete
reti ; Analog Comparator
reti ; External Interrupt Request 2
reti ; Timer/Counter0 Compare Match
reti ; EEPROM Ready
reti ; Store Program memory Ready
;-------------------------------------------------------------------------------
; Stackpointer, Ports setzen
;-------------------------------------------------------------------------------
Start:
ldi temp0, LOW(RAMEND)
out SPL, temp0
ldi temp0, HIGH(RAMEND)
out SPH, temp0
ldi temp0, 0b00000001 ; CS00 setzen: Teiler 1
out TCCR0, temp0
ldi temp0, (1<<TOIE0) ; Interrupt bei Timer Overflow
out TIMSK, temp0
sei ; Interrupts aktivieren
ldi temp0, 0xff
out DDRA, temp0 ; PortA auf Ausgang (PWM-Ausgang)
;-------------------------------------------------------------------------------
; LED 2 Auf- und abfaden, LED1 bleibt bei "5"
;-------------------------------------------------------------------------------
Fade_Loop:
ldi LED1, 5
ldi LED2, 0
Fade_an:
rcall warten
inc LED2
cpi LED2, 9
brlo Fade_an
Fade_aus:
rcall warten
dec LED2
brne Fade_aus
rjmp Fade_Loop
;-------------------------------------------------------------------------------
; ISR für Software-PWM
;-------------------------------------------------------------------------------
ISR_PWM:
push temp0
in temp0, SREG
push temp0
ldi temp0, 0b00000011 ; Grundzustand 1 = LED an, 0 = LED aus
inc PWM_Count ; PWM Zähler von 0 bis 255 durchzählen
cp PWM_Count, LED1 ; Ist der Grenzwert für LED1 erreicht?
brlo PWM_LED2 ; nein, weiter zu LED2
andi temp0, 0b11111110 ; ja, LED1 aus
PWM_LED2:
cp PWM_Count, LED2 ; Ist der Grenzwert für LED2 erreicht?
brlo PWM_Ausgabe ; nein, weiter zur Ausgabe
andi temp0, 0b11111101 ; ja, LED2 aus
PWM_Ausgabe: ; Neue Bitbelegung ausgeben
out PORTA, temp0
pop temp0
out SREG, temp0 ; Statusregister + Temp0 wiederherstellen
pop temp0
reti
;-------------------------------------------------------------------------------
; Warteschleife
;-------------------------------------------------------------------------------
warten: ; 3 verschachtelte Warteschleifen
push temp2 ; Statusregister + Temp sichern
push temp1
push temp0
in temp0, SREG
push temp0
ldi temp0, 255 ; 255 Wiederholungen
loop0:
ldi temp1, 255 ; 255 Wiederholungen
loop1:
ldi temp2, 60 ; 60 Wiederholungen
loop2:
dec temp2
brne loop2
dec temp1
brne loop1
dec temp0
brne loop0
pop temp0
out SREG, temp0 ; Statusregister + Temp wiederherstellen
pop temp0
pop temp1
pop temp2
ret
;-------------------------------------------------------------------------------
[/code:1]
Unten auch noch ein animiertes Gif, auf dem man (leider nicht so toll) den Effekt sieht:
Die linke LED ist fest auf "5" (von 255), die rechte fadet auf - wenn die rechte ebenfalls "5" erreicht hat, werden beide dunkler, bei "6" bleibt die rechte auf diesem Wert (oder wird evtl. eine Stufe heller, läßt sich nicht so genau erkennen, flackert jedenfalls mal kurz), die linke wird jedoch heller (also heller als davor), ab "7" geht's wieder normal weiter... (da ist dann das Gif zuende)
Rückwärts das umgekehrte Spiel: bei "5" werden wieder beide dunkler, bei "4" die rechte jedoch wieder heller (obwohl sie ja abfadet), die linke auch wieder (aber dunkler als vorher), dann fadet die rechte bis Null...
Also irgendwie so, als wenn die rechte kurz mal "hängenbleiben" würde, und die linke so "halb" mitfadet (obwohl an dem Register ja nix geändert wird)...
also in der Art (links/rechts): 5/0 - 5/1 - 5/2 - 5/3 - 5/4 - 4/3 - 6/5 - 6/7 - 6/8 - ...
Das mit 5 ist jetzt nur ein Beispiel - das geht mit jeder anderen Zahl zwischen 1 und 254 auch - immer, wenn beide LEDs die selbe Helligkeit haben, tritt dieses Phänomen auf...
Und ich habe keine Ahnung, woran das liegen könnte - stehe irgendwie total auf der Leitung, evtl. sehe ich auch nur den Wald vor lauter Bäumen nicht?!?! Habe jetzt schon über drei Stunden da erfolglos rumprobiert...
Dass es was mit der Hardware zu tun hat, schließe ich aus: der Effekt ist immer gleich, egal ob mit den Rebels über Mosfet und LM 317 (auf 200 mA) oder mit "kleinen" LEDs direkt am µC - sowohl gegen Gnd als auch gegen Vcc (da PWM-Polarität natürlich umgekehrt). µC hab' ich auch schon gewechselt, um da einen Schaden dran auszuschließen... Netzteil liefert 20 W, stabilisiert, fetter Siebelko (3.300 µF), µC hat ein eigenes NT mit 7805 etc.
Fusebits sind auch richtig gesetzt, der µC läuft auch wirklich auf 16 MHz... Statusregister und sonstige verwendete werden in den Subroutinen immer brav gesichert...
Ich habe keine Ahnung, was da vor sich geht....?