Recent changes
SerialPC
Creating a program
Downloading a program
Setup guide
Exporting to Code Red
Exporting to uVision
Order
tag order
From the mbed microcontroller Handbook.  

PwmOut

/media/uploads/mbedofficial/pwmout_interfaces.png

The PwmOut interface is used to control the frequency and mark-space ratio of a digital pulse train.

Hello World!

Example code for dimming an on-board LED

#include "mbed.h"

PwmOut led(LED1);

int main() {
    while(1) {
        for(float p = 0.0f; p < 1.0f; p += 0.1f) {
            led = p;
            wait(0.1);
        }
    }
}

API

API summary

PwmOutA pulse-width modulation digital output
Functions
PwmOutCreate a PwmOut connected to the specified pin
writeSet the ouput duty-cycle, specified as a percentage (float)
readReturn the current output duty-cycle setting, measured as a percentage (float)
periodSet the PWM period, specified in seconds (float), keeping the duty cycle the same.
period_msSet the PWM period, specified in milli-seconds (int), keeping the duty cycle the same.
period_usSet the PWM period, specified in micro-seconds (int), keeping the duty cycle the same.
pulsewidthSet the PWM pulsewidth, specified in seconds (float), keeping the period the same.
pulsewidth_msSet the PWM pulsewidth, specified in milli-seconds (int), keeping the period the same.
pulsewidth_usSet the PWM pulsewidth, specified in micro-seconds (int), keeping the period the same.
operator=A operator shorthand for write()
operator float()An operator shorthand for read()
class PwmOut : public Base
A pulse-width modulation digital output
PwmOut(PinName pin,  
const char *name =  NULL)
Create a PwmOut connected to the specified pin
void write(float value)
Set the ouput duty-cycle, specified as a percentage (float)
float read()
Return the current output duty-cycle setting, measured as a percentage (float)
void period(float seconds)
Set the PWM period, specified in seconds (float), keeping the duty cycle the same.
void period_ms(int ms)
Set the PWM period, specified in milli-seconds (int), keeping the duty cycle the same.
void period_us(int us)
Set the PWM period, specified in micro-seconds (int), keeping the duty cycle the same.
void pulsewidth(float seconds)
Set the PWM pulsewidth, specified in seconds (float), keeping the period the same.
void pulsewidth_ms(int ms)
Set the PWM pulsewidth, specified in milli-seconds (int), keeping the period the same.
void pulsewidth_us(int us)
Set the PWM pulsewidth, specified in micro-seconds (int), keeping the period the same.
PwmOut& operator= (float value)
A operator shorthand for write()
operator float()
An operator shorthand for read()

Details

The hardware has 6 PWM channels, and the PwmOut Interface can be used on mbed pins p21-p26.

The default period is 0.020s, and the default pulsewidth is 0.

The PwmOut interface can express the pulse train in many ways depening on how it is to be used. The period and pulse width can be expressed directly in units of seconds, millisecond or microseconds. The pulsewidth can also be expressed as a percentage of the the period.

Implementation details

LPC2368 and LPC1768

You can also specify the LED1-LED4 as PwmOut. Note that these are just different pinout options for the same underlying PWM hardware, so they are just alternative routing rather than extra PWM channels. So you can pin them out can't be used at the same time:

PWM H/W ChannelPinout Options
PWM_1P2_0/p26 or P1_18/LED1
PWM_2P2_1/p25 or P1_20/LED2
PWM_3P2_2/p24 or P1_21/LED3
PWM_4P2_3/p23 or P1_23/LED4
PWM_5P2_4/p22
PWM_6P2_5/p21

On the mbed LPC2368 and LPC1768, the PwmOut hardware is limited to share the period value between all outputs. Therefore, if you change the period of one output, you change them all. The pulsewidth can be set independently for each output.

LPC11U24

Pin under the same "Timer" share the same period:

