Library that allows for higher resolution and speed than standard mbed PWM library using same syntax (drop-in replacement).

Dependents:   PwmOscillator FastStepDriver TLC5940 CameraTest ... more

FastPWM is a library that unlocks alot more of the potential of the mbed's PWM units than the normal PWM library. It is currently available for the LPC1768, LPC11u24, KLxxZ, K20D50M and most STM32 targets (those lacking are fairly easy to add). (Since I generally forget to update this list, if you want to know if your target is supported see if it compiles).

The two main points it allows for compared to the regular PwmOut library is clock cycle precision PWM and (automated) changing prescalers. It isn't perfect yet, but for now it will have to do ;). For those familiar with version 1, version 2 is almost completely rewritten to add more functions.

Usage

FastPWM is largely a drop-in replacement for the normal PwmOut library. All the same functions are available, with some extras.

Prescaler

Warning

All prescaler options are disabled for 32-bit PWM units currently, the prescaler is fixed at 1

fastpwm.prescaler(value);

With this function you can set the value of the prescaler. Aditionally the second argument of the constructor is used for the same to directly set it from the constructor. It returns the actual prescaler which is set. If the requested one isn't available it is always rounded up (unless it is larger than the maximum prescaler).

There are three options for this function. Any value larger than zero will simply be set. (Yes it is signed, so yes you cannot use the full 32-bit prescaler if your device supports it, I cannot imagine why you possibly would want that). If the value is zero dynamic prescaling is disabled and the current prescaler is returned. If the value is -1 dynamic prescaling is enabled and the current prescaler is returned.

So what is dynamic prescaling? This is the default option for FastPWM, don't use any prescaler option and it is enabled. To start with the negative, it adds quite some processing cycles, so changing the period takes longer. Luckily generally the PWM period is constant. The good part is that it automatically adapts the prescaler unit to give as much accuracy as possible: It gives highest accuracy for the duty-cycle, and also allows you to generate a wide range of periods. For example you can now create a LED blinking at 1Hz with FastPWM on the LPC11u24/Nucleo 16-bit PWM units. (On the KL25Z this isn't possible due to limitted value of the prescaler).

As the nice warning message above says, this is currently only implemented for 16-bit PWM units, simply because normally you won't need it for 32-bit PWM units. For those it is automatically disabled, and you cannot enable it. However for example the majority of the PWM units of the LPC11u24 can't be used to make servo signals with PwmOut, with FastPWM they can.

TL;DR, by default it uses dynamic prescaling. Unless period is changed very often just keep it on default and enjoy your larger range of possible periods and higher accuracy.

Ticks

fastpwm.period_ticks(ticks);
fastpwm.pulsewidth_ticks(ticks);

These two functions allow you to directly write the pwm period and pulsewidth in clock ticks. This is useful if you need to have very little overhead. It is dependent on which device you use, since they have different clock rates. You can get the current clock speed of your device with SystemCoreClock.

Double

PwmOut uses floats for setting the time in seconds, and ints for milliseconds and microseconds. All three of those don't give enough accuracy to fully use the PWM units. Which is why FastPWM uses besides int for milliseconds and microseconds, it uses doubles for seconds and also for microseconds. Generally it is adviced to use these doubles, sometimes you might need to explicitly cast your variables to doubles.

Currently setting pulsewidth in microseconds with an int is a risk with some prescaler values (not on the 32-bit timers). See known-issues.

Adding other microcontrollers

Look at the other device files on how to add other microcontrollers. Functions that need to be implemented:

Known Issues

Here the TL;DR is: Preferably set the period/prescaler once at the beginning before setting the duty-cycle/pulsewidth. If that isn't possible, take into account duty cyles need to be set again. And preferably use doubles.

Credits

Some of the ideas are 'loaned' from Jochen Krapf's fork of the original FastPWM: http://mbed.org/users/jocis/code/HighPWM/

Changes

