Skip to main content
Everybody needs a little color in their life! This color changer mixes light from high-power LEDs to create more than 16 million colors. A smooth auto-fader cycles the colors, or you can hook it up to a USB port and control it from your computer.

A great toy for architectural lighting, parties, and holidays. Since the circuit will run from 12 volts, it can even be installed in a car.

Learn how to build your own, after the fold.

USB color changer(click thumbnails to view gallery)

Color changing light and nixie tubesUSB color changer and LED lightsUsing the USB color changer

All the files for this project are included in a .zip archive, you can download it here.

This color changer borrows a well-known color model used in TVs and LCD panels. These displays blend red, green, and blue light to create a vast number of colors. Look closely at your monitor -- this image of the DIY Life site is made of tiny red, green, and blue dots. We'll mimic this technique by mixing light from red, green, and blue LEDs.

The easiest way to dim LEDs is to blink them and vary the ratio of on and off time. If the LED blinks fast enough, we perceive it as a solid light of lower intensity. This method of dimming is known as pulse-width modulation (PWM). The figure below shows a single period in a pulse-width modulation cycle. At the start of the period, the signal is high (the LED is on) for the time defined as the duty cycle. When the duty cycle is finished, the signal goes low (the LED is off) for the remainder of the period. Adjusting the duty cycle varies the brightness of the LED. By extending this to red, green, and blue channels, we can mix a nearly infinite number of colors.

We'll need some red, green, and blue LEDs to use with the fader. A possible way to group a bunch of LEDs is a small, round light board. This board is based on a design by Big Clive, but I've fattened the traces and changed the routing to make the board a easier to etch and solder. See Big Clive for his version. My design is part of the si-light project.

USB color changer overview(click thumbnails to view gallery)

Pulse-Width Modulation FigureLED circuits and resistorsLED fixture PCBLED light fixture

Hardware design
I chose the Microchip PIC 18F2550 as the microcontroller for this project (IC1). It has a full-speed USB connection and a free firmware framework for a generic serial port to USB emulator. It's got a ton of program space for fancy, stand-alone fading programs. As far as support gear goes, we need a 0.1uF capacitor between the power and ground pins (C6), and a resistor and diode are needed for the ICSP programming header (R7,D1). The on-chip USB peripheral requires an additional two 0.1uF capacitors (C7,8) and a 20 MHz crystal (Q1)-- don't forget two 27pF caps for the crystal (C1,2). Crystals vary, but 27pF capacitors usually work.

The device should continue to run a nice color fading program when the USB isn't connected. This type of USB device is 'self powered' -- it has an external power source and runs independently of the USB connection. This setup requires one microcontroller pin to monitor the power line of the USB cable. When a cable is attached, the PIC senses a voltage and opens the USB connection. The USB power line is connected to the PIC through two small resistors (R8,9), in order to cut down on noise and protect the chip. I used 100K ohm and 10K ohm resistors, but any close values should work fine.

The PIC has two hardware PWMs that could be used to fade LEDs, but we need a total of three channels -- one each for red, green, and blue. We could use a hardware device, but with so much power in the PIC we can do it in software without the added expense.

A microcontroller pin is unable to power more than a few LEDs directly. Instead, the PIC will switch the LEDs with a transistor or MOSFET (Q2,3,4). This diagram shows a simple LED circuit, and switching circuits that use a FET and transistor.

I used an IRLZ44 MOSFET, but there are many options. You should choose a FET that switches completely at 5 volts or less. The data sheet usually has a graph of operation over a range of switching voltages (Vgs). A FET with a minimum gate voltage of 12 volts will never turn on when switched by the PIC running at 5 volts.

You can also use a transistor to switch the LEDs.A transistor requires an extra current-limiting resistor (R4 in the figure above), whereas a FET doesn't. FETs are preferable, but we'll put a spot for resistors on the circuit board, just in case (R3,4,5). Those of us with FETs will jumper over those dirty resistor holes. Transistor people, use a 1K resistor here.

