PwmOut

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

Hello World!

Import program

#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

Import library

Public Member Functions

  PwmOut (PinName pin)
  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 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

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 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);
        }
    }
}



4 related questions:

1
answers
KL25Z? Jon Z
7 months, 4 weeks ago

PwmOut


62 comments:

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:

#include "mbed.h"

PwmOut servo(p21);

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

is valid code, whereas something like:

#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

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

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,

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

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

Posting new comments for this page has been disabled