Timer/Match RegisterPinout Options
CT16B0/MR0p5 (P0_9)
CT16B0/MR1p6 (P0_8)
CT16B0/MR2p34 (P1_15)
CT16B1/MR0p36 (P0_21)
CT16B1/MR1p20 (P0_22) and p14 (P1_23)
CT32B0/MR0p25 (P1_24)
CT32B0/MR1p26 (P1_25) and USBTX (P0_19)
CT32B0/MR2p10 (P1_26)

Examples

Control a R/C model servo

#include "mbed.h"

PwmOut servo(p21);

int main() {
    servo.period(0.020);          // servo requires a 20ms period
    while (1) {
        for(float offset=0.0; offset<0.001; offset+=0.0001) {
            servo.pulsewidth(0.001 + offset); // servo position determined by a pulsewidth between 1-2ms
            wait(0.25);
        }
    }
}



calendar Page history
Last modified 08 Dec 2011, by   user Emilio Monti   tag No tags | 40 comments      

40 comments on PwmOut:

10 Dec 2010

if I try to set the period with the above statement servo.period(0.020); I get an error statement "This declaration has no storage class or type specifier (E77-D)"

any idea what is wrong?

Lothar

10 Dec 2010

Hi Lothar,

I'm going to have to guess as you haven't provided much details of the code that is giving you problems, but for example:

Code

#include "mbed.h"

PwmOut servo(p21);

int main() {
    servo.period(0.020);          // servo requires a 20ms period
}

is valid code, whereas something like:

Code

#include "mbed.h"

PwmOut servo(p21);

servo.period(0.020);          // servo requires a 20ms period

int main() {
}

would give the error you describe. Program code must be within a function (such as main).

Hope that helps!

Simon

13 Dec 2010

Hi Simon,

thanks a lot; that did it. You can see that I am a bloody beginner but its great fun nevertheless.

Lothar

07 Jan 2011

I have 4 PWM channels controlling motor ESCs for a quadrotor and 2 servo channels for controlling a camera platform. I am attempting to reduce the period of the two camera servo PWM channels by setting the pulse width of these two channels to zero for 4 out 5 of the cycles. The motor updates are at 200Hz.

The synchronisation is performed by capturing a motor pulse edge and then setting the masking conditional which in turn is used to set the widths to zero for the camera channels.

So the questions:

1) are the pulse width updates guaranteed to occur within one cycle? 2) is there an easier way to detect when the positive pulse edge occurs without wiring the output pin to an detection input using an interrupt (an internal event perhaps)?

Thanks Greg

07 Jan 2011

Hi Greg,

1) When you set the pulsewidth, it is placed in a holding register in the pwm hardware which automatically updates the pulswidth at the start of the next period (so, yes)

2) The mbed APIs don't provide anything, so that may well be the easiest way. You may be able to find some specific features of the LPC1768 pwm hardware that gives you what you want (reading the counter registers? some form of interrupt?), but you'd need to investigate the LPC1768 manual here.

Sounds like an interesting project!

Simon

11 Jan 2011

Hello all,

I was just experimenting with the PwmOut function a moment ago. It seems that the function has some odd behavior when the PWM output pin is set to something other than p21-26 or LED1-4. I tried it with p20, and it seemed to affect all LED pins. I did not check the other PWM pins to see if they were affected. This result was unexpected as I thought the output would just not occur.

11 Jan 2011

user Michael Lau wrote:

Hello all,

I was just experimenting with the PwmOut function a moment ago. It seems that the function has some odd behavior when the PWM output pin is set to something other than p21-26 or LED1-4. I tried it with p20, and it seemed to affect all LED pins. I did not check the other PWM pins to see if they were affected. This result was unexpected as I thought the output would just not occur.

mbed is quite versatile with regards to assigning outputs to various pins; however it doesn't like it if you assign an output that *must* go through certain pins to a different one. It probably tries to output what it would do if it was going through the PWM circuitry that applies to p21-26?

13 Jan 2011

user Simon Ford wrote:

Hi Greg,

....

Sounds like an interesting project!

Simon

Thanks Simon,

I finally went for a software solution (below) and will now use all six PWM outputs for the motors allowing hexacopters etc.

I must put something up here but the Wiki is at:

