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 Olieman

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.

Committer:
jocis
Date:
Thu May 23 10:39:29 2013 +0000
Revision:
4:923b54e7c2c1
based on FastPWM, changed double calculation to int calculation for most functions

Who changed what in which revision?

UserRevisionLine numberNew contents of line
jocis 4:923b54e7c2c1 1 #include "HighPWM.h"
jocis 4:923b54e7c2c1 2
jocis 4:923b54e7c2c1 3 HighPWM::HighPWM(PinName pin) : PWMObject(pin){
jocis 4:923b54e7c2c1 4 //Set clock source to CPU clock (without devider)
jocis 4:923b54e7c2c1 5 LPC_SC->PCLKSEL0 |= 1<<12;
jocis 4:923b54e7c2c1 6
jocis 4:923b54e7c2c1 7 _pulsewidth = 0;
jocis 4:923b54e7c2c1 8 _period = 0;
jocis 4:923b54e7c2c1 9
jocis 4:923b54e7c2c1 10 if (pin==p26||pin==LED1) {
jocis 4:923b54e7c2c1 11 PWMUnit=1;
jocis 4:923b54e7c2c1 12 MR=&LPC_PWM1->MR1;
jocis 4:923b54e7c2c1 13 }
jocis 4:923b54e7c2c1 14 else if (pin==p25||pin==LED2){
jocis 4:923b54e7c2c1 15 PWMUnit=2;
jocis 4:923b54e7c2c1 16 MR=&LPC_PWM1->MR2;
jocis 4:923b54e7c2c1 17 }
jocis 4:923b54e7c2c1 18 else if (pin==p24||pin==LED3){
jocis 4:923b54e7c2c1 19 PWMUnit=3;
jocis 4:923b54e7c2c1 20 MR=&LPC_PWM1->MR3;
jocis 4:923b54e7c2c1 21 }
jocis 4:923b54e7c2c1 22 else if (pin==p23||pin==LED4){
jocis 4:923b54e7c2c1 23 PWMUnit=4;
jocis 4:923b54e7c2c1 24 MR=&LPC_PWM1->MR4;
jocis 4:923b54e7c2c1 25 }
jocis 4:923b54e7c2c1 26 else if (pin==p22){
jocis 4:923b54e7c2c1 27 PWMUnit=5;
jocis 4:923b54e7c2c1 28 MR=&LPC_PWM1->MR5;
jocis 4:923b54e7c2c1 29 }
jocis 4:923b54e7c2c1 30 else if (pin==p21){
jocis 4:923b54e7c2c1 31 PWMUnit=6;
jocis 4:923b54e7c2c1 32 MR=&LPC_PWM1->MR6;
jocis 4:923b54e7c2c1 33 }
jocis 4:923b54e7c2c1 34 else
jocis 4:923b54e7c2c1 35 error("Invalid hardware PWM pin\n\r");
jocis 4:923b54e7c2c1 36
jocis 4:923b54e7c2c1 37 frequency(10000); // 10kHz
jocis 4:923b54e7c2c1 38 }
jocis 4:923b54e7c2c1 39
jocis 4:923b54e7c2c1 40 void HighPWM::frequency(double frq)
jocis 4:923b54e7c2c1 41 {
jocis 4:923b54e7c2c1 42 if ( frq>0.0 )
jocis 4:923b54e7c2c1 43 period(1.0/frq);
jocis 4:923b54e7c2c1 44 }
jocis 4:923b54e7c2c1 45
jocis 4:923b54e7c2c1 46 void HighPWM::period(double seconds)
jocis 4:923b54e7c2c1 47 {
jocis 4:923b54e7c2c1 48 period_ticks((unsigned int)(seconds*s_2_F_CLK+0.5));
jocis 4:923b54e7c2c1 49 }
jocis 4:923b54e7c2c1 50
jocis 4:923b54e7c2c1 51 void HighPWM::period_us(double us)
jocis 4:923b54e7c2c1 52 {
jocis 4:923b54e7c2c1 53 period_ticks((unsigned int)(us*us_2_F_CLK+0.5));
jocis 4:923b54e7c2c1 54 }
jocis 4:923b54e7c2c1 55
jocis 4:923b54e7c2c1 56 void HighPWM::period_ms(unsigned int ms)
jocis 4:923b54e7c2c1 57 {
jocis 4:923b54e7c2c1 58 period_ticks(ms*ms_2_F_CLK);
jocis 4:923b54e7c2c1 59 }
jocis 4:923b54e7c2c1 60
jocis 4:923b54e7c2c1 61 void HighPWM::period_us(unsigned int us)
jocis 4:923b54e7c2c1 62 {
jocis 4:923b54e7c2c1 63 period_ticks(us*us_2_F_CLK);
jocis 4:923b54e7c2c1 64 }
jocis 4:923b54e7c2c1 65
jocis 4:923b54e7c2c1 66 void HighPWM::period_ticks(unsigned int ticks)
jocis 4:923b54e7c2c1 67 {
jocis 4:923b54e7c2c1 68 double duty = (double)_pulsewidth/(double)_period;
jocis 4:923b54e7c2c1 69
jocis 4:923b54e7c2c1 70 LPC_PWM1->MR0 = ticks;
jocis 4:923b54e7c2c1 71 LPC_PWM1->LER |= 1;
jocis 4:923b54e7c2c1 72 _period = ticks;
jocis 4:923b54e7c2c1 73 pulsewidth_ticks((int)(duty*(double)_period+0.5));
jocis 4:923b54e7c2c1 74 }
jocis 4:923b54e7c2c1 75
jocis 4:923b54e7c2c1 76 void HighPWM::pulsewidth(double seconds)
jocis 4:923b54e7c2c1 77 {
jocis 4:923b54e7c2c1 78 pulsewidth_ticks((unsigned int)(seconds*s_2_F_CLK+0.5));
jocis 4:923b54e7c2c1 79 }
jocis 4:923b54e7c2c1 80
jocis 4:923b54e7c2c1 81 void HighPWM::pulsewidth_us(double us)
jocis 4:923b54e7c2c1 82 {
jocis 4:923b54e7c2c1 83 pulsewidth_ticks((unsigned int)(us*us_2_F_CLK+0.5));
jocis 4:923b54e7c2c1 84 }
jocis 4:923b54e7c2c1 85
jocis 4:923b54e7c2c1 86 void HighPWM::pulsewidth_ms(unsigned int ms)
jocis 4:923b54e7c2c1 87 {
jocis 4:923b54e7c2c1 88 pulsewidth_ticks(ms*ms_2_F_CLK);
jocis 4:923b54e7c2c1 89 }
jocis 4:923b54e7c2c1 90
jocis 4:923b54e7c2c1 91 void HighPWM::pulsewidth_us(unsigned int us)
jocis 4:923b54e7c2c1 92 {
jocis 4:923b54e7c2c1 93 pulsewidth_ticks(us*us_2_F_CLK);
jocis 4:923b54e7c2c1 94 }
jocis 4:923b54e7c2c1 95
jocis 4:923b54e7c2c1 96 void HighPWM::pulsewidth_ticks(unsigned int ticks)
jocis 4:923b54e7c2c1 97 {
jocis 4:923b54e7c2c1 98 *MR = ticks;
jocis 4:923b54e7c2c1 99 LPC_PWM1->LER |= 1<<PWMUnit;
jocis 4:923b54e7c2c1 100 _pulsewidth = ticks;
jocis 4:923b54e7c2c1 101 }
jocis 4:923b54e7c2c1 102
jocis 4:923b54e7c2c1 103 void HighPWM::write(double duty)
jocis 4:923b54e7c2c1 104 {
jocis 4:923b54e7c2c1 105 pulsewidth_ticks((int)(duty*(double)_period+0.5));
jocis 4:923b54e7c2c1 106 }
jocis 4:923b54e7c2c1 107
jocis 4:923b54e7c2c1 108 double HighPWM::read( void )
jocis 4:923b54e7c2c1 109 {
jocis 4:923b54e7c2c1 110 return (double)_pulsewidth/(double)_period;
jocis 4:923b54e7c2c1 111 }
jocis 4:923b54e7c2c1 112
jocis 4:923b54e7c2c1 113 HighPWM & HighPWM::operator= (double value)
jocis 4:923b54e7c2c1 114 {
jocis 4:923b54e7c2c1 115 write(value);
jocis 4:923b54e7c2c1 116 return(*this);
jocis 4:923b54e7c2c1 117 }
jocis 4:923b54e7c2c1 118
jocis 4:923b54e7c2c1 119 HighPWM::operator double()
jocis 4:923b54e7c2c1 120 {
jocis 4:923b54e7c2c1 121 return read();
jocis 4:923b54e7c2c1 122 }
jocis 4:923b54e7c2c1 123