HSV color changing led driven by AVR tiny45

21
Jun
0

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):

  1.  
  2. #include <avr/io.h>
  3. #include <avr/interrupt.h>
  4. #include <avr/pgmspace.h>
  5. #include <avr/eeprom.h>
  6. #include <avr/wdt.h>
  7. #include <util/delay.h>
  8. #include <math.h>
  9.  
  10. #define R_PIN   PB0
  11. #define G_PIN   PB1
  12. #define B_PIN   PB2
  13.  
  14. static float h=0,s=0.8,v=0.5,r=0,g=0,b=0;
  15. static int ri,gi,bi;
  16.  
  17. void HSVtoRGB( float *r, float *g, float *b, float h, float s, float v )
  18. {
  19.         int i;
  20.         float f, p, q, t;
  21.  
  22.         if( s == 0 ) {
  23.                 *r = *g = *b = v; // achromatic (grey)
  24.                 return;
  25.         }
  26.  
  27.         h /= 60;                        // sector 0 to 5
  28.         i = floor( h );
  29.         f = h – i;                      // factorial part of h
  30.         p = v * ( 1 – s );
  31.         q = v * ( 1 – s * f );
  32.         t = v * ( 1 – s * ( 1 – f ) );
  33.  
  34.         switch( i )
  35.         {
  36.                 case 0:
  37.                         *r = v;
  38.                         *g = t;
  39.                         *b = p;
  40.                         break;
  41.                 case 1:
  42.                         *r = q;
  43.                         *g = v;
  44.                         *b = p;
  45.                         break;
  46.                 case 2:
  47.                         *r = p;
  48.                         *g = v;
  49.                         *b = t;
  50.                         break;
  51.                 case 3:
  52.                         *r = p;
  53.                         *g = q;
  54.                         *b = v;
  55.                         break;
  56.                 case 4:
  57.                         *r = t;
  58.                         *g = p;
  59.                         *b = v;
  60.                         break;
  61.                 default:
  62.                         *r = v;
  63.                         *g = p;
  64.                         *b = q;
  65.                         break;
  66.         }
  67. }
  68.  
  69. ISR(TIM0_COMPA_vect)
  70. {
  71.         static unsigned char count = 0;
  72.  
  73.         if (count == 0)
  74.            PORTB = _BV(R_PIN) | _BV(G_PIN) | _BV(B_PIN);
  75.  
  76.         if (count==ri)
  77.            PORTB^=_BV(R_PIN);
  78.  
  79.         if (count==gi)
  80.            PORTB^=_BV(G_PIN);
  81.  
  82.         if (count==bi)
  83.            PORTB^=_BV(B_PIN);
  84.  
  85.         count++;
  86. }
  87.  
  88. int main()
  89. {
  90.         // Enable PORTB as output
  91.         DDRB=0xff;
  92.  
  93.         // Enable global interrupts
  94.         sei();
  95.  
  96.         // Setting timer in CTC mode
  97.         TCCR0A = _BV(WGM01);
  98.  
  99.         // Setting no prescaler
  100.         TCCR0B = _BV(CS00);
  101.  
  102.         // Enabling compa
  103.         TIMSK =  _BV(OCIE0A);
  104.  
  105.         // Setting compare to make a frequency of 60*256 Hz
  106.         OCR0A = 0×82;
  107.  
  108.         while(1)
  109.         {
  110.                 if (h==360)
  111.                         h=0;
  112.  
  113.                 h++;
  114.  
  115.                 HSVtoRGB(&r,&g,&b,h,s,v);
  116.  
  117.                 ri = r*255.;
  118.                 gi = g*255.;
  119.                 bi = b*255.;
  120.  
  121.                 _delay_ms(100);
  122.         }
  123.  
  124.         return 0;
  125. }
  126.  
  127.