http://code.google.com/p/uavp-mods/wiki/UAVXArm

For others the code I used is:

CameraTicker.attach_us(&CamPWMOnISR, 22000);

void CamPWMOnISR(void) {

PWMCamRoll.write(1);

CamRollTimeout.attach_us(&CamRollPWMOffISR, 1000 + PWM[CamRollC]);

PWMCamPitch.write(1);

CamPitchTimeout.attach_us(&CamPitchPWMOffISR, 1000 + PWM[CamPitchC]);

}

void CamRollPWMOffISR(void) {

PWMCamRoll.write(0);

CamRollTimeout.detach(); redundant?

}

void CamPitchPWMOffISR(void) {

PWMCamPitch.write(0);

CamPitchTimeout.detach(); redundant?

}

Probably could be simpler (do I need the detach or does this just happen after the timeout for example?) but seems to work fine with now visible performance impact on anything else.

Greg

13 Jan 2011

Hi Michael,

user Michael Lau wrote:

I was just experimenting with the PwmOut function a moment ago. It seems that the function has some odd behavior when the PWM output pin is set to something other than p21-26 or LED1-4. I tried it with p20, and it seemed to affect all LED pins. I did not check the other PWM pins to see if they were affected. This result was unexpected as I thought the output would just not occur.

You are probably seeing mbed's "Blue Lights of Death" flashing pattern, as described in the handbook debugging page. This indicates a runtime error, such as trying to use a pin assignment not available for a certain interface. Sometimes an error message will also be printed on the usb serial port to help track it down.

Hope that makes things clear.

Simon

14 Jan 2011

Does PWM operate using timers & interrupts? If I use PWM for several output pins, each with different duty cycles, are different timers involved, and does each different PWM output use/generate a different interrupt? Or is a single timer used along with a list of times to generate interrupts?

Bill

14 Jan 2011

PWM outputs does not use any kind of interrupts. For generating PWM is used a dedicated timer. You don't have to worry about interrupts when using PWM outputs.

14 Jan 2011

Ok, another question about PWM, sort of.

My frail understanding of USB is that there needs to be some housekeeping/maintenance between the OS and a USB device so that the OS knows the device is still present. This has to happen from time to time. I'm wondering whether a program that is running on the device for a while is able to fulfill this maintenance while it's executing its code. Interrupt driven techniques mean that this code can perform these maintenance calls in between interrupt driven code execution (like toggling pins involved in PWM). I want my embedded device to stay connected to a host throughout so the host can send it commands, data, etc., and I fear that while the device is running its internal stuff it may not be available to service this OS maintenance.

No doubt I have a muddy view; can anyone straighten me out?

Thanks.

Bill

15 Jan 2011

And another thing...

I've gotten a variant of one of the PWM examples going on my mbed. When I plug it into my Mac, a new device shows up in my /dev folder, and after I bring up a terminal and identify which device the mbed is. I can command the LEDs in my test circuit fine.

On a Windows 7 machine, when I plug in the mbed it shows up as a removable device like a thumb drive in the Device Manager. If I then bring up a terminal program, all I see are com ports, none of which is any use. Any pointers on this?

Thanks,

equipoise

15 Jan 2011

I found out how to get my mbed recognized and working on WIndows 7 - amazing how this "instructions" concept works. Still have questions about how or if there is a need to maintain a USB connection while code is running on the mbed.

Bill

15 Jan 2011

You can run any app with serial communication over USB (commands /data) no matter when you have to use it inside your runing program.

15 Jan 2011

I wonder why there is not a function to GET the period... only one to get the dutycycle?

Or is there something I am missing?

Tue

17 Jan 2011

user Tue Myren wrote:

I wonder why there is not a function to GET the period... only one to get the dutycycle?

Or is there something I am missing?

Tue

The default period is 0.020s. Presumably if you changed it to something other than this you would know what you changed it to and so a function to GET the period would be redundant?

17 Jan 2011

