PIC16F628 4 RGB LED PWM Controller

I am a big fan of LEDs.  Bright, colorful, flashing LEDs.  So, given my affinity for LEDs, I decided to work on a controller that me and a few of my friends could use as an art project/passive information display.  I have posted videos from the first prototypes (here and here), but it has been tough to dedicate time to further development given my research, so I thought I would post the information so that anyone can take the design and modify it to their liking!

Some insipration came from the BlinkM “smart LED” and the ShiftBrite RGB LED Module, but I was interested in using RS232 serial control.  Therefore, I chose one of my favorite simple-to-use microcontrollers, the PIC16F628.  The advantages include the built-in 4MHz oscillator, hardware USART, and ease of reprogramming.  A couple of features I had in mind during the design:

  1. Multiple intensities for each color (using PWM)
  2. Multiple individually controllable RGB LEDs
  3. High-speed update rate
  4. Daisy-chainable and addressable
  5. Simple serial control

is the full schematic for the driver. I chose to use a PIC16F628 as the microcontroller because it is cheap, has a internal oscillator (4 MHz) and an internal USART. NOTE: There is an error in this schematic and a pull-up resistor on RA5 (pin 4 in the schematic) is necessary.  See the bottom of the post for an updated schematic and board.

I decided I would try getting a PCB printed for the first time, so I got boards created at BatchPCB.com for $5 each.  The total for 4 boards shipped was $32.36 (4 x $5 for the boards and $12.36 for shipping and handling).  They took a long time to arrive, but the quality was well worth the wait.  NOTE: There is an error on the first revision of the board and a pull-up resistor on RA5 (pin 4 in the schematic above) is necessary.  You can see how I compensated for the mistake in the second picture below (look on the back of the upper-left board).  This will be corrected in future revisions.  See the bottom of the post for an updated schematic and board.

Control Format
The current firmware has 8 commands (the 9th, self-test was removed to save space).  See the source code for the firmware for how the commands are implemented, but here is some example usage:

  • Turn off all LEDs: 0h2000FF
  • Make all LEDs full-intensity red: 0h2F00FF
  • Make all LEDs full-intensity red: 0h1F00F00F00F00FF
  • Make all LEDs at address 1 half-intensity green: 0h207001
  • Make LED 2 at address 1 half-intensity green: 0h100007000000001
  • Load start-up settings for all controllers: 0h40FF


  1. Update individual LEDs using 4-bit exponential update
    Byte 1, Nibble 1 = led1Red;   Byte 1, Nibble 2 = led1Green
    Byte 2, Nibble 1 = led1Blue;  Byte 2, Nibble 2 = led2Red
    Byte 3, Nibble 1 = led2Green; Byte 3, Nibble 2 = led2Blue
    Byte 4, Nibble 1 = led3Red;   Byte 4, Nibble 2 = led3Green
    Byte 5, Nibble 1 = led3Blue;  Byte 5, Nibble 2 = led4Red
    Byte 6, Nibble 1 = led4Green; Byte 6, Nibble 2 = led4Blue
    Byte 7 = theAddress
  2. Update all LEDs using 4-bit exponential update
    Byte 0, Nibble 2 = led1Red = led2Red = led3Red = led4Red
    Byte 1, Nibble 1 = led1Green = led2Green = led3Green = led4Green
    Byte 1, Nibble 2 = led1Blue = led2Blue = led3Blue = led4Blue
    Byte 2 = theAddress
  3. Save start-up settings
    Byte 1 = theAddress
  4. Load start-up settings
    Byte 1 = theAddress
  5. Get address
    Byte 1 = theAddress
  6. Set address (one-time set)
    Byte 1 = theAddress to save
    Byte 2 = theAddress
  7. Disabled in this release.
    Self test
    Byte 1 = theAddress
  8. Update individual LEDs using 6-bit update
    Byte 1 = led1Red;    Byte 2 = led1Green
    Byte 3 = led1Blue;   Byte 4 = led2Red
    Byte 5 = led2Green;  Byte 6 = led2Blue
    Byte 7 = led3Red;    Byte 8 = led3Green
    Byte 9 = led3Blue;   Byte 10 = led4Red
    Byte 11 = led4Green; Byte 12 = led4Blue
    Byte 13 = theAddress
  9. Update all LEDs using 6-bit update
    Byte 1 = led1Red = led2Red = led3Red = led4Red
    Byte 2 = led1Green = led2Green = led3Green = led4Green
    Byte 3 = led1Blue = led2Blue = led3Blue = led4Blue
    Byte 4 = theAddress

Source Code
The PIC16F628 needs to be programmed with the firmware below.  The Windows application is included as an example of how one could control a 2×2 array of the PIC16F628 4 RGB LED PWM Controller boards (4×4 LEDs).

The first couple of prototypes have worked well, but I am still working on refining the PCB, circuit, firmware, and software design.  Here are a few pictures of the boards:

Update (01/06/2008)
Here is an updated schematic and board with the corrected MCLR pullup:

