HSV color changing led driven by AVR tiny45
21
Jun0
Jun0
In my last post I focused on delivering an integer only based algorithm to make a HSV to RGB conversion. I wanted to to drive a mood lamp with an AVR tiny13 which as only a 1K byte program memory. I ended gaving up on this idea because, I was not having good results.
I decided to get a new chip, with more program memory. The chosen one was the tiny45 with 4K bytes of program memory.
I got back in time and started again with the floating point version of the algorithm. And voila! It is working. It has a few glitches which increase with a small interval between color changing.
At this point, the code is very simple and it is like this (assumes a 2Mhz clock on the tiny45):
-
-
#include <avr/io.h>
-
#include <avr/interrupt.h>
-
#include <avr/pgmspace.h>
-
#include <avr/eeprom.h>
-
#include <avr/wdt.h>
-
#include <util/delay.h>
-
#include <math.h>
-
-
#define R_PIN PB0
-
#define G_PIN PB1
-
#define B_PIN PB2
-
-
static float h=0,s=0.8,v=0.5,r=0,g=0,b=0;
-
static int ri,gi,bi;
-
-
void HSVtoRGB( float *r, float *g, float *b, float h, float s, float v )
-
{
-
int i;
-
float f, p, q, t;
-
-
if( s == 0 ) {
-
*r = *g = *b = v; // achromatic (grey)
-
return;
-
}
-
-
h /= 60; // sector 0 to 5
-
i = floor( h );
-
f = h – i; // factorial part of h
-
p = v * ( 1 – s );
-
q = v * ( 1 – s * f );
-
t = v * ( 1 – s * ( 1 – f ) );
-
-
switch( i )
-
{
-
case 0:
-
*r = v;
-
*g = t;
-
*b = p;
-
break;
-
case 1:
-
*r = q;
-
*g = v;
-
*b = p;
-
break;
-
case 2:
-
*r = p;
-
*g = v;
-
*b = t;
-
break;
-
case 3:
-
*r = p;
-
*g = q;
-
*b = v;
-
break;
-
case 4:
-
*r = t;
-
*g = p;
-
*b = v;
-
break;
-
default:
-
*r = v;
-
*g = p;
-
*b = q;
-
break;
-
}
-
}
-
-
ISR(TIM0_COMPA_vect)
-
{
-
static unsigned char count = 0;
-
-
if (count == 0)
-
PORTB = _BV(R_PIN) | _BV(G_PIN) | _BV(B_PIN);
-
-
if (count==ri)
-
PORTB^=_BV(R_PIN);
-
-
if (count==gi)
-
PORTB^=_BV(G_PIN);
-
-
if (count==bi)
-
PORTB^=_BV(B_PIN);
-
-
count++;
-
}
-
-
int main()
-
{
-
// Enable PORTB as output
-
DDRB=0xff;
-
-
// Enable global interrupts
-
sei();
-
-
// Setting timer in CTC mode
-
TCCR0A = _BV(WGM01);
-
-
// Setting no prescaler
-
TCCR0B = _BV(CS00);
-
-
// Enabling compa
-
TIMSK = _BV(OCIE0A);
-
-
// Setting compare to make a frequency of 60*256 Hz
-
OCR0A = 0×82;
-
-
while(1)
-
{
-
if (h==360)
-
h=0;
-
-
h++;
-
-
HSVtoRGB(&r,&g,&b,h,s,v);
-
-
ri = r*255.;
-
gi = g*255.;
-
bi = b*255.;
-
-
_delay_ms(100);
-
}
-
-
return 0;
-
}
-
-
No Comments
No comments yet.
Leave a comment
You must be logged in to post a comment.