LED's sind gerade auf breiter Front dabei, sich für Beleuchtungszwecke zu etablieren. Meistens werden die LED's dabei jedoch nur einfach ein oder ausgeschaltet. Im folgenden Projekt wird eine Software für den Atmel Tiny12 Controller vorgestellt, welche die Helligkeit von 3 LED's mittels Pulsweitenmodulation periodisch ändert. Dadurch ergeben sich eine Vielzahl unterschiedlicher Mischfarben. Die Änderungsgeschwindigkeit kann dabei für jeden Kanal getrennt eingestellt werden, so dass für jede Stimmung das passende Programm gewählt werden kann.
Aufgebaut mit z.B, dieser Schaltung, erhält man eine winzige Platine, die sich leicht in eine Vielzahl von Anwendungen zur Beleuchtung integrieren lässt.
Das ASM-File zum Download gibts hier, fertig programmierte Controller auf Anfrage.
Das Programm selbst ist recht einfach, aber es verwendet eine Reihe von Techniken, welche auch in grösseren Projekten benötigt werden, z.B.
Lesen und Schreiben des EEPROMs
Timer-Interrupt
Software-Counter
In der Hauptroutine des Programms wird lediglich das PWM Signal erzeugt. Über den Timer Interrupt wird der Taster abgefragt und die Helligkeiten geändert.
Dabei sind folgende Funktionen impementiert:
Die drei angeschlossenen LED’s ändern Ihre Helligkeit periodisch zwischen 0 und 100%. Für jede der LED’s kann die Änderungsgeschwindigkeit in 8 Stufen eingestellt werden, so dass sich eine Vielzahl unterschiedlicher Farbwechseleffekte ergibt.
Der Taster hat dabei folgende Funktion: (Taster an PB3 oder PB4)
Drücken Sie den Taster einmal kurz( ca 0.5s), so wird die Periodendauer für die aktuell ausgewählte Farbe geändert. Insgesamt sind 8 Stufen möglich.
Drücken Sie den Taster etwas länger (ca 1 s) so können Sie die LED auswählen, für welche die Periodendauer geändert werden soll. Nach dem Loslassen des Tasters leuchtet die gewählte LED kurz auf, während die anderen beiden dunkel geschaltet werden. Dies ermöglicht eine schnelle Identifizierung der gewählten LED
Halten Sie den Taster ca 3s lang gedrückt, weden die eingestellten Änderungsgeschwindigkeiten permanent abgespeichert.
Wenn Sie den Taster gedrückt halten, während die Betriebsspannung angelegt wird, führt das Modul einen internen Reset durch und alle 3 Kanäle ändern sich synchron mit der maximal möglichen Frequenz.
Das Programm wurde mit AVR Studio 4.10 erstellt.
Beim Programmieren bitte den OSCCAL-Wert in die EEPROM-Zelle $3f speichern!
ASM-File gibts hier.
;COLOR MAGIC MOOD LIGHT
;(C) 2004 Markus Vohburger
;Gewerbliche Nutzung untersagt
.include "tn12def.inc"
.equ EE_OSCCAL =$3f
.equ EE_SPEED0 =$00
.equ EE_SPEED1 =$01
.equ EE_SPEED2 =$02
.def speed0 = r02
.def speed1 = r03
.def speed2 = r04
.def temp1 = r16
.def swcount0 = r17
.def swcount1 = r18
.def swcount2 = r19
.def output = r20
.def pwmcount = r21
.def pwmvalue_red = r22
.def pwmvalue_green = r23
.def pwmvalue_blue = r24
.def director = r25
.def pwmvalue = r27
.def dirty = r28
.def swcount3 = r29
.def colorselect = r30
.def temp2 = r31
.equ timer_value = $d0
;reset handler
.org $0000
rjmp main
;timer overflow interrut handler
.org OVF0Addr
rjmp OVF0Handler
.org $0010
main:
;stack setup
;read osccal byte
ldi temp1,EE_OSCCAL
rcall readeeprom
out osccal,temp1
;port setup
;port b input with pullups
ldi temp1,$07
out ddrb,temp1
;port b output off, pullups on
ldi temp1,$1f
out portb,temp1
setstatus:
sbic eecr,eewe
rjmp setstatus
ldi temp1,$03
out eear,temp1
sbi eecr,eere
in temp1,eedr
cpi temp1,$00
breq ok
cpi temp1,$07
breq ok
ldi temp1,$07
ok:
out ddrb,temp1
;Toggle Power On Mode
sbis pinb,4
rjmp toggle
sbic pinb,3
rjmp notoggle
toggle:
ldi temp2,$00
ldi temp1,EE_SPEED0
rcall writeeeprom
ldi temp1,EE_SPEED1
rcall writeeeprom
ldi temp1,EE_SPEED2
rcall writeeeprom
;neuen status schreiben
writeok:
notoggle:
;Timer zurücksetzen
ldi temp1,timer_value
out tcnt0,temp1
;Timer interrupts an
ldi temp1,(1 <<toie0)
out timsk,temp1
;Timer starten, clck/8
ldi temp1,$04
out tccr0,temp1
ldi swcount0, $00
ldi swcount1, $00
ldi swcount2, $00
ldi swcount3, $00
ldi pwmvalue_red,$00
ldi pwmvalue_green,$00
ldi pwmvalue_blue,$00
ldi colorselect,$00
ldi pwmcount,$00
ldi director,$00
ldi dirty,$00
ldi temp1,EE_SPEED0
rcall readeeprom
andi temp1,$07
mov speed0,temp1
ldi temp1,EE_SPEED1
rcall readeeprom
andi temp1,$07
mov speed1,temp1
ldi temp1,EE_SPEED2
rcall readeeprom
andi temp1,$07
mov speed2,temp1
sei
loop:
;leds aus
ldi output,$1f
cp pwmvalue_red,pwmcount
brsh check_green
;leds an
cbr output,$01
check_green:
cp pwmvalue_green,pwmcount
brsh check_blue
;leds an
cbr output,$02
check_blue:
cp pwmvalue_blue,pwmcount
brsh writeoutput
;leds an
cbr output,$04
writeoutput:
out portb,output
inc pwmcount
rjmp loop
OVF0Handler:
in r1,sreg
inc swcount0
cp swcount0,speed0
brlo end_change_red
ldi swcount0,$00
sbrc director,$00
rjmp do_red_inc
dec pwmvalue_red
cpi pwmvalue_red,$00
brne end_change_red
sbr director,$01
rjmp end_change_red
do_red_inc:
inc pwmvalue_red
cpi pwmvalue_red,$ff
brne end_change_red
cbr director,$01
end_change_red:
inc swcount1
cp swcount1,speed1
brlo end_change_green
ldi swcount1,$00
sbrc director,$01
rjmp do_green_inc
dec pwmvalue_green
cpi pwmvalue_green,$00
brne end_change_green
sbr director,$02
rjmp end_change_green
do_green_inc:
inc pwmvalue_green
cpi pwmvalue_green,$ff
brne end_change_green
cbr director,$02
end_change_green:
inc swcount2
cp swcount2,speed2
brlo end_change_blue
ldi swcount2,$00
sbrc director,$02
rjmp do_blue_inc
dec pwmvalue_blue
cpi pwmvalue_blue,$00
brne end_change_blue
sbr director,$04
rjmp end_change_blue
do_blue_inc:
inc pwmvalue_blue
cpi pwmvalue_blue,$ff
brne end_change_blue
cbr director,$04
end_change_blue:
sbis pinb,3
rjmp pressedhandler
sbis pinb,4
rjmp pressedhandler
cpi swcount3,$80
brsh writesettings
cpi swcount3,$20
brsh colorselect
cpi swcount3,$05
brlo releasehandler
cpi colorselect,$00
brne testgb
mov temp1,speed0
inc temp1
andi temp1,$07
mov speed0,temp1
rjmp releasehandler
testgb:
cpi colorselect,$01
brne testb
mov temp1,speed1
inc temp1
andi temp1,$07
mov speed1,temp1
rjmp releasehandler
testb:
mov temp1,speed2
inc temp1
andi temp1,$07
mov speed2,temp1
rjmp releasehandler
releasehandler:
ldi swcount3,$00
exit_ovf0Handler:
ldi temp1,timer_value
out tcnt0,temp1
out sreg,r1
reti
pressedhandler:
cpi swcount3,$80
brsh exit_ovf0handler
inc swcount3
rjmp exit_ovf0Handler
colorselect:
inc colorselect
cpi colorselect,$03
brne nocolorrollover
ldi colorselect,$00
nocolorrollover:
ldi temp1,0b00011110
cpi colorselect,$00
breq docolorselect
ldi temp1,0b00011101
cpi colorselect,$01
breq docolorselect
ldi temp1,0b00011011
docolorselect:
out portb,temp1
ldi temp1,$00
ldi temp2,$00
delay:
nop
nop
nop
nop
nop
dec temp1
brne delay
dec temp2
brne delay
rjmp releasehandler
writesettings:
ldi temp1,EE_SPEED0
mov temp2,speed0
rcall writeeeprom
ldi temp1,EE_SPEED1
mov temp2,speed1
rcall writeeeprom
ldi temp1,EE_SPEED2
mov temp2,speed2
rcall writeeeprom
rjmp releasehandler
;lese byte aus EEprom, adresse in temp1, gelesener wert ebenfalls in temp1
readeeprom:
sbic eecr,eewe
rjmp waitstable_readeeprom
out eear,temp1
waitstable_readeeprom:
sbi eecr,eere
in temp1,eedr
ret
writeeeprom:
sbic eecr,eewe
rjmp writeeeprom
out eear,temp1
out eedr,temp2
sbi eecr,eemwe
sbi eecr,eewe
ret |