Categories
Main

Exploring the Netduino #4: Make LEDs *really* Glow (or: Fun with PWM)

In our last entry, “Exploring the Netduino #3: Building the circuit on a Breadboard“, we covered the step-by-step method to wire up the proposed schematic for switching an LED on and off via a power MOSFET. In this entry, we are going to get to the fun stuff: CODE!

But first, a little bit on LEDs

Light Emitting Diodes (LEDs) may function a lot like (incandescent) lightbulbs, but they should never be treated like them. Like lightbulbs, LEDs can be dimmed by controlling the forward voltage. Unlike light bulbs, this range tends to be rather narrow and as such is somewhat difficult to control. Fortunately, dimming LEDs can happen another way that is particularly easy to do with a digital circuit: Pulse Width Modulation (PWM).


PWM and why it’s important

Pulse width modulation (in relation to LEDs) is the act of turning the LED On and Off very rapidly such that the LED’s *perceived* brightness can be controlled. Essentially, the LED blinks so fast that the human eye cannot tell that the LED is actually blinking Full ON (digital logic 1) and Full OFF (digital logic 0). Instead when the LED is blinking, it appears that the LED is merely dimmer than if it were fully On.

For example, if the LED is instructed to *continually* cycle:

  • ON for 9ms and OFF for 1ms, then the LED would appear to be at 90% brightness.
  • ON for 5ms and OFF for 5ms, then the LED would appear to be at 50% brightness.
  • ON for 2ms and OFF for 8ms, then the LED would appear to be at 20% brightness.

As you can probably discern by now, controlling the brightness is about the ratio of On to Off. In the above 3 examples, the ratio was 9:1 (90%), 1:1 (50%), and 1:4 (20%), respectively.

Implementing Brightness via the Netduino

To start this exercise, we are going to implement code similar to the code implemented in the getting started guide by just blinking our new MOSFET-LED circuit on and off. In Visual Studio 2010, start a new Netduino project and add the following lines in the “using” section at the top of the Program.cs file.

[cc lang="csharp"]using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using SecretLabs.NETMF.Hardware;
using SecretLabs.NETMF.Hardware.Netduino;[/cc]

and insert the following code in your “Main()” method:

[cc lang="csharp"]var led = new OutputPort(Pins.GPIO_PIN_D10, false);
for(int x = 0; x < 200; x++)
{
   led.Write(true);
   Thread.Sleep(50); //milliseconds
   led.Write(false);
   Thread.Sleep(50); //milliseconds
}[/cc]

If you build and run this code on your Netduino, you will see your LED blink on and off quite rapidly. Even though the ratio here is a 1:1 (50%) brightness, both the ON duration and the OFF duration are too long for the human eye to perceive this as dimmed brightness. Instead, you just see flickering.

  • Shorten both sleep times to 5 milliseconds? That works. 50% brightness.
  • What about 1 and 9, respectively? Dimmer than before. 10% brightness.
  • What about 1 and 99? 1 percent brightness? Hmmm… no. Blinking again.

So how do we fix this?

Better Brightness Control

The good news is that the smart folks at Secret Labs, LLC (the makers of the Netduino) have already solved this problem for us by creating a Pulse-Width Modulation class called (appropriately enough): PWM

The PWM class has only 1 constructor which takes a single parameter: pin.
It also has 2 primary methods:

  • SetDutyCycle(uint dutycycle)
  • SetPulse(uint period, uint duration)

The first method is the easiest to use. The parameter “dutycycle” can be considered the percent (%) brightness.

[cc lang="csharp"]var led = new PWM(Pins.GPIO_PIN_D10);
uint dutyCycle = 100;
while (dutyCycle > 0)
{
   Debug.Print("DutyCycle = " + dutyCycle);
   led.SetDutyCycle(dutyCycle);
   Thread.Sleep(1000);
   dutyCycle = dutyCycle / 2;
}[/cc]

When this code is run, the LED is turned on to 100% brightness and then each second its brightness is reduced by 1/2 until it hits 1%.

This is pretty good. Granular control from 0 to 100% with no noticeable blinking or flickering. And the best part is that we do not need to stay in a WHILE-loop turning the digital out on and off. SetDutyCycle() does it for us automatically!

But maybe you are thinking:

1% is still quite bright

And it is true. 1% *is* rather bright. And if you had not noticed already, SetDutyCycle only takes unsigned Integers (uint). So the only thing dimmer than 1% is 0% (OFF). How do we get dimmer than 1%, but not completely Off (0%)? That’s what SetPulse() is for!

SetPulse is slightly different in that it takes 2 unsigned Ints: period and duration. The Duration varies the brightness, while the Period sets the granularity (precision). If it helps, you can think of them as a fraction:

Duration is the “numerator”
————————————
Period
is the “denominator”

Let us try this again (changing our code a little bit):

[cc lang="csharp"]var led = new PWM(Pins.GPIO_PIN_D10);
uint period = 1000;
uint duration = period;
while (duration > 0)
{
    float brightness = (duration / (float)period) * 100;
    Debug.Print("Percent brightness = " + brightness);
    led.SetPulse(period, duration);
    Thread.Sleep(1000);
    duration = duration / 2;
}[/cc]

The code starts at 100% brightness and reduces the brightness by 50% every second, until it hits 1/10 of 1%. That’s much dimmer.

Can we go lower? Sure! Try it. Change the period from 1,000 to 10,000. (You may need to cup your hands over your breadboard to see how dark the LED is at the end.)

So what else? Well, at this point I bet you can probably imagine a bunch of different things you can do with this. Here’s another, for example:

Make it glow like a laptop in Sleep mode

Ever see a closed laptop with its fancy LED  on the bezel softly glow light to dark to let you know it is “sleeping”? Well, that’s pretty easy to do with the Netduino.

[cc lang="csharp"]var led = new PWM(Pins.GPIO_PIN_D10);
uint period = 1000;
uint duration = period;
while (true)
{
    for (duration = period; duration > 0; duration--)
    {
        led.SetPulse(period, duration);
        Thread.Sleep(1);
    }
    for (duration = 0; duration < period; duration++)
    {
        led.SetPulse(period, duration);
        Thread.Sleep(1);
    }
}[/cc]

Experiment. See what else you can come up with.

IDEA: Get 3 different color LEDs (like Red, Green, and Blue) and rig up 3 parallel circuits like we designed in the previous lessons to be driven by 3 of the Digital PWMs and try cycling thru various color combinations. (Note: Blue LEDs have a higher voltage drop than Red or Green, so check your specs and size your current limiting resistors accordingly.)

Next Time: BJTs vs MOSFETs (or playing with a buzzer/speaker or maybe benchmarking the Netduino. I’m not sure, yet.)


4 replies on “Exploring the Netduino #4: Make LEDs *really* Glow (or: Fun with PWM)”

Leave a Reply to awaiK Cancel reply

Your email address will not be published. Required fields are marked *