ServoEasing
ServoEasing.h
Go to the documentation of this file.
1 /*
2  * ServoEasing.h
3  *
4  * Copyright (C) 2019-2025 Armin Joachimsmeyer
5  * armin.joachimsmeyer@gmail.com
6  *
7  * This file is part of ServoEasing https://github.com/ArminJo/ServoEasing.
8  *
9  * ServoEasing is free software: you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation, either version 3 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17  * See the GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program. If not, see <http://www.gnu.org/licenses/gpl.html>.
21  */
22 
23 #ifndef _SERVO_EASING_H
24 #define _SERVO_EASING_H
25 
26 #define VERSION_SERVO_EASING "3.6.0"
27 #define VERSION_SERVO_EASING_MAJOR 3
28 #define VERSION_SERVO_EASING_MINOR 6
29 #define VERSION_SERVO_EASING_PATCH 0
30 // The change log is at the bottom of the file
31 
32 #if defined(USE_LEIGHTWEIGHT_SERVO_LIB)
33 #define USE_LIGHTWEIGHT_SERVO_LIBRARY // for backwards compatibility
34 #endif
35 
36 /*
37  * Macro to convert 3 version parts into an integer
38  * To be used in preprocessor comparisons, such as #if VERSION_SERVO_EASING_HEX >= VERSION_HEX_VALUE(3, 0, 0)
39  */
40 #define VERSION_HEX_VALUE(major, minor, patch) ((major << 16) | (minor << 8) | (patch))
41 #define VERSION_SERVO_EASING_HEX VERSION_HEX_VALUE(VERSION_SERVO_EASING_MAJOR, VERSION_SERVO_EASING_MINOR, VERSION_SERVO_EASING_PATCH)
42 
43 #if !defined(MILLIS_IN_ONE_SECOND)
44 #define MILLIS_IN_ONE_SECOND 1000L
45 #endif
46 
47 // The eclipse formatter has problems with // comments in undefined code blocks
48 // !!! Must be without trailing comment and closed by @formatter:on
49 // @formatter:off
50 #define START_EASE_TO_SPEED 5 // If not specified use 5 degree per second. It is chosen so low in order to signal that it was forgotten to specify by program.
51 
52 /*
53  * USE_PCA9685_SERVO_EXPANDER is for use with e.g. the Adafruit PCA9685 16-Channel Servo Driver board.
54  * It has a resolution of 4096 per 20 ms => 4.88 us per step/unit.
55  * One PCA9685 has 16 outputs. You must modify MAX_EASING_SERVOS below, if you have more than one PCA9685 attached!
56  * All internal values *MicrosecondsOrUnits now contains no more microseconds but PCA9685 units!!!
57  */
58 //#define USE_PCA9685_SERVO_EXPANDER
59 /*
60  * Use of PCA9685 normally disables use of regular servo library to save programming space and RAM.
61  * You can force additional using of regular servo library by defining USE_SERVO_LIB.
62  * Therefore it is only required if USE_PCA9685_SERVO_EXPANDER is defined.
63  */
64 //#define USE_SERVO_LIB
65 
66 /*
67  * If you have a different servo implementation, e.g. this M5Stack Servo expander https://shop.m5stack.com/products/8-channel-servo-driver-unit-stm32f030
68  * you can provide your own servo library by activating USE_USER_PROVIDED_SERVO_LIB
69  * You must also include the .h file of your library e.g. `#include "DummyServo.h"`.
70  * The library must define a class "Servo" and implement: attach(pin, min, max), detach() and writeMicroseconds(value).
71  */
72 //#define USE_USER_PROVIDED_SERVO_LIB
73 //#include <DummyServo.h>
74 
75 /*
76  * If you have only one or two servos at pin 9 and/or 10 and an ATmega328, then you can save program memory by defining symbol `USE_LIGHTWEIGHT_SERVO_LIBRARY`.
77  * This saves 742 bytes program memory and 42 bytes RAM.
78  * Using Lightweight Servo library (or PCA9685 servo expander) makes the servo pulse generating immune
79  * to other libraries blocking interrupts for a longer time like SoftwareSerial, Adafruit_NeoPixel and DmxSimple.
80  * If not using the Arduino IDE take care that Arduino Servo library sources are not compiled / included in the project.
81  * Use of Lightweight Servo library disables use of regular servo library.
82  */
83 //#define USE_LIGHTWEIGHT_SERVO_LIBRARY
84 
85 #if defined(USE_LIGHTWEIGHT_SERVO_LIBRARY) && !(defined(__AVR_ATmega328P__) || defined(__AVR_ATmega328__) || defined (__AVR_ATmega328PB__) || defined(__AVR_ATmega2560__))
86 #error USE_LIGHTWEIGHT_SERVO_LIBRARY can only be activated for the Atmega328 or ATmega2560 CPU
87 #endif
88 
89 /*
90  * If defined, the void handleServoTimerInterrupt() function must be provided by the user program.
91  * This enables the reuse of the Servo timer interrupt e.g. for synchronizing with NeoPixel updates,
92  * which otherwise leads to servo twitching. See QuadrupedNeoPixel.cpp of QuadrupedControl example.
93  * This interrupt routine is called in an ISR context and (at least on Uno, Nano etc.) 100 microseconds
94  * before a new servo period starts to leave the first servo signals undisturbed.
95  * See also setTimer1InterruptMarginMicros()
96  */
97 //#define ENABLE_EXTERNAL_SERVO_TIMER_HANDLER
98 #if defined(ENABLE_EXTERNAL_SERVO_TIMER_HANDLER)
99 extern void handleServoTimerInterrupt();
100 #endif
101 
102 #if !( defined(__AVR__) || defined(ESP8266) || defined(ESP32) || defined(STM32F1xx) || defined(__STM32F1__) || defined(__SAM3X8E__) || defined(ARDUINO_ARCH_SAMD) || defined(ARDUINO_ARCH_APOLLO3) || defined(ARDUINO_ARCH_MBED) || defined(ARDUINO_ARCH_RP2040) || defined(TEENSYDUINO))
103 #warning No periodic timer support existent (or known) for this platform. Only blocking functions and simple example will run!
104 #endif
105 
106 /*
107  * Include of the appropriate Servo.h file
108  */
109 #if !defined(USE_USER_PROVIDED_SERVO_LIB) && (!defined(USE_PCA9685_SERVO_EXPANDER) || defined(USE_SERVO_LIB))
110 # if defined(ESP32)
111 // This does not work in Arduino IDE for step "Generating function prototypes..."
112 //# if ! __has_include("ESP32Servo.h")
113 //#error This ServoEasing library requires the "ESP32Servo" library for running on an ESP32. Please install it via the Arduino library manager.
114 //# endif
115 #include <ESP32Servo.h>
116 
117 # elif defined(MEGATINYCORE)
118 #include <Servo_megaTinyCore.h>
119 
120 # elif defined(MEGACOREX)
121 # if __has_include("ServoMegaCoreX.h")
122 #include <ServoMegaCoreX.h> // since Version 1.1.1 of MEGACOREX
123 # else
124 #include <Servo.h>
125 # endif
126 
127 # else // defined(ESP32)
128 # if defined(USE_LIGHTWEIGHT_SERVO_LIBRARY)
129 #include "LightweightServo.h"
130 # if !defined(MAX_EASING_SERVOS)
131 # if defined(__AVR_ATmega2560__)
132 #define MAX_EASING_SERVOS 3 // default value for Mega.
133 # else
134 #define MAX_EASING_SERVOS 2 // default value for Uno etc.
135 # endif
136 # endif
137 # else
138 #include <Servo.h>
139 # endif // !defined(USE_LIGHTWEIGHT_SERVO_LIBRARY)
140 # endif // defined(ESP32)
141 #endif // defined(USE_SERVO_LIB)
142 
143 #if defined(ARDUINO_ARCH_MBED) // Arduino Nano 33 BLE
144 #include "mbed.h"
145 #endif
146 
147 #if defined(USE_PCA9685_SERVO_EXPANDER)
148 # if !defined(MAX_EASING_SERVOS)
149 #define MAX_EASING_SERVOS 16 // One PCA9685 has 16 outputs. You must MODIFY this, if you have more than one PCA9685 attached!
150 # endif // defined(USE_PCA9685_SERVO_EXPANDER)
151  #include <Wire.h>
152 // PCA9685 works with up to 1 MHz I2C frequency according to the datasheet
153 # if !defined(I2C_CLOCK_FREQUENCY)
154 # if defined(ESP32)
155 // The ESP32 I2C interferes with the Ticker / Timer library used.
156 // Even with 100 kHz clock we have some dropouts / NAK's because of sending address again instead of first data.
157 # define I2C_CLOCK_FREQUENCY 100000 // 200000 does not work for my ESP32 module together with the timer even with external pullups :-(
158 # elif defined(ESP8266)
159 #define I2C_CLOCK_FREQUENCY 400000 // 400000 is the maximum for 80 MHz clocked ESP8266 (I measured real 330000 Hz for this setting)
160 # else
161 #define I2C_CLOCK_FREQUENCY 800000 // 1 MHz from datasheet does not work for my Arduino Nano, maybe because of parasitic breadboard capacities
162 # endif
163 # endif
164 #endif // defined(USE_PCA9685_SERVO_EXPANDER)
165 
166 /*****************************************************************************************
167  * Important definition of MAX_EASING_SERVOS !!!
168  * If this value is smaller than the amount of servos declared,
169  * attach() will return error and other library functions will not work as expected.
170  * Of course all *AllServos*() functions and isOneServoMoving() can't work correctly!
171  * Saves 4 byte RAM per servo.
172  ****************************************************************************************/
173 #if !defined(MAX_EASING_SERVOS)
174 # if defined(MAX_SERVOS) // defined in Sevos.h
175 #define MAX_EASING_SERVOS MAX_SERVOS // =12 use default value from Servo.h for Uno etc.
176 # else
177 #define MAX_EASING_SERVOS 12 // just take default value from Servo.h for Uno etc.
178 # endif
179 #endif // !defined(MAX_EASING_SERVOS)
180 
181 #if !defined(DEFAULT_PULSE_WIDTH)
182 #define DEFAULT_PULSE_WIDTH 1500 // default pulse width when servo is attached (from Servo.h)
183 #endif
184 #if !defined(SERVO_REFRESH_INTERVAL) && defined(REFRESH_INTERVAL)
185 #define SERVO_REFRESH_INTERVAL_MICROS REFRESH_INTERVAL // // minimum time to refresh servos in microseconds (from Servo.h)
186 #endif
187 #if !defined(SERVO_REFRESH_INTERVAL) && defined(REFRESH_USEC)
188 #define SERVO_REFRESH_INTERVAL_MICROS REFRESH_USEC // // minimum time to refresh servos in microseconds (from ESP32Servo.h)
189 #endif
190 #if !defined(SERVO_REFRESH_INTERVAL_MICROS)
191 #define SERVO_REFRESH_INTERVAL_MICROS 20000 // // minimum time to refresh servos in microseconds (from Servo.h)
192 #endif
193 #if !defined(INVALID_SERVO)
194 #define INVALID_SERVO 255 // flag indicating an invalid servo index (from Servo.h)
195 #endif
196 #define SERVO_REFRESH_INTERVAL_MILLIS (SERVO_REFRESH_INTERVAL_MICROS/1000) // 20 - used for delay()
197 #define SERVO_REFRESH_FREQUENCY (MILLIS_IN_ONE_SECOND/SERVO_REFRESH_INTERVAL_MILLIS) // 50
198 
199 /*
200  * Define `DISABLE_COMPLEX_FUNCTIONS` if space (1850 bytes) matters.
201  * It disables the SINE, CIRCULAR, BACK, ELASTIC, BOUNCE and PRECISION easings.
202  * The saving comes mainly from avoiding the sin() cos() sqrt() and pow() library functions in this code.
203  * If you need only a single complex easing function and want to save space,
204  * you can specify it any time as a user function. See EaseQuadraticInQuarticOut() function in AsymmetricEasing example line 206.
205  */
206 #if !defined(DISABLE_COMPLEX_FUNCTIONS)
207 //#define DISABLE_COMPLEX_FUNCTIONS
208 #endif
209 
210 /*
211  * If you need only the linear movement you may define `PROVIDE_ONLY_LINEAR_MOVEMENT`. This saves additional 1540 bytes program memory.
212  */
213 #if !defined(PROVIDE_ONLY_LINEAR_MOVEMENT)
214 //#define PROVIDE_ONLY_LINEAR_MOVEMENT
215 #endif
216 
217 /*
218  * If you do not require passing microsecond values as parameter instead of degree values. This saves 128 bytes program memory.
219  */
220 //#define DISABLE_MICROS_AS_DEGREE_PARAMETER
221 
222 #if !defined(THRESHOLD_VALUE_FOR_INTERPRETING_VALUE_AS_MICROSECONDS)
223 #define THRESHOLD_VALUE_FOR_INTERPRETING_VALUE_AS_MICROSECONDS 360 // treat values less than 360 as angles in degrees, others are handled as microseconds
224 #endif
225 
226 #if !defined(va_arg)
227 // workaround for STM32
228 #include <stdarg.h>
229 #endif
230 
231 // @formatter:on
232 /*
233  * The next values are smaller and greater than the values used by the Arduino Servo library to be more versatile
234  * They are used as parameter for the Arduino Servo attach() function, to avoid that the underlying Arduino writeMicroseconds()
235  * clips its parameter value to 544 us (MIN_PULSE_WIDTH) and 2400 us (MAX_PULSE_WIDTH)
236  * We do not use the Arduino write() function, which interprets this values as values for 0 and 180 degrees (and clips at 0 and 180 degrees).
237  */
238 #if !defined(MINIMUM_PULSE_WIDTH)
239 #define MINIMUM_PULSE_WIDTH 400 // The shortest pulse which can be sent to a servo by this library. Checked by underlying Arduino writeMicroseconds().
240 #endif
241 #if !defined(MAXIMUM_PULSE_WIDTH)
242 #define MAXIMUM_PULSE_WIDTH 3500 // the longest pulse which can be sent sent to a servo by this library. Checked by underlying Arduino writeMicroseconds().
243 #endif
244 
245 // Approximately 10 microseconds per degree
246 #define DEFAULT_MICROSECONDS_FOR_0_DEGREE 544
247 #define DEFAULT_MICROSECONDS_FOR_45_DEGREE (544 + ((2400 - 544) / 4)) // 1008
248 #define DEFAULT_MICROSECONDS_FOR_90_DEGREE (544 + ((2400 - 544) / 2)) // 1472
249 #define DEFAULT_MICROSECONDS_FOR_135_DEGREE (2400 - ((2400 - 544) / 4)) // 1936
250 #define DEFAULT_MICROSECONDS_FOR_180_DEGREE 2400
251 
252 // Approximately 2 units per degree
253 #define DEFAULT_PCA9685_UNITS_FOR_0_DEGREE 111 // 111.411 = 544 us
254 #define DEFAULT_PCA9685_UNITS_FOR_45_DEGREE (111 + ((491 - 111) / 4)) // 206
255 #define DEFAULT_PCA9685_UNITS_FOR_90_DEGREE (111 + ((491 - 111) / 2)) // 301 = 1472 us
256 #define DEFAULT_PCA9685_UNITS_FOR_135_DEGREE (491 - ((491 - 111) / 4)) // 369
257 #define DEFAULT_PCA9685_UNITS_FOR_180_DEGREE 491 // 491.52 = 2400 us
258 
259 /*
260  * Definitions for continuous rotating servo - Values are taken from the Parallax Continuous Rotation Servo manual
261  * and rely on a stop value of exactly 1500 microseconds.
262  * If the stop value of your servo is NOT exactly 1500 microseconds, you must change the value of MICROSECONDS_FOR_ROTATING_SERVO_STOP.
263  * My modified MG90 servo has 1630 and 1400 as max.
264  *
265  * Use attach(PIN, MICROSECONDS_FOR_ROTATING_SERVO_CLOCKWISE_MAX, MICROSECONDS_FOR_ROTATING_SERVO_COUNTER_CLOCKWISE_MAX, 100, -100);
266  * Use write(100) for maximum clockwise and write(-100) for maximum counter clockwise rotation.
267  */
268 #if !defined(MICROSECONDS_FOR_ROTATING_SERVO_STOP)
269 #define MICROSECONDS_FOR_ROTATING_SERVO_STOP 1500 // Change this value to your servos real stop value
270 #endif
271 /*
272  * Definitions here are only for convenience. You may freely modify them.
273  */
274 #define MICROSECONDS_FOR_ROTATING_SERVO_CLOCKWISE_MAX (MICROSECONDS_FOR_ROTATING_SERVO_STOP - 200)
275 #define MICROSECONDS_FOR_ROTATING_SERVO_CLOCKWISE_HALF (MICROSECONDS_FOR_ROTATING_SERVO_STOP - 100)
276 #define MICROSECONDS_FOR_ROTATING_SERVO_CLOCKWISE_QUARTER (MICROSECONDS_FOR_ROTATING_SERVO_STOP - 50)
277 #define MICROSECONDS_FOR_ROTATING_SERVO_COUNTER_CLOCKWISE_MAX (MICROSECONDS_FOR_ROTATING_SERVO_STOP + 200)
278 #define MICROSECONDS_FOR_ROTATING_SERVO_COUNTER_CLOCKWISE_HALF (MICROSECONDS_FOR_ROTATING_SERVO_STOP + 100)
279 #define MICROSECONDS_FOR_ROTATING_SERVO_COUNTER_CLOCKWISE_QUARTER (MICROSECONDS_FOR_ROTATING_SERVO_STOP + 50)
280 
281 #if (!(defined(ENABLE_EASE_QUADRATIC) || defined(ENABLE_EASE_CUBIC) || defined(ENABLE_EASE_QUARTIC) \
282 || defined(ENABLE_EASE_SINE) || defined(ENABLE_EASE_CIRCULAR) || defined(ENABLE_EASE_BACK) \
283 || defined(ENABLE_EASE_USER) \
284 || defined(ENABLE_EASE_ELASTIC) || defined(ENABLE_EASE_BOUNCE)|| defined(ENABLE_EASE_PRECISION) \
285 ))
286 #define ENABLE_EASE_QUADRATIC
287 #define ENABLE_EASE_CUBIC
288 #define ENABLE_EASE_QUARTIC
289 #define ENABLE_EASE_USER
290 # if !defined(DISABLE_COMPLEX_FUNCTIONS)
291 #define ENABLE_EASE_SINE
292 #define ENABLE_EASE_CIRCULAR
293 #define ENABLE_EASE_BACK
294 #define ENABLE_EASE_ELASTIC
295 #define ENABLE_EASE_BOUNCE
296 #define ENABLE_EASE_PRECISION
297 # endif
298 #endif
299 
300 /*
301  * The different easing functions:
302  *
303  * In order to reuse the IN functions for OUT and IN_OUT functions, the following call and result conversions are used internally.
304  * FactorOfMovementCompletion is multiplied with delta microseconds and added to StartPosition to get the current position.
305  *
306  * 1. Using IN function direct: Call with PercentageOfCompletion/100 | 0.0 to 1.0. FactorOfMovementCompletion is returnValue (from 0.0 to 1.0)
307  * 2. Using IN function to generate OUT function: Call with (1 - PercentageOfCompletion/100) | 1.0 to 0.0. FactorOfMovementCompletion = (1 - returnValue)
308  * 3. Using IN function to generate IN_OUT function:
309  * In the first half, call with (2 * PercentageOfCompletion/100) | 0.0 to 1.0. FactorOfMovementCompletion = (0.5 * returnValue)
310  * In the second half, call with (2 - (2 * PercentageOfCompletion/100)) | 1.0 to 0.0. FactorOfMovementCompletion = ( 1- (0.5 * returnValue))
311  * 4. Using IN function to generate bouncing_OUT_IN / mirrored_OUT function, which return to start point (like the upper half of a sine):
312  * In the first half, call with (1 - (2 * PercentageOfCompletion/100)) | 1.0 to 0.0. FactorOfMovementCompletion = (1 - returnValue) -> call OUT 2 times faster.
313  * In the second half, call with ((2 * PercentageOfCompletion/100) - 1) | 0.0 to 1.0. FactorOfMovementCompletion = (1- returnValue) -> call OUT 2 times faster and backwards.
314  *
315  */
316 // Offset to decide if the user function returns degrees instead of 0.0 to 1.0.
317 #define EASE_FUNCTION_DEGREE_INDICATOR_OFFSET 200 // Returns 20 for -180 degree, 110 for -90 degree, 200 for 0 degree and 380 for 180 degree.
318 #define EASE_FUNCTION_DEGREE_THRESHOLD (EASE_FUNCTION_DEGREE_INDICATOR_OFFSET - 180) // allows -180 degree.
319 #define EASE_FUNCTION_MICROSECONDS_INDICATOR_OFFSET (EASE_FUNCTION_DEGREE_INDICATOR_OFFSET + 200) // Offset to decide if the user function returns microseconds instead of 0.0 to 1.0. => returns 256 for 0 degree.
320 
321 /*
322  * Values for provided EaseTypes
323  * The call style is coded in the upper 2 bits
324  */
325 #define CALL_STYLE_DIRECT 0x00 // == IN
326 #define CALL_STYLE_IN 0x00
327 #define CALL_STYLE_OUT 0x40
328 #define CALL_STYLE_IN_OUT 0x80
329 #define CALL_STYLE_BOUNCING_OUT_IN 0xC0 // Bouncing has double movement, so double time (half speed) is taken for this modes
330 
331 #define CALL_STYLE_MASK 0xC0
332 #define EASE_TYPE_MASK 0x0F
333 
334 #define EASE_LINEAR 0x00 // No bouncing available
335 
336 #if defined(ENABLE_EASE_QUADRATIC)
337 #define EASE_QUADRATIC_IN 0x01
338 #define EASE_QUADRATIC_OUT 0x41
339 #define EASE_QUADRATIC_IN_OUT 0x81
340 #define EASE_QUADRATIC_BOUNCING 0xC1
341 #endif
342 
343 #if defined(ENABLE_EASE_CUBIC)
344 #define EASE_CUBIC_IN 0x02
345 #define EASE_CUBIC_OUT 0x42
346 #define EASE_CUBIC_IN_OUT 0x82
347 #define EASE_CUBIC_BOUNCING 0xC2
348 #endif
349 
350 #if defined(ENABLE_EASE_QUARTIC)
351 #define EASE_QUARTIC_IN 0x03
352 #define EASE_QUARTIC_OUT 0x43
353 #define EASE_QUARTIC_IN_OUT 0x83
354 #define EASE_QUARTIC_BOUNCING 0xC3
355 #endif
356 
357 #if defined(ENABLE_EASE_USER)
358 #define EASE_USER_DIRECT 0x06
359 #define EASE_USER_IN 0x06
360 #define EASE_USER_OUT 0x46
361 #define EASE_USER_IN_OUT 0x86
362 #define EASE_USER_BOUNCING 0xC6
363 #endif
364 
365 #define EASE_DUMMY_MOVE 0x07 // can be used as delay
366 
367 #if defined(ENABLE_EASE_SINE)
368 #define EASE_SINE_IN 0x08
369 #define EASE_SINE_OUT 0x48
370 #define EASE_SINE_IN_OUT 0x88
371 #define EASE_SINE_BOUNCING 0xC8
372 #endif
373 
374 #if defined(ENABLE_EASE_CIRCULAR)
375 #define EASE_CIRCULAR_IN 0x09
376 #define EASE_CIRCULAR_OUT 0x49
377 #define EASE_CIRCULAR_IN_OUT 0x89
378 #define EASE_CIRCULAR_BOUNCING 0xC9
379 #endif
380 
381 #if defined(ENABLE_EASE_BACK)
382 #define EASE_BACK_IN 0x0A
383 #define EASE_BACK_OUT 0x4A
384 #define EASE_BACK_IN_OUT 0x8A
385 #define EASE_BACK_BOUNCING 0xCA
386 #endif
387 
388 #if defined(ENABLE_EASE_ELASTIC)
389 #define EASE_ELASTIC_IN 0x0B
390 #define EASE_ELASTIC_OUT 0x4B
391 #define EASE_ELASTIC_IN_OUT 0x8B
392 #define EASE_ELASTIC_BOUNCING 0xCB
393 #endif
394 
395 #if defined(ENABLE_EASE_BOUNCE)
396 // the coded function is an OUT function
397 #define EASE_BOUNCE_IN 0x4C // call OUT function inverse
398 #define EASE_BOUNCE_OUT 0x0C // call OUT function direct
399 #endif
400 
401 #if defined(ENABLE_EASE_PRECISION)
402 #define EASE_PRECISION_IN 0x0D // Negative bounce for movings from above (go in to origin)
403 #define EASE_PRECISION_OUT 0x4D // Positive bounce for movings from below (go out from origin)
404 #endif
405 
406 // !!! Must be without trailing comment and closed by @formatter:on
407 // @formatter:off
408 extern const char easeTypeLinear[] PROGMEM;
409 #if !defined(PROVIDE_ONLY_LINEAR_MOVEMENT)
410 extern const char easeTypeQuadratic[] PROGMEM;
411 extern const char easeTypeCubic[] PROGMEM;
412 extern const char easeTypeQuartic[] PROGMEM;
413 extern const char easeTypePrecision[] PROGMEM;
414 extern const char easeTypeUser[] PROGMEM;
415 extern const char easeTypeDummy[] PROGMEM;
416 # if !defined(DISABLE_COMPLEX_FUNCTIONS)
417 extern const char easeTypeSine[] PROGMEM;
418 extern const char easeTypeCircular[] PROGMEM;
419 extern const char easeTypeBack[] PROGMEM;
420 extern const char easeTypeElastic[] PROGMEM;
421 extern const char easeTypeBounce[] PROGMEM;
422 # endif // !defined(DISABLE_COMPLEX_FUNCTIONS)
423 #endif // !defined(PROVIDE_ONLY_LINEAR_MOVEMENT)
424 // @formatter:on
425 extern const char *const easeTypeStrings[] PROGMEM;
426 
427 // some PCA9685 specific constants
428 #define PCA9685_GENERAL_CALL_ADDRESS 0x00
429 #define PCA9685_SOFTWARE_RESET 6
430 #define PCA9685_DEFAULT_ADDRESS 0x40
431 #define PCA9685_MAX_CHANNELS 16 // 16 PWM channels on each PCA9685 expansion module
432 #define PCA9685_MODE1_REGISTER 0x0
433 #define PCA9685_MODE_1_RESTART 7
434 #define PCA9685_MODE_1_AUTOINCREMENT 5
435 #define PCA9685_MODE_1_SLEEP 4
436 #define PCA9685_MODE1_EXTCLK 6 // Use EXTCLK pin clock
437 #define PCA9685_FIRST_PWM_REGISTER 0x06
438 #define PCA9685_PRESCALE_REGISTER 0xFE
439 #if !defined(PCA9685_ACTUAL_CLOCK_FREQUENCY)
440 // See chapter 2 and 5 of the PCA9685 Datasheet "25 MHz typical internal oscillator requires no external components"
441 #define PCA9685_ACTUAL_CLOCK_FREQUENCY 25000000L // 25 MHz this is the default frequency
442 #endif
443 
444 #define PCA9685_PRESCALER_FOR_20_MS ((PCA9685_ACTUAL_CLOCK_FREQUENCY /(4096L * 50)) - 1) //for 25 MHz it is: 121 / 0x79 for 20 ms or 50 Hz
445 
446 // to be used as values for parameter bool aStartUpdateByInterrupt
447 #define START_UPDATE_BY_INTERRUPT true
448 #define DO_NOT_START_UPDATE_BY_INTERRUPT false
449 
450 #define mCurrentMicrosecondsOrUnits mLastTargetMicrosecondsOrUnits // to be backwards compatible
451 /*
452  * Size is 46 bytes RAM per servo
453  */
455 #if (!defined(USE_PCA9685_SERVO_EXPANDER) || defined(USE_SERVO_LIB)) && !defined(USE_LIGHTWEIGHT_SERVO_LIBRARY)
456  : public Servo
457 #endif
458 {
459 public:
460 
461 #if defined(USE_PCA9685_SERVO_EXPANDER)
462 # if defined(ARDUINO_SAM_DUE)
463  ServoEasing(uint8_t aPCA9685I2CAddress, TwoWire *aI2CClass = &Wire1);
464 # else
465 # if defined(USE_SOFT_I2C_MASTER)
466  ServoEasing(uint8_t aPCA9685I2CAddress);
467 # else
468  ServoEasing(uint8_t aPCA9685I2CAddress, TwoWire *aI2CClass = &Wire);
469 # endif
470 # endif
471  void I2CInit();
472  void PCA9685Reset();
473  void PCA9685Init();
474  void PCA9685Init(uint32_t aActualPCA9685ClockFrequencyHertz);
475  void PCA9685InitWithExternalClock(uint32_t aExternalClockFrequencyHertz);
476  void I2CWriteByte(uint8_t aAddress, uint8_t aData);
477  void setPWM(uint16_t aPWMOffValueAsUnits);
478  void setPWM(uint16_t aPWMOnStartValueAsUnits, uint16_t aPWMPulseDurationAsUnits);
479  // main mapping functions for us to PCA9685 Units (20000/4096 = 4.88 us) and back
480  int MicrosecondsToPCA9685Units(int aMicroseconds);
481  int PCA9685UnitsToMicroseconds(int aPCA9685Units);
482 #endif // defined(USE_PCA9685_SERVO_EXPANDER)
483 
484  ServoEasing();
485 
486  uint8_t attach(int aPin);
487  uint8_t attach(int aPin, int aInitialDegreeOrMicrosecond);
488  uint8_t attachWithTrim(int aPin, int aTrimDegreeOrMicrosecond, int aInitialDegreeOrMicrosecond);
489  // Here no units accepted, only microseconds!
490  uint8_t attach(int aPin, int aMicrosecondsForServo0Degree, int aMicrosecondsForServo180Degree);
491  uint8_t attach(int aPin, int aInitialDegreeOrMicrosecond, int aMicrosecondsForServo0Degree, int aMicrosecondsForServo180Degree);
492  uint8_t attachWithTrim(int aPin, int aTrimDegreeOrMicrosecond, int aInitialDegreeOrMicrosecond,
493  int aMicrosecondsForServo0Degree, int aMicrosecondsForServo180Degree);
494  uint8_t attach(int aPin, int aMicrosecondsForServoLowDegree, int aMicrosecondsForServoHighDegree, int aServoLowDegree,
495  int aServoHighDegree);
496  uint8_t attach(int aPin, int aInitialDegreeOrMicrosecond, int aMicrosecondsForServoLowDegree,
497  int aMicrosecondsForServoHighDegree, int aServoLowDegree, int aServoHighDegree);
498  uint8_t attachWithTrim(int aPin, int aTrimDegreeOrMicrosecond, int aInitialDegreeOrMicrosecond,
499  int aMicrosecondsForServoLowDegree, int aMicrosecondsForServoHighDegree, int aServoLowDegree, int aServoHighDegree);
500 
501  uint8_t reattach();
502  void detach(); // No servo signal is generated for a detached servo / the output is constant LOW.
503  void setReverseOperation(bool aOperateServoReverse); // You should call it before using setTrim, or better use attach function with 6 parameters
504 
505  void setTrim(int aTrimDegreeOrMicrosecond, bool aDoWrite = false);
506  void _setTrimMicrosecondsOrUnits(int aTrimMicrosecondsOrUnits, bool aDoWrite = false);
507 
508 #if defined(ENABLE_MIN_AND_MAX_CONSTRAINTS)
509  void setMaxConstraint(int aMaxDegreeOrMicrosecond);
510  void setMinConstraint(int aMinDegreeOrMicrosecond);
511  void setMinMaxConstraint(int aMinDegreeOrMicrosecond, int aMaxDegreeOrMicrosecond);
512 #endif
513 
514 #if !defined(PROVIDE_ONLY_LINEAR_MOVEMENT)
515  void setEasingType(uint_fast8_t aEasingType);
516  uint_fast8_t getEasingType();
517 
518  float callEasingFunction(float aPercentageOfCompletion); // used in update()
519 
520 # if defined(ENABLE_EASE_USER)
521  void registerUserEaseInFunction(float (*aUserEaseInFunction)(float aPercentageOfCompletion, void *aUserDataPointer),
522  void *aUserDataPointer = nullptr);
523  void setUserDataPointer(void *aUserDataPointer);
524 # endif
525 #endif
526 
527  void write(int aTargetDegreeOrMicrosecond); // Apply trim and reverse to the value and write it direct to the Servo library.
528  void _writeMicrosecondsOrUnits(int aTargetMicrosecondsOrUnits);
529 
530  void easeTo(int aTargetDegreeOrMicrosecond); // blocking move to new position using mLastSpeed
531  void easeTo(int aTargetDegreeOrMicrosecond, uint_fast16_t aDegreesPerSecond); // blocking move to new position using speed
532  void easeToD(int aTargetDegreeOrMicrosecond, uint_fast16_t aMillisForMove); // blocking move to new position using duration
533 
534  bool setEaseTo(int aTargetDegreeOrMicrosecond); // shortcut for startEaseTo(..,..,DO_NOT_START_UPDATE_BY_INTERRUPT)
535  bool setEaseTo(unsigned int aTargetDegreeOrMicrosecond); // shortcut for startEaseTo(..,..,DO_NOT_START_UPDATE_BY_INTERRUPT)
536  bool setEaseTo(int aTargetDegreeOrMicrosecond, uint_fast16_t aDegreesPerSecond); // shortcut for startEaseTo(..,..,DO_NOT_START_UPDATE_BY_INTERRUPT)
537  bool startEaseTo(int aTargetDegreeOrMicrosecond); // shortcut for startEaseTo(aDegree, mSpeed, START_UPDATE_BY_INTERRUPT)
538  bool startEaseTo(unsigned int aTargetDegreeOrMicrosecond); // shortcut for startEaseTo(aDegree, mSpeed, START_UPDATE_BY_INTERRUPT)
539  bool startEaseTo(int aTargetDegreeOrMicrosecond, uint_fast16_t aDegreesPerSecond, bool aStartUpdateByInterrupt =
541  bool startEaseTo(unsigned int aTargetDegreeOrMicrosecond, uint_fast16_t aDegreesPerSecond, bool aStartUpdateByInterrupt =
543  bool setEaseToD(int aTargetDegreeOrMicrosecond, uint_fast16_t aDegreesPerSecond); // shortcut for startEaseToD(..,..,DO_NOT_START_UPDATE_BY_INTERRUPT)
544  bool setEaseToD(unsigned int aTargetDegreeOrMicrosecond, uint_fast16_t aDegreesPerSecond); // shortcut for startEaseToD(..,..,DO_NOT_START_UPDATE_BY_INTERRUPT)
545  bool startEaseToD(int aTargetDegreeOrMicrosecond, uint_fast16_t aMillisForMove, bool aStartUpdateByInterrupt =
547  bool startEaseToD(unsigned int aTargetDegreeOrMicrosecond, uint_fast16_t aMillisForMove, bool aStartUpdateByInterrupt =
549  // The float versions
550  void write(float aTargetDegreeOrMicrosecond); // Apply trim and reverse to the value and write it direct to the Servo library.
551 
552  void easeTo(float aTargetDegreeOrMicrosecond); // blocking move to new position using mLastSpeed
553  void easeTo(float aTargetDegreeOrMicrosecond, uint_fast16_t aDegreesPerSecond); // blocking move to new position using speed
554  void easeToD(float aTargetDegreeOrMicrosecond, uint_fast16_t aMillisForMove); // blocking move to new position using duration
555 
556  bool setEaseTo(float aTargetDegreeOrMicrosecond); // shortcut for startEaseTo(..,..,DO_NOT_START_UPDATE_BY_INTERRUPT)
557  bool setEaseTo(float aTargetDegreeOrMicrosecond, uint_fast16_t aDegreesPerSecond); // shortcut for startEaseTo(..,..,DO_NOT_START_UPDATE_BY_INTERRUPT)
558  bool startEaseTo(float aTargetDegreeOrMicrosecond); // shortcut for startEaseTo(aDegree, mSpeed, START_UPDATE_BY_INTERRUPT)
559  bool startEaseTo(float aTargetDegreeOrMicrosecond, uint_fast16_t aDegreesPerSecond, bool aStartUpdateByInterrupt =
561  bool setEaseToD(float aTargetDegreeOrMicrosecond, uint_fast16_t aDegreesPerSecond); // shortcut for startEaseToD(..,..,DO_NOT_START_UPDATE_BY_INTERRUPT)
562  bool startEaseToD(float aTargetDegreeOrMicrosecond, uint_fast16_t aMillisForMove, bool aStartUpdateByInterrupt =
564 
565  bool noMovement(uint_fast16_t aMillisToWait); // stay at the position for aMillisToWait
566 
567  void setSpeed(uint_fast16_t aDegreesPerSecond); // This speed is taken if no speed argument is given.
568  uint_fast16_t getSpeed();
569 
570  void stop();
571  void pause();
572  void resumeWithInterrupts();
574  bool update();
575 
576  void setTargetPositionReachedHandler(void (*aTargetPositionReachedHandler)(ServoEasing*));
577 
578  // To be compatible to Servo library
579  int readMicroseconds();
580  int read();
581 
582  int getCurrentAngle();
588  bool isMoving();
589  bool isMovingAndCallYield()
590  __attribute__ ((deprecated ("Replaced by isMoving(). Often better to use areInterruptsActive() instead.")));
591 
592  int MicrosecondsOrUnitsToDegree(int aMicrosecondsOrUnits);
593  int MicrosecondsToDegree(int aMicroseconds);
594  int MicrosecondsOrUnitsToMicroseconds(int aMicrosecondsOrUnits);
595  int DegreeOrMicrosecondToMicrosecondsOrUnits(int aDegreeOrMicrosecond);
596  int DegreeOrMicrosecondToMicrosecondsOrUnits(float aDegreeOrMicrosecond);
597 // int DegreeToMicrosecondsOrUnits(float aDegree);
599 
600  int applyTrimAndReverseToTargetMicrosecondsOrUnits(int aTargetMicrosecondsOrUnits);
601  void print(Print *aSerial, bool doExtendedOutput = true); // Print dynamic and static info
602  void printDynamic(Print *aSerial, bool doExtendedOutput = true);
603  void printStatic(Print *aSerial);
604  void printExtra(Print *aSerial);
605 
606  static void printEasingType(Print *aSerial, uint_fast8_t aEasingType);
607 
608  /*
609  * Included easing functions
610  */
611  static float QuadraticEaseIn(float aPercentageOfCompletion);
612  static float CubicEaseIn(float aPercentageOfCompletion);
613  static float QuarticEaseIn(float aPercentageOfCompletion);
614  static float SineEaseIn(float aPercentageOfCompletion);
615  static float CircularEaseIn(float aPercentageOfCompletion);
616  static float BackEaseIn(float aPercentageOfCompletion);
617  static float ElasticEaseIn(float aPercentageOfCompletion);
618  // Non symmetric function
619  static float EaseOutBounce(float aPercentageOfCompletion);
620  // Special non static function
621  float LinearWithQuadraticBounce(float aPercentageOfCompletion);
622 
623  /*
624  * Convenience function
625  */
626 #if defined(USE_PCA9685_SERVO_EXPANDER)
627 # if defined(__AVR__)
628  bool InitializeAndCheckI2CConnection(Print *aSerial) __attribute__ ((deprecated ("Use initializeAndCheckI2CConnection()")));
629  bool initializeAndCheckI2CConnection(Print *aSerial); // Using Print class saves 95 bytes flash
630 # else
631  bool InitializeAndCheckI2CConnection(Stream *aSerial); __attribute__ ((deprecated ("Use initializeAndCheckI2CConnection()")));
632  bool initializeAndCheckI2CConnection(Stream *aSerial); // Print class has no flush() here
633 # endif
634 #endif
635 
636  /*
637  * Static functions
638  */
639  static bool areInterruptsActive(); // The recommended test if at least one servo is moving yet.
640 
649 
653  uint_fast16_t mSpeed;
654 
655 #if !defined(PROVIDE_ONLY_LINEAR_MOVEMENT)
656  uint8_t mEasingType; // EASE_LINEAR, EASE_QUADRATIC_IN_OUT, EASE_CUBIC_IN_OUT, EASE_QUARTIC_IN_OUT
657 # if defined(ENABLE_EASE_USER)
659  float (*mUserEaseInFunction)(float aPercentageOfCompletion, void *aUserDataPointer);
660 # endif
661 #endif
662 
663  volatile bool mServoMoves; // Servo is moving on next call to update()
664 
665 #if defined(USE_PCA9685_SERVO_EXPANDER)
666 # if defined(USE_SERVO_LIB)
667  // Here we can have both types of servo connections
668  bool mServoIsConnectedToExpander; // to distinguish between different using microseconds or PWM units and appropriate write functions
669 # endif
670  uint8_t mPCA9685I2CAddress;
671 # if !defined(USE_SOFT_I2C_MASTER)
672  TwoWire *mI2CClass;
673 # endif
674 #endif
675  uint8_t mServoPin;
676 
677  uint8_t mServoIndex;
678 
680  uint_fast16_t mMillisForCompleteMove;
681 #if !defined(DISABLE_PAUSE_RESUME)
684 #endif
685 
692 #if defined(ENABLE_MIN_AND_MAX_CONSTRAINTS)
693  int mMaxMicrosecondsOrUnits;
694  int mMinMicrosecondsOrUnits;
695 #endif
697 
702  int mServo0DegreeMicrosecondsOrUnits; // default is DEFAULT_MICROSECONDS_FOR_0_DEGREE (544)
703  int mServo180DegreeMicrosecondsOrUnits; // default is DEFAULT_MICROSECONDS_FOR_180_DEGREE (2400)
704 
706 
713  static volatile bool sInterruptsAreActive;
714 
720  static uint_fast8_t sServoArrayMaxIndex;
723  /*
724  * Macros for backward compatibility
725  */
726 #define areInterruptsActive() ServoEasing::areInterruptsActive()
727 #define sServoArray ServoEasing::ServoEasingArray
728 #define sServoNextPositionArray ServoEasing::ServoEasingNextPositionArray
729 
730 };
731 
732 /*
733  * Functions working on all servos in the list
734  */
735 void writeAllServos(int aTargetDegreeOrMicrosecond);
736 void setSpeedForAllServos(uint_fast16_t aDegreesPerSecond);
737 #if defined(va_arg)
738 void setIntegerDegreeForAllServos(uint_fast8_t aNumberOfValues, va_list *aDegreeValues);
739 void setFloatDegreeForAllServos(uint_fast8_t aNumberOfValues, va_list *aDegreeValues);
740 #endif
741 #if defined(va_start)
742 void setDegreeForAllServos(uint_fast8_t aNumberOfValues, ...)
743  __attribute__ ((deprecated ("Please use setIntegerDegreeForAllServos().")));
744 void setIntegerDegreeForAllServos(uint_fast8_t aNumberOfValues, ...);
745 void setFloatDegreeForAllServos(uint_fast8_t aNumberOfValues, ...);
746 #endif
747 
748 bool setEaseToForAllServos();
749 bool setEaseToForAllServos(uint_fast16_t aDegreesPerSecond);
750 bool setEaseToDForAllServos(uint_fast16_t aMillisForMove);
752 void setEaseToForAllServosSynchronizeAndStartInterrupt(uint_fast16_t aDegreesPerSecond);
753 void synchronizeAllServosAndStartInterrupt(bool aStartUpdateByInterrupt = START_UPDATE_BY_INTERRUPT, bool aSynchronizeToMinimumDuration = false);
754 
755 #if !defined(PROVIDE_ONLY_LINEAR_MOVEMENT)
756 void setEasingTypeForAllServos(uint_fast8_t aEasingType);
757 void setEasingTypeForMultipleServos(uint_fast8_t aNumberOfServos, uint_fast8_t aEasingType);
758 #endif
759 
760 // blocking wait functions
762 bool delayAndUpdateAndWaitForAllServosToStop(unsigned long aMillisDelay, bool aTerminateDelayIfAllServosStopped = false);
764 void setEaseToForAllServosSynchronizeAndWaitForAllServosToStop(uint_fast16_t aDegreesPerSecond);
765 void synchronizeAndEaseToArrayPositions() __attribute__ ((deprecated ("Please use setEaseToForAllServosSynchronizeAndWait().")));
766 void synchronizeAndEaseToArrayPositions(uint_fast16_t aDegreesPerSecond)
767  __attribute__ ((deprecated ("Please use setEaseToForAllServosSynchronizeAndWait().")));
769 
770 void printArrayPositions(Print *aSerial);
771 bool isOneServoMoving();
772 void stopAllServos();
775 bool updateAllServos();
776 
778 #if defined(__AVR_ATmega328P__)
779 void setTimer1InterruptMarginMicros(uint16_t aInterruptMarginMicros);
780 #endif
782 
783 int clipDegreeSpecial(uint_fast8_t aDegreeToClip);
784 
785 //extern float (*sEaseFunctionArray[])(float aPercentageOfCompletion);
786 
787 // Static convenience function
788 #if defined(__AVR__)
789 bool checkI2CConnection(uint8_t aI2CAddress, Print *aSerial); // Using Print class saves 95 bytes flash
790 #else
791 bool checkI2CConnection(uint8_t aI2CAddress, Stream *aSerial); // Print class has no flush() here
792 #endif
793 
794 #if !defined(STR_HELPER) && !defined(STR)
795 #define STR_HELPER(x) #x
796 #define STR(x) STR_HELPER(x)
797 #endif
798 
799 /*
800  *
801  * Version 3.6.0 - 02/2026
802  * - Renamed macro REFRESH_INTERVAL_MILLIS to SERVO_REFRESH_INTERVAL_MICROS.
803  * - Added new functions PCA9685Init(uint32_t aActualPCA9685ClockFrequencyHertz) and PCA9685InitWithExternalClock(uint32_t aExternalClockFrequencyHertz).
804  * - Added parameter bool aSynchronizeToMinimumDuration to synchronizeAllServosAndStartInterrupt().
805  *
806  * Version 3.5.0 - 9/2025
807  * - Fixed serious bug in reattach();
808  * - Renamed InitializeAndCheckI2CConnection() to initializeAndCheckI2CConnection().
809  * - Renamed applyTrimAndreverseToTargetMicrosecondsOrUnits() to applyTrimAndReverseToTargetMicrosecondsOrUnits().
810  * - Housekeeping.
811  *
812  * Version 3.4.0 - 10/2024
813  * - LightweightServo support for ATmega2560.
814  * - Renamed mCurrentMicrosecondsOrUnits to mLastTargetMicrosecondsOrUnits to make clear, that trim and reverse is NOT applied to this value.
815  * - Changed DISABLE_MIN_AND_MAX_CONSTRAINTS to ENABLE_MIN_AND_MAX_CONSTRAINTS. Constraint checking is now disabled by default.
816  * - candorgander fixed a bug in printEasingType() for non AVR platforms.
817  *
818  * Version 3.3.0 - 08/2024
819  * - Added functions `setEaseTo()`, `setEaseToD()`, `startEaseTo()` and `startEaseToD()` with first parameter as `unsigned int` to avoid compiler errors `call of overloaded 'startEaseTo(unsigned int...`.
820  * - Added functions read() and readMicroseconds() to be compatible to Servo library.
821  * - Added function reattach() without parameters to be used after detach().
822  * - Added `USE_USER_PROVIDED_SERVO_LIB` macro.
823  *
824  * Version 3.2.1 - 03/2023
825  * - Renamed function `setDegreeForAllServos()` to `setIntegerDegreeForAllServos()` and added function `setFloatDegreeForAllServos()`.
826  *
827  * Version 3.2.0 - 02/2023
828  * - ATmega4808 support added.
829  * - Added function `getCurrentMicroseconds()`.
830  * - Improved many and added workaround for ESP32 bug in while loops in examples.
831  * - Added `PCA9685_ACTUAL_CLOCK_FREQUENCY` macro.
832  * - Renamed function `synchronizeAndEaseToArrayPositions()` to `setEaseToForAllServosSynchronizeAndWaitForAllServosToStop()`.
833  *
834  * Version 3.1.0 - 08/2022
835  * - SAMD51 support by Lutz Aumueller.
836  * - Added support to pause and resume and `DISABLE_PAUSE_RESUME`.
837  * - Fixed some bugs for PCA9685 expander introduced in 3.0.0.
838  * - Feather Huzzah support with the help of Danner Claflin.
839  * - Added `ENABLE_EXTERNAL_SERVO_TIMER_HANDLER` macro.
840  *
841  * Version 3.0.0 - 05/2022
842  * - Added target reached callback functionality, to enable multiple movements without loop control.
843  * - Changed `ENABLE_MICROS_AS_DEGREE_PARAMETER` to `DISABLE_MICROS_AS_DEGREE_PARAMETER` thus enabling micros as parameter by default.
844  * - Fixed some bugs for micros as parameter.
845  * - Changed constants for easing types.
846  * - Additional parameter aUserDataPointer for user easing function.
847  * - New easing type `PRECISION`.
848  * - New function `printEasingType()`.
849  * - Easing functions are converted to static member functions now.
850  * - Easing types can be disabled individually.
851  * - Improved PCA9685 handling / support for SoftI2CMaster.
852  * - Changed default for parameter `doWrite` for `setTrim()` from `false` to `true`.
853  * - Added min and max constraints for servo write() and `DISABLE_MIN_AND_MAX_CONSTRAINTS`.
854  *
855  * Version 2.4.1 - 02/2022
856  * - RP2040 support added.
857  * - Fix for Nano Every interrupts.
858  *
859  * Version 2.4.0 - 10/2021
860  * - New `attach()` functions with initial degree parameter to be written immediately. This replaces the `attach()` and `write()` combination at setup.
861  * - Renamed ServoEasing.cpp.h to ServoEasing.hpp and LightweightServo.cpp to LightweightServo.hpp.
862  *
863  * Version 2.3.4 - 02/2021
864  * - ENABLE_MICROS_AS_DEGREE_PARAMETER also available for PCA9685 expander.
865  * - Moved `sServoArrayMaxIndex`, `sServoNextPositionArray` and `sServoArray` to `ServoEasing::sServoArrayMaxIndex`, `ServoEasing::ServoEasingNextPositionArray` and `ServoEasing::ServoEasingArray`.
866  *
867  * Version 2.3.3 - 11/2020
868  * - Added compile option `ENABLE_MICROS_AS_DEGREE_PARAMETER` to allow usage of microseconds instead of degree as function arguments for all functions using degrees as argument.
869  * - Improved LightweightServo API.
870  *
871  * Version 2.3.2 - 9/2020
872  * - Removed blocking wait for ATmega32U4 Serial in examples.
873  * - Improved output for Arduino Serial Plotter.
874  *
875  * Version 2.3.1 - 9/2020
876  * - Fixed wrong timer selection for `STM32F1xx` / `ARDUINO_ARCH_STM32`.
877  * - Documentation.
878  *
879  * Version 2.3.0 - 7/2020
880  * - Fixed EASE_LINEAR formula bug introduced with 2.0.0 for 32 bit CPU's.
881  * - Added `stop()`, `continueWithInterrupts()` and `continueWithoutInterrupts()` functions.
882  *
883  * Version 2.2.0 - 7/2020
884  * - ATmega4809 (Uno WiFi Rev 2, Nano Every) support.
885  * - Corrected position of macro for MAX_EASING_SERVOS.
886  *
887  * Version 2.1.1 - 6/2020
888  * - Fixed bug in detach of first servo.
889  *
890  * Version 2.1.0 - 6/2020
891  * - Teensy support.
892  *
893  * Version 2.0.0 - 5/2020
894  * - `PCA9685_Expander` and standard Servos can be controlled simultaneously by defining `USE_SERVO_LIB`.
895  * - Changed some types to _fast types
896  * - Standardize pins for all examples
897  *
898  * Version 1.6.1 - 5/2020
899  * - Fix bug for **Arduino SAMD** boards.
900  *
901  * Version 1.6.0 - 4/2020
902  * - Added support of Apollo3 boards.
903  * - Print library version in examples.
904  *
905  * Version 1.5.2 - 3/2020
906  * - More examples using `areInterruptsActive()`.
907  * - Added support of Arduino SAMD boards.
908  *
909  * Version 1.5.1 - 3/2020
910  * - Added support for STM32 cores of Arduino Board manager. Seen in the Arduino IDE as "Generic STM32F1 series" from STM32 Boards.
911  * - Inserted missing `Wire.begin()` in setup of `PCA9685_Expander` example.
912  * - In `isMovingAndCallYield()` yield() only called/required for an ESP8266.
913  * - New function `areInterruptsActive()`, especially for ESP32.
914  *
915  * Version 1.5.0 - 2/2020
916  * - Use type `Print *` instead of `Stream *`.
917  * - New LightweightServoExample.
918  * - Added function `delayAndUpdateAndWaitForAllServosToStop()`.
919  * - Added Arduino Due support by using timer 8.
920  * - New PCA9685_ExpanderFor32Servos example.
921  *
922  * Version 1.4.3 - 12/2019
923  * - Improved detach() handling.
924  * - Initialize mSpeed explicitly to 0 in constructor. On an ESP8266 it was NOT initialized to 0 :-(.
925  *
926  * Version 1.4.2 - 11/2019
927  * - Improved INVALID_SERVO handling.
928  * - Speed 0 (not initialized) handling.
929  * - Fixed bug in ThreeServos example.
930  *
931  * Version 1.4.1 - 11/2019
932  * - Improved documentation and definitions for continuous rotating servo. Thanks to Eebel!
933  * - Improved support and documentation for generating Arduino Serial Plotter output.
934  * - Support of STM32F1 / BluePill boards.
935  *
936  * Version 1.4.0 - 11/2019
937  * - setTrim has additional parameter 'doWrite' which is default 'false' in contrast to older versions, where a write was always performed.
938  * - New attach( aPin, aMicrosecondsForServoLowDegree, aMicrosecondsForServoHighDegree, aServoLowDegree, aServoHighDegree) function for arbitrary mapping of servo degree to servo pulse width.
939  * - Order of Servos in 'sServoArray[]' now depends from order of calling attach() and not from order of declaration.
940  * - New example for continuous rotating servo.
941  * - Support for multiple PCA9685 expander.
942  *
943  * Version 1.3.1 - 6/2019
944  * - Added detach() function.
945  *
946  * Version 1.3.0 - 6/2019
947  * - Added ESP32 support by using ESP32Servo.h and Ticker.h instead of Servo.h timer interrupts.
948  * - Changed degree parameter and values from uint8_t to integer to support operating a servo from -90 to + 90 degree with 90 degree trim.
949  * - RobotArmControl + QuadrupedControl examples refactored.
950  * - Extended SpeedTest example. Now also able to change the width of the refresh period.
951  * - Changed "while" to "for" loops to avoid a gcc 7.3.0 atmel6.3.1 bug.
952  *
953  * Version 1.2 - 5/2019
954  * - Added ESP8266 support by using Ticker instead of timer interrupts for ESP.
955  * - AsymetricEasing example overhauled.
956  *
957  * Version 1.1 - 4/2019
958  * - corrected sine, circular, back and elastic IN functions.
959  * - easeTo() and write() store their degree parameter now also in sServoNextPositionArray.
960  * - added setSpeed(), getSpeed(), setSpeedForAllServos().
961  * - added easeTo(uint8_t aDegree) and setEaseTo(uint8_t aDegree).
962  * - added setEaseToForAllServos(), setEaseToForAllServosSynchronizeAndStartInterrupt(), synchronizeAndEaseToArrayPositions().
963  * - added getEndMicrosecondsOrUnits(), getDeltaMicrosecondsOrUnits().
964  * - added setDegreeForAllServos(uint8_t aNumberOfValues, va_list * aDegreeValues),setDegreeForAllServos(uint8_t aNumberOfValues, ...).
965  * - added compile switch PROVIDE_ONLY_LINEAR_MOVEMENT to save additional 1500 bytes program memory if enabled.
966  * - added convenience function clipDegreeSpecial().
967  */
968 
969 #if !defined(_SERVO_EASING_HPP) && !defined(SUPPRESS_HPP_WARNING)
970 #warning You probably must change the line #include "ServoEasing.h" to #include "ServoEasing.hpp" in your ino file or define SUPPRESS_HPP_WARNING before the include to suppress this warning.
971 #endif
972 
973 #endif // _SERVO_EASING_H
ServoEasing::getDeltaMicrosecondsOrUnits
int getDeltaMicrosecondsOrUnits()
Definition: ServoEasing.hpp:1822
setEaseToForAllServosSynchronizeAndWaitForAllServosToStop
void setEaseToForAllServosSynchronizeAndWaitForAllServosToStop()
Synchronize and blocking wait until all servos are stopped Take the longer duration in order to move ...
Definition: ServoEasing.hpp:2416
enableServoEasingInterrupt
void enableServoEasingInterrupt()
Timer1 is used for the Arduino Servo library.
Definition: ServoEasing.hpp:2048
ServoEasing::_setTrimMicrosecondsOrUnits
void _setTrimMicrosecondsOrUnits(int aTrimMicrosecondsOrUnits, bool aDoWrite=false)
Definition: ServoEasing.hpp:807
ServoEasing::MicrosecondsOrUnitsToDegree
int MicrosecondsOrUnitsToDegree(int aMicrosecondsOrUnits)
Used to convert e.g.
Definition: ServoEasing.hpp:1029
ServoEasing::getSpeed
uint_fast16_t getSpeed()
Definition: ServoEasing.hpp:775
ServoEasing::mSpeed
uint_fast16_t mSpeed
max speed is 450 degree/sec for SG90 and 540 degree/second for MG90 servos -> see speedTest....
Definition: ServoEasing.h:653
ServoEasing::mServoMoves
volatile bool mServoMoves
Definition: ServoEasing.h:663
ServoEasing::_writeMicrosecondsOrUnits
void _writeMicrosecondsOrUnits(int aTargetMicrosecondsOrUnits)
Internal function Before sending the value to the underlying Servo library, trim and reverse is appli...
Definition: ServoEasing.hpp:902
ServoEasing::update
bool update()
Definition: ServoEasing.hpp:1558
ServoEasing::mLastTargetMicrosecondsOrUnits
volatile int mLastTargetMicrosecondsOrUnits
Internally only microseconds (or units (= 4.88 us) if using PCA9685 expander) and not degree are used...
Definition: ServoEasing.h:645
updateAndWaitForAllServosToStop
void updateAndWaitForAllServosToStop()
Blocking wait until all servos are stopped.
Definition: ServoEasing.hpp:2650
ServoEasing::attach
uint8_t attach(int aPin)
Specify the microseconds values for 0 and 180 degree for the servo.
Definition: ServoEasing.hpp:473
ServoEasing
Definition: ServoEasing.h:458
ServoEasing::readMicroseconds
int readMicroseconds()
Definition: ServoEasing.hpp:1807
ServoEasing::setReverseOperation
void setReverseOperation(bool aOperateServoReverse)
Definition: ServoEasing.hpp:771
ServoEasing::getEasingType
uint_fast8_t getEasingType()
Definition: ServoEasing.hpp:840
disableServoEasingInterrupt
void disableServoEasingInterrupt()
Definition: ServoEasing.hpp:2257
ServoEasing::TargetPositionReachedHandler
void(* TargetPositionReachedHandler)(ServoEasing *)
Is called any time when target servo position is reached.
Definition: ServoEasing.h:705
ServoEasing::mStartMicrosecondsOrUnits
int mStartMicrosecondsOrUnits
Only used with millisAtStartMove to compute currentMicrosecondsOrUnits in update()
Definition: ServoEasing.h:646
ServoEasing::getMillisForCompleteMove
int getMillisForCompleteMove()
Definition: ServoEasing.hpp:1826
ServoEasing::setTargetPositionReachedHandler
void setTargetPositionReachedHandler(void(*aTargetPositionReachedHandler)(ServoEasing *))
Definition: ServoEasing.hpp:1516
ServoEasing::mServo0DegreeMicrosecondsOrUnits
int mServo0DegreeMicrosecondsOrUnits
Values contain always microseconds except for servos connected to a PCA9685 expander,...
Definition: ServoEasing.h:702
ServoEasing::mTrimMicrosecondsOrUnits
int mTrimMicrosecondsOrUnits
This value is always added by the function _writeMicrosecondsOrUnits() to the requested degree/units/...
Definition: ServoEasing.h:696
areInterruptsActive
#define areInterruptsActive()
Definition: ServoEasing.h:726
ServoEasing::mServoPin
uint8_t mServoPin
pin number / port number of PCA9685 [0-15] or NO_SERVO_ATTACHED_PIN_NUMBER - at least required for Li...
Definition: ServoEasing.h:675
ServoEasing::setEaseTo
bool setEaseTo(int aTargetDegreeOrMicrosecond)
Definition: ServoEasing.hpp:1209
ServoEasing::getEndMicrosecondsOrUnits
int getEndMicrosecondsOrUnits()
Definition: ServoEasing.hpp:1811
ServoEasing::resumeWithInterrupts
void resumeWithInterrupts()
Definition: ServoEasing.hpp:1501
synchronizeAndEaseToArrayPositions
void synchronizeAndEaseToArrayPositions() __attribute__((deprecated("Please use setEaseToForAllServosSynchronizeAndWait().")))
Definition: ServoEasing.hpp:2426
Servo
Definition: DummyServo.h:40
ServoEasing::stop
void stop()
This stops the servo at any position.
Definition: ServoEasing.hpp:1484
setEaseToForAllServos
bool setEaseToForAllServos()
Sets target position using content of ServoEasingNextPositionArray.
Definition: ServoEasing.hpp:2535
ServoEasing::attachWithTrim
uint8_t attachWithTrim(int aPin, int aTrimDegreeOrMicrosecond, int aInitialDegreeOrMicrosecond)
Combination of attach with initial setTrim() and write().
Definition: ServoEasing.hpp:492
ServoEasing::noMovement
bool noMovement(uint_fast16_t aMillisToWait)
stay at the position for aMillisToWait Used as delay for callback
Definition: ServoEasing.hpp:1357
checkI2CConnection
bool checkI2CConnection(uint8_t aI2CAddress, Stream *aSerial)
ServoEasing::isMoving
bool isMoving()
Test if servo is moving yet.
Definition: ServoEasing.hpp:1761
ServoEasing::setUserDataPointer
void setUserDataPointer(void *aUserDataPointer)
Definition: ServoEasing.hpp:850
ServoEasing::pause
void pause()
Definition: ServoEasing.hpp:1494
printArrayPositions
void printArrayPositions(Print *aSerial)
Prints content of ServoNextPositionArray for debugging purposes.
Definition: ServoEasing.hpp:2440
ServoEasing::mServoIsPaused
bool mServoIsPaused
Definition: ServoEasing.h:682
delayAndUpdateAndWaitForAllServosToStop
bool delayAndUpdateAndWaitForAllServosToStop(unsigned long aMillisDelay, bool aTerminateDelayIfAllServosStopped=false)
Definition: ServoEasing.hpp:2662
ServoEasing::printExtra
void printExtra(Print *aSerial)
Definition: ServoEasing.hpp:1980
ServoEasing::BackEaseIn
static float BackEaseIn(float aPercentageOfCompletion)
see: https://easings.net/#easeInOutBack and https://github.com/warrenm/AHEasing/blob/master/AHEasing/...
Definition: ServoEasing.hpp:2788
ServoEasing::mEndMicrosecondsOrUnits
int mEndMicrosecondsOrUnits
Only used once as last value if movement was finished to provide exact end position.
Definition: ServoEasing.h:647
ServoEasing::DegreeToMicrosecondsOrUnitsWithTrimAndReverse
int DegreeToMicrosecondsOrUnitsWithTrimAndReverse(int aDegree)
Mainly for testing, since trim and reverse are applied at each write.
Definition: ServoEasing.hpp:1136
ServoEasing::applyTrimAndReverseToTargetMicrosecondsOrUnits
int applyTrimAndReverseToTargetMicrosecondsOrUnits(int aTargetMicrosecondsOrUnits)
Definition: ServoEasing.hpp:1863
ServoEasing::LinearWithQuadraticBounce
float LinearWithQuadraticBounce(float aPercentageOfCompletion)
PRECISION (LinearWithQuadraticBounce) is like linear, but adds a 5 degree bounce in the last 20 % of ...
Definition: ServoEasing.hpp:2815
ServoEasing::setTrim
void setTrim(int aTrimDegreeOrMicrosecond, bool aDoWrite=false)
Definition: ServoEasing.hpp:789
ServoEasing::printDynamic
void printDynamic(Print *aSerial, bool doExtendedOutput=true)
Prints values which may change from move to move.
Definition: ServoEasing.hpp:1877
clipDegreeSpecial
int clipDegreeSpecial(uint_fast8_t aDegreeToClip)
Clips the unsigned degree value and handles unsigned underflow.
Definition: ServoEasing.hpp:1991
ServoEasing::mEasingType
uint8_t mEasingType
Definition: ServoEasing.h:656
ServoEasing::MicrosecondsOrUnitsToMicroseconds
int MicrosecondsOrUnitsToMicroseconds(int aMicrosecondsOrUnits)
Definition: ServoEasing.hpp:1066
LightweightServo.h
ServoEasing::mMillisForCompleteMove
uint_fast16_t mMillisForCompleteMove
Definition: ServoEasing.h:680
ServoEasing::EaseOutBounce
static float EaseOutBounce(float aPercentageOfCompletion)
!!! ATTENTION !!! we have only the out function implemented see: https://easings.net/de#easeOutBounce...
Definition: ServoEasing.hpp:2891
setEasingTypeForAllServos
void setEasingTypeForAllServos(uint_fast8_t aEasingType)
60 us for single servo + 160 us per servo if using I2C e.g.for PCA9685 expander at 400 kHz or + 100 a...
Definition: ServoEasing.hpp:2386
ServoEasing::resumeWithoutInterrupts
void resumeWithoutInterrupts()
Definition: ServoEasing.hpp:1509
ServoEasing::print
void print(Print *aSerial, bool doExtendedOutput=true)
Do a printDynamic() and a printStatic()
Definition: ServoEasing.hpp:1835
ServoEasing::mMillisAtStartMove
uint32_t mMillisAtStartMove
Definition: ServoEasing.h:679
ServoEasing::easeToD
void easeToD(int aTargetDegreeOrMicrosecond, uint_fast16_t aMillisForMove)
Definition: ServoEasing.hpp:1183
stopAllServos
void stopAllServos()
Definition: ServoEasing.hpp:2588
ServoEasing::mUserEaseInFunction
float(* mUserEaseInFunction)(float aPercentageOfCompletion, void *aUserDataPointer)
Definition: ServoEasing.h:659
ServoEasing::getCurrentAngle
int getCurrentAngle()
Definition: ServoEasing.hpp:1795
ServoEasing::MicrosecondsToDegree
int MicrosecondsToDegree(int aMicroseconds)
Only used in startEaseTo to compute target degree For PCA9685, we have stored units in mServo0DegreeM...
Definition: ServoEasing.hpp:1009
setEasingTypeForMultipleServos
void setEasingTypeForMultipleServos(uint_fast8_t aNumberOfServos, uint_fast8_t aEasingType)
Sets easing type aEasingType for the first aNumberOfServos in ServoEasingArray[].
Definition: ServoEasing.hpp:2393
resumeWithInterruptsAllServos
void resumeWithInterruptsAllServos()
Definition: ServoEasing.hpp:2611
ServoEasing::printStatic
void printStatic(Print *aSerial)
Prints values which normally does NOT change from move to move.
Definition: ServoEasing.hpp:1936
PROGMEM
const char easeTypeLinear[] PROGMEM
Definition: ServoEasing.h:410
setSpeedForAllServos
void setSpeedForAllServos(uint_fast16_t aDegreesPerSecond)
Definition: ServoEasing.hpp:2475
ServoEasing::callEasingFunction
float callEasingFunction(float aPercentageOfCompletion)
Definition: ServoEasing.hpp:1700
ServoEasing::startEaseToD
bool startEaseToD(int aTargetDegreeOrMicrosecond, uint_fast16_t aMillisForMove, bool aStartUpdateByInterrupt=START_UPDATE_BY_INTERRUPT)
Sets up all the values required for a smooth move to new value Lower level function with time instead...
Definition: ServoEasing.hpp:1370
ServoEasing::CircularEaseIn
static float CircularEaseIn(float aPercentageOfCompletion)
It is very fast in the middle! see: https://easings.net/#easeInOutCirc and https://github....
Definition: ServoEasing.hpp:2780
handleServoTimerInterrupt
void handleServoTimerInterrupt()
Update all servos from list and check if all servos have stopped.
Definition: ServoEasing.hpp:2012
ServoEasing::detach
void detach()
No servo signal is generated for a detached servo / the output is constant LOW.
Definition: ServoEasing.hpp:730
ServoEasing::mMillisAtStopMove
uint32_t mMillisAtStopMove
Definition: ServoEasing.h:683
ServoEasing::startEaseTo
bool startEaseTo(int aTargetDegreeOrMicrosecond)
Definition: ServoEasing.hpp:1235
ServoEasing::getEndMicrosecondsOrUnitsWithTrim
int getEndMicrosecondsOrUnitsWithTrim()
Not used internally.
Definition: ServoEasing.hpp:1818
ServoEasing::ServoEasing
ServoEasing()
Definition: ServoEasing.hpp:426
ServoEasing::reattach
uint8_t reattach()
Definition: ServoEasing.hpp:547
setEaseToForAllServosSynchronizeAndStartInterrupt
void setEaseToForAllServosSynchronizeAndStartInterrupt()
Definition: ServoEasing.hpp:2402
ServoEasing::ServoEasingNextPositionArray
static float ServoEasingNextPositionArray[MAX_EASING_SERVOS]
Used exclusively for *ForAllServos() functions.
Definition: ServoEasing.h:722
ServoEasing::getCurrentMicroseconds
int getCurrentMicroseconds()
Definition: ServoEasing.hpp:1803
ServoEasing::sInterruptsAreActive
static volatile bool sInterruptsAreActive
It is required for ESP32, where the timer interrupt routine does not block the loop.
Definition: ServoEasing.h:713
isOneServoMoving
bool isOneServoMoving()
Definition: ServoEasing.hpp:2579
ServoEasing::mServo180DegreeMicrosecondsOrUnits
int mServo180DegreeMicrosecondsOrUnits
Definition: ServoEasing.h:703
ServoEasing::printEasingType
static void printEasingType(Print *aSerial, uint_fast8_t aEasingType)
Definition: ServoEasing.hpp:1844
ServoEasing::ServoEasingArray
static ServoEasing * ServoEasingArray[MAX_EASING_SERVOS]
Definition: ServoEasing.h:721
MAX_EASING_SERVOS
#define MAX_EASING_SERVOS
Definition: ServoEasing.h:177
ServoEasing::DegreeOrMicrosecondToMicrosecondsOrUnits
int DegreeOrMicrosecondToMicrosecondsOrUnits(int aDegreeOrMicrosecond)
We have around 10 us per degree Used to convert (external) provided degree values to internal microse...
Definition: ServoEasing.hpp:1080
ServoEasing::QuadraticEaseIn
static float QuadraticEaseIn(float aPercentageOfCompletion)
The simplest non linear easing function.
Definition: ServoEasing.hpp:2755
setEaseToDForAllServos
bool setEaseToDForAllServos(uint_fast16_t aMillisForMove)
Sets target position using content of ServoEasingNextPositionArray and use aMillisForMove instead of ...
Definition: ServoEasing.hpp:2568
ServoEasing::UserDataPointer
void * UserDataPointer
Definition: ServoEasing.h:658
ServoEasing::registerUserEaseInFunction
void registerUserEaseInFunction(float(*aUserEaseInFunction)(float aPercentageOfCompletion, void *aUserDataPointer), void *aUserDataPointer=nullptr)
Definition: ServoEasing.hpp:845
START_UPDATE_BY_INTERRUPT
#define START_UPDATE_BY_INTERRUPT
Definition: ServoEasing.h:447
ServoEasing::SineEaseIn
static float SineEaseIn(float aPercentageOfCompletion)
Take half of negative cosines of first quadrant Is behaves almost like QUADRATIC.
Definition: ServoEasing.hpp:2771
ServoEasing::mOperateServoReverse
bool mOperateServoReverse
Reverse means, that values for 180 and 0 degrees are swapped by: aValue = mServo180DegreeMicroseconds...
Definition: ServoEasing.h:691
synchronizeAllServosAndStartInterrupt
void synchronizeAllServosAndStartInterrupt(bool aStartUpdateByInterrupt=START_UPDATE_BY_INTERRUPT, bool aSynchronizeToMinimumDuration=false)
Take the longest duration in order to move all servos synchronously.
Definition: ServoEasing.hpp:2691
ServoEasing::read
int read()
Definition: ServoEasing.hpp:1799
ServoEasing::sServoArrayMaxIndex
static uint_fast8_t sServoArrayMaxIndex
Two arrays of all servos to enable synchronized movings Servos are inserted in the order,...
Definition: ServoEasing.h:720
synchronizeAllServosStartAndWaitForAllServosToStop
void synchronizeAllServosStartAndWaitForAllServosToStop()
Synchronize and blocking wait until all servos are stopped.
Definition: ServoEasing.hpp:2682
writeAllServos
void writeAllServos(int aTargetDegreeOrMicrosecond)
Definition: ServoEasing.hpp:2467
ServoEasing::mDeltaMicrosecondsOrUnits
int mDeltaMicrosecondsOrUnits
end - start
Definition: ServoEasing.h:648
ServoEasing::setEaseToD
bool setEaseToD(int aTargetDegreeOrMicrosecond, uint_fast16_t aDegreesPerSecond)
Definition: ServoEasing.hpp:1345
ServoEasing::mServoIndex
uint8_t mServoIndex
Index in sServoArray or INVALID_SERVO if error while attach() or if detached.
Definition: ServoEasing.h:677
ServoEasing::setSpeed
void setSpeed(uint_fast16_t aDegreesPerSecond)
Definition: ServoEasing.hpp:779
ServoEasing::isMovingAndCallYield
bool isMovingAndCallYield() __attribute__((deprecated("Replaced by isMoving(). Often better to use areInterruptsActive() instead.")))
Call yield here (actually only for ESP8266), so the user do not need to care for it in long running l...
Definition: ServoEasing.hpp:1791
ServoEasing::write
void write(int aTargetDegreeOrMicrosecond)
Tested value of 400 for my PCA9685 expander 10/25 (was effectively 382 us / - 2 %,...
Definition: ServoEasing.hpp:860
resumeWithoutInterruptsAllServos
void resumeWithoutInterruptsAllServos()
Definition: ServoEasing.hpp:2619
updateAllServos
bool updateAllServos()
Definition: ServoEasing.hpp:2630
ServoEasing::CubicEaseIn
static float CubicEaseIn(float aPercentageOfCompletion)
Definition: ServoEasing.hpp:2759
ServoEasing::easeTo
void easeTo(int aTargetDegreeOrMicrosecond)
Definition: ServoEasing.hpp:1146
ServoEasing::ElasticEaseIn
static float ElasticEaseIn(float aPercentageOfCompletion)
see: https://easings.net/#easeInOutElastic and https://github.com/warrenm/AHEasing/blob/master/AHEasi...
Definition: ServoEasing.hpp:2797
ServoEasing::QuarticEaseIn
static float QuarticEaseIn(float aPercentageOfCompletion)
Definition: ServoEasing.hpp:2763
ServoEasing::setEasingType
void setEasingType(uint_fast8_t aEasingType)
Definition: ServoEasing.hpp:836