Archive

Archive for the ‘Arduino’ Category

HSL to RGB tutorial + Updated Rotary Encoder Library

April 22nd, 2009

Background:

I am in the design process of a new project that uses a lot of RGB LEDs. In the project I want to allow the user to select various colours and I was looking for a fairly intuitive way to do this.

If one has ever worked with RGB LEDs you know you have to PWM the values of each channel (R, G or B). Therefore for Red, I would PWM (255,0,0), for Green – (0,255,0), etc.

Now since each LED has 3 channels, you have to control three outputs. Therefore if I wanted to allow the user to be able to control the colour of an LED, I would have to have him control three sensors. That is a lot of inputs for one output (3 inputs per output). For an application like this I would normally consider three potentiometer’s to control the LED

But I wanted to be able to control the LED with one sensor. Doing some research I found that the HSL colour scheme was exactly what I need. I stumbled across this Rotary Encoder on Seeedstudio and it fit my price range. The reason I chose an encoder is you can use it to act like a pot but it allows continuous rotation.

My solution was to use an HSL Color Schemer. If I set the luminance and saturation to a suitable value, I can then use the rotary encoder to cycle through the Hue spectrum. Now while this does not give me every single RGB combination, it does give me 360 combinations across all the RGB colour channels.

Integration:

The major stumbling block I had was the Rotary Encoder. The reason it was so cheap was because it was a Mechanical Encoder. Therefore I has some serious debounce factor to consider – either through software or hardware. I found a little Rotary Encoder library written by SunBox on the Arduino Forums. However, the way it worked was you had to set a max and a min and once either extreme was reached, it no longer counted forward or backward.

I added a restart function to the library. Setting restart to a value of 1, tells the library to start counting from the min value.

restart(1);

I’ve attached the library below:
Rotary Encoder Library

Note: the library currently counts up by 20 on every edge. I used this cause I had a 20 detent encoder and that means a full rotation goes just over the whole hue range. I will add a function that allows you to choose how much to count by on each edge

Here is some sample code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
#include "RotaryEncoder.h"
 
RotaryEncoder rotary(3, 2, 4);
int Rpin=10;
int Gpin=9;
int Bpin=11;
float H,S,L,Rval,Gval,Bval;
 
void HSL(float H, float S, float L, float& Rval, float& Gval, float& Bval);
float Hue_2_RGB( float v1, float v2, float vH );
 
void setup()
{
  Serial.begin(9600);
 
  //set up encoder with rotary library
  rotary.minimum(0);
  rotary.maximum(360);
  rotary.position(320);
  rotary.restart(1);
  pinMode(12, OUTPUT); 
}
 
 
void loop()
{
  H=rotary.position();
  S=1;
  L=.5;
  Rval=0;
  Gval=0;
  Bval=0;
  HSL(float(rotary.position())/360,S,L,Rval,Gval,Bval);
 
  //common anode configuration
  //analogWrite(Rpin, 255-Rval);
  //analogWrite(Gpin, 255-Gval);
  //analogWrite(Bpin, 255-Bval);
  //digitalWrite(12,HIGH);
 
  //common cathode configuration
  analogWrite(Rpin, Rval);
  analogWrite(Gpin, Gval);
  analogWrite(Bpin, Bval);
  digitalWrite(12,LOW);
 
  //print statements for debug
  Serial.print("position:");
  Serial.print(H);
  Serial.print(" R:");
  Serial.print(Rval);
  Serial.print(" G:");
  Serial.print(Gval);
  Serial.print(" B:");
  Serial.println(Bval);
  delay(1000);
}
 
void HSL(float H, float S, float L, float& Rval, float& Gval, float& Bval)
{
  float var_1;
  float var_2;
  float Hu=H+.33;
  float Hd=H-.33;
  if ( S == 0 )                       //HSL from 0 to 1
  {
     Rval = L * 255;                      //RGB results from 0 to 255
     Gval = L * 255;
     Bval = L * 255;
  }
  else
  {
     if ( L < 0.5 ) 
       var_2 = L * ( 1 + S );
     else           
       var_2 = ( L + S ) - ( S * L );
 
     var_1 = 2 * L - var_2;
 
     Rval = round(255 * Hue_2_RGB( var_1, var_2, Hu ));
     Serial.print("Rval:");
     Serial.println(Hue_2_RGB( var_1, var_2, Hu ));
     Gval = round(255 * Hue_2_RGB( var_1, var_2, H ));
     Bval = round(255 * Hue_2_RGB( var_1, var_2, Hd ));
  }
 
}
float Hue_2_RGB( float v1, float v2, float vH )             //Function Hue_2_RGB
{
   if ( vH < 0 ) 
     vH += 1;
   if ( vH > 1 ) 
     vH -= 1;
   if ( ( 6 * vH ) < 1 ) 
     return ( v1 + ( v2 - v1 ) * 6 * vH );
   if ( ( 2 * vH ) < 1 ) 
     return ( v2 );
   if ( ( 3 * vH ) < 2 ) 
     return ( v1 + ( v2 - v1 ) * (.66-vH) * 6 );
   return ( v1 );
}

Hope this helps someone, I will be adding pictures soon. If you need any other modifications made to the library don’t hesitate to ask.

Darius Gai Arduino

Seeedstudio Issues Part II (Resolved!!)

April 21st, 2009

The issues have been resolved.
It did take some back and forth with Eric (the owner of seeedstudio) over email. Eric tried to help me through various options that would let me salvage the anode LEDs, but all the ideas we put together would cost me additional money and take up more space in my eventual design. Eric finally conceded that cathode LEDs would be the right way to go and then we went through arrangements for them to send me the cathode LEDs over. Initally they wanted me to pay for the new LEDs, but I stayed strong to my arguement that the mistake was their fault and Eric finally did concede.