The PIC has a serial port (USART) that requires no additional hardware. This is exposed on the pins so that the device can also take serial commands from a PC or another microcontroller.

Three small LEDs show power, USB, and serial status. Note that the LEDs are the small 3mm variety, not the more common 5mm variety. The circuit runs at 5 volts, so a 330 ohm resistor will suffice for the LEDs (R1,2,6).

This circuit requires two power supplies, one for the microcontroller and one for the LEDs. The microcontroller runs at 5 volts, which is provided by a common 7805 regulator (IC2). The 7805 needs a 0.1uF decoupling capacitor between each power pin and ground (C9,10). Make sure that the capacitors on the supply side of the 7805 (C9) are rated for double your intended supply voltage -- I used an 18 volt wall wart and capacitors rated for 50 volts. The TO220-size part (IC2) is usually good for 1-1.5 amps. This is overkill! Only a few hundred milliamps are used, but smaller regulators don't leave any room for expansion and get uncomfortably hot when the supply voltage is high.

The example light board uses two strings of two green and blue LEDs, and one string of four red LEDs. The red string requires 10 volts, and the green and blue strings need 6.6 volts. A 12-volt supply is perfect for this circuit, with a 220 ohm resistor on the red string and a 270 ohm resistor on the green and blue strings. The 12-volt supply is provided by a 7812 (IC3).Many voltages will work, just calculate the correct LED resistor. Make sure that the 0.1uF decoupling caps (C3,4) and supply filter capacitor (C5) are rated at least double your intended operating voltage.

Download a full-sized image of the schematic.

USB color changer circuit(click thumbnails to view gallery)

LED switching circuitUSB color changer circuit

PCB layout
The circuit and PCB are made using Cadsoft's Eagle Layout Editor. A freeware version of Eagle is available for download. This is my first project for DIY Life, so I decided to do an all through-hole design. Most unused pins are routed to headers for maximum expansion possibilities.

There are two jumper wires on the board. The jumper from the LED voltage supply regulator to the connector wouldn't route well on single-sided board. This will be an ugly jumper if you make a single-sided board, like I did. Another jumper connects the USB power line to a PIC pin.

There are additional vias on the ground plane near the MOSFETS. If you plan to connect a bunch of LEDs, solder some wires here to reinforce the ground plane. These vias could also connect to a thick ground plane on the top layer of a two-sided board. If you connect a LOT of LEDs, move the FETs to a separate board and add heat sinks.

Parts list
  • C1,2 - 27pf
  • C3,4,6,7,8,9,10 - 0.1uf/50V
  • C5,11 - 22uF/50V
  • D1 - 1N4148
  • IC1 - PIC18F2550 28DIP + 28 pin DIP socket
  • IC2 - 7805TTO220H
  • IC3 - 7812TTO220H
  • SERIAL - strip of 4 pin header
  • ICSP. PORTA - strip of 5 pin header
  • LED1,2,3 -LED 3MM
  • Q1 - 20MhzcrystalHC49U-V
  • Q2,3,4 - IRLZ44 MOSFETTO220BV
  • R1,2,6 - 330R (330 ohms)0.25 watt
  • R3,4,5 - 1K (1000 ohms) 0.25 watt
  • R7 - 10K (10,000 ohms) 0.25 watt
  • R9 - 100K (100,000 ohms) 0.25 watt
  • USB- Female, B style USB Connector, PCB mount
  • X1,3,4- screw clamp (2 sockets per block)

USB color changer PCB(click thumbnails to view gallery)

Circuit board layoutCircuit board layoutCircuit board layoutCircuit board layoutRendering of the USB color changer

The firmware is compiled in Microchip's MPLAB with the PIC C18 compiler. MPLAB is free, you can grab it here. Evaluation and free student editions of the C18 compiler are available for download here. A compiled .hex file, ready to program to a PIC, is included in the project archive. If you want to compile the project yourself, see the instructions at the end of this article.

