Forum: Mikrocontroller und Digitale Elektronik Programmablauf für 3-Kanal LED-Fading


von Christoph B. (nuke)


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

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.