Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
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 | } |