Software Pulse-Width Modulator
The software-based pulse-width modulator creates a dimming effect by blinking LEDs very quickly. The PWM has a period (total time) and a duty cycle (the 'on' time). Each period of the pulse-width modulator is broken up into 255 time segments of equal length. These 'slices' are tracked with a one-byte counter, which conveniently counts to 255 and resets to 0. At the beginning of slice 0, all LEDs are on. At the beginning of each time slice, we check the desired light intensity settings against the counter value. If the counter is equal to the intensity level, then the LED is turned off. For example, if we want 50% blue (126 parts of 255) and the counter hits 126, the blue LED is switched off. This comprises the duty cycle. The actual switching is done on a buffer in memory, and then placed on all output pins at once. This ensures that channels set to 0 are always off, and that all switching happens simultaneously.

Why all this 255 stuff? A byte in a microcontroller is capable of storing a number from 0-255 (256 levels). We track the time slices with a byte and store the desired intensity levels for each channel (RGB) in a byte. Thus each color channel has 255 possible intensity levels.This is a well-established color storage method known as 24-bit color. You might recognize this if you've worked with web page colors or a photo-editing program. 255 brightness levels per color yields 16.7 million color combinations! We could expand everything to be 10, 12, or even 16 bits, giving about 65 thousand intensity levels per channel. This is silly, though, because 16.7 million colors are far more than the human eye can perceive. Using a 24-bit color representation also maintains compatibility with common color picker color codes used by computers.

The PWM code is time-sensitive. If a cycle is missed, the color-mixing effect will be ruined. We can achieve this exact scheduling with a hardware timer and alarm. The timer is set at the beginning of each time slice. When the alarm sounds, the PIC immediately stops whatever it's doing and processes the PWM code. On a computer or microcontroller this alarm is called an interrupt.

Although the software-based PWM has priority, it can interrupt time-sensitive USB activities. It's important that the code for processing the interrupt is as short as possible, and the time between interrupts be as long as possible, in order to prevent flaky USB connections. The microcontroller is running at 12 million instructions per second, on a 48 Mhz clock, so we have a lot of processing power to work with. I could have done some calculations to find a good setting for the timer, but I just adjusted it until it looked right.

The PWM code is fairly easy to use and is well-documented in the source (see user.c). The desired brightness setting is put into the SoftPWM.R/G/B variables. The soft PWM is double-buffered -- this means that the new values are not directly used. Instead, we set an update flag (SoftPWM.UPDATE) and then the new values are copied into the working variables on the next interrupt. Double-buffering prevents erratic behavior (such as irregular flashing) if an interrupt occurs while the auto-fader is in the middle of changing colors.

The auto-fader program runs when there is no USB connection. It cycles between a pallet of colors stored in an array. This simple fader has lots of room for improvement. You can add pallets or change the pallet. It was ported from BASIC source code used in the si-light project.

USB interface
When a USB connection is enumerated, the auto-fader stops and the device waits for commands from the PC. The protocol for setting the color is quite simple: values for red, green, and blue channels are sent, separated by a space, and followed by a full newline (CR+LF, 0x0D 0x0A).

Set all colors to 100%
  • 255 255 255
Set all colors to 0%
  • 0 0 0
Set to a color (e.g., purple)
  • 255 0 255

We're sending ASCII values to the virtual serial port, not a true byte value. Rather than sending the value "255", we send the ASCII sequence "0x32,0x35,0x35". This means we can input values using a terminal program, but each sequence needs to be converted to an actual byte-based decimal value on the PIC. Refer to the source code to see exactly how this is done. When a full command sequence is successfully received, ASCII 0 (0x30) is sent on a new line.

All low-level USB operations are handled by the Microchip Full Speed USB Firmware, which makes USB development much easier. See the USB specification and Microchips framework documentation [pdf] for further info.

Microchip offers both a Human Interface Device (HID) firmware and a communications device class (virtual serial port, or CDC) firmware. Both are generic protocols, already supported by many operating systems (including MS Windows). The HID driver is used in devices like keyboards, mice, and joysticks, where data primarily flows from device to computer. We want to send data from the computer to the device, so the CDC driver is a better choice. A CDC device appears as an additional serial port on your computer. Any program that works with a serial port can send color data to the device. The software will never know that it's talking through USB instead of an old serial cable.

