enabled specifying numeric config values using all strtof capabilities
[clinton/Smoothieware.git] / src / libs / Pwm.cpp
CommitLineData
11f8ba4e
MM
1#include "Pwm.h"
2
3#include "nuts_bolts.h"
4
5#define PID_PWM_MAX 256
6
93694d6b
AW
7// What ?
8
11f8ba4e
MM
9Pwm::Pwm()
10{
11 _max = PID_PWM_MAX - 1;
12 _pwm = -1;
11f8ba4e
MM
13}
14
15void Pwm::pwm(int new_pwm)
16{
17 _pwm = confine(new_pwm, 0, _max);
18}
19
20Pwm* Pwm::max_pwm(int new_max)
21{
6377620d 22 _max = confine(new_max, 0, PID_PWM_MAX - 1);
a7f12bed 23 _pwm = confine( _pwm, 0, _max);
11f8ba4e
MM
24 return this;
25}
26
27int Pwm::max_pwm()
28{
29 return _max;
30}
31
32void Pwm::set(bool value)
33{
34 _pwm = -1;
cb3460e9 35 Pin::set(value);
11f8ba4e
MM
36}
37
38uint32_t Pwm::on_tick(uint32_t dummy)
39{
40 if ((_pwm < 0) || (_pwm >= PID_PWM_MAX))
41 return dummy;
42
b0c686e6
MM
43 /*
44 * Sigma-Delta PWM algorithm
45 *
46 * This Sigma-Delta implementation works by increasing _sd_accumulator by _pwm until we reach _half_ of max,
47 * then decreasing by (max - target_pwm) until we hit zero
48 *
49 * While we're increasing, the output is 0 and while we're decreasing the output is 1
50 *
51 * For example, with pwm=128 and a max of 256, we'll see the following pattern:
52 * ACC ADD OUT
53 * 0 128 1 // after the add, we hit 256/2 = 128 so we change direction
54 * 128 -128 0 // after the add, we hit 0 so we change direction again
55 * 0 128 1
56 * 128 -128 0
57 * as expected
58 *
59 * with a pwm value of 192 (75%) we'll see this:
60 * ACC ADD OUT
61 * 0 192 0 // after the add, we are beyond max/2 so we change direction
62 * 192 -64 1 // haven't reached 0 yet
63 * 128 -64 1 // haven't reached 0 yet
64 * 64 -64 1 // after this add we reach 0, and change direction
65 * 0 192 0
66 * 192 -64 1
67 * 128 -64 1
68 * 64 -64 1
69 * 0 192 0
70 * etcetera
71 *
72 * with a pwm value of 75 (about 29%) we'll see this pattern:
73 * ACC ADD OUT
74 * 0 75 0
75 * 75 75 0
76 * 150 -181 1
77 * -31 75 0
78 * 44 75 0
79 * 119 75 0
80 * 194 -181 1
81 * 13 -181 1
82 * -168 75 0
83 * -93 75 0
84 * -18 75 0
85 * 57 75 0
86 * 132 -181 1
87 * -49 75 0
88 * 26 75 0
89 * 101 75 0
90 * 176 -181 1
91 * -5 75 0
92 * 70 75 0
93 * 145 -181 1
94 * -36 75 0
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
96 */
97
98 // this line should never actually do anything, it's just a sanity check in case our accumulator gets corrupted somehow.
99 // If we didn't check and the accumulator is corrupted, we could leave a heater on for quite a long time
100 // the accumulator is kept within these limits by the normal operation of the Sigma-Delta algorithm
11f8ba4e
MM
101 _sd_accumulator = confine(_sd_accumulator, -PID_PWM_MAX, PID_PWM_MAX << 1);
102
b0c686e6 103 // when _sd_direction == false, our output is 0 and our accumulator is increasing by _pwm
11f8ba4e
MM
104 if (_sd_direction == false)
105 {
b0c686e6 106 // increment accumulator
11f8ba4e 107 _sd_accumulator += _pwm;
b0c686e6 108 // if we've reached half of max, flip our direction
11f8ba4e
MM
109 if (_sd_accumulator >= (PID_PWM_MAX >> 1))
110 _sd_direction = true;
111 }
b0c686e6 112 // when _sd_direction == true, our output is 1 and our accumulator is decreasing by (MAX - _pwm)
11f8ba4e
MM
113 else
114 {
b0c686e6 115 // decrement accumulator
11f8ba4e 116 _sd_accumulator -= (PID_PWM_MAX - _pwm);
b0c686e6 117 // if we've reached 0, flip our direction
11f8ba4e
MM
118 if (_sd_accumulator <= 0)
119 _sd_direction = false;
120 }
cb3460e9 121 Pin::set(_sd_direction);
11f8ba4e
MM
122
123 return dummy;
124}