Programmablauf für 3-Kanal LED-Fading

OP #1781103
Lesenswert?

Hallo allerseits,

Ich hab mich in letzter Zeit mal wieder ein bisschen mit Software PWM 
beschäftigt und möchte nun eine 3-Kanal PWM zum Dimmen einer (oder 
mehrerer ;-) ) RGB-LED(s) realisieren. Ich nutze einen Atmel Atmega8. 
Mein bisheriger Code dimmt eine LED logarithmisch in einer festgelegten 
Geschwindigkeit zwischen einem MIN und einem MAX Wert rauf und runter, 
ist aber schon gut auf die 3 LEDs erweiterbar.
1
.include "m8def.inc"
2

3
.def counter = r16        ;PWM-Counter
4
.def temp = r17          ;temp-Register
5
.def port = r18          ;Port-Byte
6

7
.def led1 = r19          ;Helligkeitswert 1 mit Gammakorrektur
8
.def led2 = r20          ;Helligkeitswert 2 mit Gammakorrektur
9
.def led3 = r21          ;Helligkeitswert 3 mit Gammakorrektur
10

11
.def ledpointer1 = r22      ;Helligkeitswert 1 ohne Gammakorrektur
12
.def ledpointer2 = r23      ;Helligkeitswert 2 ohne Gammakorrektur
13
.def ledpointer3 = r24      ;Helligkeitswert 3 ohne Gammakorrektur
14

15
.def dir = r25          ;Richtungs-Flagregister
16
.def speed1 = r26        ;Counter 1 für Geschwindiggkeit
17

18
.equ CMAX = 255          ;PWM-Counter Maximalwert
19

20
.equ MIN1 = 50          ;Minimalwert 1
21
.equ MAX1 = 255          ;Maximalwert 1
22

23
.cseg
24
.org $0000
25
    rjmp reset        ; Reset Handler
26
    reti          ; IRQ0
27
    reti          ; IRQ1
28
    reti          ; Timer/Counter2 Compare Match
29
    reti          ; Timer/Counter2 Overflow
30
    reti          ; Timer/Counter1 Capture Event
31
    reti          ; Timer/Counter1 Compare Match A
32
    reti          ; Timer/Counter1 Compare Match B
33
    reti          ; Timer/Counter1 Overflow
34
    rjmp calc_leds      ; Timer/Counter0 Overflow
35
    reti          ; Serial Transfer Complete
36
    reti          ; USART, Rx Complete
37
    reti          ; USART, Data Register Empty
38
    reti          ; USART, Tx Complete
39
    reti          ; ADC Conversion Complete
40
    reti          ; EEPROM Ready
41
    reti          ; Analog Comparator
42
    reti          ; Two-Wire Serial Interface
43
    reti          ; Store Program Memory Ready
44

45
reset:
46
    ldi temp, LOW(RAMEND)  ;Init Stackpointer
47
    out SPL, temp
48
    ldi temp, HIGH(RAMEND)
49
    out SPH, temp
50

51
    ldi ZL, LOW(pwm_seq*2)  ;Init Z-Pointer
52
    ldi ZH, HIGH(pwm_seq*2)
53

54
    ldi temp, 0xFF      ;Config Port D
55
    out DDRD, temp
56
    out PORTD, temp      ;LEDs aus
57
    
58
    ldi led2, 0
59
    ldi led3, 0
60

61
    ldi temp, 1<<TOIE0    ;Config Timer/Counter0
62
    out TIMSK, temp
63
    ldi temp, 0x00
64
    out TCNT0, temp
65
    ldi temp, 0b00000001  ;ohne Prescaler
66
    out TCCR0, temp
67

68
    sei
69

70
    clr speed1
71
    clr ledpointer1
72
    clr dir
73

74
main:
75
    brtc main        ;Idle-Schleife, solange PWM-Zyklus noch nicht fertig
76
    
77
    inc speed1
78
    cpi speed1,3
79
    brne fade_end
80

81
    cpi dir,255
82
    breq backward
83

