Fork of Smoothie to port to mbed non-LPC targets.
Fork of Smoothie by
libs/Pwm.cpp@3:f151d08d335c, 2014-03-02 (annotated)
- Committer:
- Bigcheese
- Date:
- Sun Mar 02 06:33:08 2014 +0000
- Revision:
- 3:f151d08d335c
- Parent:
- 2:1df0b61d3b5a
Bunch of stuff. Need to locally merge in updated USB changes.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
Michael J. Spencer |
2:1df0b61d3b5a | 1 | #include "Pwm.h" |
Michael J. Spencer |
2:1df0b61d3b5a | 2 | |
Michael J. Spencer |
2:1df0b61d3b5a | 3 | #include "nuts_bolts.h" |
Michael J. Spencer |
2:1df0b61d3b5a | 4 | |
Michael J. Spencer |
2:1df0b61d3b5a | 5 | #define PID_PWM_MAX 256 |
Michael J. Spencer |
2:1df0b61d3b5a | 6 | |
Michael J. Spencer |
2:1df0b61d3b5a | 7 | // What ? |
Michael J. Spencer |
2:1df0b61d3b5a | 8 | |
Michael J. Spencer |
2:1df0b61d3b5a | 9 | Pwm::Pwm() |
Michael J. Spencer |
2:1df0b61d3b5a | 10 | { |
Michael J. Spencer |
2:1df0b61d3b5a | 11 | _max = PID_PWM_MAX - 1; |
Michael J. Spencer |
2:1df0b61d3b5a | 12 | _pwm = -1; |
Michael J. Spencer |
2:1df0b61d3b5a | 13 | } |
Michael J. Spencer |
2:1df0b61d3b5a | 14 | |
Michael J. Spencer |
2:1df0b61d3b5a | 15 | void Pwm::pwm(int new_pwm) |
Michael J. Spencer |
2:1df0b61d3b5a | 16 | { |
Michael J. Spencer |
2:1df0b61d3b5a | 17 | _pwm = confine(new_pwm, 0, _max); |
Michael J. Spencer |
2:1df0b61d3b5a | 18 | } |
Michael J. Spencer |
2:1df0b61d3b5a | 19 | |
Michael J. Spencer |
2:1df0b61d3b5a | 20 | Pwm* Pwm::max_pwm(int new_max) |
Michael J. Spencer |
2:1df0b61d3b5a | 21 | { |
Michael J. Spencer |
2:1df0b61d3b5a | 22 | _max = confine(new_max, 0, PID_PWM_MAX - 1); |
Michael J. Spencer |
2:1df0b61d3b5a | 23 | _pwm = confine( _pwm, 0, _max); |
Michael J. Spencer |
2:1df0b61d3b5a | 24 | return this; |
Michael J. Spencer |
2:1df0b61d3b5a | 25 | } |
Michael J. Spencer |
2:1df0b61d3b5a | 26 | |
Michael J. Spencer |
2:1df0b61d3b5a | 27 | int Pwm::max_pwm() |
Michael J. Spencer |
2:1df0b61d3b5a | 28 | { |
Michael J. Spencer |
2:1df0b61d3b5a | 29 | return _max; |
Michael J. Spencer |
2:1df0b61d3b5a | 30 | } |
Michael J. Spencer |
2:1df0b61d3b5a | 31 | |
Michael J. Spencer |
2:1df0b61d3b5a | 32 | void Pwm::set(bool value) |
Michael J. Spencer |
2:1df0b61d3b5a | 33 | { |
Michael J. Spencer |
2:1df0b61d3b5a | 34 | _pwm = -1; |
Michael J. Spencer |
2:1df0b61d3b5a | 35 | Pin::set(value); |
Michael J. Spencer |
2:1df0b61d3b5a | 36 | } |
Michael J. Spencer |
2:1df0b61d3b5a | 37 | |
Michael J. Spencer |
2:1df0b61d3b5a | 38 | uint32_t Pwm::on_tick(uint32_t dummy) |
Michael J. Spencer |
2:1df0b61d3b5a | 39 | { |
Michael J. Spencer |
2:1df0b61d3b5a | 40 | if ((_pwm < 0) || (_pwm >= PID_PWM_MAX)) |
Michael J. Spencer |
2:1df0b61d3b5a | 41 | return dummy; |
Michael J. Spencer |
2:1df0b61d3b5a | 42 | |
Michael J. Spencer |
2:1df0b61d3b5a | 43 | /* |
Michael J. Spencer |
2:1df0b61d3b5a | 44 | * Sigma-Delta PWM algorithm |
Michael J. Spencer |
2:1df0b61d3b5a | 45 | * |
Michael J. Spencer |
2:1df0b61d3b5a | 46 | * This Sigma-Delta implementation works by increasing _sd_accumulator by _pwm until we reach _half_ of max, |
Michael J. Spencer |
2:1df0b61d3b5a | 47 | * then decreasing by (max - target_pwm) until we hit zero |
Michael J. Spencer |
2:1df0b61d3b5a | 48 | * |
Michael J. Spencer |
2:1df0b61d3b5a | 49 | * While we're increasing, the output is 0 and while we're decreasing the output is 1 |
Michael J. Spencer |
2:1df0b61d3b5a | 50 | * |
Michael J. Spencer |
2:1df0b61d3b5a | 51 | * For example, with pwm=128 and a max of 256, we'll see the following pattern: |
Michael J. Spencer |
2:1df0b61d3b5a | 52 | * ACC ADD OUT |
Michael J. Spencer |
2:1df0b61d3b5a | 53 | * 0 128 1 // after the add, we hit 256/2 = 128 so we change direction |
Michael J. Spencer |
2:1df0b61d3b5a | 54 | * 128 -128 0 // after the add, we hit 0 so we change direction again |
Michael J. Spencer |
2:1df0b61d3b5a | 55 | * 0 128 1 |
Michael J. Spencer |
2:1df0b61d3b5a | 56 | * 128 -128 0 |
Michael J. Spencer |
2:1df0b61d3b5a | 57 | * as expected |
Michael J. Spencer |
2:1df0b61d3b5a | 58 | * |
Michael J. Spencer |
2:1df0b61d3b5a | 59 | * with a pwm value of 192 (75%) we'll see this: |
Michael J. Spencer |
2:1df0b61d3b5a | 60 | * ACC ADD OUT |
Michael J. Spencer |
2:1df0b61d3b5a | 61 | * 0 192 0 // after the add, we are beyond max/2 so we change direction |
Michael J. Spencer |
2:1df0b61d3b5a | 62 | * 192 -64 1 // haven't reached 0 yet |
Michael J. Spencer |
2:1df0b61d3b5a | 63 | * 128 -64 1 // haven't reached 0 yet |
Michael J. Spencer |
2:1df0b61d3b5a | 64 | * 64 -64 1 // after this add we reach 0, and change direction |
Michael J. Spencer |
2:1df0b61d3b5a | 65 | * 0 192 0 |
Michael J. Spencer |
2:1df0b61d3b5a | 66 | * 192 -64 1 |
Michael J. Spencer |
2:1df0b61d3b5a | 67 | * 128 -64 1 |
Michael J. Spencer |
2:1df0b61d3b5a | 68 | * 64 -64 1 |
Michael J. Spencer |
2:1df0b61d3b5a | 69 | * 0 192 0 |
Michael J. Spencer |
2:1df0b61d3b5a | 70 | * etcetera |
Michael J. Spencer |
2:1df0b61d3b5a | 71 | * |
Michael J. Spencer |
2:1df0b61d3b5a | 72 | * with a pwm value of 75 (about 29%) we'll see this pattern: |
Michael J. Spencer |
2:1df0b61d3b5a | 73 | * ACC ADD OUT |
Michael J. Spencer |
2:1df0b61d3b5a | 74 | * 0 75 0 |
Michael J. Spencer |
2:1df0b61d3b5a | 75 | * 75 75 0 |
Michael J. Spencer |
2:1df0b61d3b5a | 76 | * 150 -181 1 |
Michael J. Spencer |
2:1df0b61d3b5a | 77 | * -31 75 0 |
Michael J. Spencer |
2:1df0b61d3b5a | 78 | * 44 75 0 |
Michael J. Spencer |
2:1df0b61d3b5a | 79 | * 119 75 0 |
Michael J. Spencer |
2:1df0b61d3b5a | 80 | * 194 -181 1 |
Michael J. Spencer |
2:1df0b61d3b5a | 81 | * 13 -181 1 |
Michael J. Spencer |
2:1df0b61d3b5a | 82 | * -168 75 0 |
Michael J. Spencer |
2:1df0b61d3b5a | 83 | * -93 75 0 |
Michael J. Spencer |
2:1df0b61d3b5a | 84 | * -18 75 0 |
Michael J. Spencer |
2:1df0b61d3b5a | 85 | * 57 75 0 |
Michael J. Spencer |
2:1df0b61d3b5a | 86 | * 132 -181 1 |
Michael J. Spencer |
2:1df0b61d3b5a | 87 | * -49 75 0 |
Michael J. Spencer |
2:1df0b61d3b5a | 88 | * 26 75 0 |
Michael J. Spencer |
2:1df0b61d3b5a | 89 | * 101 75 0 |
Michael J. Spencer |
2:1df0b61d3b5a | 90 | * 176 -181 1 |
Michael J. Spencer |
2:1df0b61d3b5a | 91 | * -5 75 0 |
Michael J. Spencer |
2:1df0b61d3b5a | 92 | * 70 75 0 |
Michael J. Spencer |
2:1df0b61d3b5a | 93 | * 145 -181 1 |
Michael J. Spencer |
2:1df0b61d3b5a | 94 | * -36 75 0 |
Michael J. Spencer |
2:1df0b61d3b5a | 95 | * 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 |
Michael J. Spencer |
2:1df0b61d3b5a | 96 | */ |
Michael J. Spencer |
2:1df0b61d3b5a | 97 | |
Michael J. Spencer |
2:1df0b61d3b5a | 98 | // this line should never actually do anything, it's just a sanity check in case our accumulator gets corrupted somehow. |
Michael J. Spencer |
2:1df0b61d3b5a | 99 | // If we didn't check and the accumulator is corrupted, we could leave a heater on for quite a long time |
Michael J. Spencer |
2:1df0b61d3b5a | 100 | // the accumulator is kept within these limits by the normal operation of the Sigma-Delta algorithm |
Michael J. Spencer |
2:1df0b61d3b5a | 101 | _sd_accumulator = confine(_sd_accumulator, -PID_PWM_MAX, PID_PWM_MAX << 1); |
Michael J. Spencer |
2:1df0b61d3b5a | 102 | |
Michael J. Spencer |
2:1df0b61d3b5a | 103 | // when _sd_direction == false, our output is 0 and our accumulator is increasing by _pwm |
Michael J. Spencer |
2:1df0b61d3b5a | 104 | if (_sd_direction == false) |
Michael J. Spencer |
2:1df0b61d3b5a | 105 | { |
Michael J. Spencer |
2:1df0b61d3b5a | 106 | // increment accumulator |
Michael J. Spencer |
2:1df0b61d3b5a | 107 | _sd_accumulator += _pwm; |
Michael J. Spencer |
2:1df0b61d3b5a | 108 | // if we've reached half of max, flip our direction |
Michael J. Spencer |
2:1df0b61d3b5a | 109 | if (_sd_accumulator >= (PID_PWM_MAX >> 1)) |
Michael J. Spencer |
2:1df0b61d3b5a | 110 | _sd_direction = true; |
Michael J. Spencer |
2:1df0b61d3b5a | 111 | } |
Michael J. Spencer |
2:1df0b61d3b5a | 112 | // when _sd_direction == true, our output is 1 and our accumulator is decreasing by (MAX - _pwm) |
Michael J. Spencer |
2:1df0b61d3b5a | 113 | else |
Michael J. Spencer |
2:1df0b61d3b5a | 114 | { |
Michael J. Spencer |
2:1df0b61d3b5a | 115 | // decrement accumulator |
Michael J. Spencer |
2:1df0b61d3b5a | 116 | _sd_accumulator -= (PID_PWM_MAX - _pwm); |
Michael J. Spencer |
2:1df0b61d3b5a | 117 | // if we've reached 0, flip our direction |
Michael J. Spencer |
2:1df0b61d3b5a | 118 | if (_sd_accumulator <= 0) |
Michael J. Spencer |
2:1df0b61d3b5a | 119 | _sd_direction = false; |
Michael J. Spencer |
2:1df0b61d3b5a | 120 | } |
Michael J. Spencer |
2:1df0b61d3b5a | 121 | Pin::set(_sd_direction); |
Michael J. Spencer |
2:1df0b61d3b5a | 122 | |
Michael J. Spencer |
2:1df0b61d3b5a | 123 | return dummy; |
Michael J. Spencer |
2:1df0b61d3b5a | 124 | } |