Introduction: Magical Colour Copying Chameleon Lamp

Picture of Magical Colour Copying Chameleon Lamp

In this Instructable, I will show you how to make an Arduino powered lamp that detects the colour under it and then attempts to emulate that colour. All using easy to find parts (most can be found in the Dollar store with the exception of the Arduino of course).

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

To build the colour detection module you will need
  • 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)
Tools that you will need
  • soldering iron
  • glue gun
  • x-acto knife
  • tape
  • white glue
  • paint brush
  • imagination
I decided to leave mine tethered to my computer for power, but you may want to add an on/off switch, and batteries.

Step 2: Random Thoughts

Picture of Random Thoughts

Some of you might be wondering how a CdS photocell can detect colours. Well it is surprisingly simple and provides pretty accurate results.

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

Picture of Build the Colour Sensor

I like to build things in modules and use headers and jumpers to connect them, but it is not strictly necessary. I may want/need this thing again, so I built the sensor as a separate module.

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

Picture of Build the Colour Emulator

The colour emulator is a run of the mill RGB lamp or Mood light. Attach a red LED with a 330 ohm resistor to pin 9 on the Arduino, A green LED/resistor combo to pin 10, and a blue one to pin 11.

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

Picture of Closure

Now it is time to load the whole thing into the enclosure. I used a tomato preserving container that I found at the Dollar store. Everything fit nicely inside and it had a decent shape, and I thought it would made a good diffuser.

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

Picture of The Genie in the Lamp

Okay, there is no magic genie, but it is finally, time to get to coding the Arduino, playing with your new sensor, and enjoying all the benefits that come along with having a lamp so discreet that it tries to blend in with its surroundings..
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

Picture of Ecetera

When you power up your programmed lamp, it will immediately go into setup mode where it will perform the white/black balancing scans.

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.


dhvinay (author)2016-09-22

Hey.. great ible.. I went thorough your ible for detecting colours too.. But I still have a basic question- why do you use leds to provide light which then reflects from the surface (to be colour sensed)?

While writing this question I'm guessing it is to increase the dimensions or channels from 1 to 3. But can you please elaborate a bit on it (if it is correct)
Sorry if it is already answered, but the science kept bothering me.

ArifSae (author)2016-02-26

a lovely and unique Project. thumbsup

ChitreshS (author)2015-09-27

what shall be the cost of the same?

tofutofu (author)2015-06-24

I love this instructable!!! Enjoying it so much:D
This was my first project with arduino and all the prototyping boards and things.

I was stuck for quite a long time in installing the libraries.

users/documnts/arduino/libraries/moodlamp(I made it)/moodlamp.cpp and moodlamp.h(from the "rgb lamp with custom moodlamp")

I did this and tried compiling chameleon.txt, got a lot of errors that said something like

Wprogram.h is not found

lamp is not declared in this scope


what I did was

1, install the arduino ver22 and use that one instead of the newest release(Thanks to the other comentor!)

2, changed "Wprogram.h" to "Arduino.h" in the cpp and .h

and it finally worked!!!;-D yayyy

