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



Usage of the AD-Converter

Moving Average Digital filter


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:







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"


.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


;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


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


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



;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


;Hauptschleife für PWM


;leds aus

ldi output,$0f

cp pwmvalue_1,pwmcount

brsh check_green

;leds an

and output,mode_1


cp pwmvalue_2,pwmcount

brsh check_blue

;leds an

and output,mode_2


cp pwmvalue_3,pwmcount

brsh writeoutput

;leds an

and output,mode_3


eor output,omod

out portb,output

inc pwmcount

brne loop

inc pwmcount

rjmp loop

;Timer Interrupt


;Status sichern

in sbuffer,sreg

;AD-Wandler lesen

in temp1,adch


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


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


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


com r0

mov pwmvalue_3,r0

;Taster abfragen

sbic pinb,pb3

rjmp releasehandler

cpi swcount,$20

brsh exit_ovf0Handler

inc swcount


out sreg,sbuffer


;write mode to eeprom


cpi swcount,$20

breq writemode

ignore short pulses

cpi swcount,$02

brsh key_valid

clr swcount

rjmp exit_ovf0handler


initializing routines


Complete sourcecode available on request here .

Additional Information,Basics,DIY Kit, Links for Schematic
Sponsored Ads:

You are Visitor Nr. 185766