Altogether the back and forth of emails took about 2 days, and the LEDs came in today (18 days later) at the cost of seeedstudio. Through out the process Eric was extremely polite, and replied promptly to my emails.

Thanks seeedstudio!!

Darius Gai Arduino

Seeedstudio Issues

March 31st, 2009

As of late I’ve been getting into bigger and bigger projects. Late last month I put in an order for a whole whack of parts from seeedstudio. The parts came in a week later and I tucked them away.

Last week my LED Driver ICs came in from Maxim, so today (now that PDEng is over with) I decided was a good time to start tinkering and working on a new project.

The main component of my order from seeedstudio was 50 RGB LEDs that I planned to interface with the LED Drivers. The LEDs I ordered were supposed to be common CATHODE, so I went about hooking all of them up on a breadboard to test them.

After 30 mins of tinkering I had nothing, not even a flicker. I kept looking over my wiring thinking I had messed up something obvious, but nothing came to the eye. When I used a normal red led to test, everything worked fine.

About an hour into the process, I was starting to give up, when I suddenly decided to just flip all the leads on the RGB Led around. Suprisingly it worked!

Now completely confused, I started going through my circuit again. Apparently, the LEDs I recieved were not common cathode, but common ANODE.  To make matters worse, they didn’t even fit the datasheet shown on the website (also shown below):

RGB LED datasheet

RGB LED datasheet

Instead they followed this pattern:

————–
|    |    |   |
|    |    |   |
G  B  +  R

This blows… common anode LEDs are useless to me for my application. To use my LED drivers I need common cathode LEDs

I just whipped out an email to seeedstudio, hopefully they’ll sort me out.

Darius Gai Arduino

Hacking a digital alarm clock

February 22nd, 2009

 

Philips AJ3540

Philips AJ3540

About 6 months ago, I purchased an digital alarm clock/radio from Walmart. The model i purchased was the Philips AJ3540 for about $40. I purchased it for the large display, which I did not see available for other clocks in the same price range.

The clock is not without its flaws, however. The sound of the alarm buzzer is deafening and the backlight on the display is just too bright, even on the lowest settings for both on their respective control knobs. 

This week I finally had enough and decided something needed to be done.

On opening up the alarm clock I saw that the clock was divided into 3 segments – the display, the controls and the “brains”. The brains section had some interesting components. The buzzer was actually a high wattage piezo buzzer, I haven’t ever seen a piezo buzzer that was this loud. Also the circuit used to convert the incoming ac to dc was interesting.

Anyway, down to business.

How do I reduce the sound of a piezo buzzer?

This was suprisingly easy. The incoming AC power is converted to 5v DC, so all I had to do was find the power rails and hook up a potentiometer to it. I then hooked up the wiper on the potentiometer to the buzzer, where it was previously connected straight to 5v. After setting the alarm to go off, I moved the wiper around till I found a volume I found suitable. 

Basicly that is really all you need to do. However I didn’t want to just leave the potentiometer there inside the alarm clock. The first idea I had was to cut a hole into the casing of the alarm clock and use the pot as my new volume control knob. However, I do not have a dremel handy for cutting a clean hole, so this would not do. Also I only have 1 potentiometer currently in my possession (I need to put an order in for parts!), so I didn’t want to give it up, especially since I use them quite regularry for testing.

After some thinking I suddenly remembered that the way I was using the pot was similar to a voltage divider. Which brings us to step 2 of our procedure.

What is the voltage I want to step down to?

This wasn’t as easy as I thought it would be. 

At first I hooked up my Arduino to the clock – share the ground and hook the wiper up to an Analog Pin through a 10K resistor. I then intended on displaying the data on my computer monitor serially. However, this wasn’t simple, as the circuit on the alarm clock was pulsing the buzzer faster (PWM) than the arduino could print values to the screen. At times like these, I wish I had an oscilloscope…

Anyway, there is always a way around difficulties! I calibrated the pot to the volume I wanted it and then removed it from the alarm clock. I then hooked it up to the arduino through the 5V power out. The reading I got out was 4.8V. This part still doesn’t make sense to me, as for a drop of .2V the volume decreased by quite a bit! Guess the buzzer doesn’t follow a linear curve (which would make sense as its based on frequency).

A little voltage divider math showed that my R2 should be equal to around 24 times my R1. Looking through my available resistors I used a 300 ohm resistor for R1 and a 5.1K and a 2K resistor in series for my R2. 

Soldered the resistors on and voila!! Your sound is now exactly how you want it!

I went on and did the same thing for my display backlight.

Hope this helps someone out! I planned on adding pictures but I my SD card on my laptop reader isn’t working :(

Darius Gai Arduino, Projects, personal

Learning Eagle

February 11th, 2009

I have been dabbling a lot with Eagle as of late. And today I started to make some inroads. I created my first part in Eagle and have started a library. The part I created was the AS1106 LED Driver from Austria Microsystems: http://www.austriamicrosystems.com/eng/Products/Lighting-Management/LED-Drivers/AS1106

It is a cheaper alternative of the MAX2219 LED driver from Maxim-IC. I recently embarked on created a game using the Arduino that incorporates tons of LEDs and depending on my final configuration (haven’t decided on this yet), it would require 2-3 of these LED Drivers.

I also plan on using this project to Learn Eagle and since my AS1106 chips came in yesterday I thought I’d start by creating a part for them. It wasn’t as bad as I thought it would be and the Sparkfun tutorials on Eagle are a good starting point.

 Next I want to create a small protoboard with a single piece of each component type. Once I make sure that the footprint of each one is right, I’ll finish up the board and then I am set to go!

Darius Gai Arduino, Projects