1
1
/*
2
- ESP32 PWM, SERVO and TONE Library, Version 5.0.1
2
+ ESP32 PWM, SERVO and TONE Library, Version 5.0.2
3
3
by dlloydev https://github.com/Dlloydev/ESP32-ESP32S2-AnalogWrite
4
4
License: MIT
5
5
*/
@@ -45,90 +45,20 @@ float Pwm::write(int pin, uint32_t duty, uint32_t frequency, uint8_t resolution,
45
45
return mem[ch].frequency ;
46
46
}
47
47
48
- float Pwm::writeServo (int pin, float value, double speed, double ke) {
49
- uint8_t ch = attached (pin);
50
- wr_servo (pin, value, speed, ke);
51
- return mem[ch].ye ; // normalized easing position (0.0 - 1.0)
52
- }
53
-
54
- float Pwm::writeServo (int pin, float value) {
48
+ uint8_t Pwm::attach (int pin) {
55
49
uint8_t ch = attached (pin);
56
50
if (ch == 253 ) { // free channels exist
57
51
for (uint8_t c = 0 ; c < chMax; c++) {
58
52
if (mem[c].pin == 255 && ch == 253 ) { // first free ch
59
53
mem[c].pin = pin;
60
54
ch = c;
61
- if (mem[ch].frequency < 40 || mem[ch].frequency > 900 ) mem[ch].frequency = 50 ;
62
- if (mem[ch].resolution > widthMax) mem[ch].resolution = widthMax;
63
- else if (mem[ch].resolution < 14 && widthMax == 20 ) mem[ch].resolution = 16 ;
64
- else if (mem[ch].resolution < 14 ) mem[ch].resolution = 14 ;
65
55
ledcSetup (ch, mem[ch].frequency , mem[ch].resolution );
66
56
if (sync) pause (ch);
67
57
ledcAttachPin (pin, ch);
58
+ return ch;
68
59
}
69
60
}
70
61
}
71
- wr_servo (pin, value, mem[ch].speed , mem[ch].ke );
72
- return mem[ch].ye ; // normalized easing position (0.0 - 1.0)
73
- }
74
-
75
- void Pwm::tone (int pin, uint32_t frequency, uint16_t duration, uint16_t interval) {
76
- uint8_t ch = attach (pin);
77
- if (ch < chMax) {
78
- uint32_t ms = millis ();
79
- static bool durDone = false ;
80
- #if defined(CONFIG_IDF_TARGET_ESP32C3)
81
- if (frequency < 153 ) frequency = 153 ;
82
- #else
83
- if (frequency < 4 ) frequency = 4 ;
84
- #endif
85
- if (!durDone) {
86
- if (frequency != mem[ch].frequency && (ms - mem[ch].startMs > interval)) {
87
- mem[ch].startMs = ms;
88
- mem[ch].frequency = frequency;
89
- ledcChangeFrequency (ch, frequency, mem[ch].resolution );
90
- write (pin, 127 , frequency, 8 );
91
- resume (ch);
92
- }
93
- if ((duration && ((ms - mem[ch].startMs ) > duration)) || (duration == 0 )) {
94
- mem[ch].startMs = ms;
95
- durDone = true ;
96
- if (duration < 0xffff ) pause (ch);
97
- }
98
- } else if (ms - mem[ch].startMs > interval) durDone = false ;
99
- }
100
- }
101
-
102
- void Pwm::note (int pin, note_t note, uint8_t octave, uint16_t duration, uint16_t interval) {
103
- const uint16_t noteFrequencyBase[12 ] = {
104
- // C C# D Eb E F F# G G# A Bb B
105
- 4186 , 4435 , 4699 , 4978 , 5274 , 5588 , 5920 , 6272 , 6645 , 7040 , 7459 , 7902
106
- };
107
- uint32_t noteFreq = (uint32_t )noteFrequencyBase[note] / (uint32_t )(1 << (8 - octave));
108
- if (octave <= 8 || note <= NOTE_MAX) tone (pin, noteFreq, duration, interval);
109
- }
110
-
111
- float Pwm::read (int pin) {
112
- uint8_t ch = attached (pin);
113
- if (ch < chMax) {
114
- float deg = (readMicroseconds (pin) - mem[ch].servoMinUs ) / (mem[ch].servoMaxUs - mem[ch].servoMinUs ) * 180.0 ;
115
- return deg < 0 ? 0 : deg;
116
- }
117
- else return 0 ;
118
- }
119
-
120
- float Pwm::readMicroseconds (int pin) {
121
- uint8_t ch = attached (pin);
122
- if (ch < chMax) return mem[ch].duty * ((1000000.0 / mem[ch].frequency ) / ((1 << mem[ch].resolution ) - 1.0 )); // μs
123
- else return 0 ;
124
- }
125
-
126
- uint8_t Pwm::attach (int pin) {
127
- uint8_t ch = firstFreeCh ();
128
- if (ch < chMax) mem[ch].pin = pin;
129
- ledcSetup (ch, mem[ch].frequency , mem[ch].resolution );
130
- if (sync) pause (ch);
131
- ledcAttachPin (pin, ch);
132
62
return ch;
133
63
}
134
64
@@ -180,8 +110,7 @@ uint8_t Pwm::attachServo(int pin, int ch) {
180
110
181
111
uint8_t Pwm::attachServo (int pin, int ch, bool invert) {
182
112
if (ch < chMax) config_servo (ch, mem[ch].servoMinUs , mem[ch].servoMaxUs );
183
- uint8_t chan = (invert) ? attachInvert (pin, ch) : attach (pin, ch);
184
- return chan;
113
+ return (invert) ? attachInvert (pin, ch) : attach (pin, ch);
185
114
}
186
115
187
116
uint8_t Pwm::attachServo (int pin, int minUs, int maxUs) {
@@ -197,8 +126,7 @@ uint8_t Pwm::attachServo(int pin, int ch, int minUs, int maxUs) {
197
126
198
127
uint8_t Pwm::attachServo (int pin, int ch, int minUs, int maxUs, bool invert) {
199
128
config_servo (ch, minUs, maxUs);
200
- uint8_t chan = (invert) ? attachInvert (pin, ch) : attach (pin, ch);
201
- return chan;
129
+ return (invert) ? attachInvert (pin, ch) : attach (pin, ch);
202
130
}
203
131
204
132
uint8_t Pwm::attachServo (int pin, int minUs, int maxUs, double speed, double ke) {
@@ -214,8 +142,85 @@ uint8_t Pwm::attachServo(int pin, int ch, int minUs, int maxUs, double speed, do
214
142
215
143
uint8_t Pwm::attachServo (int pin, int ch, int minUs, int maxUs, double speed, double ke, bool invert) {
216
144
config_servo (ch, minUs, maxUs, speed, ke);
217
- uint8_t chan = (invert) ? attachInvert (pin, ch) : attach (pin, ch);
218
- return chan;
145
+ return (invert) ? attachInvert (pin, ch) : attach (pin, ch);
146
+ }
147
+
148
+ float Pwm::read (int pin) {
149
+ uint8_t ch = attached (pin);
150
+ if (ch < chMax) {
151
+ float deg = (readMicroseconds (pin) - mem[ch].servoMinUs ) / (mem[ch].servoMaxUs - mem[ch].servoMinUs ) * 180.0 ;
152
+ return deg < 0 ? 0 : deg;
153
+ }
154
+ else return 0 ;
155
+ }
156
+
157
+ float Pwm::readMicroseconds (int pin) {
158
+ uint8_t ch = attached (pin);
159
+ if (ch < chMax) return mem[ch].duty * ((1000000.0 / mem[ch].frequency ) / ((1 << mem[ch].resolution ) - 1.0 )); // μs
160
+ else return 0 ;
161
+ }
162
+
163
+ float Pwm::writeServo (int pin, float value, double speed, double ke) {
164
+ uint8_t ch = attached (pin);
165
+ wr_servo (pin, value, speed, ke);
166
+ return mem[ch].ye ; // normalized easing position (0.0 - 1.0)
167
+ }
168
+
169
+ float Pwm::writeServo (int pin, float value) {
170
+ uint8_t ch = attached (pin);
171
+ if (ch == 253 ) { // free channels exist
172
+ for (uint8_t c = 0 ; c < chMax; c++) {
173
+ if (mem[c].pin == 255 && ch == 253 ) { // first free ch
174
+ mem[c].pin = pin;
175
+ ch = c;
176
+ if (mem[ch].frequency < 40 || mem[ch].frequency > 900 ) mem[ch].frequency = 50 ;
177
+ if (mem[ch].resolution > widthMax) mem[ch].resolution = widthMax;
178
+ else if (mem[ch].resolution < 14 && widthMax == 20 ) mem[ch].resolution = 16 ;
179
+ else if (mem[ch].resolution < 14 ) mem[ch].resolution = 14 ;
180
+ ledcSetup (ch, mem[ch].frequency , mem[ch].resolution );
181
+ if (sync) pause (ch);
182
+ ledcAttachPin (pin, ch);
183
+ }
184
+ }
185
+ }
186
+ wr_servo (pin, value, mem[ch].speed , mem[ch].ke );
187
+ return mem[ch].ye ; // normalized easing position (0.0 - 1.0)
188
+ }
189
+
190
+ void Pwm::tone (int pin, uint32_t frequency, uint16_t duration, uint16_t interval) {
191
+ uint8_t ch = attach (pin);
192
+ if (ch < chMax) {
193
+ uint32_t ms = millis ();
194
+ static bool durDone = false ;
195
+ #if defined(CONFIG_IDF_TARGET_ESP32C3)
196
+ if (frequency < 153 ) frequency = 153 ;
197
+ #else
198
+ if (frequency < 4 ) frequency = 4 ;
199
+ #endif
200
+ if (!durDone) {
201
+ if (frequency != mem[ch].frequency && (ms - mem[ch].startMs > interval)) {
202
+ mem[ch].startMs = ms;
203
+ mem[ch].frequency = frequency;
204
+ ledcChangeFrequency (ch, frequency, mem[ch].resolution );
205
+ write (pin, 127 , frequency, 8 );
206
+ resume (ch);
207
+ }
208
+ if ((duration && ((ms - mem[ch].startMs ) > duration)) || (duration == 0 )) {
209
+ mem[ch].startMs = ms;
210
+ durDone = true ;
211
+ if (duration < 0xffff ) pause (ch);
212
+ }
213
+ } else if (ms - mem[ch].startMs > interval) durDone = false ;
214
+ }
215
+ }
216
+
217
+ void Pwm::note (int pin, note_t note, uint8_t octave, uint16_t duration, uint16_t interval) {
218
+ const uint16_t noteFrequencyBase[12 ] = {
219
+ // C C# D Eb E F F# G G# A Bb B
220
+ 4186 , 4435 , 4699 , 4978 , 5274 , 5588 , 5920 , 6272 , 6645 , 7040 , 7459 , 7902
221
+ };
222
+ uint32_t noteFreq = (uint32_t )noteFrequencyBase[note] / (uint32_t )(1 << (8 - octave));
223
+ if (octave <= 8 || note <= NOTE_MAX) tone (pin, noteFreq, duration, interval);
219
224
}
220
225
221
226
uint8_t Pwm::attached (int pin) {
@@ -243,9 +248,9 @@ void Pwm::detach(int pin) {
243
248
uint8_t ch = attached (pin);
244
249
if (ch < chMax) {
245
250
reset_fields (ch);
246
- if (digitalRead (pin) == HIGH) delay ( 3 ); // wait until low
247
- ledcWrite (ch, 4 ); // minimal duty for jitterless detach
248
- ledcDetachPin (mem[ch].pin );
251
+ if (digitalRead (pin) == HIGH) delayMicroseconds (mem[ch]. servoMaxUs ); // wait until LOW
252
+ ledcWrite (ch, 4 ); // set minimal duty
253
+ ledcDetachPin (mem[ch].pin ); // jitterless
249
254
REG_SET_FIELD (GPIO_PIN_MUX_REG[pin], MCU_SEL, GPIO_MODE_DEF_DISABLE);
250
255
}
251
256
}
0 commit comments