Hello from Switzerland I need 4 PWM-outputs, all of the same base frequency. Now my problem: Each of the 4 PWM should have a delay one to each other. So the PWMs are not synchronous anymore. Can someone give me a tip, how to resolve this in a efficient way? Grazie Mille.

Hello Titi Tix; Thank you for your hardware-solution with external RC's and Schmitt-triggers. What i am looking for, is a solution by software. Looking at the user manual of the m-controller, you can find in the chapter PWM (page 511 / fig. 119) , that you can preset the different match registers... just i did not get a working result yet.

17 Jan 2011

It depends on the delays. Try this way: FirstPwmOut - R1- C2 to GND - triggerschmidt (74hc14) - out This introduces a delay determined by RC . Use biger delay for SecondPwmOut and so on. Also instead of 74hc14 you can use CD4093. Pay attention in software that the PWM obtained this way is inverted hardware or use another inverter for the output.

22 Jan 2011

Hi there, I'm having some trouble understanding what happens when you set the PwmOut itself to a value. For example:

  1. include "mbed.h"

PwmOut led(p21); AnalogIn ain(p20);

main(){ while (1){ led=ain; } }

We are setting the 'led' to a value. But what in particular are we changing? The output voltage? Or some percentage? Sorry if it's a stupid question, I'm new at this! Thanks

22 Jan 2011
25 Jan 2011

Thanks, it's useful but it didn't answer my question unfortunately. What are we changing when we set the PWM to a value? I Understand the ratios/ percentages duty cycles and what not, but what is the actual value changing? (Read my other post if that didn't make sense)

Thanks!

25 Jan 2011

Hi Oliver,

led = ain is simply using the PwmOut operator= shorthand for led.write(ain), which is used to "Set the ouput duty-cycle, specified as a percentage (float)".

So for example, if you wrote:

led = 0.25;

...the duty cycle would be 25%, meaning the high-time pulsewidth would be 1/4 of the period.

Hope that helps! Simon

26 Jan 2011

Hey guys...

I was wondering, is it possible to obtain a negative voltage without using an external inverter? As an example, imagine I set the PWM to 50% duty cycle. This would produce around 1.35V. But I need -1.35V. Is there an internal mechanism for this, or should I use an OpAmp? Thanks

29 Jan 2011

user Simon Ford wrote:

Hi Oliver,

led = ain is simply using the PwmOut operator= shorthand for led.write(ain), which is used to "Set the ouput duty-cycle, specified as a percentage (float)".

So for example, if you wrote:

led = 0.25;

...the duty cycle would be 25%, meaning the high-time pulsewidth would be 1/4 of the period.

Hope that helps! Simon

Thank you very much for the clear explanation, Simon!

24 Feb 2011

Hi guys! I would like to know how i can switch off or switch on the PwmOut. Many thanks! Raphael

24 Feb 2011

user raphael bendel wrote:

Hi guys! I would like to know how i can switch off or switch on the PwmOut.

I think you can set the duty cycle to 0 or 1, which should give a steady signal (but I have not tested this).

28 Apr 2011

Hi all,

I want to drive 18 servo's using PWMout. As the mbed has 6 PWMout pins, I was thinking about using 2 Decade counters (CD 4017) and feeding them each with one mbed PWMout pin which would then give me up to 2 x 10 = 20 servo's. For this I need to be able to change the duty cycle before every time period. I could connect the PWMout pin to a Interruptin pin and handle the duty cycle change in the ISR, but I hate to loose 2 pins... Are there any better alternatives ? Thanks.

28 Apr 2011

user Bart Janssens wrote:

Hi all,

I want to drive 18 servo's using PWMout. As the mbed has 6 PWMout pins, I was thinking about using 2 Decade counters (CD 4017) and feeding them each with one mbed PWMout pin which would then give me up to 2 x 10 = 20 servo's. For this I need to be able to change the duty cycle before every time period. I could connect the PWMout pin to a Interruptin pin and handle the duty cycle change in the ISR, but I hate to loose 2 pins... Are there any better alternatives ? Thanks.

Never mind, I have found a better solution. I will publish it shortly.

19 May 2011

user Bart Janssens wrote:

Hi all,

I want to drive 18 servo's using PWMout. As the mbed has 6 PWMout pins, I was thinking about using 2 Decade counters (CD 4017) and feeding them each with one mbed PWMout pin which would then give me up to 2 x 10 = 20 servo's. For this I need to be able to change the duty cycle before every time period. I could connect the PWMout pin to a Interruptin pin and handle the duty cycle change in the ISR, but I hate to loose 2 pins... Are there any better alternatives ? Thanks.

Hey there, I also needed more than 6 servos for a project a while back. I wrote the UniServ library, which I published in the cook book.

This library follows the mBed servo API quite closely, but allows a servo on any I/O pin. I hope you find it useful :)