27 Comments / Add your own comment below

  1. That’s cool and I guess almost everyone is fascinated by LED’s, I can even remember my first projects, they we’re all based on LED’s :)

  2. man you’re the boss
    your work is truly amazing
    and the LEDs ooooooh!!!!! the LEDs are beautiful.
    your work really inspired me
    Thanks for sharing

  3. Shouldnt disabling MCLR eliminate the need for the RA5 pullup!!!

  4. Hey, good work.
    Give a look at mine, very similar work, http://www.agilesystems.it/?p=56


  5. why the 4 elcos? i see only one on the pcb?

    and how far from each other can you connect the PCB and that it stil works?

    and on al other side i read that you always need a kristal if you use rs232? but this works good?

  6. Pingback: 4 RGB LED PWM Controller using PIC16F628 - Hacked Gadgets - DIY Tech Blog

  7. Pingback: 4 RGB LED PWM Controller using PIC16F628 | Gizmo Addiction

  8. Pingback: 4 LED RGB controller | Diy all the Way

  9. Pingback: 4 RGB LED PWM Controller using PIC16F628

  10. Pingback: 4 RGB LED PWM Controller using PIC16F628 | DoGizmo

  11. santiago acha


    what Eric Flynn Says is correct, you can use NOMCLR instead of MCLR and remove the resistor, but declare that pin as an output.

    the resistors that you are using, what values they have?

    you are using a pwm working at 61,03515625 hz, timer0 overflow at 256us, but using 18 bits color (64 it’s the maximum in the pwmcount), so you can’t use values higher than 64 (0x40), right? have you try it to make it work with higher values on pwmcount?

    very interesting project anyway!!!

    pd: my english is not perfect, i speak spanish 😉

  12. I am trying to do a project for myself where I can control three channels of led lights (red/green/blue) via RS232 serial control from my PC. There will be at least three of each colour led, probably each led will need 3v/18mA but each colour channel could be wired in series.

    I need to control the brightness of each colour channel and control on /off flashes of each colour via rs232 (but do not need to control each led individually at this time)

    Ideally I would also like to power it via 9v battery as well as giving a choice for a mains power adaptor

    Any idea whether this project will do this as not sure about controlling the individual led colour brightness? Would be interested to know whether the pic program can be altered to suit if not

    Thanks for your help


  13. The led colour brightness would quite a few levels of intensity, say 50-100 if possible

  14. Hi! I’ve tried to make a very similar project but I couldn’t succeed using internal RC with serial communication. It allways generated framing error. What do you think I might be missing?



  15. Hi! Great project and thanks for sharing it!
    I’m trying it out but I don’t know what fuses/config word to use, could you tell me? And is there a way to test if it is working?
    I have tried your program and changed com3 to com1 but It didn’t work, I’ll check the circuit again meanwhile :)

  16. Ok, got it all working :) com1 and theadress was set to zero.
    Time to learn how to send data to it! This is fun. Thanks!

  17. This is some great eye candy! Have you considered combining your multicolored jewel with some of these low-cost RF receivers?: http://www.futurlec.com/Radio.shtml $6 for a receiver or $7 for a transceiver. I’m going to have to peak at your code and see how the timing works out for 12 pwm channels on a single chip! Nice work!

  18. I have build it too, and it works…. I give them a adress with a terminal porgram….

    but if i let the visual basic program run for a long time… after a while one by one they stop with working…. … is see the rs232 still sending data too the PCB, but the don’t respons anymore….

    do somebody know why? a bug in the program?

    the only to start them again, is stop the movie, turn of the power for al the pcbs,and turn the power back on, start the movie again…. and than it works for a hour…or something

    Help somebody…

  19. for the record, i was thinking about Connection Cloud today and was wishing that it was still up somewhere, and that led to wondering if maybe it was in a different form which led to a search which then led to finding your blog. I’m sad that cc isn’t still up, but that’s life, and at least it let me discover the stuff that you’re doing now with the LEDs and such which is awesome. A while back i did a collaborative project with a friend that knows much more about microcontrollers than i do build the hardware/circuit board to interface with a program called Max/MSP which allowed for infrared sensors to control music and video &c, and it’s always good to see projects like that crop up in other places and in unique ways. keep up the good work.

  20. Hello, I’ve been looking on the net and I have a somewhat self-ish question.
    I saw the pic of the printed board layout, are you allowing people to have the circuit design you created copied for personal use?
    Also, have you considered expanding the circuit to do something like PC control via usb?
    (Just curious)

  21. Pingback: semifluid.com » Blog Archive » 4 RGB LED Controller Update

  22. Your demo program? is that using commando 1? or 8?

  23. wow , good for you. i’m just started to learn 89c51 micro controller and when i see this ,i say to myself you can’t Never done .

  24. I am working with a friend to write a driver interface for our Christmas Lighting program called Vixen to run these. However, I do not see a whole lot on how to set them up. Especially getting the address set and how to send the different commands.

    Can I get some more details on that please?

  25. Pingback: semifluid.com » Blog Archive » 8×8 RGB LED Display

  26. RA5 is not the same as MCLR on those parts. RA5 is a regular I/O pin, except that the output driver is open-drain. I was bitten by the same RA5 problem with the 16F627A a few years back.

  27. Hi ,We can use this project to video screen or RGB display.Thanks

Leave a Reply