Fork of Smoothie to port to mbed non-LPC targets.
Fork of Smoothie by
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 }
Generated on Tue Jul 12 2022 20:09:02 by 1.7.2