Programming the PIC

See how I program the PIC, and build your own programmer, in my PIC programming tutorial.

The PIC is a through-hole (DIP) chip, so it's possible to program it in a socketed programmer. All of the pins needed to program the PIC are brought to a header, so in-circuit programming and debugging (ICSP) is also possible. To learn more about programming a PIC, read some of the PIC programming tutorials linked at the end of this project.

Connecting to a PC
Warning -- you are about to connect something you cooked up in your shed to a delicate PC with lots of data... are you sure you want to do this? Use a junk computer or a USB hub with galvanic isolation.

Windows Connection Procedure
  1. Connect the color changer to a power supply before connecting it to a PC. The circuit is not designed to draw power from the USB port.
  2. The auto-fader will start when the device powers up.
  3. Plug in the USB cable.
  4. Windows will prompt you for a driver file. You don't really need a driver, just a file that associates the device with a driver that's already part of Windows. Microchip provides this as part of the USB framework; it's in the project archive or you can download it here. Navigate to the location of mchpcdc.inf and choose it as the driver, click OK.
  5. Windows will recognize the device and add it as a serial port to your computer.
  6. To see the device's assigned port, go to the windows control panel, click the system icon, choose the hardware tab, click device manager. Expand the "port" listing and verify that you have a new COM port. Note the COM port number, because you will use it in the terminal test.

Testing the USB connection
Using a simple terminal program to send a few settings to the device is an easy way to test the USB connection. Windows Hyperterminal will work in a pinch. The project archive contains a saved Hyperterminal session so you don't have to do all the steps below-- just double-click to load Hyperterminal with the correct settings. You still need to go to File->Properties and change the "Connect to" port to the proper setting for your computer.
  1. Open Windows Hyperterminal, usually found in the "Communications" folder (part of the default Windows install).
  2. Create a new connection-- Hyperterminal may prompt you for a new name.
  3. After naming the connection you will be prompted for connection details. Change the "Connect Using" drop-down to the new COM port that was added when you connected the device. Click OK.
  4. Next, enter the port settings. You can choose any speed, and the USB driver will sort everything out in the background. Change "Flow Control" to none. Click OK.
  5. Next, configure the correct newline characters. Go to Files->Properties. Click the "Settings" tab. Click "ASCII setup". Tick the top two boxes: "Send line ends with line feeds" enables a proper newline, and "Echo typed characters locally" lets you see what you're typing as you type it. Click OK and then click OK again.
Now, send some light intensity commands to the device. Enter intensity levels for red, green, and blue as ASCII characters and finish by pressing Enter. To set all the LEDs to full, type:
  • 255 255 255
and press Enter. All outputs should go to 100% and the device will respond with '0' on a new line.

Next, turn all the lights off. Type:
  • 0 0 0
and press Enter. All outputs should go to 0 volts. The device will again respond with '0' on a new line.

Finally, disconnect the USB cable. The auto-fader program will resume.

USB color changer(click thumbnails to view gallery)

Color changing light and nixie tubesUSB color changer and LED lightsUsing the USB color changer

Compile procedure
So you want to fidget with the code? Here's the deal--

The Microchip USB driver comes as an install package. Its not easy to transfer an existing project to your computer and get it working correctly. This is the absolute best method I've found to get the source up and running. Its seems involved, but it actually takes less than 60 seconds.

Software you'll need
MPLAB (I used 8.01) (installed).
PIC C18 Compiler (I used 3.15) (installed).
Microchip USB source code install package (this project based on version 1.2).
The replacement files included in the project archive. These are already in the proper directories so they can be copied over the Microchip USB source.