RevisionDateWhoCommit message
34:c0b2265cff9c 2 weeks agoSissorsRemoved wait statement which was for debug default tip
33:2ca2e47f9650 2 weeks agoSissorsKSDK (K64F) update
32:e880dcb178f4 8 months agoSissorsFixed issue where STM32 PWM on MCUs with high clock frequency could be a factor of two too fast
31:10e2e171f430 12 months agoSissorsTemporary fix for K64F with new mbed lib:
30:87e38b846651 18 months agoSissorsShould fix for LPC824
29:3e4d3b900850 18 months agoSissorsAdded LPC81x/LPC82x support
28:3c8a0d977bc3 18 months agoSissorsSTM32F3, F4, L4, etc now use the channels number from the mbed library. The others still need to use the manual way.
27:7f484dd7323d 19 months agoSissorsAdded extra Nucleo/Disco targets (by https://developer.mbed.org/users/mimi3/)
26:0c924507a81f 19 months agoSissorsAdded two more NUCLEO Targets
25:8b1bf34c72aa 24 months agoalpsayinadded pins for ST32F303RE
24:1f451660d8c0 2015-06-20SissorsChanged F103 registers to 32-bit from 16-bit
23:ed690a19dc55 2015-04-19SissorsAdded LPC11XX_LPC11cXX support (LPC1114). Should work. Probably.
22:db9c0cf445e2 2015-04-16SissorsFixed a bug for STM targets. The mbed library did not enable syncing of the period register, resulting in sometimes a smaller period being set than the current timer value -> it would first need to overflow before it worked properly. Which takes long o...
21:aa2884be5496 2015-01-12altaranAdded F072RB target, including PWMx/1N channels
20:3c609bc4ae9c 2015-01-06altaranAdded F072RB
19:ba7a5bf634b3 2014-11-10SissorsAdded F334 (Untested but requested, hey that rhymes).
18:d91c0629e4e6 2014-10-04jocisMinor optimisation in updateTicks()
17:8378bc456f0d 2014-10-04jocisAdded NUCLEO F103RB; adapted t 32/16 bit pwm struct for NUCLEO
16:ec208b5ec0bb 2014-10-02jocisAdded NUCLEO F103RB
15:49a7eff133b3 2014-10-01jocisAdded Nucleo F411RE
14:b30038fbba51 2014-09-30SissorsAdded KSDK support, probably smashed buggy on KLxx platform.
13:cdefd9d75b64 2014-07-20SissorsAdded NUCLEO support (F030 + F401, but others should be easily added).
12:4600daab8a83 2014-07-20SissorsPreparation for Nucleo devices: Added option to have a device specific container with variables (such as pointer to match registers, since nucleo pwmout class lacks those).
11:e0a8f0fcb1c9 2014-07-16SissorsK20D50M added
10:36362e9067b0 2014-06-27SissorsSame error as for the KLxx removed when multiple FastPWMs are used. Contrary to KLxx this gives a bit more overhead, but not much I can do about it while keeping the lib tidy
9:c50f688cad07 2014-06-27SissorsPeriod of KLxx decreased by 1 before writing to make sure it is exactly correct for my beloved users.
8:a7745c791b0c 2014-06-27SissorsKLxx bugfix when using multiple FastPwm
7:1b5df740bcd7 2014-05-01SissorsFixed https://mbed.org/forum/bugs-suggestions/topic/4886/?page=1#comment-24302 and improved in general LPC11u24 code
6:0f57969697b6 2014-03-17SissorsChanging period now keeps pulsewidth the same instead of duty cycle
5:2812f0a115f7 2014-02-28SissorsKL25Z renamed to KLXX, should work fine for all KLXX devices.
4:a7b9f778c4b4 2013-08-13Sissorsv2.0
3:3094d3806cfc 2012-07-25SissorsFixed clk_sel, latch registers and constant duty when changing period
2:4b8de6ae5885 2012-07-12Sissorsms and us functions were multiplying by 1k(k) instead of dividing
1:1aed61747ed6 2012-07-12SissorsASCII art turtle added
0:f8c1b0ad5371 2012-07-12Sissorsv1.0, seems completely functional