24 Jun 2011

The description of the parameter to write() shouldn't say:

"Set the ouput duty-cycle, specified as a percentage (float)"

as the expected range of values is 0.0 ... 1.0. Were it to be a percentage, the expected values would be 0.0 ... 100.0. "ouput" should also read "output".

A better specification of this method would be:

"Set the output duty-cycle, specified as a (float) fraction of 1.0"

10 Aug 2011

Hey guys!

What is the resolution of this PWMOut? How much bits do I actually get? What is the dependence to period time?

22 Oct 2011

Hello mbed Team! I'm getting to know this atomic ant :) and I have a question: Have you implemented the delete operator for this and other base classes? Specifically, I want to know if the implementation of the operator returns the hardware to the previous/default/non-operational state. Thank you!

22 Oct 2011

Hi Luis,

No we don't. Do you think that would be useful? We could disable the pwm channel, but would be interesting to know if you'd want to go as far as returning the pin to an input?

Simon

08 Dec 2011

PwmOut on the mbed-m0 and just when I needed it :)

I have tried it out and it doesn't quite work the way I expected based on the documentation above. It seems like pins such as p25, p26, and p10 which are on the same timer should have the same period but allow for different duty cycles. However when I try to use different duty cycles for each of these pins, the last write() call wins. As an example, the following sample code attempts to just blink one of the LEDs (the one connected to p10) but in actuality all three LEDs (p25, p26, and p10) blink.

Code

#include <mbed.h>

int main() 
{
    PwmOut  RedLED(p25);
    PwmOut  GreenLED(p26);
    PwmOut  WhiteLED(p10);
    
    RedLED.write(0.0f);
    GreenLED.write(0.0f);
    WhiteLED.write(0.0f);
    
    while(1) 
    {
        wait(0.25f);
        WhiteLED.write(1.0f);
        wait(0.25f);
        WhiteLED.write(0.0f);
    }
}
09 Dec 2011

user Adam Green wrote:

it doesn't quite work the way I expected based on the documentation above. It seems like pins such as p25, p26, and p10 which are on the same timer should have the same period but allow for different duty cycles.

Originally, I thought of treating each timer as a separate PWM (with one period and one duty cycle), so this behaviour was the intended one.

Considering that LPC2368 and LPC1768 share the same period for all the 6 PWMs, I can see the point in expecting a separate duty cycle for each MR with a shared period.

I updated the LPC11U24 implementation to match this behaviour. [Rev 31]

Cheers, Emilio

09 Dec 2011

user Emilio Monti wrote:

I updated the LPC11U24 implementation to match this behaviour. [Rev 31]

Thanks! I upgraded to rev 31 and its works a charm!

19 Dec 2011

Hello everyone. I would like to ask if it's possible to change output voltage of PwmOut. Have 3.3V but about 5V is needed (and I would prefer some kind of settings than amp =). Any suggestions? Thanks a lot!

19 Dec 2011

The PwmOut is hardwired inside the LPC1768, which runs on 3.3V. But you could attach a MOSFET, which connects to 5V, so this was the way around.

Lerche

19 hours, 45 minutes ago

The PWMOut LED code example will not run on the LPC11U24 - might make this a bit clearer near the example code. Might also indicate which pins can PWM in the pin function picture for the LPC11U24 somehow.

Please login to post comments.