 |
Voltage Controlled RGB LED
|
LED's have found their way into numerous illumination applications. Most of the time however, they are simply turned on and off.
The following project introduces a software for the Atmel TINY15 Controller, that allows 3 LED's to be controlled by a analog voltage from 0.. 2.5V, ideally suited for monitoring and indicator purposes, like fan RPM, temperature, voltage...
This program uses a number of techniques that may be useful in other projects:
Reading and writing of EEPROM
Timer-Interrupt
Software-Counter
Usage of the AD-Converter
Moving Average Digital filter
Usage:
Connect your RGB-LED or three separate LED's to Pin PB0-PB2 (with current limiting resistors of course!)
A pushbutton switch is connected to PB3. The analog Signal is routed to PB4, preferably through a RC Lowpass 100k/100nF
The Main loop of the program generates the PWM Signal for 3 Channels. The Timer Interrupt reads the AD Converter, a Moving average digital filter smoothens the input signal, and a lookup table implements a physiological brightnes correction.
The following functions are implemented:
Pushing the button once for s short period of time changes the order in which the LED's begin to light up. There are 6 possibilities:
RED-GREEN-BLUE
RED-BLUE-GREEN
BLUE-RED-GREEN
BLUE-GREEN-RED
GREEN-RED-BLUE
GREEN-BLUE-RED
pressing the button for more then 3 seconds makes the change permanent, stored in the internal EEPROM
When pressing the button during power-up, the polarity of the output signal is inverted, to provide simple interfacing to driver stages or using LED's with common cathode or anode.
Program developed with AVR Studio 4.10.
When programming, store the OSCCAL-value in EEPROM-Cell $3f ;
Complete sourcecode available on request here .
;Voltage Control RGB
;(C) 2004 Markus Vohburger
Only for private purposest
;Definitionen für Tiny15
.include "tn15def.inc"
;Programmvariablen
.def pwmcount = r01
.def pwmvalue_1 = r02
.def pwmvalue_2 = r03
.def pwmvalue_3 = r04
.def mode_1=r05
.def mode_2=r06
.def mode_3=r07
.def omod=r08
.def sbuffer=r09
.def temp1 = r16
.def temp2 = r17
.def output = r18
.def swcount=r19
.def mode=r20
;movin' average filter
.def adcold1 = r23
.def adcold2 = r24
.def adcold3 = r25
.equ EE_MODE = $00
.equ EE_OMOD = $01
.equ EE_OSCCAL = $3f
.equ timer_value = $80
;reset handler
.org $0000
rjmp main
;timer overflow interrut handler
.org T0OVAddr
rjmp T0OVHandler
.org $0010
main:
;read osccal byte
ldi temp1,EE_OSCCAL
rcall readeeprom
out osccal,temp1
ldi temp1,$07
out ddrb,temp1
;port b output LED's Off,, pullup on pb3
ldi temp1,$0f
out portb,temp1
ldi temp1,EE_MODE
rcall readeeprom
cpi temp1,$06
brlo mode_ok
ldi temp1,$00
mode_ok:
mov mode,temp1
rcall readsettings
ldi temp1,EE_OMOD
rcall readeeprom
cpi temp1,$00
breq omod_ok
cpi temp1,$07
breq omod_ok
ldi temp1,$00
omod_ok:
mov omod,temp1
;Taster an PB3 überprüfen
sbic pinb,pb3
rjmp no_omod_change
ldi temp1,$07
eor omod,temp1
;Mode umschalten
ldi temp1,EE_OMOD
mov temp2,omod
rcall writeeeprom
;port setup
;port pb0,1,2 outputs
no_omod_change:
notoggle:
;Timer zurücksetzen
ldi temp1,timer_value
out tcnt0,temp1
;Timer interrupts an
ldi temp1,(1<<toie0)
out timsk,temp1
;Timer starten
ldi temp1,0b00000100
out tccr0,temp1
rcall init_adc
clr swcount
sei
;Hauptschleife für PWM
loop:
;leds aus
ldi output,$0f
cp pwmvalue_1,pwmcount
brsh check_green
;leds an
and output,mode_1
check_green:
cp pwmvalue_2,pwmcount
brsh check_blue
;leds an
and output,mode_2
check_blue:
cp pwmvalue_3,pwmcount
brsh writeoutput
;leds an
and output,mode_3
writeoutput:
eor output,omod
out portb,output
inc pwmcount
brne loop
inc pwmcount
rjmp loop
;Timer Interrupt
T0OVHandler:
;Status sichern
in sbuffer,sreg
;AD-Wandler lesen
in temp1,adch
;dividieren
lsr temp1
lsr temp1
lsr temp1
;Moving Average Filter
mov temp2,temp1
add temp1,adcold1
adc temp1,adcold2
adc temp1,adcold3
mov adcold3,adcold2
mov adcold2,adcold1
mov adcold1,temp2
lsr temp1
lsr temp1
;pwm-lookup table
clr r0
ldi zl,low(table_pwm_1<<1)
ldi zh,high(table_pwm_1<<1)
add zl,temp1
adc zh,r0
lpm
com r0
mov pwmvalue_1,r0
clr r0
ldi zl,low(table_pwm_2<<1)
ldi zh,high(table_pwm_2<<1)
add zl,temp1
adc zh,r0
lpm
com r0
mov pwmvalue_2,r0
clr r0
ldi zl,low(table_pwm_3<<1)
ldi zh,high(table_pwm_3<<1)
add zl,temp1
adc zh,r0
lpm
com r0
mov pwmvalue_3,r0
;Taster abfragen
sbic pinb,pb3
rjmp releasehandler
cpi swcount,$20
brsh exit_ovf0Handler
inc swcount
exit_ovf0Handler:
out sreg,sbuffer
reti
;write mode to eeprom
releasehandler:
cpi swcount,$20
breq writemode
ignore short pulses
cpi swcount,$02
brsh key_valid
clr swcount
rjmp exit_ovf0handler
Tables
initializing routines
etc...
Complete sourcecode available on request here .
|
More on this Subject:
Sponsored Links:
|