Fork of Smoothie to port to mbed non-LPC targets.

Dependencies:   mbed

Fork of Smoothie by Stéphane Cachat

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers Pwm.cpp Source File

Pwm.cpp

00001 #include "Pwm.h"
00002 
00003 #include "nuts_bolts.h"
00004 
00005 #define PID_PWM_MAX 256
00006 
00007 // What ?
00008 
00009 Pwm::Pwm()
00010 {
00011     _max = PID_PWM_MAX - 1;
00012     _pwm = -1;
00013 }
00014 
00015 void Pwm::pwm(int new_pwm)
00016 {
00017     _pwm = confine(new_pwm, 0, _max);
00018 }
00019 
00020 Pwm* Pwm::max_pwm(int new_max)
00021 {
00022     _max = confine(new_max, 0, PID_PWM_MAX - 1);
00023     _pwm = confine(   _pwm, 0, _max);
00024     return this;
00025 }
00026 
00027 int Pwm::max_pwm()
00028 {
00029     return _max;
00030 }
00031 
00032 void Pwm::set(bool value)
00033 {
00034     _pwm = -1;
00035     Pin::set(value);
00036 }
00037 
00038 uint32_t Pwm::on_tick(uint32_t dummy)
00039 {
00040     if ((_pwm < 0) || (_pwm >= PID_PWM_MAX))
00041         return dummy;
00042 
00043     /*
00044      * Sigma-Delta PWM algorithm
00045      *
00046      * This Sigma-Delta implementation works by increasing _sd_accumulator by _pwm until we reach _half_ of max,
00047      * then decreasing by (max - target_pwm) until we hit zero
00048      *
00049      * While we're increasing, the output is 0 and while we're decreasing the output is 1
00050      *
00051      * For example, with pwm=128 and a max of 256, we'll see the following pattern:
00052      * ACC  ADD OUT
00053      *   0  128   1 // after the add, we hit 256/2 = 128 so we change direction
00054      * 128 -128   0 // after the add, we hit 0 so we change direction again
00055      *   0  128   1
00056      * 128 -128   0
00057      *  as expected
00058      *
00059      * with a pwm value of 192 (75%) we'll see this:
00060      *  ACC  ADD OUT
00061      *    0  192   0 // after the add, we are beyond max/2 so we change direction
00062      *  192  -64   1 // haven't reached 0 yet
00063      *  128  -64   1 // haven't reached 0 yet
00064      *   64  -64   1 // after this add we reach 0, and change direction
00065      *    0  192   0
00066      *  192  -64   1
00067      *  128  -64   1
00068      *   64  -64   1
00069      *    0  192   0
00070      * etcetera
00071      *
00072      * with a pwm value of 75 (about 29%) we'll see this pattern:
00073      *  ACC  ADD OUT
00074      *    0   75   0
00075      *   75   75   0
00076      *  150 -181   1
00077      *  -31   75   0
00078      *   44   75   0
00079      *  119   75   0
00080      *  194 -181   1
00081      *   13 -181   1
00082      * -168   75   0
00083      *  -93   75   0
00084      *  -18   75   0
00085      *   57   75   0
00086      *  132 -181   1
00087      *  -49   75   0
00088      *   26   75   0
00089      *  101   75   0
00090      *  176 -181   1
00091      *   -5   75   0
00092      *   70   75   0
00093      *  145 -181   1
00094      *  -36   75   0
00095      * etcetera. This pattern has 6 '1's over a total of 21 lines which is on 28.57% of the time. If we let it run longer, it would get closer to the target as time went on
00096      */
00097 
00098     // this line should never actually do anything, it's just a sanity check in case our accumulator gets corrupted somehow.
00099     // If we didn't check and the accumulator is corrupted, we could leave a heater on for quite a long time
00100     // the accumulator is kept within these limits by the normal operation of the Sigma-Delta algorithm
00101     _sd_accumulator = confine(_sd_accumulator, -PID_PWM_MAX, PID_PWM_MAX << 1);
00102 
00103     // when _sd_direction == false, our output is 0 and our accumulator is increasing by _pwm
00104     if (_sd_direction == false)
00105     {
00106         // increment accumulator
00107         _sd_accumulator += _pwm;
00108         // if we've reached half of max, flip our direction
00109         if (_sd_accumulator >= (PID_PWM_MAX >> 1))
00110             _sd_direction = true;
00111     }
00112     // when _sd_direction == true, our output is 1 and our accumulator is decreasing by (MAX - _pwm)
00113     else
00114     {
00115         // decrement accumulator
00116         _sd_accumulator -= (PID_PWM_MAX - _pwm);
00117         // if we've reached 0, flip our direction
00118         if (_sd_accumulator <= 0)
00119             _sd_direction = false;
00120     }
00121     Pin::set(_sd_direction);
00122 
00123     return dummy;
00124 }