84
forward:
85
    inc ledpointer1
86

87
    cpi ledpointer1,MAX1
88
    brne next1
89

90
    com dir
91

92
next1:
93
    clr speed1
94

95
    rjmp fade_end
96

97
backward:
98
    dec ledpointer1
99

100
    cpi ledpointer1,MIN1
101
    brne next2
102

103
    com dir
104

105
next2:
106
    clr speed1
107

108
fade_end:
109
    clt
110
    
111
    rjmp main
112

113
calc_leds:
114
    ldi ZL, LOW(pwm_seq*2)  ;Gammakorrektur
115
    ldi ZH, HIGH(pwm_seq*2)
116
    ldi temp,0
117

118
    add ZL,ledpointer1
119
    adc ZH,temp
120

121
    lpm led1,Z
122
    
123

124
check_led1:
125
    ldi port, 0b11111000  ;Alle LEDs an
126

127
    cp counter, led1    ;LED1 vergleichen
128
    brlo check_led2
129

130
    ori  port, 0b00000001  ;wenn led1>=counter: LED1 aus
131

132
check_led2:
133
    cp counter, led2    ;LED2 vergleichen
134
    brlo check_led3
135

136
    ori  port, 0b00000010  ;wenn led2>=counter: LED2 aus
137

138
check_led3:
139
    cp counter, led3    ;LED3 vergleichen
140
    brlo check_end
141

142
    ori  port, 0b00000100  ;wenn led3>=counter: LED3 aus
143

144
check_end:
145
    out PORTD, port      ;Portausgabe
146

147
    cpi counter, CMAX    ;Maximalwert erreicht?
148
    breq cycleReset      ;ja: PWM-Zyklus zu Ende
149
    inc counter        ;nein: counter+1
150

151
    reti
152

153
cycleReset:
154
    clr counter        ;counter = 0
155

156
    set            ;T-Flag im SREG setzen, PWM-Zyklus fertig
157

158
    reti
159

160
pwm_seq:            ;logarithmische Helligkeitswerte für Gammakorrektur
161
    .db 0,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,5,5,5,5,5,5,5,6,6,6,6,6,7,7,7,7,7,7,8,8,8,8,8,9,9,9,9,10,10,10,10,10,11,11,11,11,12,12,12,13,13,13,13,14,14,14,15,15,15,15,16,16,16,17,17,17,18,18,18,19,19,20,20,20,21,21,22,22,22,23,23,24,24,25,25,26,26,26,27,27,28,28,29,30,30,31,31,32,32,33,33,34,35,35,36,37,37,38,38,39,40,41,41,42,43,43,44,45,46,46,47,48,49,50,51,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,71,72,73,74,75,77,78,79,80,82,83,84,86,87,89,90,92,93,95,96,98,99,101,102,104,106,107,109,111,113,115,116,118,120,122,124,126,128,130,132,134,137,139,141,143,145,148,150,153,155,157,160,162,165,168,170,173,176,179,181,184,187,190,193,196,199,202,206,209,212,216,219,222,226,229,233,237,241,244,248,252,255

Jetzt würde ich gern eine Art Programmablauf im Programmspeicher 
speichern, wo die nächsten Helligkeitswerte der einzelnen LEDs (noch 
ohne logarithmischen Verlauf, sprich "ledpointerX" im Code), sprich die 
nächste Farbe und die Fade-Geschwindigkeiten gespeichert sind. Dieser 
Programmablauf soll dann zyklisch durchlaufen werden.
Also z.B. R1,G1,B1,Zeit1,R2,G2,B2,Zeit2,...
Das Problem besteht jetzt darin, alle 3 Helligkeitswerte in der 
vorgegebenen Zeit von drei unterschiedlichen Anfangswerten zu drei 
unterschiedlichen Endwerten zu dimmen, also die Farbe zu wechseln.

Vielleicht hat sowas schonmal jemand gemacht (bestimmt) und kann mir 
weiterhelfen.

Vielen Dank!

Grüße,
Christoph

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren