You can build this in about an hour if you've got the materials and the level of Arduino expertise it takes to upload a demo project to the board. I always like to walk people through my solutions, so you can change and extend to project, but this one is a fairly simply copy and paste if that's what you want to do. Most Arduino starter kits will come with the components you need for this project.
- Lights - You need an least a red, a green, and a blue LED. I've added a white too, but it works without. If you want to add loads more LEDs, go for it - just copy the R, G, B (and possibly W) values to all the extra pins. I've used 1.8V LEDs with 220 Ohm resistors, because they're common, but you could go for 5v LEDs up to 400mA (that'd get you to lamp brightness without having to double up)
- Saturation and Luminosity dials - These are just variable resistors. I'm using 10K, but it's not terribly important.
- Hue Wheel - You need a rotary encoder for this. It's the only slightly specialist component in this build. They're pretty standard in Arduino kits, cheap to buy separately, or you can take one off some old hifi equipment or a mouse - if it goes round and round, and clicks, there's a rotary encoder under it.
Step 1: Get the Lights Up and Running.
Building a circuit with an Arduino is actually much simpler than without. None of the components have to work together. You just have to know how to connect each individual component to the board, then you add a little programming. Programming is easier than electrical engineering.
Adruino boards are covered with 5V pins. You go - 5v pin --> Resistor --> LED --> Ground (0v) pin. It doesn't matter which order the resistor and LED go in. If you're using 1.8v LEDs (if you're not sure, you probably are) you need 220 Ohm resistors. There are calculators online if you want to use something different.
LEDs need to go in the correct way. There are two ways to tell which side is which. If the legs haven't been cut, the short one goes to ground. If you can't tell from the legs, hold the bulb up to the light. There are two pieces of metal in there, with a small gap between them. The large piece of metal goes to ground.
The diagram image is our whole circuit diagram. The only bit you need to do now if the highlighted section. Then copy that code and upload it to the board. All the LEDs should light up.
- Setup - this method gets called once at the start
- Loop - this method gets called repeatedly. There's no code in it yet.
- pinMode - we've set the three pins we use to output so we can write to them.
- analogWrite - passing 255 to this switches the LEDs on. We could do this more simply with digitalWrite, but this is the method we'll be using later. You can change that value to adjust the brightness. It switches the LEDs on and off rapidly to simulate dimmer light.
You don't have to use such a tiny breadboard, but I did because I thought it was cute.
Step 2: Remaining Components
At this point, your board is connected and working, you're able to upload code, and you've followed first part of the circuit diagram. The rest is just a jigsaw.
The one item I'll talk a little about, is the rotary encoder. The pins of interest here are dt and clk (sometimes called A and B). Whenever you rotate the dial a single click, these will change in a manner which tells you which way it was turned. They rest low (0v) but will change to high (5v) briefly following each click. The order which they go high, tells you which way the wheel is turning. I'll go into more detail in the next step.
My rotary encoder has a nice wheel on it I took from a Sharp Mini Disc player. The axles on rotary encoders and variable resistors are fairly standard, so go find yourself something nice if you want them to be easy to turn.
Step 3: Put the Code In
Get the code here - https://github.com/seanbouk/hue_light_arduino/blob...
If you've copied the previous steps exactly, you can just upload it. If you want to change it, or you've had to make a change to fir your components and layout, or you're just interested, I'll explain what it does.
- red, green, blue, white - digital pin numbers for the LEDs. Change these if you're moved anything.
- sat, lum - analogue pin numbers for the middle pin on the saturation and luminosity variable resistors.
- re0 and re1 - digital pin numbers for the data pins from the rotary encoder
- lastRE and reVal - current and previous state for the rotary encoder
- h, s, and l - the hue, saturation, and luminosity values. We derive these from the inputs on the board, then use them to generate red, green, and blue values...
- r, g, b - ...which we store here.
- setup - just pinMode stuff, and a commented out setup for debugging on COM3. If you uncomment all the Serial methods and open the Serial Monitor, you'll see debug values output to your computer's screen. I don't think there's anything interesting there; it's just whatever state I left it in. Being able to debug this way is another reason Arduino is simpler than just using components!
- loop - my method names are fairly readable. It gets an update from the rotary encoder, then is updates the hue, sat, and lum values, then the RGB values, then adjusts the LEDs. The white LED is a bit hacky (and difficult to read if you're looking at a font which has identical l and 1) Lots of lum and no sat, means full white, so the white goes down when it's dark or vivid.
- updateRGB and hue2rgb - as far as I'm aware this code is public domain. I've used it half a dozen times before in various guises. I've adjusted it here to use the range of values and the variable names and I needed, and to make it work hard typed (ino files are basically C++, but I copied this code from some JS). You might also notice I'm squaring the values in the last three lines (eg, tempR * tempR). I do that because the LEDs looked too bright when they were supposed to be around half way. YMMV.
- updateHSL - The hue uses the current rotary encoder value, divided by 36 to make the hue change with fewer clicks. The sat and lum are just analogue reads.
- updateRE - There's example code on the Arduino site to handle this, but I don't like it. It keeps separate current and previous states for each data pin. My code works by assuming a value to each pin - one of them is worth a 1, and the other a 2 - then adding them together so a single integer can represent the entire rotary encoder state - simplifying state management is key to producing bug free code. My code looks for a change, when the previous value was three (3 = 1 + 2, so both pins were high), then branches on the current value. If the 3 changes to a 1, we decrement our value, otherwise we increment it.
If you want further help with the code, message me in the comments section.
To test your lamp, place a piece of tracing paper in front of it, and turn your main lights down. Now twiddle all those dials.
Participated in the
Colors of the Rainbow Contest