It turns out that a colour detection module can be built for next to nothing, and the results are astoundingly good for the investment.
The biggest hurtle in this project is getting the balance right on our sensor as we are using LEDs to represent the colour being detected, which becomes our limit. Dark colours are more difficult to represent. The sensor still does a good job at detecting and giving a reliable reading, but again, balancing becomes the real issue. Reflectivity will also play with the readings. That being said, this sensor would work great for all manner of colour detecting projects. Best of all it is super cheap to make.
I really hope that a few of you out there both copy and improve on my lamp, or find some other great uses for this cheap, easy to make, Arduino friendly Colour sensor.
Step 1: Get Stuff
- a CdS photocell (cadmium sulfide), also called an LDR or light dependent resistor. Anyways, it is one of those little light detectors on most garden lamps, night-lights, etc.
- A 10K resistor
- A red LED
- a green LED
- a blue LED
- alternatively you could use an RGB(red green blue) LED
- A 220 ohm resitor
- a bit of shrink wrap or a cut section of a pen or anything else that would be a decent shroud for the LDR
- a shroud for the entire sensor (film case cut, pvc pipe, bits of plastic, again anything to shield the whole ensemble from ambient light a bit)
- a bit of prototyping board.
- Hookup wire (I also use male header pins and jumpers, but this is not required)
To make the rest of the lamp, you will also need.
- An enclosure
- a diffuser (I managed to get mine all in one with a tomato container from the Dollar store)
- an Arduino that will fit in your enclosure (I used a mini)
- another RGB LED or a red, green and blue LED
- three 220 ohm resistors
- some decor (use your imagination here, I went for the magic lamp look, you do what pleases you or go with what you have on hand as I did)
- soldering iron
- glue gun
- x-acto knife
- white glue
- paint brush
Step 2: Random Thoughts
We see colour as a frequency of light reflected from an object. So different colours reflect different wavelengths which our eyes then interpret as colours. (Maybe brain...I am no scientist)
A common CdS photocell has a very similar response to colour as the human eye.
Because colours absorb certain wavelengths and reflect certain wavelengths, we can use different wavelengths(colours) of light and take readings(from a sensor that has nearly human responses) and thereby make a pretty good guess at what colour the sensor is being exposed to.
It also turns out that a computer represents colours as a red, green, and blue value in order to display it to our screen. We will be using red, green and blue LEDs for both detection and representation of colour.
Follow all that? No? Don't worry, stay with me and build it, everything will become clearer.
Step 3: Build the Colour Sensor
Start by wiring up the CdS photocell. One side should go to a 5V pin on the Arduino. The other end should go out to ground via a 10k resistor, and also to analog pin 2 on the Arduino. (see wiring diagram, it is marked pin 0, but the code uses pin 2, either will work, just make the appropriate changes)
The sensitivity of the sensor can be changed by altering the resistor. A higher resistance will provide a better sensitivity to darker colours. Anywhere from 1k up to 10k should be decent. I used a 10k because it was what I had on hand, but I believe that a lower value would have been better for this application.
Once the the Cds photocell is wired up, wire in the 3 LEDs with their grounds going through the 220 ohm resistor. The red LED will connect to digital pin 2 on the Arduino. The green to pin 3, and the blue to pin 4.
Try to arrange the LEDs so that they are equidistant from the photocell. Another hint is to try and leave a little bit of wire leads above your proto-board so that you can gently bend them in order to fine tune the beams. You want the LEDs to illuminate the area beneath the photocell as equally as you can manage. (see wiring diagram)
Use some heat shrink tubing or something else to shroud the CdS from direct exposure from the LEDs. While we will be doing balancing to our readings, we don't want to contend with to much extra light. We are trying to detect what light is detected, and having too much exposure to direct light will throw the reading off. I used a section cut from a cheap black pen to make my shroud, and hot glued it in place.
Once the circuit is built and the shroud is added to the CdS photocell, you can go ahead and shroud the entire sensor ensemble. It is not necessary, but will help the sensor to keep a decent balance even when the ambient light changes. An added bonus is that it hides all the flashing from the sensor doing it's thing. I used a bit of black plastic I had kicking around from a garden light to make mine.
I cut it to fit my project, and also a bit to allow the sensor to sit, and then glued my board in place.
To further cut back on ambient light interfering, I went on to wrap the whole ensemble in black electrical tape.
Step 4: Build the Colour Emulator
If you want to have a better look at a RGB lamp with Arduino, I wrote another Instructable called RGB Moodlamp with Custom Library . I use the same library to control the lamp in this project, so it might be worth a visit.
A good trick for diffusing the light from an LED is to remove the lens. This is easy, just sand them down gently until the lens is gone (the curved part). Be careful not to sand too far as you can damage the LED. This will help in blending the colours together, especially when you are using separate LEDs, as I am in this project.
It would have been better to use a proper RGB LED for this side of things, but I used what I had on hand. Still nice.
I wired mine up on a little circular board with an Arduino mini mounted to the underside. I put my board onto some stand-offs that allowed for my colour sensor to be seated beneath the lamp.
Step 5: Closure
First mark off where your sensor and stand-offs will go and make the appropriate mounting holes. Your sensor needs a clear sight to the colour beneath it, so cut a hole where it will sit.
Use hot glue to position your sensor, connect all wires and fasten your stand-offs.
the container was a good size, but I underestimated its ability to diffuse my LEDs enough. I used some watered down white glue and some toilet paper to add another layer of diffusion. Slather some glue on to your surface with a paint brush, lie paper on top and paint it down with more glue. Let it dry overnight.
I also covered up the bottom and added a plastic bezel I found to give it some lift and look. I enveloped the bottom section of the container in a funky bit of fabric, and then added a little strip of brass for pizazz.
Looks kind of magical. Kinda. Could have probably put more effort into the look of the thing. Ah well, we all do what interests us most. Mine is simply realizing an idea, which I was anxious to get to.
Something good to do while you are waiting for glue to dry is to prepare a balance board and and testing board.
For the balancing board, you will need a sample of white, a sample of black, and some ranges in between (greys). This will give you some versatility when setting up your sensor.
For a test board you just need some different colour swatches that you would like to see your lamp emulate, and are large enough to get your sensor over.
Step 6: The Genie in the Lamp
Umm, if you can think of a benefit, let me know, I was having trouble with that one.
I have included the code as a text file, you will have to open it in a text editor and then copy and paste it into the Arduino environment. Or, if you prefer, just open the Arduino software and follow along writing it as we go.
For the emulation lamp I am using my custom Moodlamp library, you can get the library files and documentation on my other RGB Instructable, RGB Moodlamp with Custom Library. Otherwise you can just copy the colour sensor handling code and output to your RGB lamp in your preferred manner.
So let`s look at the code.
Start with the first image, or follow along with the text file.
We start with an include statement followed by a couple of declarations.
The include statement is for the Moodlamp library. The declaration beneath is just saying that our instance of Moodlamp will be called lamp.
Then we set up a couple of place holders.
The first is an array that we will use to address the pins the that LEDs are connected to. Remember we connected our sensor lights to those same pin numbers.
The others should be clear enough by the notes in the image, if not, never fear, they are just some place holders for values that we will use later on.
The place holder for the average reading is not special, it got it’s own image because it was almost overlooked.
Once all our declarations have been made, we will now have to write the setup function. We start by assigning our sensor output pins. We do not need to declare the analog input of the sensor, and the lamps pins are taken care of by the Moodlamp library.
Then we start serial communication so that we can get some debugging information back from our lamp.
After that we can proceed with our loop function. The loop is the code that the Arduino will run again and again. As you can see we are calling a few functions.
First we call checkBalance to see if the balance has been set and set it if needed. (When it turns on)
Then we check the colour under the sensor. Once we have a colour, we print it to the screen, and then set the colour of the lamp. The last call to getReading does nothing useful at all, left it in there by accident. Oh well, I could claim that I was just keeping the lamp from being too idle.
So let`s look at the different functions.
CheckBalance is pretty straight-forward, it checks to see if a balance exists and if it doesn’t, then it sets it by calling the setBalance function.
Let’s look at the setBalance function, it is the longest one.
First we pulse the light red twice and then white using the Moodlamp library. This is to warn the operator that the white scan is about to take place. Leaving the lamp white(all three colour on) leaves as much interfering light as possible for our baseline scans which keeps them equally balanced.
What the following section does is light the red, then green, then green LEDs while taking a sensor reading at each step. This gives us some data about how much of each colour was reflected back to the sensor. These readings should be high as it is white, which should reflect a lot for each colour.
If the meaning is not inferred, you must place a sample of white ( a card or a paper) under the sensor while this scan takes place. The whole thing lasts about three seconds. The scan less than one.
When finished with scanning white, we will scan black. There are some warning lights again, a delay, and then the scan. Here you will want a black or grey sample under the lamp. We will talk a little more on what your sample should be later.
Once the balancing scans are completed, the lamp will turn off, and we set the Boolean value for whether or not balancing values have been established to true.
Once the balances have been set, our program will now start checking the colour beneath the sensor, chances are that in the physical world you still haven’t removed it from your black sample, but never mind that, we were talking about the code.
If you followed what was going on with the balancing scan, we are pretty much doing the same thing. The big difference is that we are using some math to balance our reading now. Basically we are altering our reading based on the maximum and minimum possible readings, and making it a value we can use, namely between 0-255(roughly). Which gives us a pretty fair representation of the colour.
After that, we simply set the colour. We need to just tweek the numbers a little, because often the math above returns greater than or less than our acceptable values. Then we set the red green and blue variables and use the Moodlamp library to facilitate displaying the colour.
I almost forgot to mention the getReading function, which just gets an average reading for times number of readings. Not strickly necessary, as one reading seems sufficient, but I did not know that at the time.
The two print functions are for debugging purposes, and simply print our readings to the serial port. Yes I know I call one in the loop, but you don't have to. I just like scrolling numbers sometimes. Plus I was outputting it to processing during testing, to see exactly what colour the sensor is seeing. I will try to find the time to document and upload that sketch in the near future, but for now you are on your own. (Not hard if you are familiar with Processing and serial communication)
Once you have finished writing your code, upload it to the lamp and start playing. By playing I mean testing....but in a fun way.
Step 7: Ecetera
It will pulse red (to warn white scan is coming) then white, then stay white for two seconds, and then scan. You need to have your white sample under it.
Then it will pulse blue. Change your sample for black before it scans again (about three seconds).
Now, I say black, but this is where having prepared a couple of samples of greys will help. You will need to use a grey for this lamp application, the reason being is that dark colours are hard to make with a light.
This means that you will have to test your lamp by resetting it and trying different greys until you are happy. I am pleased with the results when using a dark middle grey, but much will depend on your lamp construction, your shrouding and your diffuser.
That being said, black will give the best actual real colour return value (the truest when you try the values via a monitor), if you are planning to use the sensor for a different application.
I hope you enjoyed this Instructable. Please give me some feedback, and post your projects if you used this as a starting point or inspiration.
Vote for me, follow me and all that good shameless stuff. I like prizes, I love feedback.
Share and enjoy.