now I`m going to get working with the hardware part.

looking so much forward!

thanx again for the awesome project!!!

Ploopy (author)2015-06-13


LiveCrafts (author)2015-05-27

Sooo coool. I've seen products like this on Vat19. This is cool how you made one!!

Star1buck (author)2015-03-17

I finished the project and have a few suggestions. The drawing shows the use of Analog pin 2 while the program calls for using Analog pin 0. Also, I was unable to get usable readings using a 100K resistor with the photocell. I reduced it to 6.2K and it now works well. Thanks for your project !

mahi_thati (author)2015-02-06

how do you managed to distinguish the ranges exactly for different color?

VladimirM (author)2014-09-06

This is coolest applied-color-theory
I've ever seen.

Kudos to you sir, this good work! :)

e2748028 (author)2013-05-09

i am not able to calibrate the sensor. please help!

mooner77 (author)2012-03-29

could you guys please help me make a diagram for a RGB LED.

fjordcarver (author)mooner772012-03-29

hope this helps

lioncour (author)2012-02-23

Hi. I got some trouble.

I put the .ccp and .h files in libreary/moodlamp.
I got no skteches folder.
Using IDE 0022

when i try to compile the library i get this error.

sketch_feb23a.cpp:1:22: error: moodlamp.h: No such file or directory

Any idea what i am doing wrong?

aemery1 (author)2012-01-22

How would you do this using a common anode rgb.
would it be okay to use one resistor on the anode?

fjordcarver (author)aemery12012-01-23

no, you would use one resistor on each cathode, and your code would be different as well. The leds will light when pins go low as opposed to high.

fjordcarver (author)2011-12-26

As I already replied. You have left a comment uncommented. Just putt // in front of the line that is a comment and not code that reads" pulse white".

fjordcarver (author)fjordcarver2011-12-27

like this
//pulse white
would it be too much to ask that you remove the over zealous post (the one above where you have posted the entire sketch)? It sure takes up a lot of room for something that could have been posted with a single line. I don't think anyone needs the sketch with a typo in it. It is already included in the instructable.Thanks.

robot1398 (author)fjordcarver2011-12-27


robot1398 (author)2011-12-21

i am getting errors compiling the code

fjordcarver (author)robot13982011-12-21

Could you be more specific?

fjordcarver (author)fjordcarver2011-12-21

what does the error say?

robot1398 (author)fjordcarver2011-12-23

it says
"moodlamp does not name a type

fjordcarver (author)robot13982011-12-24

Sounds like you don't have the library or a typo in your code. Did you install the library?

robot1398 (author)fjordcarver2011-12-26

how do i do that??

fjordcarver (author)robot13982011-12-26

From step 6 - 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.
the information that you want is on step 3.
If you are using Arduino 1.0, there is a potential issue with the library which I will address soon(a little busy with Holiday celebrations still). See the post in the comments here for some additional info.

robot1398 (author)fjordcarver2011-12-26

downloaded the libarary successfully
it gives another error "pulse not defined in the scope" for the statement pulse whit

fjordcarver (author)robot13982011-12-26

could you show me the code as you have it in your sketch? it sounds as if you have a comment uncommented
meaning one of the lines of comment text is on a new line. putting a // in front of the text that is not code is important. either backspace the line feed that has been inadvertantly added, or add // in front of comment text that is on its own line.

foamyguy (author)2011-12-21

If you get an error message that says something about

"WProgram.h not found"

This seems to be a bug with the Arduino 1.0 IDE. Switch back to 22 or 23 and it should compile and run fine.

fjordcarver (author)foamyguy2011-12-21

Would this error be when compiling the moodlamp library? I have not seen that, but thanks for the tip.

foamyguy (author)fjordcarver2011-12-21

Im not really familiar with the Arduino IDE and programming with it yet. So I don't know for sure what part of the process caused it. But here is what happened:
1. create libraries folder in my sketch book folder
2. create Moodlamp folder inside libraries
3. paste the .cpp and .h files into Moodlamp folder (you should consider attaching these files to this instructable too. I eventually found them on the other one that you link to, but it threw me off for a while.)
4. paste the code into arduino IDE
5. press the upload button - at this point there was an error that said something about WProgram.h not found.

When I switch to IDE 0022 and repeat these steps everything works as expected.

fjordcarver (author)foamyguy2011-12-21

I think if you comment out the #include at the top of the .cpp file, it may work in 1.0...maybe, let me know if you try

fjordcarver (author)foamyguy2011-12-21

Thank you for the awesome feedback. I have not had this error, so I looked it up, it appears that after 1.0 the filename WProgram.h was changed. Your work around appears to be the best method at a glance so thank you for sharing. I have not had the time to delve deeper, but will certainly look and will update the step to reflect your solution as well.
I also appreciate you pointing out that I should include the files, I will fix that later as well. I am a newer author here, and really appreciate knowing what people want/expect.
If you got everything working I'd love to have a picture posted, it'd be my first.

I sent you a private message.;) Thanks for being Awesome!!

LexanPanda (author)2011-12-11

This is a great instructable, and really well done! Am I correct in assuming you got the idea from ThinkGeek's Huey? :)

fjordcarver (author)LexanPanda2011-12-11

Actually no,(believe it or not) but I found out about Huey while I was finishing it up. I was bummed, but I googled Chameleon Lamp to make sure it was the only one (nothing ever is) and found Huey. Huey is cuter, but mine is better. Lol. Actually I like that Huey writes to his eeprom to store his balance scan, I should have done that too. Then you only set the lamp one time. I need to set mine every time I turn it on.

LexanPanda (author)fjordcarver2011-12-11

Yep, custom made is always better than store-bought(and usually cheaper, too). How hard do you think it would be to update your code to store balancing data?

I'll see if I can't build a chameleon lamp myself, and post my result here. Wish me luck!

fjordcarver (author)LexanPanda2011-12-11

It would not be too hard, a couple of lines, but I probably won't get around too it. For myself, the thrill of seeing an idea work is all that I am after. I will leave the better version for the next person to build.
If you like. build yours, post it, and I will help you (if you need it) to add the functionality to yours. All you would need to do is write the array to eeprom when you take it and add a bit of code to the checkBalance function to verify if the eeprom is storing any value. You could also just check if it is there in setup.

janw (author)2011-12-09

Great project. I will definately try to buid such a colorsensor.

definately worth 5 stars

fjordcarver (author)janw2011-12-09

Thanks!! Post a picture if you do!

matt.e.jenkins (author)2011-12-08

You have some very cool projects and I'm jealous because I'm in the same contests. Great Job. I'm going to have to build one of these.

Thanks, quite the compliment. You could always vote for me.
Your projects are awesome too.
I just wrote a new one detailing just the sensor aspect on a breadboard, I included Processing code that lets you see what colour the sensor sees, it might be of interest to you. 

adar1 (author)fjordcarver2011-12-08

Hey, in that picture I can see you wrote digital and analog can you explain how this system work of this chameleon lamp works, please!!!

fjordcarver (author)adar12011-12-08

I am not sure what it is that you are missing. Sometimes it is difficult to understand what somebody is having trouble with, so try and be as clear as possible in your questions.
Digital and Analog pins correspond to pins on the Arduino. The Arduino is a microcontroller and is doing the 'Thinking'.
Most sensors have outputs that in turn connect to inputs somewhere when in use. In this case I am connecting the sensor to an Arduino which in turn is interpreting the data it is recieving. (The output connects to an analog pin as it is outputting an analog voltage)
The LEDs are connected to pins on the Arduino as well, digital pins, which in this case (see the code) are setup as outputs. This allows you to turn the lights on and off.
This information is all in the Instructable, so please try reading it again.

adar1 (author)2011-12-08

Hey, can you give me more technical details on how the circuit and the system works of the chameleon lamp!!! I think you you made a cool lamp and I am going to try this out!!!! thanks you!!!!

fjordcarver (author)adar12011-12-08

Thanks for the compliment
Step 2, has the details on how it works, Steps 3 and 4 detail the circuit, and the code is on step 6. You will have to be more specific as I am not sure what information you are missing.
If you would like to see the sensor simplified and taken out of the lamp you can read my other Instructable, Using an RGB LED to Detect Colours.

adar1 (author)fjordcarver2011-12-08


amaze1 (author)2011-12-07

Very COOL !!!
One of the smartest led color "change" application ever seen, I'll made one for sure. Great !

fjordcarver (author)amaze12011-12-07

Thanks so much! Be sure to post a picture when you finish!

fjordcarver (author)2011-12-06

No Problem! Glad you enjoyed it.

skumdog (author)2011-12-06

Very nice. I hope I learn to write code like you one day. I am just starting with Arduino and it can be very confusing, to the beginner, at times. Thanks for this great instructable.

nanoBorg88 (author)2011-11-27

Nice instructable, there was a recent instructable on change-of-tilt sensor that may be a nice addition to this when deciding when to chose new colours.
When the input to another pin on your arduino is kept constant, i.e the mood sensor is stationary, it would then search for the colour.
Is the white and black readings require for every time you choose a colour?

The other instructable is here:

About This Instructable




Bio: Dad, maker, dreamer, hacker, painter.
More by fjordcarver:Make A 2D Video Game with UnityAcoustic/Electric Cookie Tin UnitarMake a Keepsake Book of your Child's Artwork
Add instructable to: