Simple PWM control for LED strip

I have been playing around with building a lamp for my desk using a LED strip and constant current driver that I bought from Deal Extreme a while ago combined with a PIC12f683 to provide variable brightness via Pulse Width Modulation (PWM).

The demo using a plain old green LED as the output.

[UPDATE OCT 20 2010] I’ve updated the firmware for this project to include new features. More info and firmware download here.

What I need is a desk lamp that can work in various different situations.

  1. As a normal desk lamp during the evenings for reading etc.
  2. As a late night gaming light providing the most minimal illumination necessary to be able to see the keyboard whilst playing games late into the early hours of the morning.
  3. As an inspection lamp giving strong and diffuse illumination when fiddling with tiny electronics stuff.

So I decided to create a simple circuit using the PWM output from a PIC12f683 as a dimmer sitting between the constant current driver and the LED strip to allow me to choose the amount of light I need.  For more information about PWM go here.

The constant current driver is actually designed for driving three 1W LEDs at 320mA without current limiting resistors.  The led strip is 3W and built to run off 12v so already contains current limiting resistors which gives a current rating 250mA (3W/12v).  It’s not an ideal situation.  The LED strip is very bright and gets a quite hot after running for just ten minutes.  So by using PWM not only can vary the light intensity but I can also limit the average current to the strip to the quarter Amp that it is designed for by putting a ceiling on the maximum duty cycle.  That’s the idea anyway.

I’m not sure if the driver will like being used like this and I’m not certain that the LED will survive being pulsed at 320mA.  But both the driver and the LED strip are fairly inexpensive so if all goes wrong I’ll not be heart broken.

3W 48-LED 15ni 180-Lumen Aluminium Alloy Light Strip (Click for DX link)

3*1W 320mA Constant Current LED Driver. (Click for DX link)



Circuit version 1

The circuit is really simple consisting of the PIC12f683 to generate the PWM, a rotary encoder interfaced to the PIC to set the duty/brightness and a MOSFET to act as the switch.  A constant current supply doesn’t regulate the voltage of it’s output – that’s kind of the whole point of it – so a voltage regulator is needed to provide the PIC with stable supply.  I chose an L78L05 as I happened to have a bunch of them in my parts box and I wanted to run the PIC at 5v to ensure I can switch the FET properly.  An LM317 or similar would do just as well I’m sure.  The current draw of the PIC is so tiny that I could probably get away with using a Zener diode as a regulator (more info about that here) but I don’t have any of them hanging around…

The MOSFET is an N-Channel 2N7000 that again I have in my parts box.  It’s capable of switching a continuous load of 350mA and is a “logic level” FET which means the Gate threshold voltage is fairly low at around 3v which means it can be driven directly by a microprocessor.  The PIC is running at VDD = 5V, a high output is VDD – 0.7V so that gives a Gate voltage (VGS) of 4.3V which should be more than enough to switch the FET fully on.  At least I think so…

One thing to note that caused me lots of confusion is that to easily drive the FET directly from a microprocessor the FET must be used as a sink – ie. below the load – rather than as a source above the load.

The reason is actually fairly simple but it got my head all messed up for a while so I’ll explain below just in case like me you’re more familiar with transistors rather than FETs.

FETs in a lot of ways are pretty similar to transistors and in a lot of situations can be used to do the same thing.  However there’s one fundamental and really important difference! A FET is a voltage operated device whereas a transistor is current operated.  So where with a transistor you turn it on by poking some current into it’s Base pin, with a FET you turn it on by poking a voltage into it’s Gate pin and that voltage is relative to the voltage at it’s Source pin – (kind of the same as an NPN transistor’s Emitter).  So if like in my case you are using the FET to switch 12V and  your microprocessor output is 4.3V then you need to put the FET after the Load in the circuit so that the FET Source pin is at GND which means that your VGS will be relative to GND too and therefore the FET will switch.
If you put the FET before the Load then the voltage at the FET Source pin will be dependant on the resistance of your Load. If your FET drain is at 12V then most likely the voltage at the Source pin will be higher than the 4.3V you are providing at the Gate and so the FET will not switch.

I’ve not explained that very well. If I’ve got this all wrong please tell me I don’t want to pass on my idiocy!
There’s much more useful information here; Electronics Tutorial about Transistors and FET’s and here; Using a MOSFET as a Switch

Anyway I didn’t really think about that and had the FET as a source for while and was really confused as to why it wasn’t working.


I chose to use a Rotary Encoder as input the the PIC as I’ve not used them before.  I built a quick version using a potentiometer connected to the PIC ADC but I really wanted to try using the encoder.  I got the encoder from Sure Electronics. It’s outputs a 2 bit grey code with 20 cycles per rotation and one detent (bump) per cycle.  Rotary encoders are actually really easy to use with the PIC you can either sample the input on a frequent basis or as I did connect the inputs to pins that can use the PIC’s interrupt on change feature (IOC) and handle the processing in an interrupt routine.  There’s a good PDF here with more info on using rotary encoders. The detents mean that the encoder has a sort of bumpiness to it as you turn it and in my case they are aligned with the start/end of each cycle so the output always reads 00 at a detent. Different encoders have different mechanical configurations though so yours might be different.


The pic 12f683 has a single Capture and Compare peripheral that can be used as a very flexible hardware PWM output at up to 10bits of resolution. It’s completely handled in hardware so needs no servicing to keep it running and has a double buffered duty cycle to avoid glitchy changes in duty.  It’s really easy once you have it up and running, the most complex thing is that the duty register is 10bit and split over two 8bit registers so you need write to two places and to do a bit of rotating and masking to get your bits in the right positions.

The update frequency (period) depends on the main PIC oscillator (TOSC) and the chosen PWM output resolution.  It’s explained pretty clearly in the PIC12f683 datasheet but it generally speaking a toss up between two things, resolution and refresh rate. The higher your resolution the more ticks it will take to complete a cycle and so the lower the refresh rate (period) will be for any given oscillator frequency.  I’m using the PIC’s internal oscillator at 8Mhz (osccon = 0b01110001;) to give me the highest TOSC speed the PIC can generate without using an external oscillator.  I’m using 8bits of resolution for my PWM output giving a PWM frequency of 31KHz (8,000,000 / 256).  I not sure I really need that much resolution but for now it’s fine and 31KHz is so far above what the eye can register as to be irrelevant.

One thing that is important – and my reasoning for using the highest TOSC – is to have the shortest duration possible for a single step, or tick of the PWM cycle.  This is important to give you good control at the lower end of the brightness scale. eg. when going from fully off PWM=0 to the very first step where PWM=1.  LEDs can be switched on and off extremely fast and the human eye is very sensitive to even very short bursts of  light (strobe lights for example).  This means that the eye is very sensitive to very small difference in brightness at the low end whereas once the brightness increases it is harder to spot the difference.  The shorter a single PWM pulse is the better.  With an 8Mhz base clock the duration of a single PWM step is 125nS long.  That’s pretty damn short but still very easy to spot when you increase the PWM from off to tick 1.

I feel that I don’t fully understanding the issues at play here with regards to PWM frequency and resolution. I’m not sure if it is better to have a lower frequency PWM and have more resolution to play with or have less resolution with a higher frequency.  Either way the 8Mhz TOSC acts as the limit on the step size so it ultimately doesn’t make much difference.  An advantage of a higher resolution PWM cycle would be that I could use the extra resolution to map an exponential increase in PWM duty in response to the linear input from the encoder.  At the moment without any mapping function the first 40% of the PWM duty cycle appears to contain all the change; it’s during this region that the LED goes from off, though a gradual increase in brightness until at about 40%  the LED is just “bloody bright” and you don’t really notice that it is any getting brighter.  Adding a mapping function to this interface would allow me to have finer control over the lower end of the brightness scale and would give a more linear feel to the interface. It would also mean I could condense the “action” into 3 or 4 complete turns from full off to fully on rather than the almost 13 turns that it takes now.

Another option is to add some acceleration into the interface and a bit of inertia to the current brightness.  The idea being that turning the dial rapidly would accelerate the rate of increase in brightness whereas turning the dial slowly would allow for a small and constant increase. Similar to how you can set your mouse up on Windows move it slowly and it stays slow and accurate, give it a quick flick and it flies across the screen. Mind you I hate that feature in mice…

But that’s something for a later date.


I used Eagle CAD to draw the circuit schematic and also to layout a prototype sized to fit a scrap bit perf-board that I had lying around (18 by 14 holes).

Perf-board prototype with some extra wires to sort out my FET problems.

Underneath isn't pretty... but it works!

The input from the constant current source is the black connector on the left, the output to the LED strip is the green connector on the right.  The red and green 5mm LEDs are used as indicators to show a pulse up or down and also to show when you hit the maximum. brightness limit.  The momentary action switch (push the knob) is connected to MCLR so at the moment it resets the PIC when you push it, but I might set the PIC up to use MCLR as an input and do something useful with it. There’s a bit of space on the board to double up the FET to handle more load if necessary, but so far after a few continuous hours of use it hasn’t gotten warm.

The code is here.  It’s written in BoostC , there is a free version if you don’t have it.

Currently it’s pretty basic.  I have only implemented a basic linear step, no fancy mapping function yet and I think I need to de-bounce the encoder inputs as I’m getting a bit of 2 steps forward, one step back when turning the dial. But other than that it does work ok so what more could I ask for at this stage.

Here’s a very poor quality video (my camera is a bit dated)

6 thoughts on “Simple PWM control for LED strip

  1. Hey Matt: longtime no chat…glad I came back here to look around, I see you are using the same rotary encoder I bought from Sure about 8 months ago! I am now motivated to start playing with it; very exciting!

    Thanks for posting this stuff, you’ll be hearing from me soon!


    • Yes they should be fine. I don’t think you’d want to use a constant current source as 12v DC LED strip are normally built with resistors included to limit the current.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s