Jeroen Swart

.NET Architect

NetDuino - Getting Started with PWM

PWM (or Pulse Width Modulation) is a technique that basically allows digital circuits to control analog circuits. One of the applications for this is to control the speed of a motor or, as I will show you in a second, the brightness of a LED.

A digital port is either on or off. This is very logical, but not very helpful when controlling an analog device like a motor. The speed of a motor is usually controlled by varying the voltage: if you set the voltage higher, more current will flow and the speed of the motor will increase.

With PWM, the digital port is switched on and off really fast. The effective voltage for analog (DC) use is the average of the on and off levels and depends on how fast the port is switched. The time the port has been switched both on and off is called the period, the time the port is on is called the pulse and the time the port is on, relative to the period, is called the duty-cycle and is expressed in percentage. By controlling the width of the pulse, you control the effective voltage on the output. Luckily, most microcontrollers have one or more PWM ports. You only need to set the period, pulse and/or duty-cycle, and the microcontroller takes care of the rest.


This image shows a PWM signal with a 50% duty-cycle. With a supply voltage of 3.3V, like on the Netduino, this will result in an average output of 1.65V.


This image shows a PWM signal with a 25% duty-cycle. This will result in an average output of 0.825V when using a supply voltage of 3.3V.

The Netduino has 4 ports that are capable of producing PWM signals: D5, D6, D9 and D10. The PWM class is used to control one of these ports. It provides two methods to configure the port. With the SetDutyCycle method, the duty-cycle is simply set as a percentage. Passing 0 sets the port off all the time, resulting in an effective 0V output. Passing 100 sets the port on all the time, resulting in an effective 3.3V output. Passing 50 results in an pulse that’s on during 50% of the period, resulting in a 1.65V output. The SetPulse method allows a little more control. The first argument is the length of the period and the second argument is the duration of the pulse, both in microseconds. So calling SetPulse(1000, 250), results in a pulse that starts every 1ms and lasts 0.25ms; the duty-cycle in this case is 25%.

In the simple example below, the LED is dimmed to a specific level. Since the on-board LED is not connected to a port that allows PWM, we need to connect a LED ourselves. This example will work with a LED & resistor connected directly as shown here, or using a transistor as shown here. The only difference is that you need to use one of the PWM ports. The code below is using port D5. Please note that for controlling anything other than a LED, you will need a transistor to provide a decent amount of current.

public class Program
{
    public static void Main()
    {
        // initialize one of the digital pins (that support PWM!) for PWM
        PWM pwm = new PWM(Pins.GPIO_PIN_D5);

        // set the duty-cycle to a specific value
        pwm.SetDutyCycle(50);

        // wait forever...
        Thread.Sleep(Timeout.Infinite);
    }
}

In the example below, the LED is dimmed repeatedly from totally off to totally on and back again. It uses the same port and components as in the previous example.

public class Program
{
    public static void Main()
    {
        // initialize one of the digital pins (that support PWM!) for PWM
        PWM pwm = new PWM(Pins.GPIO_PIN_D5);

        // we start with the LED off
        int dutyCycle = 0;
        // we start with making the LED brighter
        bool up = true;

        // do forever...
        while (true)
        {
            // if making the LED more bright
            if (up)
            {
                // increase duty-cycle
                dutyCycle++;

                // if we're at 100%, start making the LED less bright
                if (dutyCycle >= 100)
                {
                    up = false;
                }
            }
            else
            {
                // decrease duty-cycle
                dutyCycle--;

                // if we're at 0%, start making the LED more bright
                if (dutyCycle

Another application for PWM is controlling servos, as are used in remote controlled cars and small robots. In this case the duration of the pulse controls the angle of the servo. The period is 20ms and a pulse of 1.5ms (duty-cycle 7.5%) puts the servo in the center or zero position. A pulse of 1ms (duty-cycle 5%) turns the servo completely to one side and a pulse of 2ms (duty-cycle 10%) turns the servo completely to the other side.

Next: using the ADC.

Comments (4) -

  • V.Thejeeswar

    2/21/2012 6:05:56 AM |

    k
    got the required one

  • Chris Lovett

    5/6/2012 2:41:33 AM |

    In case you want to control the speed of a brushless motor connected to an ESC controller (like the setup for an Arducopter http://code.google.com/p/arducopter/wiki/AC2_ESC) using the analog input of a potentiometer for the speed control, here's the code:


    AnalogInput pin0 = new AnalogInput(Pins.GPIO_PIN_A0);
    pin0.SetRange(0, 1000);

    // initialize one of the digital pins (that support PWM!) for PWM        
    PWM pwm = new PWM(Pins.GPIO_PIN_D6);

    while (true)
    {
        // We want 50 Hz PWM ouput whose pulse width varies from 1ms to 2ms.
        // analog input varies from 0 to 1023
        uint value = (uint)pin0.Read();

        // 20000 microseconds is frequency 1000000/20000 = 50Hz.
        // Duration will range from 1000=1ms to a possible 20000 which is 2ms full speed
        pwm.SetPulse(20000, 1000 + value);

        // You cannot read the analog pin any faster than about this often.
        Thread.Sleep(50);
    }

  • M3mPhis

    2/3/2013 4:31:28 PM |

    uint dutyCicle = 0;

  • M3mPhis

    2/3/2013 4:32:49 PM |

    unit dutyCycle = 0; //Sorry! xD

Pingbacks and trackbacks (3)+

Comments are closed