Install the framework
  1. Install the Microchip USB source code (version 1.2).
  2. Open the replacement file archive and extract the directories over the Microchip USB source code. The directory structure is contained in the archive so that all the files go to the proper place. If Windows prompts, choose 'yes' to overwrite the existing files. If you'd like to copy the files by hand, these are the files that you need to replace:
  • MCHPFSUSB\fw\Cdc\18f2550(i).lkr
    • Linker files for the 18f2550, use the 'I' version when using a debugging tool like the ICD2.
  • MCHPFSUSB\fw\Cdc\io_cfg.h
    • Modifications: Set custom USB sense PIN, LED PINS.
  • MCHPFSUSB\fw\Cdc\autofiles\usbcfg.h
    • Modifications: Disabled USB power mode, enabled self power mode.
  • MCHPFSUSB\fw\Cdc\system\usb\usbdrv\usbdrv.c
    • Modifications: Disable sleep mode on USB disconnect.
  • MCHPFSUSB\fw\Cdc\user\user.c
    • Modifications: Software PWM, color auto-fader,USB interface.
Update the project settings
  1. Open the MPLAB Workspace file installed with the USB source code (MCHPFSUSB.mcw).
  2. Find the Project window in MPLAB -- it should say MCHPFSUSB.mcw at the top and contain a list of files. Remove the unnecessary file 'temperature.c' from the source files list, it will cause a compile error.
  3. Now scroll down past header files to the linker script folder. Remove the linker script for the 18F4550 (right click, remove). Replace it with the 18F2550 version included in the replacement files (right click, add).
  4. Now update the device used in the project. From the MPLAB top menu select Configure->Select device. In the device menu choose the 18F2550. Click OK and you're done.

Taking it further...
This design leaves plenty of room for new functionality to be added through firmware upgrades, or by adding new hardware to the various headers. A fader program with multiple color pallets and buttons for speed/pallet selection is an obvious upgrade. The serial port is exposed, but unimplemented -- with this port the board can communicate with another microcontroller or a PC serial port. Analog-to-digital converters on the upper pins of PORTA are exposed on a header -- these can measure the output of a preamplified microphone for beat detection based color mixing.

Have fun mixing colors, and stay safe.

New to electronics? Here are some introductory tutorials to help you get started.

Eagle CAD tutorials
Draw Circuits with Eagle
Turn your Eagle Schematic into a PCB
Eagle Design Rules
Create a Custom Parts Library

Make circuit boards
Toner Transfer
Professionally, online

Soldering Tutorials
How to Solder
Sparkfun Soldering Basics

