Library that allows for higher resolution and speed than standard mbed PWM library. Based on FastPWM without floating point calculation in most functions

Fork of FastPWM by Erik -

Library that allows faster and/or higher resolution PWM output.

This library is based original on FastPWM by Erik Olieman but without floating point (double) calculation in each call of pulsewidth_xx. This change was nessecary to get a performant motion controller.

Library can directly replace standard mbed PWM library. Only limitation is that the maximum PWM period is four times shorter The maximum achievable period is roughly 40 seconds, I dont think that should be a problem. Do take into account all PWM objects (based on defailt PWM lib) will run four times faster than default.

Contrary to the default mbed library, this library takes doubles instead of floats. The compiler will autocast if needed, but do take into account it is done for a reason, your accuracy will otherwise be limitted by the floating point precision.

Using this library for a RC servo the resolution of steps (min to max) is increased from 1000 to 96000.

This library can be also used as a analoge output (with external low-pass filter) with a frequency of e.g. 20kHz and a resolution 4800 steps (similar to a 12 bit DAC) instead of 50 steps (similar to a 5 bit DAC) on original PWM lib.

In your program you can define F_CLK if you use a different clock frequency than the default one.

Only works on LPC1768 for now. If you want support for the other one, send a PM and I will have a look, but I cannot even compile for it.

Files at this revision

API Documentation at this revision

Comitter:
Sissors
Date:
Wed Jul 25 07:14:39 2012 +0000
Parent:
2:4b8de6ae5885
Child:
4:923b54e7c2c1
Commit message:
Fixed clk_sel, latch registers and constant duty when changing period

Changed in this revision

FastPWM.cpp Show annotated file Show diff for this revision Revisions of this file
FastPWM.h Show annotated file Show diff for this revision Revisions of this file
--- a/FastPWM.cpp	Thu Jul 12 19:26:43 2012 +0000
+++ b/FastPWM.cpp	Wed Jul 25 07:14:39 2012 +0000
@@ -1,20 +1,35 @@
 #include "FastPWM.h"
 
 FastPWM::FastPWM(PinName pin) : PWMObject(pin){
+    //Set clock source
+    LPC_SC->PCLKSEL0|=1<<12;
+    
     _duty=0;
     _period=0.02;
-    if (pin==p26||pin==LED1)
+    if (pin==p26||pin==LED1) {
+        PWMUnit=1;
         MR=&LPC_PWM1->MR1;
-    else if (pin==p25||pin==LED2)
+        }
+    else if (pin==p25||pin==LED2){
+        PWMUnit=2;
         MR=&LPC_PWM1->MR2;
-    else if (pin==p24||pin==LED3)
+        }
+    else if (pin==p24||pin==LED3){
+        PWMUnit=3;
         MR=&LPC_PWM1->MR3;
-    else if (pin==p23||pin==LED4)
+        }
+    else if (pin==p23||pin==LED4){
+        PWMUnit=4;
         MR=&LPC_PWM1->MR4;
-    else if (pin==p22)
+        }
+    else if (pin==p22){
+        PWMUnit=5;
         MR=&LPC_PWM1->MR5;
-    else if (pin==p21)
+        }
+    else if (pin==p21){
+        PWMUnit=6;
         MR=&LPC_PWM1->MR6;
+        }
     else
         error("No hardware PWM pin\n\r");
     
@@ -23,8 +38,9 @@
 
 void FastPWM::period(double seconds) {
     LPC_PWM1->MR0 = (unsigned int) (seconds * (double)F_CLK);
-    pulsewidth(_duty*seconds);
+    LPC_PWM1->LER |= 1;
     _period = seconds;
+    pulsewidth(_duty*_period);
 }
 
 void FastPWM::period_ms(int ms) {
@@ -41,6 +57,8 @@
 
 void FastPWM::pulsewidth(double seconds) {
     *MR=(unsigned int) (seconds * (double)F_CLK);
+    LPC_PWM1->LER |= 1<<PWMUnit;
+    _duty=seconds/_period;
 }
 
 void FastPWM::pulsewidth_ms(int ms) {
--- a/FastPWM.h	Thu Jul 12 19:26:43 2012 +0000
+++ b/FastPWM.h	Wed Jul 25 07:14:39 2012 +0000
@@ -115,6 +115,7 @@
     PwmOut PWMObject;
     double _duty;
     double _period;
+    unsigned int PWMUnit;
     
     __IO uint32_t *MR;