Skip to content

Commit 5584857

Browse files
committed
Bumped version to 3.5.0 - Fixed serious bug in reattach();
1 parent 7afa070 commit 5584857

File tree

10 files changed

+158
-73
lines changed

10 files changed

+158
-73
lines changed

README.md

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ For instructions how to enable these alternatives, see [Compile options / macros
9393
- **Float angels** are supported to allow **fine-grained servo control** comparable to using microseconds.
9494
- **User-specified callback function at "servo arrived" enables movement control independent of main loop**.
9595
- **Stop and resume** of servo movement.
96-
- **Detach and reattach**. No servo signal is generated for a detached servo. Therefore, it is not blocked and can be moved manually.
96+
- **Detach and reattach**. No servo signal is generated for a detached servo / the output is constant LOW. Therefore, it is not blocked and can be moved manually.
9797
- A **trim value** can be set for any servo. Its value is internally added to each requested position.
9898
- **Reverse operation** of servo is possible e.g. if it is mounted head down.
9999
- **Constraints for minimum and maximum servo degree** can be specified. Trim and reverse are applied after constraint processing.
@@ -190,8 +190,8 @@ You can handle multiple servos simultaneously by [special functions](https://git
190190
<br/>
191191

192192
# Initial movement of Servo
193-
**Servos are buld to reach the target position as fast as possible.**
194-
To achieve slow movement, this library gradually adjusts the target position,
193+
**Servos are build to reach the target position as fast as possible.**
194+
To achieve slow movement, this library gradually adjusts the target position,
195195
and the servo attempts to respond to these changes as quickly as possible.
196196
This creates the appearance of slow movement even when the servo reacts very quickly.<br/>
197197
Initially, after powering on, the software has no information about the actual servo position!<br/>
@@ -448,6 +448,12 @@ This will print internal information visible in the Arduino *Serial Monitor* whi
448448
<br/>
449449

450450
# Revision History
451+
### Version 3.5.0
452+
- Fixed serious bug in reattach();
453+
- Renamed InitializeAndCheckI2CConnection() to initializeAndCheckI2CConnection().
454+
- Renamed applyTrimAndreverseToTargetMicrosecondsOrUnits() to applyTrimAndReverseToTargetMicrosecondsOrUnits().
455+
- Housekeeping.
456+
451457
### Version 3.4.0
452458
- LightweightServo support for ATmega2560.
453459
- Renamed `mCurrentMicrosecondsOrUnits` to `mLastTargetMicrosecondsOrUnits` to make clear, that trim and reverse is NOT applied to this value.

examples/OneServo/OneServo.ino

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
*
44
* Shows smooth linear movement from one servo position to another in different flavors.
55
*
6-
* Copyright (C) 2019-2024 Armin Joachimsmeyer
6+
* Copyright (C) 2019-2025 Armin Joachimsmeyer
77
88
*
99
* This file is part of ServoEasing https://github.com/ArminJo/ServoEasing.
@@ -81,6 +81,7 @@ ServoEasing Servo1;
8181
#endif
8282

8383
#define START_DEGREE_VALUE 0 // The degree value written to the servo at time of attach.
84+
#define DELAY_BETWEEN_ACTIONS_MILLIS 1000
8485
void blinkLED();
8586

8687
void setup() {
@@ -124,7 +125,7 @@ void setup() {
124125
}
125126

126127
// Wait for servo to reach start position.
127-
delay(2000);
128+
delay(DELAY_BETWEEN_ACTIONS_MILLIS);
128129
#if defined(PRINT_FOR_SERIAL_PLOTTER)
129130
// Legend for Arduino Serial plotter
130131
Serial.println(); // end of line of attach values
@@ -158,13 +159,13 @@ void loop() {
158159
} while (!Servo1.update());
159160
#endif
160161

161-
delay(1000);
162+
delay(DELAY_BETWEEN_ACTIONS_MILLIS);
162163

163164
#if !defined(PRINT_FOR_SERIAL_PLOTTER)
164165
Serial.println(F("Move to 45 degree in one second using interrupts"));
165166
Serial.flush(); // Just in case interrupts do not work
166167
#endif
167-
Servo1.startEaseToD(45, 1000);
168+
Servo1.startEaseToD(45, MILLIS_IN_ONE_SECOND);
168169
// Servo1.startEaseToD((544 + ((2400 - 544) / 4)), 1000); // Alternatively you can specify the target as microsecond value
169170
// Blink until servo stops
170171
while (Servo1.isMoving()) {
@@ -174,15 +175,15 @@ void loop() {
174175
blinkLED();
175176
}
176177

177-
delay(2000); // wait one second after servo has arrived at target position
178+
delay(DELAY_BETWEEN_ACTIONS_MILLIS);
178179

179180
#if !defined(PRINT_FOR_SERIAL_PLOTTER)
180181
Serial.println(F("Move to 135 degree and back nonlinear in one second each using interrupts"));
181182
#endif
182183
Servo1.setEasingType(EASE_CUBIC_IN_OUT); // EASE_LINEAR is default
183184

184185
for (int i = 0; i < 2; ++i) {
185-
Servo1.startEaseToD(135, 1000);
186+
Servo1.startEaseToD(135, MILLIS_IN_ONE_SECOND);
186187
// Servo1.startEaseToD((544 + (((2400 - 544) / 4) * 3)), 1000); // Alternatively you can specify the target as microsecond value
187188
// isMoving() calls yield for the ESP8266 boards
188189
while (Servo1.isMoving()) {
@@ -207,7 +208,7 @@ void loop() {
207208
}
208209
Servo1.setEasingType(EASE_LINEAR);
209210

210-
delay(2000); // wait one second after servo has arrived at target position
211+
delay(DELAY_BETWEEN_ACTIONS_MILLIS);
211212

212213
/*
213214
* The LED goes on if servo reaches 120 degree
@@ -227,7 +228,7 @@ void loop() {
227228
; // Here you can insert your own code
228229
}
229230

230-
delay(1000);
231+
delay(DELAY_BETWEEN_ACTIONS_MILLIS);
231232

232233
/*
233234
* The LED goes off when servo theoretical reaches 90 degree
@@ -238,7 +239,7 @@ void loop() {
238239
Servo1.startEaseTo(0, 90, START_UPDATE_BY_INTERRUPT);
239240
// Servo1.startEaseTo(DEFAULT_MICROSECONDS_FOR_0_DEGREE, 360, true); // Alternatively you can specify the target as microsecond value
240241
// Wait. The servo should have moved 90 degree.
241-
delay(1000);
242+
delay(MILLIS_IN_ONE_SECOND);
242243
digitalWrite(LED_BUILTIN, LOW);
243244

244245
#if !defined(DISABLE_PAUSE_RESUME)
@@ -249,24 +250,30 @@ void loop() {
249250
* Demonstrate pause and resume in the middle of a movement
250251
*/
251252
Servo1.pause();
252-
delay(1000);
253+
delay(MILLIS_IN_ONE_SECOND);
253254
// resume movement using interrupts
254255
Servo1.resumeWithInterrupts();
255256
#endif
256257
while (Servo1.isMoving())
257258
; // wait for servo to stop
258259

259260
# if !defined(PRINT_FOR_SERIAL_PLOTTER)
260-
Serial.println(F("Detach the servo for 5 seconds. During this time you can move the servo manually."));
261+
Serial.println(F("Detach the servo for 10 seconds. During this time you can move the servo manually."));
261262
# endif
262263

263264
Servo1.detach();
264265
/*
265-
* After detach the servo is "not powered" for 5 seconds, i.e. no servo signal is generated.
266+
* After detach the servo is "not powered" for 10 seconds, i.e. no servo signal is generated.
266267
* This allows you to easily move the servo manually.
267268
*/
268-
delay(5000); // wait 5 seconds
269-
Servo1.attach(SERVO1_PIN, 0);
269+
delay(10000); // wait 10 seconds
270+
271+
# if !defined(PRINT_FOR_SERIAL_PLOTTER)
272+
Serial.println(F("Reattach the servo and wait for 3 seconds."));
273+
# endif
274+
Servo1.reattach();
275+
276+
delay(3000); // wait extra 3 seconds after reattach()
270277
}
271278

272279
void blinkLED() {

examples/PCA9685_Expander/PCA9685_Expander.ino

Lines changed: 38 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
*
77
* Shows smooth linear movement from one servo position to another.
88
*
9-
* Copyright (C) 2019-2022 Armin Joachimsmeyer
9+
* Copyright (C) 2019-2025 Armin Joachimsmeyer
1010
1111
*
1212
* This file is part of ServoEasing https://github.com/ArminJo/ServoEasing.
@@ -84,6 +84,8 @@ ServoEasing Servo1;
8484
#endif
8585

8686
#define START_DEGREE_VALUE 0 // The degree value written to the servo at time of attach.
87+
#define DELAY_BETWEEN_ACTIONS_MILLIS 1000
88+
8789
void blinkLED();
8890

8991
void setup() {
@@ -127,7 +129,7 @@ void setup() {
127129
}
128130

129131
// Wait for servo to reach start position.
130-
delay(500);
132+
delay(DELAY_BETWEEN_ACTIONS_MILLIS);
131133
#if defined(PRINT_FOR_SERIAL_PLOTTER)
132134
// Legend for Arduino Serial plotter
133135
Serial.println(); // end of line of attach values
@@ -159,14 +161,14 @@ void loop() {
159161
} while (!Servo1.update());
160162
#endif
161163

162-
delay(1000);
164+
delay(DELAY_BETWEEN_ACTIONS_MILLIS);
163165

164166
#if !defined(PRINT_FOR_SERIAL_PLOTTER)
165167
Serial.println(F("Move to 45 degree in one second using interrupts"));
166168
Serial.flush(); // Just in case interrupts do not work
167169
#endif
168-
Servo1.startEaseToD(45, 1000);
169-
// Servo1.startEaseToD((544 + ((2400 - 544) / 4)), 1000); // Alternatively you can specify the target as microsecond value
170+
Servo1.startEaseToD(45, MILLIS_IN_ONE_SECOND);
171+
// Servo1.startEaseToD((544 + ((2400 - 544) / 4)), MILLIS_IN_ONE_SECOND); // Alternatively you can specify the target as microsecond value
170172
// Blink until servo stops
171173
while (Servo1.isMoving()) {
172174
/*
@@ -175,16 +177,16 @@ void loop() {
175177
blinkLED();
176178
}
177179

178-
delay(2000); // wait one second after servo has arrived at target position
180+
delay(DELAY_BETWEEN_ACTIONS_MILLIS);
179181

180182
#if !defined(PRINT_FOR_SERIAL_PLOTTER)
181183
Serial.println(F("Move to 135 degree and back nonlinear in one second each using interrupts"));
182184
#endif
183185
Servo1.setEasingType(EASE_CUBIC_IN_OUT); // EASE_LINEAR is default
184186

185187
for (uint_fast8_t i = 0; i < 2; ++i) {
186-
Servo1.startEaseToD(135, 1000);
187-
// Servo1.startEaseToD((544 + (((2400 - 544) / 4) * 3)), 1000); // Alternatively you can specify the target as a microsecond value
188+
Servo1.startEaseToD(135, MILLIS_IN_ONE_SECOND);
189+
// Servo1.startEaseToD((544 + (((2400 - 544) / 4) * 3)), MILLIS_IN_ONE_SECOND); // Alternatively you can specify the target as a microsecond value
188190
// isMoving() calls yield for the ESP8266 boards
189191
while (Servo1.isMoving()) {
190192
/*
@@ -199,8 +201,8 @@ void loop() {
199201
; // no delays here to avoid break between forth and back movement
200202
#endif
201203
}
202-
Servo1.startEaseToD(45, 1000);
203-
// Servo1.startEaseToD((544 + ((2400 - 544) / 4)), 1000); // Alternatively you can specify the target as microsecond value
204+
Servo1.startEaseToD(45, MILLIS_IN_ONE_SECOND);
205+
// Servo1.startEaseToD((544 + ((2400 - 544) / 4)), MILLIS_IN_ONE_SECOND); // Alternatively you can specify the target as microsecond value
204206
while (Servo1.isMoving()) {
205207
#if defined(ESP32)
206208
// ESP32 requires it, delay(0) or yield() or taskYIELD() is not sufficient here,
@@ -213,7 +215,7 @@ void loop() {
213215
}
214216
Servo1.setEasingType(EASE_LINEAR);
215217

216-
delay(2000); // wait one second after servo has arrived at target position
218+
delay(DELAY_BETWEEN_ACTIONS_MILLIS);
217219

218220
/*
219221
* The LED goes on if servo reaches 120 degree
@@ -231,7 +233,7 @@ void loop() {
231233
; // wait for servo to stop
232234
}
233235

234-
delay(1000);
236+
delay(DELAY_BETWEEN_ACTIONS_MILLIS);
235237

236238
/*
237239
* The LED goes off when servo theoretical reaches 90 degree
@@ -241,8 +243,8 @@ void loop() {
241243
#endif
242244
Servo1.startEaseTo(0, 90, START_UPDATE_BY_INTERRUPT);
243245
// Servo1.startEaseTo(DEFAULT_MICROSECONDS_FOR_0_DEGREE, 360, true); // Alternatively you can specify the target as microsecond value
244-
// Wait. The servo should have moved 90 degree.
245-
delay(1000);
246+
// Wait until the servo should have moved to 90 degree, then demonstrate pause().
247+
delay(MILLIS_IN_ONE_SECOND);
246248
digitalWrite(LED_BUILTIN, LOW);
247249

248250
#if !defined(DISABLE_PAUSE_RESUME)
@@ -253,12 +255,31 @@ void loop() {
253255
* Demonstrate pause and resume in the middle of a movement
254256
*/
255257
Servo1.pause();
256-
delay(1000);
258+
delay(MILLIS_IN_ONE_SECOND);
257259
// resume movement using interrupts
258260
Servo1.resumeWithInterrupts();
259-
#endif
261+
#endif // !defined(DISABLE_PAUSE_RESUME)
262+
263+
while (Servo1.isMoving()) {
264+
; // wait for servo to stop
265+
}
266+
267+
# if !defined(PRINT_FOR_SERIAL_PLOTTER)
268+
Serial.println(F("Detach the servo for 10 seconds. During this time you can move the servo manually."));
269+
# endif
270+
271+
Servo1.detach();
272+
/*
273+
* After detach the servo is "not powered" for 10 seconds, i.e. no servo signal is generated.
274+
* This allows you to easily move the servo manually.
275+
*/
276+
delay(10000); // wait 10 seconds
277+
# if !defined(PRINT_FOR_SERIAL_PLOTTER)
278+
Serial.println(F("Reattach the servo and wait for 3 seconds."));
279+
# endif
280+
Servo1.reattach();
260281

261-
delay(3000); // wait extra 2 seconds
282+
delay(3000); // wait extra 3 seconds after reattach()
262283
}
263284

264285
void blinkLED() {

0 commit comments

Comments
 (0)