Microchip's PIC microcontroller
Microchip Website
PIC In-Circuit Serial Programming
The original JDM2 Programmer
Business Card PIC Programmer
Multi-Socket PIC Programmer
USB PIC Programmer

  • Alan Parekh

    Nice job! Well documented.

  • Grant Robertson


    Nicely done. Great video, too.

  • james burney

    A great site.

  • 8Way

    Nice design. I wonder if you get subtle flickers when updating the PWM values. I've found in my designs on the 14bit pics, that I have to update the PWM when my " 1 byte cycle counter" wraps to zero rather than immediately. You are clocking at a higher clock rate (I use 4-8mhz internal clocks with up to 10 PWM channels), so your design may not be so sensitive.

    Recently, i've given up on the PIC and it's goofy architecture and moved to the Cypress PSOC parts. They are really neat with dedicated digital and analog blocks. You can set up up to 16 PWM (actually I use pseudo random bit sequences, which have less flicker) outputs, and the C compiler is really reliable vs the buggy stuff i've experienced w/ the pic (though the PSOC compiler generates crap code). The PSOC has it's own shortcomings, such as a really inefficient CPU, but the digital and analog blocks more than make up for it b/c stuff is done in HW vs SW. PSOC is really fun, esp when u wrap your head around it's way of doing things.

  • Ian

    Thanks 8 way...

    I did have a problem with flicker, but it happened because I didn't double buffer the software PWM registers on the first code revision. This was around Christmas time and I had the lights installed in a tree. Every so often I noticed a flicker out of the corner of my eye. The high clock speed really helps too. If the CPU was slowed down by a few factors, all sorts of little bugs would probably be noticeable.

    Thanks for the tip on the Cypress parts. I've not used it yet, but I'll check it out soon. Eventually, I hope we have articles that cover many uCs --PIC, AVR, MSP430, ARM, etc.

  • Per Jensen

    Where is the schematic ?

    The schematic images you're showing ( ) is unreadable!

    I want to make this on a piece of perfboard, so the schematic would be nice.

    Regards, Per!

  • Ian

    The circuit and PCB are included in the project archive in the Cadsoft Eagle format. Eagle is a free download from the

    There are some limitations of the blogging software that prevent me from posting a full sized image -- I'll be sure and post one to Flickr or include it in the project archive next time. I can add a link to a full sized version if Eagle doesn't work out for you.

    Let me know how your color changer turns out.


  • Ian

    I uploaded a full-sized PNG image of the schematic. You can download it here:

    Thanks for letting me know about this. I'll be sure there is a full sized schematic image available for download in the future.

  • Per Jensen

    Hi Ian.

    I Tried importing the board into Eagle (both windows and OS X) and i'm missing the copper "fill" on the board, is there any way to switch it on ?

    Btw. to other readers - the software for the PIC works with Mac OS X (Yay!)

    // Per.

  • ian

    Hi Per Jensen,

    There is a button in the Eagle tool bar that activates the fill layer. It has to be done every time Eagle is started -- it makes the traces easier to see, I guess. It looks like an "X" with green balls on the ends.


  • Mike Jones

    Hi Ian,

    Cheeky request, but any chance of you building me a couple of these?? All costs will be covered by me of course, plus extra for your time.. Tried in vain to find your e-mail, probably not looking hard enough.


  • Fallentemplar

    The USB control works through hyperterminal for me, but are there any ohter ways to control it? I tired the .NET package to control the lights, it sees the COM port and succeedes on sending data to it, but the controller does not respond at all (no light change anything) just wondering if you could direct me on how to make this controable from a custom program.


  • Lawrence

    Hi! Awesome stuff here - is there somewhere I can learn what all this means? I just want to play around with maybe turning a LED on or off via USB, that's it. I have no experience though, and your tutorial is wayy to advanced for me :)


  • turbatus

    Hi there! Nice "thingy"! I programmed the .hex file and worked straight away! When I tried to play with the source files I'm getting an error: Include file user.h not found! Please tell me where can I get this file? I downloaded the whole .zip file, but I can't find it. Thanx

  • c0ldfuse

    I'm going to dive into this as a first big project outside of simple circut work.

    I'm planning on setting up multiple light color lamps into globe-like balls which I'll hang across my ceiling and connect for wave color changes. Eventually I'd like to build in beat based color changes from my turntables to have the entire ceiling turn into a real life milkdrop visualization.

  • pameal

    Where can I buy something like this in the US? I'm opening a small restaurant and would love to use this effect on the open ceiling.


  • Farkas

    can you send me the source code in C for updatig a little for my needs.
    I want to use a 18f4455 pic. THX

  • Farkas

    what kind of software do you use.? this works under win 7 to??

  • utku

    hi !
    it's a fabulous work..
    I would like to control this color-changing lamp via my laptop. For ex; when i press button x, it should switch to red.. and so on.. Is it possible ?
    Thanks a lot..

  • Kevin Groce

    I would like one of the boards. Seems like a fun project.

  • 20 Comments / 1 Pages

Add Your Comments

  • New Users
  • Returning

If you are posting a comment for the first time, please enter your name and email address in the fields above. Your name will be displayed with your comment. Your email address will never be displayed.

Add Your Comment

Please keep your comments relevant to this blog entry. Email addresses are never displayed, but they are required to confirm your comments.

When you enter your name and email address, you'll be sent a link to confirm your comment, and a password. To leave another comment, just use that password.

To create a live link, simply type the URL (including http://) or email address and we will make it a live link for you. You can put up to 3 URLs in your comments. Line breaks and paragraphs are automatically converted — no need to use <p> or <br /> tags.


Follow Us

  • No features currently available.

  • More Hot Topics The Daily Fix  •  DIY Warrior  •  Home Ec  •  Handmade
    DIY Disaster Doctor  •  In the Workshop  •  Product Picks

    Home Improvement Videos