ServoEasing
ServoEasing.h
Go to the documentation of this file.
1 /*
2  * ServoEasing.h
3  *
4  * Copyright (C) 2019-2023 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 
24 #ifndef _SERVO_EASING_H
25 #define _SERVO_EASING_H
26 
27 #define VERSION_SERVO_EASING "3.2.0"
28 #define VERSION_SERVO_EASING_MAJOR 3
29 #define VERSION_SERVO_EASING_MINOR 2
30 #define VERSION_SERVO_EASING_PATCH 0
31 // The change log is at the bottom of the file
32 
33 /*
34  * Macro to convert 3 version parts into an integer
35  * To be used in preprocessor comparisons, such as #if VERSION_SERVO_EASING_HEX >= VERSION_HEX_VALUE(3, 0, 0)
36  */
37 #define VERSION_HEX_VALUE(major, minor, patch) ((major << 16) | (minor << 8) | (patch))
38 #define VERSION_SERVO_EASING_HEX VERSION_HEX_VALUE(VERSION_SERVO_EASING_MAJOR, VERSION_SERVO_EASING_MINOR, VERSION_SERVO_EASING_PATCH)
39 
40 #define MILLIS_IN_ONE_SECOND 1000L
41 
42 // The eclipse formatter has problems with // comments in undefined code blocks
43 // !!! Must be without comment and closed by @formatter:on
44 // @formatter:off
45 #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.
46 
47 /*
48  * USE_PCA9685_SERVO_EXPANDER is for use with e.g. the Adafruit PCA9685 16-Channel Servo Driver board.
49  * It has a resolution of 4096 per 20 ms => 4.88 us per step/unit.
50  * One PCA9685 has 16 outputs. You must modify MAX_EASING_SERVOS below, if you have more than one PCA9685 attached!
51  * All internal values *MicrosecondsOrUnits now contains no more microseconds but PCA9685 units!!!
52  */
53 //#define USE_PCA9685_SERVO_EXPANDER
54 /*
55  * Use of PCA9685 normally disables use of regular servo library to save programming space and RAM.
56  * You can force additional using of regular servo library by defining USE_SERVO_LIB.
57  * Therefore it is only required if USE_PCA9685_SERVO_EXPANDER is defined.
58  */
59 //#define USE_SERVO_LIB
60 
61 /*
62  * 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_LEIGHTWEIGHT_SERVO_LIB`.
63  * This saves 742 bytes program memory and 42 bytes RAM.
64  * Using Lightweight Servo library (or PCA9685 servo expander) makes the servo pulse generating immune
65  * to other libraries blocking interrupts for a longer time like SoftwareSerial, Adafruit_NeoPixel and DmxSimple.
66  * If not using the Arduino IDE take care that Arduino Servo library sources are not compiled / included in the project.
67  * Use of Lightweight Servo library disables use of regular servo library.
68  */
69 //#define USE_LEIGHTWEIGHT_SERVO_LIB
70 
71 #if defined(USE_LEIGHTWEIGHT_SERVO_LIB) && !(defined(__AVR_ATmega328P__) || defined(__AVR_ATmega328__))
72 #error USE_LEIGHTWEIGHT_SERVO_LIB can only be activated for the Atmega328 CPU
73 #endif
74 
75 /*
76  * If defined, the void handleServoTimerInterrupt() function must be provided by an external program.
77  * This enables the reuse of the Servo timer interrupt e.g. for synchronizing with NeoPixel updates,
78  * which otherwise leads to servo twitching. See QuadrupedNeoPixel.cpp of QuadrupedControl example.
79  */
80 //#define ENABLE_EXTERNAL_SERVO_TIMER_HANDLER
81 #if defined(ENABLE_EXTERNAL_SERVO_TIMER_HANDLER)
82 __attribute__((weak)) extern void handleServoTimerInterrupt();
83 #endif
84 
85 #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))
86 #warning No periodic timer support existent (or known) for this platform. Only blocking functions and simple example will run!
87 #endif
88 
89 /*
90  * Include of the appropriate Servo.h file
91  */
92 #if !defined(USE_PCA9685_SERVO_EXPANDER) || defined(USE_SERVO_LIB)
93 # if defined(ESP32)
94 // This does not work in Arduino IDE for step "Generating function prototypes..."
95 //# if ! __has_include("ESP32Servo.h")
96 //#error This ServoEasing library requires the "ESP32Servo" library for running on an ESP32. Please install it via the Arduino library manager.
97 //# endif
98 #include <ESP32Servo.h>
99 
100 # elif defined(MEGATINYCORE)
101 #include <Servo_megaTinyCore.h>
102 
103 # elif defined(MEGACOREX)
104 # if __has_include("ServoMegaCoreX.h")
105 #include <ServoMegaCoreX.h> // since Version 1.1.1 of MEGACOREX
106 # else
107 #include <Servo.h>
108 # endif
109 
110 # else // defined(ESP32)
111 # if defined(USE_LEIGHTWEIGHT_SERVO_LIB)
112 #include "LightweightServo.h"
113 # if !defined(MAX_EASING_SERVOS)
114 #define MAX_EASING_SERVOS 2 // default value for UNO etc.
115 # endif
116 # else
117 #include <Servo.h>
118 # endif // !defined(USE_LEIGHTWEIGHT_SERVO_LIB)
119 # endif // defined(ESP32)
120 #endif // defined(USE_SERVO_LIB)
121 
122 #if defined(ARDUINO_ARCH_MBED) // Arduino Nano 33 BLE
123 #include "mbed.h"
124 #endif
125 
126 
127 
128 #if defined(USE_PCA9685_SERVO_EXPANDER)
129 # if !defined(MAX_EASING_SERVOS)
130 #define MAX_EASING_SERVOS 16 // One PCA9685 has 16 outputs. You must MODIFY this, if you have more than one PCA9685 attached!
131 # endif // defined(USE_PCA9685_SERVO_EXPANDER)
132  #include <Wire.h>
133 // PCA9685 works with up to 1 MHz I2C frequency
134 # if defined(ESP32)
135 // The ESP32 I2C interferes with the Ticker / Timer library used.
136 // Even with 100 kHz clock we have some dropouts / NAK's because of sending address again instead of first data.
137 # define I2C_CLOCK_FREQUENCY 100000 // 200000 does not work for my ESP32 module together with the timer even with external pullups :-(
138 # elif defined(ESP8266)
139 #define I2C_CLOCK_FREQUENCY 400000 // 400000 is the maximum for 80 MHz clocked ESP8266 (I measured real 330000 Hz for this setting)
140 # else
141 #define I2C_CLOCK_FREQUENCY 800000 // 1000000 does not work for my Arduino Nano, maybe because of parasitic breadboard capacities
142 # endif
143 #endif // defined(USE_PCA9685_SERVO_EXPANDER)
144 
145 
146 /*****************************************************************************************
147  * Important definition of MAX_EASING_SERVOS !!!
148  * If this value is smaller than the amount of servos declared,
149  * attach() will return error and other library functions will not work as expected.
150  * Of course all *AllServos*() functions and isOneServoMoving() can't work correctly!
151  * Saves 4 byte RAM per servo.
152  ****************************************************************************************/
153 #if !defined(MAX_EASING_SERVOS)
154 # if defined(MAX_SERVOS)
155 #define MAX_EASING_SERVOS MAX_SERVOS // =12 use default value from Servo.h for UNO etc.
156 # else
157 #define MAX_EASING_SERVOS 12 // just take default value from Servo.h for UNO etc.
158 # endif
159 #endif // !defined(MAX_EASING_SERVOS)
160 
161 #if !defined(DEFAULT_PULSE_WIDTH)
162 #define DEFAULT_PULSE_WIDTH 1500 // default pulse width when servo is attached (from Servo.h)
163 #endif
164 #if !defined(REFRESH_INTERVAL)
165 #define REFRESH_INTERVAL 20000 // // minimum time to refresh servos in microseconds (from Servo.h)
166 #endif
167 #if !defined(INVALID_SERVO)
168 #define INVALID_SERVO 255 // flag indicating an invalid servo index (from Servo.h)
169 #endif
170 #define REFRESH_INTERVAL_MICROS REFRESH_INTERVAL // 20000
171 #define REFRESH_INTERVAL_MILLIS (REFRESH_INTERVAL/1000) // 20 - used for delay()
172 #define REFRESH_FREQUENCY (MILLIS_IN_ONE_SECOND/REFRESH_INTERVAL_MILLIS) // 50
173 
174 /*
175  * Define `DISABLE_COMPLEX_FUNCTIONS` if space (1850 bytes) matters.
176  * It disables the SINE, CIRCULAR, BACK, ELASTIC, BOUNCE and PRECISION easings.
177  * The saving comes mainly from avoiding the sin() cos() sqrt() and pow() library functions in this code.
178  * If you need only a single complex easing function and want to save space,
179  * you can specify it any time as a user function. See EaseQuadraticInQuarticOut() function in AsymmetricEasing example line 206.
180  */
181 #if !defined(DISABLE_COMPLEX_FUNCTIONS)
182 //#define DISABLE_COMPLEX_FUNCTIONS
183 #endif
184 
185 /*
186  * If you need only the linear movement you may define `PROVIDE_ONLY_LINEAR_MOVEMENT`. This saves additional 1540 bytes program memory.
187  */
188 #if !defined(PROVIDE_ONLY_LINEAR_MOVEMENT)
189 //#define PROVIDE_ONLY_LINEAR_MOVEMENT
190 #endif
191 
192 /*
193  * If you do not require passing microsecond values as parameter instead of degree values. This saves 128 bytes program memory.
194  */
195 //#define DISABLE_MICROS_AS_DEGREE_PARAMETER
196 
197 #if !defined(THRESHOLD_VALUE_FOR_INTERPRETING_VALUE_AS_MICROSECONDS)
198 #define THRESHOLD_VALUE_FOR_INTERPRETING_VALUE_AS_MICROSECONDS 360 // treat values less than 360 as angles in degrees, others are handled as microseconds
199 #endif
200 
201 #if !defined(va_arg)
202 // workaround for STM32
203 #include <stdarg.h>
204 #endif
205 
206 // @formatter:on
207 // Approximately 10 microseconds per degree
208 #define DEFAULT_MICROSECONDS_FOR_0_DEGREE 544
209 #define DEFAULT_MICROSECONDS_FOR_45_DEGREE (544 + ((2400 - 544) / 4)) // 1008
210 #define DEFAULT_MICROSECONDS_FOR_90_DEGREE (544 + ((2400 - 544) / 2)) // 1472
211 #define DEFAULT_MICROSECONDS_FOR_135_DEGREE (2400 - ((2400 - 544) / 4)) // 1936
212 #define DEFAULT_MICROSECONDS_FOR_180_DEGREE 2400
213 
214 // Approximately 2 units per degree
215 #define DEFAULT_PCA9685_UNITS_FOR_0_DEGREE 111 // 111.411 = 544 us
216 #define DEFAULT_PCA9685_UNITS_FOR_45_DEGREE (111 + ((491 - 111) / 4)) // 206
217 #define DEFAULT_PCA9685_UNITS_FOR_90_DEGREE (111 + ((491 - 111) / 2)) // 301 = 1472 us
218 #define DEFAULT_PCA9685_UNITS_FOR_135_DEGREE (491 - ((491 - 111) / 4)) // 369
219 #define DEFAULT_PCA9685_UNITS_FOR_180_DEGREE 491 // 491.52 = 2400 us
220 
221 /*
222  * Definitions for continuous rotating servo - Values are taken from the Parallax Continuous Rotation Servo manual
223  * and rely on a stop value of exactly 1500 microseconds.
224  * If the stop value of your servo is NOT exactly 1500 microseconds, you must change the value of MICROSECONDS_FOR_ROTATING_SERVO_STOP.
225  * My modified MG90 servo has 1630 and 1400 as max.
226  *
227  * Use attach(PIN, MICROSECONDS_FOR_ROTATING_SERVO_CLOCKWISE_MAX, MICROSECONDS_FOR_ROTATING_SERVO_COUNTER_CLOCKWISE_MAX, 100, -100);
228  * Use write(100) for maximum clockwise and write(-100) for maximum counter clockwise rotation.
229  */
230 #if !defined(MICROSECONDS_FOR_ROTATING_SERVO_STOP)
231 #define MICROSECONDS_FOR_ROTATING_SERVO_STOP 1500 // Change this value to your servos real stop value
232 #endif
233 /*
234  * Definitions here are only for convenience. You may freely modify them.
235  */
236 #define MICROSECONDS_FOR_ROTATING_SERVO_CLOCKWISE_MAX (MICROSECONDS_FOR_ROTATING_SERVO_STOP - 200)
237 #define MICROSECONDS_FOR_ROTATING_SERVO_CLOCKWISE_HALF (MICROSECONDS_FOR_ROTATING_SERVO_STOP - 100)
238 #define MICROSECONDS_FOR_ROTATING_SERVO_CLOCKWISE_QUARTER (MICROSECONDS_FOR_ROTATING_SERVO_STOP - 50)
239 #define MICROSECONDS_FOR_ROTATING_SERVO_COUNTER_CLOCKWISE_MAX (MICROSECONDS_FOR_ROTATING_SERVO_STOP + 200)
240 #define MICROSECONDS_FOR_ROTATING_SERVO_COUNTER_CLOCKWISE_HALF (MICROSECONDS_FOR_ROTATING_SERVO_STOP + 100)
241 #define MICROSECONDS_FOR_ROTATING_SERVO_COUNTER_CLOCKWISE_QUARTER (MICROSECONDS_FOR_ROTATING_SERVO_STOP + 50)
242 
243 #if (!(defined(ENABLE_EASE_QUADRATIC) || defined(ENABLE_EASE_CUBIC) || defined(ENABLE_EASE_QUARTIC) \
244 || defined(ENABLE_EASE_SINE) || defined(ENABLE_EASE_CIRCULAR) || defined(ENABLE_EASE_BACK) \
245 || defined(ENABLE_EASE_USER) \
246 || defined(ENABLE_EASE_ELASTIC) || defined(ENABLE_EASE_BOUNCE)|| defined(ENABLE_EASE_PRECISION) \
247 ))
248 #define ENABLE_EASE_QUADRATIC
249 #define ENABLE_EASE_CUBIC
250 #define ENABLE_EASE_QUARTIC
251 #define ENABLE_EASE_USER
252 # if !defined(DISABLE_COMPLEX_FUNCTIONS)
253 #define ENABLE_EASE_SINE
254 #define ENABLE_EASE_CIRCULAR
255 #define ENABLE_EASE_BACK
256 #define ENABLE_EASE_ELASTIC
257 #define ENABLE_EASE_BOUNCE
258 #define ENABLE_EASE_PRECISION
259 # endif
260 #endif
261 
262 /*
263  * The different easing functions:
264  *
265  * In order to reuse the IN functions for OUT and IN_OUT functions, the following call and result conversions are used internally.
266  * FactorOfMovementCompletion is multiplied with delta microseconds and added to StartPosition to get the current position.
267  *
268  * 1. Using IN function direct: Call with PercentageOfCompletion/100 | 0.0 to 1.0. FactorOfMovementCompletion is returnValue (from 0.0 to 1.0)
269  * 2. Using IN function to generate OUT function: Call with (1 - PercentageOfCompletion/100) | 1.0 to 0.0. FactorOfMovementCompletion = (1 - returnValue)
270  * 3. Using IN function to generate IN_OUT function:
271  * In the first half, call with (2 * PercentageOfCompletion/100) | 0.0 to 1.0. FactorOfMovementCompletion = (0.5 * returnValue)
272  * In the second half, call with (2 - (2 * PercentageOfCompletion/100)) | 1.0 to 0.0. FactorOfMovementCompletion = ( 1- (0.5 * returnValue))
273  * 4. Using IN function to generate bouncing_OUT_IN / mirrored_OUT function, which return to start point (like the upper half of a sine):
274  * In the first half, call with (1 - (2 * PercentageOfCompletion/100)) | 1.0 to 0.0. FactorOfMovementCompletion = (1 - returnValue) -> call OUT 2 times faster.
275  * 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.
276  *
277  */
278 // Offset to decide if the user function returns degrees instead of 0.0 to 1.0.
279 #define EASE_FUNCTION_DEGREE_INDICATOR_OFFSET 200 // Returns 20 for -180°, 110 for -90°, 200 for 0° and 380 for 180°.
280 #define EASE_FUNCTION_DEGREE_THRESHOLD (EASE_FUNCTION_DEGREE_INDICATOR_OFFSET - 180) // allows -180°.
281 #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.
282 
283 /*
284  * Values for provided EaseTypes
285  * The call style is coded in the upper 2 bits
286  */
287 #define CALL_STYLE_DIRECT 0x00 // == IN
288 #define CALL_STYLE_IN 0x00
289 #define CALL_STYLE_OUT 0x40
290 #define CALL_STYLE_IN_OUT 0x80
291 #define CALL_STYLE_BOUNCING_OUT_IN 0xC0 // Bouncing has double movement, so double time (half speed) is taken for this modes
292 
293 #define CALL_STYLE_MASK 0xC0
294 #define EASE_TYPE_MASK 0x0F
295 
296 #define EASE_LINEAR 0x00 // No bouncing available
297 
298 #if defined(ENABLE_EASE_QUADRATIC)
299 #define EASE_QUADRATIC_IN 0x01
300 #define EASE_QUADRATIC_OUT 0x41
301 #define EASE_QUADRATIC_IN_OUT 0x81
302 #define EASE_QUADRATIC_BOUNCING 0xC1
303 #endif
304 
305 #if defined(ENABLE_EASE_CUBIC)
306 #define EASE_CUBIC_IN 0x02
307 #define EASE_CUBIC_OUT 0x42
308 #define EASE_CUBIC_IN_OUT 0x82
309 #define EASE_CUBIC_BOUNCING 0xC2
310 #endif
311 
312 #if defined(ENABLE_EASE_QUARTIC)
313 #define EASE_QUARTIC_IN 0x03
314 #define EASE_QUARTIC_OUT 0x43
315 #define EASE_QUARTIC_IN_OUT 0x83
316 #define EASE_QUARTIC_BOUNCING 0xC3
317 #endif
318 
319 #if defined(ENABLE_EASE_USER)
320 #define EASE_USER_DIRECT 0x06
321 #define EASE_USER_IN 0x06
322 #define EASE_USER_OUT 0x46
323 #define EASE_USER_IN_OUT 0x86
324 #define EASE_USER_BOUNCING 0xC6
325 #endif
326 
327 #define EASE_DUMMY_MOVE 0x07 // can be used as delay
328 
329 #if defined(ENABLE_EASE_SINE)
330 #define EASE_SINE_IN 0x08
331 #define EASE_SINE_OUT 0x48
332 #define EASE_SINE_IN_OUT 0x88
333 #define EASE_SINE_BOUNCING 0xC8
334 #endif
335 
336 #if defined(ENABLE_EASE_CIRCULAR)
337 #define EASE_CIRCULAR_IN 0x09
338 #define EASE_CIRCULAR_OUT 0x49
339 #define EASE_CIRCULAR_IN_OUT 0x89
340 #define EASE_CIRCULAR_BOUNCING 0xC9
341 #endif
342 
343 #if defined(ENABLE_EASE_BACK)
344 #define EASE_BACK_IN 0x0A
345 #define EASE_BACK_OUT 0x4A
346 #define EASE_BACK_IN_OUT 0x8A
347 #define EASE_BACK_BOUNCING 0xCA
348 #endif
349 
350 #if defined(ENABLE_EASE_ELASTIC)
351 #define EASE_ELASTIC_IN 0x0B
352 #define EASE_ELASTIC_OUT 0x4B
353 #define EASE_ELASTIC_IN_OUT 0x8B
354 #define EASE_ELASTIC_BOUNCING 0xCB
355 #endif
356 
357 #if defined(ENABLE_EASE_BOUNCE)
358 // the coded function is an OUT function
359 #define EASE_BOUNCE_IN 0x4C // call OUT function inverse
360 #define EASE_BOUNCE_OUT 0x0C // call OUT function direct
361 #endif
362 
363 #if defined(ENABLE_EASE_PRECISION)
364 #define EASE_PRECISION_IN 0x0D // Negative bounce for movings from above (go in to origin)
365 #define EASE_PRECISION_OUT 0x4D // Positive bounce for movings from below (go out from origin)
366 #endif
367 
368 // !!! Must be without comment and closed by @formatter:on !!!
369 // @formatter:off
370 extern const char easeTypeLinear[] PROGMEM;
371 #if !defined(PROVIDE_ONLY_LINEAR_MOVEMENT)
372 extern const char easeTypeQuadratic[] PROGMEM;
373 extern const char easeTypeCubic[] PROGMEM;
374 extern const char easeTypeQuartic[] PROGMEM;
375 extern const char easeTypePrecision[] PROGMEM;
376 extern const char easeTypeUser[] PROGMEM;
377 extern const char easeTypeDummy[] PROGMEM;
378 # if !defined(DISABLE_COMPLEX_FUNCTIONS)
379 extern const char easeTypeSine[] PROGMEM;
380 extern const char easeTypeCircular[] PROGMEM;
381 extern const char easeTypeBack[] PROGMEM;
382 extern const char easeTypeElastic[] PROGMEM;
383 extern const char easeTypeBounce[] PROGMEM;
384 # endif // !defined(DISABLE_COMPLEX_FUNCTIONS)
385 #endif // !defined(PROVIDE_ONLY_LINEAR_MOVEMENT)
386 // @formatter:on
387 extern const char *const easeTypeStrings[] PROGMEM;
388 
389 // some PCA9685 specific constants
390 #define PCA9685_GENERAL_CALL_ADDRESS 0x00
391 #define PCA9685_SOFTWARE_RESET 6
392 #define PCA9685_DEFAULT_ADDRESS 0x40
393 #define PCA9685_MAX_CHANNELS 16 // 16 PWM channels on each PCA9685 expansion module
394 #define PCA9685_MODE1_REGISTER 0x0
395 #define PCA9685_MODE_1_RESTART 7
396 #define PCA9685_MODE_1_AUTOINCREMENT 5
397 #define PCA9685_MODE_1_SLEEP 4
398 #define PCA9685_FIRST_PWM_REGISTER 0x06
399 #define PCA9685_PRESCALE_REGISTER 0xFE
400 #if !defined(PCA9685_ACTUAL_CLOCK_FREQUENCY)
401 // See chapter 2 and 5 of the PCA9685 Datasheet "25 MHz typical internal oscillator requires no external components"
402 #define PCA9685_ACTUAL_CLOCK_FREQUENCY 25000000L // 25 MHz this is the default frequency
403 #endif
404 
405 #define PCA9685_PRESCALER_FOR_20_MS ((PCA9685_ACTUAL_CLOCK_FREQUENCY /(4096L * 50)) - 1) // = 121 / 0x79 at 50 Hz
406 
407 // to be used as values for parameter bool aStartUpdateByInterrupt
408 #define START_UPDATE_BY_INTERRUPT true
409 #define DO_NOT_START_UPDATE_BY_INTERRUPT false
410 
411 /*
412  * Size is 46 bytes RAM per servo
413  */
415 #if (!defined(USE_PCA9685_SERVO_EXPANDER) || defined(USE_SERVO_LIB)) && !defined(USE_LEIGHTWEIGHT_SERVO_LIB)
416  : public Servo
417 #endif
418 {
419 public:
420 
421 #if defined(USE_PCA9685_SERVO_EXPANDER)
422 # if defined(ARDUINO_SAM_DUE)
423  ServoEasing(uint8_t aPCA9685I2CAddress, TwoWire *aI2CClass = &Wire1);
424 # else
425 # if defined(USE_SOFT_I2C_MASTER)
426  ServoEasing(uint8_t aPCA9685I2CAddress);
427 # else
428  ServoEasing(uint8_t aPCA9685I2CAddress, TwoWire *aI2CClass = &Wire);
429 # endif
430 # endif
431  void I2CInit();
432  void PCA9685Reset();
433  void PCA9685Init();
434  void I2CWriteByte(uint8_t aAddress, uint8_t aData);
435  void setPWM(uint16_t aPWMOffValueAsUnits);
436  void setPWM(uint16_t aPWMOnStartValueAsUnits, uint16_t aPWMPulseDurationAsUnits);
437  // main mapping functions for us to PCA9685 Units (20000/4096 = 4.88 us) and back
438  int MicrosecondsToPCA9685Units(int aMicroseconds);
439  int PCA9685UnitsToMicroseconds(int aPCA9685Units);
440 #endif // defined(USE_PCA9685_SERVO_EXPANDER)
441 
442  ServoEasing();
443 
444  uint8_t attach(int aPin);
445  uint8_t attach(int aPin, int aInitialDegreeOrMicrosecond);
446  uint8_t attachWithTrim(int aPin, int aTrimDegreeOrMicrosecond, int aInitialDegreeOrMicrosecond);
447  // Here no units accepted, only microseconds!
448  uint8_t attach(int aPin, int aMicrosecondsForServo0Degree, int aMicrosecondsForServo180Degree);
449  uint8_t attach(int aPin, int aInitialDegreeOrMicrosecond, int aMicrosecondsForServo0Degree, int aMicrosecondsForServo180Degree);
450  uint8_t attachWithTrim(int aPin, int aTrimDegreeOrMicrosecond, int aInitialDegreeOrMicrosecond,
451  int aMicrosecondsForServo0Degree, int aMicrosecondsForServo180Degree);
452  uint8_t attach(int aPin, int aMicrosecondsForServoLowDegree, int aMicrosecondsForServoHighDegree, int aServoLowDegree,
453  int aServoHighDegree);
454  uint8_t attach(int aPin, int aInitialDegreeOrMicrosecond, int aMicrosecondsForServoLowDegree,
455  int aMicrosecondsForServoHighDegree, int aServoLowDegree, int aServoHighDegree);
456  uint8_t attachWithTrim(int aPin, int aTrimDegreeOrMicrosecond, int aInitialDegreeOrMicrosecond,
457  int aMicrosecondsForServoLowDegree, int aMicrosecondsForServoHighDegree, int aServoLowDegree, int aServoHighDegree);
458 
459  void detach();
460  void setReverseOperation(bool aOperateServoReverse); // You should call it before using setTrim, or better use attach function with 6 parameters
461 
462  void setTrim(int aTrimDegreeOrMicrosecond, bool aDoWrite = false);
463  void _setTrimMicrosecondsOrUnits(int aTrimMicrosecondsOrUnits, bool aDoWrite = false);
464 
465 #if !defined(DISABLE_MIN_AND_MAX_CONSTRAINTS)
466  void setMaxConstraint(int aMaxDegreeOrMicrosecond);
467  void setMinConstraint(int aMinDegreeOrMicrosecond);
468  void setMinMaxConstraint(int aMinDegreeOrMicrosecond, int aMaxDegreeOrMicrosecond);
469 #endif
470 
471 #if !defined(PROVIDE_ONLY_LINEAR_MOVEMENT)
472  void setEasingType(uint_fast8_t aEasingType);
473  uint_fast8_t getEasingType();
474 
475  float callEasingFunction(float aPercentageOfCompletion); // used in update()
476 
477 # if defined(ENABLE_EASE_USER)
478  void registerUserEaseInFunction(float (*aUserEaseInFunction)(float aPercentageOfCompletion, void *aUserDataPointer),
479  void *aUserDataPointer = NULL);
480  void setUserDataPointer(void *aUserDataPointer);
481 # endif
482 #endif
483 
484  void write(int aTargetDegreeOrMicrosecond); // Apply trim and reverse to the value and write it direct to the Servo library.
485  void _writeMicrosecondsOrUnits(int aTargetDegreeOrMicrosecond);
486 
487  void easeTo(int aTargetDegreeOrMicrosecond); // blocking move to new position using mLastSpeed
488  void easeTo(int aTargetDegreeOrMicrosecond, uint_fast16_t aDegreesPerSecond); // blocking move to new position using speed
489  void easeToD(int aTargetDegreeOrMicrosecond, uint_fast16_t aMillisForMove); // blocking move to new position using duration
490 
491  bool setEaseTo(int aTargetDegreeOrMicrosecond); // shortcut for startEaseTo(..,..,DO_NOT_START_UPDATE_BY_INTERRUPT)
492  bool setEaseTo(int aTargetDegreeOrMicrosecond, uint_fast16_t aDegreesPerSecond); // shortcut for startEaseTo(..,..,DO_NOT_START_UPDATE_BY_INTERRUPT)
493  bool startEaseTo(int aTargetDegreeOrMicrosecond); // shortcut for startEaseTo(aDegree, mSpeed, START_UPDATE_BY_INTERRUPT)
494  bool startEaseTo(int aTargetDegreeOrMicrosecond, uint_fast16_t aDegreesPerSecond, bool aStartUpdateByInterrupt =
496  bool setEaseToD(int aTargetDegreeOrMicrosecond, uint_fast16_t aDegreesPerSecond); // shortcut for startEaseToD(..,..,DO_NOT_START_UPDATE_BY_INTERRUPT)
497  bool startEaseToD(int aTargetDegreeOrMicrosecond, uint_fast16_t aMillisForMove, bool aStartUpdateByInterrupt =
499 
500  // The float versions
501  void write(float aTargetDegreeOrMicrosecond); // Apply trim and reverse to the value and write it direct to the Servo library.
502 
503  void easeTo(float aTargetDegreeOrMicrosecond); // blocking move to new position using mLastSpeed
504  void easeTo(float aTargetDegreeOrMicrosecond, uint_fast16_t aDegreesPerSecond); // blocking move to new position using speed
505  void easeToD(float aTargetDegreeOrMicrosecond, uint_fast16_t aMillisForMove); // blocking move to new position using duration
506 
507  bool setEaseTo(float aTargetDegreeOrMicrosecond); // shortcut for startEaseTo(..,..,DO_NOT_START_UPDATE_BY_INTERRUPT)
508  bool setEaseTo(float aTargetDegreeOrMicrosecond, uint_fast16_t aDegreesPerSecond); // shortcut for startEaseTo(..,..,DO_NOT_START_UPDATE_BY_INTERRUPT)
509  bool startEaseTo(float aTargetDegreeOrMicrosecond); // shortcut for startEaseTo(aDegree, mSpeed, START_UPDATE_BY_INTERRUPT)
510  bool startEaseTo(float aTargetDegreeOrMicrosecond, uint_fast16_t aDegreesPerSecond, bool aStartUpdateByInterrupt =
512  bool setEaseToD(float aTargetDegreeOrMicrosecond, uint_fast16_t aDegreesPerSecond); // shortcut for startEaseToD(..,..,DO_NOT_START_UPDATE_BY_INTERRUPT)
513  bool startEaseToD(float aTargetDegreeOrMicrosecond, uint_fast16_t aMillisForMove, bool aStartUpdateByInterrupt =
515 
516  bool noMovement(uint_fast16_t aMillisToWait); // stay at the position for aMillisToWait
517 
518  void setSpeed(uint_fast16_t aDegreesPerSecond); // This speed is taken if no speed argument is given.
519  uint_fast16_t getSpeed();
520 
521  void stop();
522  void pause();
523  void resumeWithInterrupts();
525  bool update();
526 
527  void setTargetPositionReachedHandler(void (*aTargetPositionReachedHandler)(ServoEasing*));
528 
529  int getCurrentAngle();
535  bool isMoving();
536  bool isMovingAndCallYield() __attribute__ ((deprecated ("Replaced by isMoving(). Often better to use areInterruptsActive() instead.")));
537 
538  int MicrosecondsOrUnitsToDegree(int aMicrosecondsOrUnits);
539  int MicrosecondsToDegree(int aMicroseconds);
540  int MicrosecondsOrUnitsToMicroseconds(int aMicrosecondsOrUnits);
541  int DegreeOrMicrosecondToMicrosecondsOrUnits(int aDegreeOrMicrosecond);
542  int DegreeOrMicrosecondToMicrosecondsOrUnits(float aDegreeOrMicrosecond);
543 // int DegreeToMicrosecondsOrUnits(float aDegree);
545 
546  void synchronizeServosAndStartInterrupt(bool doUpdateByInterrupt);
547 
548  void print(Print *aSerial, bool doExtendedOutput = true); // Print dynamic and static info
549  void printDynamic(Print *aSerial, bool doExtendedOutput = true);
550  void printStatic(Print *aSerial);
551 
552  static void printEasingType(Print *aSerial, uint_fast8_t aEasingType);
553 
554  /*
555  * Included easing functions
556  */
557  static float QuadraticEaseIn(float aPercentageOfCompletion);
558  static float CubicEaseIn(float aPercentageOfCompletion);
559  static float QuarticEaseIn(float aPercentageOfCompletion);
560  static float SineEaseIn(float aPercentageOfCompletion);
561  static float CircularEaseIn(float aPercentageOfCompletion);
562  static float BackEaseIn(float aPercentageOfCompletion);
563  static float ElasticEaseIn(float aPercentageOfCompletion);
564  // Non symmetric function
565  static float EaseOutBounce(float aPercentageOfCompletion);
566  // Special non static function
567  float LinearWithQuadraticBounce(float aPercentageOfCompletion);
568 
569  /*
570  * Convenience function
571  */
572 #if defined(__AVR__)
573  bool InitializeAndCheckI2CConnection(Print *aSerial); // Using Print class saves 95 bytes flash
574 #else
575  bool InitializeAndCheckI2CConnection(Stream *aSerial); // Print class has no flush() here
576 #endif
577 
578  /*
579  * Static functions
580  */
581  static bool areInterruptsActive(); // The recommended test if at least one servo is moving yet.
582 
591 
595  uint_fast16_t mSpeed;
596 
597 #if !defined(PROVIDE_ONLY_LINEAR_MOVEMENT)
598  uint8_t mEasingType; // EASE_LINEAR, EASE_QUADRATIC_IN_OUT, EASE_CUBIC_IN_OUT, EASE_QUARTIC_IN_OUT
599 # if defined(ENABLE_EASE_USER)
601  float (*mUserEaseInFunction)(float aPercentageOfCompletion, void *aUserDataPointer);
602 # endif
603 #endif
604 
605  volatile bool mServoMoves;
606 
607 #if defined(USE_PCA9685_SERVO_EXPANDER)
608 # if defined(USE_SERVO_LIB)
609  // Here we can have both types of servo connections
610  bool mServoIsConnectedToExpander; // to distinguish between different using microseconds or PWM units and appropriate write functions
611 # endif
612  uint8_t mPCA9685I2CAddress;
613 # if !defined(USE_SOFT_I2C_MASTER)
614  TwoWire *mI2CClass;
615 # endif
616 #endif
617  uint8_t mServoPin;
618 
619  uint8_t mServoIndex;
620 
622  uint_fast16_t mMillisForCompleteMove;
623 #if !defined(DISABLE_PAUSE_RESUME)
626 #endif
627 
634 #if !defined(DISABLE_MIN_AND_MAX_CONSTRAINTS)
637 #endif
639 
646 
648 
655  static volatile bool sInterruptsAreActive;
656 
662  static uint_fast8_t sServoArrayMaxIndex;
665  /*
666  * Macros for backward compatibility
667  */
668 #define areInterruptsActive() ServoEasing::areInterruptsActive()
669 #define sServoArray ServoEasing::ServoEasingArray
670 #define sServoNextPositionArray ServoEasing::ServoEasingNextPositionArray
671 
672 };
673 
674 /*
675  * Functions working on all servos in the list
676  */
677 void writeAllServos(int aTargetDegreeOrMicrosecond);
678 void setSpeedForAllServos(uint_fast16_t aDegreesPerSecond);
679 #if defined(va_arg)
680 void setDegreeForAllServos(uint_fast8_t aNumberOfValues, va_list *aDegreeValues);
681 #endif
682 #if defined(va_start)
683 void setDegreeForAllServos(uint_fast8_t aNumberOfValues, ...);
684 #endif
685 
686 bool setEaseToForAllServos();
687 bool setEaseToForAllServos(uint_fast16_t aDegreesPerSecond);
688 bool setEaseToDForAllServos(uint_fast16_t aMillisForMove);
690 void setEaseToForAllServosSynchronizeAndStartInterrupt(uint_fast16_t aDegreesPerSecond);
691 void synchronizeAllServosAndStartInterrupt(bool aStartUpdateByInterrupt = START_UPDATE_BY_INTERRUPT);
692 
693 #if !defined(PROVIDE_ONLY_LINEAR_MOVEMENT)
694 void setEasingTypeForAllServos(uint_fast8_t aEasingType);
695 void setEasingTypeForMultipleServos(uint_fast8_t aNumberOfServos, uint_fast8_t aEasingType);
696 #endif
697 
698 // blocking wait functions
700 bool delayAndUpdateAndWaitForAllServosToStop(unsigned long aMillisDelay, bool aTerminateDelayIfAllServosStopped = false);
702 void setEaseToForAllServosSynchronizeAndWaitForAllServosToStop(uint_fast16_t aDegreesPerSecond);
703 void synchronizeAndEaseToArrayPositions() __attribute__ ((deprecated ("Please use setEaseToForAllServosSynchronizeAndWait().")));
704 void synchronizeAndEaseToArrayPositions(uint_fast16_t aDegreesPerSecond) __attribute__ ((deprecated ("Please use setEaseToForAllServosSynchronizeAndWait().")));
706 
707 void printArrayPositions(Print *aSerial);
708 bool isOneServoMoving();
709 void stopAllServos();
712 bool updateAllServos();
713 
715 #if defined(__AVR_ATmega328P__)
716 void setTimer1InterruptMarginMicros(uint16_t aInterruptMarginMicros);
717 #endif
719 
720 int clipDegreeSpecial(uint_fast8_t aDegreeToClip);
721 
722 //extern float (*sEaseFunctionArray[])(float aPercentageOfCompletion);
723 
724 // Static convenience function
725 #if defined(__AVR__)
726 bool checkI2CConnection(uint8_t aI2CAddress, Print *aSerial); // Using Print class saves 95 bytes flash
727 #else
728 bool checkI2CConnection(uint8_t aI2CAddress, Stream *aSerial); // Print class has no flush() here
729 #endif
730 
731 #if !defined(STR_HELPER)
732 #define STR_HELPER(x) #x
733 #define STR(x) STR_HELPER(x)
734 #endif
735 
736 /*
737  * Version 3.2.0 - 02/2023
738  * - ATmega4808 support added.
739  * - Added function `getCurrentMicroseconds()`.
740  * - Improved many and added workaround for ESP32 bug in while loops in examples.
741  * - Added `PCA9685_ACTUAL_CLOCK_FREQUENCY` macro.
742  * - Renamed function `synchronizeAndEaseToArrayPositions()` to `setEaseToForAllServosSynchronizeAndWaitForAllServosToStop()`.
743  *
744  * Version 3.1.0 - 08/2022
745  * - SAMD51 support by Lutz Aumüller.
746  * - Added support to pause and resume and `DISABLE_PAUSE_RESUME`.
747  * - Fixed some bugs for PCA9685 expander introduced in 3.0.0.
748  * - Feather Huzzah support with the help of Danner Claflin.
749  * - Added `ENABLE_EXTERNAL_SERVO_TIMER_HANDLER` macro.
750  *
751  * Version 3.0.0 - 05/2022
752  * - Added target reached callback functionality, to enable multiple movements without loop control.
753  * - Changed `ENABLE_MICROS_AS_DEGREE_PARAMETER` to `DISABLE_MICROS_AS_DEGREE_PARAMETER` thus enabling micros as parameter by default.
754  * - Fixed some bugs for micros as parameter.
755  * - Changed constants for easing types.
756  * - Additional parameter aUserDataPointer for user easing function.
757  * - New easing type `PRECISION`.
758  * - New function `printEasingType()`.
759  * - Easing functions are converted to static member functions now.
760  * - Easing types can be disabled individually.
761  * - Improved PCA9685 handling / support for SoftI2CMaster.
762  * - Changed default for parameter `doWrite` for `setTrim()` from `false` to `true`.
763  * - Added min and max constraints for servo write() and `DISABLE_MIN_AND_MAX_CONSTRAINTS`.
764  *
765  * Version 2.4.1 - 02/2022
766  * - RP2040 support added.
767  * - Fix for Nano Every interrupts.
768  *
769  * Version 2.4.0 - 10/2021
770  * - New `attach()` functions with initial degree parameter to be written immediately. This replaces the `attach()` and `write()` combination at setup.
771  * - Renamed ServoEasing.cpp.h to ServoEasing.hpp and LightweightServo.cpp to LightweightServo.hpp.
772  *
773  * Version 2.3.4 - 02/2021
774  * - ENABLE_MICROS_AS_DEGREE_PARAMETER also available for PCA9685 expander.
775  * - Moved `sServoArrayMaxIndex`, `sServoNextPositionArray` and `sServoArray` to `ServoEasing::sServoArrayMaxIndex`, `ServoEasing::ServoEasingNextPositionArray` and `ServoEasing::ServoEasingArray`.
776  *
777  * Version 2.3.3 - 11/2020
778  * - 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.
779  * - Improved LightweightServo API.
780  *
781  * Version 2.3.2 - 9/2020
782  * - Removed blocking wait for ATmega32U4 Serial in examples.
783  * - Improved output for Arduino Serial Plotter.
784  *
785  * Version 2.3.1 - 9/2020
786  * - Fixed wrong timer selection for `STM32F1xx` / `ARDUINO_ARCH_STM32`.
787  * - Documentation.
788  *
789  * Version 2.3.0 - 7/2020
790  * - Fixed EASE_LINEAR formula bug introduced with 2.0.0 for 32 bit CPU's.
791  * - Added `stop()`, `continueWithInterrupts()` and `continueWithoutInterrupts()` functions.
792  *
793  * Version 2.2.0 - 7/2020
794  * - ATmega4809 (Uno WiFi Rev 2, Nano Every) support.
795  * - Corrected position of macro for MAX_EASING_SERVOS.
796  *
797  * Version 2.1.1 - 6/2020
798  * - Fixed bug in detach of first servo.
799  *
800  * Version 2.1.0 - 6/2020
801  * - Teensy support.
802  *
803  * Version 2.0.0 - 5/2020
804  * - `PCA9685_Expander` and standard Servos can be controlled simultaneously by defining `USE_SERVO_LIB`.
805  * - Changed some types to _fast types
806  * - Standardize pins for all examples
807  *
808  * Version 1.6.1 - 5/2020
809  * - Fix bug for **Arduino SAMD** boards.
810  *
811  * Version 1.6.0 - 4/2020
812  * - Added support of Apollo3 boards.
813  * - Print library version in examples.
814  *
815  * Version 1.5.2 - 3/2020
816  * - More examples using `areInterruptsActive()`.
817  * - Added support of Arduino SAMD boards.
818  *
819  * Version 1.5.1 - 3/2020
820  * - Added support for STM32 cores of Arduino Board manager. Seen in the Arduino IDE as "Generic STM32F1 series" from STM32 Boards.
821  * - Inserted missing `Wire.begin()` in setup of `PCA9685_Expander` example.
822  * - In `isMovingAndCallYield()` yield() only called/required for an ESP8266.
823  * - New function `areInterruptsActive()`, especially for ESP32.
824  *
825  * Version 1.5.0 - 2/2020
826  * - Use type `Print *` instead of `Stream *`.
827  * - New LightweightServoExample.
828  * - Added function `delayAndUpdateAndWaitForAllServosToStop()`.
829  * - Added Arduino Due support by using timer 8.
830  * - New PCA9685_ExpanderFor32Servos example.
831  *
832  * Version 1.4.3 - 12/2019
833  * - Improved detach() handling.
834  * - Initialize mSpeed explicitly to 0 in constructor. On an ESP8266 it was NOT initialized to 0 :-(.
835  *
836  * Version 1.4.2 - 11/2019
837  * - Improved INVALID_SERVO handling.
838  * - Speed 0 (not initialized) handling.
839  * - Fixed bug in ThreeServos example.
840  *
841  * Version 1.4.1 - 11/2019
842  * - Improved documentation and definitions for continuous rotating servo. Thanks to Eebel!
843  * - Improved support and documentation for generating Arduino Serial Plotter output.
844  * - Support of STM32F1 / BluePill boards.
845  *
846  * Version 1.4.0 - 11/2019
847  * - setTrim has additional parameter 'doWrite' which is default 'false' in contrast to older versions, where a write was always performed.
848  * - New attach( aPin, aMicrosecondsForServoLowDegree, aMicrosecondsForServoHighDegree, aServoLowDegree, aServoHighDegree) function for arbitrary mapping of servo degree to servo pulse width.
849  * - Order of Servos in 'sServoArray[]' now depends from order of calling attach() and not from order of declaration.
850  * - New example for continuous rotating servo.
851  * - Support for multiple PCA9685 expander.
852  *
853  * Version 1.3.1 - 6/2019
854  * - Added detach() function.
855  *
856  * Version 1.3.0 - 6/2019
857  * - Added ESP32 support by using ESP32Servo.h and Ticker.h instead of Servo.h timer interrupts.
858  * - Changed degree parameter and values from uint8_t to integer to support operating a servo from -90 to + 90 degree with 90 degree trim.
859  * - RobotArmControl + QuadrupedControl examples refactored.
860  * - Extended SpeedTest example. Now also able to change the width of the refresh period.
861  * - Changed "while" to "for" loops to avoid a gcc 7.3.0 atmel6.3.1 bug.
862  *
863  * Version 1.2 - 5/2019
864  * - Added ESP8266 support by using Ticker instead of timer interrupts for ESP.
865  * - AsymetricEasing example overhauled.
866  *
867  * Version 1.1 - 4/2019
868  * - corrected sine, circular, back and elastic IN functions.
869  * - easeTo() and write() store their degree parameter now also in sServoNextPositionArray.
870  * - added setSpeed(), getSpeed(), setSpeedForAllServos().
871  * - added easeTo(uint8_t aDegree) and setEaseTo(uint8_t aDegree).
872  * - added setEaseToForAllServos(), setEaseToForAllServosSynchronizeAndStartInterrupt(), synchronizeAndEaseToArrayPositions().
873  * - added getEndMicrosecondsOrUnits(), getDeltaMicrosecondsOrUnits().
874  * - added setDegreeForAllServos(uint8_t aNumberOfValues, va_list * aDegreeValues),setDegreeForAllServos(uint8_t aNumberOfValues, ...).
875  * - added compile switch PROVIDE_ONLY_LINEAR_MOVEMENT to save additional 1500 bytes program memory if enabled.
876  * - added convenience function clipDegreeSpecial().
877  */
878 
879 #if !defined(_SERVO_EASING_HPP) && !defined(SUPPRESS_HPP_WARNING)
880 #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.
881 #endif
882 
883 #endif // _SERVO_EASING_H
ServoEasing::getDeltaMicrosecondsOrUnits
int getDeltaMicrosecondsOrUnits()
Definition: ServoEasing.hpp:1668
setEaseToForAllServosSynchronizeAndWaitForAllServosToStop
void setEaseToForAllServosSynchronizeAndWaitForAllServosToStop()
Synchronize and blocking wait until all servos are stopped.
Definition: ServoEasing.hpp:2227
enableServoEasingInterrupt
void enableServoEasingInterrupt()
Timer1 is used for the Arduino Servo library.
Definition: ServoEasing.hpp:1866
ServoEasing::_setTrimMicrosecondsOrUnits
void _setTrimMicrosecondsOrUnits(int aTrimMicrosecondsOrUnits, bool aDoWrite=false)
Definition: ServoEasing.hpp:715
ServoEasing::MicrosecondsOrUnitsToDegree
int MicrosecondsOrUnitsToDegree(int aMicrosecondsOrUnits)
Used to convert e.g.
Definition: ServoEasing.hpp:912
ServoEasing::getSpeed
uint_fast16_t getSpeed()
Definition: ServoEasing.hpp:683
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:595
ServoEasing::mServoMoves
volatile bool mServoMoves
Definition: ServoEasing.h:605
ServoEasing::registerUserEaseInFunction
void registerUserEaseInFunction(float(*aUserEaseInFunction)(float aPercentageOfCompletion, void *aUserDataPointer), void *aUserDataPointer=NULL)
Definition: ServoEasing.hpp:745
ServoEasing::update
bool update()
Definition: ServoEasing.hpp:1420
updateAndWaitForAllServosToStop
void updateAndWaitForAllServosToStop()
Blocking wait until all servos are stopped.
Definition: ServoEasing.hpp:2434
ServoEasing::attach
uint8_t attach(int aPin)
Specify the microseconds values for 0 and 180 degree for the servo.
Definition: ServoEasing.hpp:443
ServoEasing
Definition: ServoEasing.h:418
ServoEasing::setReverseOperation
void setReverseOperation(bool aOperateServoReverse)
Definition: ServoEasing.hpp:679
ServoEasing::getEasingType
uint_fast8_t getEasingType()
Definition: ServoEasing.hpp:740
disableServoEasingInterrupt
void disableServoEasingInterrupt()
Definition: ServoEasing.hpp:2072
ServoEasing::TargetPositionReachedHandler
void(* TargetPositionReachedHandler)(ServoEasing *)
Is called any time when target servo position is reached.
Definition: ServoEasing.h:647
ServoEasing::mStartMicrosecondsOrUnits
int mStartMicrosecondsOrUnits
Only used with millisAtStartMove to compute currentMicrosecondsOrUnits in update()
Definition: ServoEasing.h:588
ServoEasing::getMillisForCompleteMove
int getMillisForCompleteMove()
Definition: ServoEasing.hpp:1672
ServoEasing::setTargetPositionReachedHandler
void setTargetPositionReachedHandler(void(*aTargetPositionReachedHandler)(ServoEasing *))
Definition: ServoEasing.hpp:1378
ServoEasing::mServo0DegreeMicrosecondsOrUnits
int mServo0DegreeMicrosecondsOrUnits
Values contain always microseconds except for servos connected to a PCA9685 expander,...
Definition: ServoEasing.h:644
ServoEasing::mTrimMicrosecondsOrUnits
int mTrimMicrosecondsOrUnits
This value is always added by the function _writeMicrosecondsOrUnits() to the requested degree/units/...
Definition: ServoEasing.h:638
areInterruptsActive
#define areInterruptsActive()
Definition: ServoEasing.h:668
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:617
ServoEasing::mMinMicrosecondsOrUnits
int mMinMicrosecondsOrUnits
Min value checked at _writeMicrosecondsOrUnits(), before trim and reverse is applied.
Definition: ServoEasing.h:636
ServoEasing::setEaseTo
bool setEaseTo(int aTargetDegreeOrMicrosecond)
Definition: ServoEasing.hpp:1087
synchronizeAllServosAndStartInterrupt
void synchronizeAllServosAndStartInterrupt(bool aStartUpdateByInterrupt=START_UPDATE_BY_INTERRUPT)
Take the longer duration in order to move all servos synchronously.
Definition: ServoEasing.hpp:2474
ServoEasing::getEndMicrosecondsOrUnits
int getEndMicrosecondsOrUnits()
Definition: ServoEasing.hpp:1657
ServoEasing::resumeWithInterrupts
void resumeWithInterrupts()
Definition: ServoEasing.hpp:1363
synchronizeAndEaseToArrayPositions
void synchronizeAndEaseToArrayPositions() __attribute__((deprecated("Please use setEaseToForAllServosSynchronizeAndWait().")))
Definition: ServoEasing.hpp:2237
ServoEasing::stop
void stop()
This stops the servo at any position.
Definition: ServoEasing.hpp:1346
setEaseToForAllServos
bool setEaseToForAllServos()
Sets target position using content of ServoEasingNextPositionArray.
Definition: ServoEasing.hpp:2322
ServoEasing::attachWithTrim
uint8_t attachWithTrim(int aPin, int aTrimDegreeOrMicrosecond, int aInitialDegreeOrMicrosecond)
Combination of attach with initial setTrim() and write().
Definition: ServoEasing.hpp:462
ServoEasing::noMovement
bool noMovement(uint_fast16_t aMillisToWait)
stay at the position for aMillisToWait Used as delay for callback
Definition: ServoEasing.hpp:1223
checkI2CConnection
bool checkI2CConnection(uint8_t aI2CAddress, Stream *aSerial)
ServoEasing::isMoving
bool isMoving()
Test if servo is moving yet.
Definition: ServoEasing.hpp:1615
ServoEasing::mMaxMicrosecondsOrUnits
int mMaxMicrosecondsOrUnits
Max value checked at _writeMicrosecondsOrUnits(), before trim and reverse is applied.
Definition: ServoEasing.h:635
ServoEasing::setUserDataPointer
void setUserDataPointer(void *aUserDataPointer)
Definition: ServoEasing.hpp:750
ServoEasing::pause
void pause()
Definition: ServoEasing.hpp:1356
printArrayPositions
void printArrayPositions(Print *aSerial)
Prints content of ServoNextPositionArray for debugging purposes.
Definition: ServoEasing.hpp:2251
ServoEasing::mServoIsPaused
bool mServoIsPaused
Definition: ServoEasing.h:624
ServoEasing::InitializeAndCheckI2CConnection
bool InitializeAndCheckI2CConnection(Stream *aSerial)
delayAndUpdateAndWaitForAllServosToStop
bool delayAndUpdateAndWaitForAllServosToStop(unsigned long aMillisDelay, bool aTerminateDelayIfAllServosStopped=false)
Definition: ServoEasing.hpp:2446
ServoEasing::BackEaseIn
static float BackEaseIn(float aPercentageOfCompletion)
see: https://easings.net/#easeInOutBack and https://github.com/warrenm/AHEasing/blob/master/AHEasing/...
Definition: ServoEasing.hpp:2561
ServoEasing::mEndMicrosecondsOrUnits
int mEndMicrosecondsOrUnits
Only used once as last value if movement was finished to provide exact end position.
Definition: ServoEasing.h:589
ServoEasing::DegreeToMicrosecondsOrUnitsWithTrimAndReverse
int DegreeToMicrosecondsOrUnitsWithTrimAndReverse(int aDegree)
Mainly for testing, since trim and reverse are applied at each write.
Definition: ServoEasing.hpp:1018
ServoEasing::setMinConstraint
void setMinConstraint(int aMinDegreeOrMicrosecond)
Definition: ServoEasing.hpp:726
ServoEasing::synchronizeServosAndStartInterrupt
void synchronizeServosAndStartInterrupt(bool doUpdateByInterrupt)
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:2588
ServoEasing::setTrim
void setTrim(int aTrimDegreeOrMicrosecond, bool aDoWrite=false)
Definition: ServoEasing.hpp:697
ServoEasing::printDynamic
void printDynamic(Print *aSerial, bool doExtendedOutput=true)
Prints values which may change from move to move.
Definition: ServoEasing.hpp:1714
clipDegreeSpecial
int clipDegreeSpecial(uint_fast8_t aDegreeToClip)
Clips the unsigned degree value and handles unsigned underflow.
Definition: ServoEasing.hpp:1821
ServoEasing::setMinMaxConstraint
void setMinMaxConstraint(int aMinDegreeOrMicrosecond, int aMaxDegreeOrMicrosecond)
Definition: ServoEasing.hpp:729
ServoEasing::mEasingType
uint8_t mEasingType
Definition: ServoEasing.h:598
ServoEasing::MicrosecondsOrUnitsToMicroseconds
int MicrosecondsOrUnitsToMicroseconds(int aMicrosecondsOrUnits)
Definition: ServoEasing.hpp:949
LightweightServo.h
ServoEasing::mMillisForCompleteMove
uint_fast16_t mMillisForCompleteMove
Definition: ServoEasing.h:622
ServoEasing::EaseOutBounce
static float EaseOutBounce(float aPercentageOfCompletion)
!!! ATTENTION !!! we have only the out function implemented see: https://easings.net/de#easeOutBounce...
Definition: ServoEasing.hpp:2664
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:2198
ServoEasing::resumeWithoutInterrupts
void resumeWithoutInterrupts()
Definition: ServoEasing.hpp:1371
ServoEasing::print
void print(Print *aSerial, bool doExtendedOutput=true)
Do a printDynamic() and a printStatic()
Definition: ServoEasing.hpp:1681
ServoEasing::mMillisAtStartMove
uint32_t mMillisAtStartMove
Definition: ServoEasing.h:621
ServoEasing::easeToD
void easeToD(int aTargetDegreeOrMicrosecond, uint_fast16_t aMillisForMove)
Definition: ServoEasing.hpp:1065
stopAllServos
void stopAllServos()
Definition: ServoEasing.hpp:2375
ServoEasing::mUserEaseInFunction
float(* mUserEaseInFunction)(float aPercentageOfCompletion, void *aUserDataPointer)
Definition: ServoEasing.h:601
ServoEasing::getCurrentAngle
int getCurrentAngle()
Definition: ServoEasing.hpp:1649
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:892
setEasingTypeForMultipleServos
void setEasingTypeForMultipleServos(uint_fast8_t aNumberOfServos, uint_fast8_t aEasingType)
Sets easing type aEasingType for the first aNumberOfServos in ServoEasingArray[].
Definition: ServoEasing.hpp:2205
resumeWithInterruptsAllServos
void resumeWithInterruptsAllServos()
Definition: ServoEasing.hpp:2398
ServoEasing::printStatic
void printStatic(Print *aSerial)
Prints values which normally does NOT change from move to move.
Definition: ServoEasing.hpp:1773
PROGMEM
const char easeTypeLinear[] PROGMEM
Definition: ServoEasing.h:372
setSpeedForAllServos
void setSpeedForAllServos(uint_fast16_t aDegreesPerSecond)
Definition: ServoEasing.hpp:2286
ServoEasing::setMaxConstraint
void setMaxConstraint(int aMaxDegreeOrMicrosecond)
Definition: ServoEasing.hpp:723
ServoEasing::callEasingFunction
float callEasingFunction(float aPercentageOfCompletion)
Definition: ServoEasing.hpp:1554
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:1232
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:2553
handleServoTimerInterrupt
void handleServoTimerInterrupt()
Update all servos from list and check if all servos have stopped.
Definition: ServoEasing.hpp:1841
ServoEasing::detach
void detach()
Mark a detached servo in the array by setting the object pointer to NULL The next attach() then uses ...
Definition: ServoEasing.hpp:638
ServoEasing::mMillisAtStopMove
uint32_t mMillisAtStopMove
Definition: ServoEasing.h:625
ServoEasing::startEaseTo
bool startEaseTo(int aTargetDegreeOrMicrosecond)
Starts interrupt for update()
Definition: ServoEasing.hpp:1110
ServoEasing::getEndMicrosecondsOrUnitsWithTrim
int getEndMicrosecondsOrUnitsWithTrim()
Not used internally.
Definition: ServoEasing.hpp:1664
ServoEasing::ServoEasing
ServoEasing()
Definition: ServoEasing.hpp:395
ServoEasing::_writeMicrosecondsOrUnits
void _writeMicrosecondsOrUnits(int aTargetDegreeOrMicrosecond)
Internal function Before sending the value to the underlying Servo library, trim and reverse is appli...
Definition: ServoEasing.hpp:801
setEaseToForAllServosSynchronizeAndStartInterrupt
void setEaseToForAllServosSynchronizeAndStartInterrupt()
Definition: ServoEasing.hpp:2214
ServoEasing::ServoEasingNextPositionArray
static float ServoEasingNextPositionArray[MAX_EASING_SERVOS]
Used exclusively for *ForAllServos() functions.
Definition: ServoEasing.h:664
ServoEasing::getCurrentMicroseconds
int getCurrentMicroseconds()
Definition: ServoEasing.hpp:1653
ServoEasing::sInterruptsAreActive
static volatile bool sInterruptsAreActive
It is required for ESP32, where the timer interrupt routine does not block the loop.
Definition: ServoEasing.h:655
isOneServoMoving
bool isOneServoMoving()
Definition: ServoEasing.hpp:2366
ServoEasing::mServo180DegreeMicrosecondsOrUnits
int mServo180DegreeMicrosecondsOrUnits
Definition: ServoEasing.h:645
ServoEasing::printEasingType
static void printEasingType(Print *aSerial, uint_fast8_t aEasingType)
Definition: ServoEasing.hpp:1690
ServoEasing::ServoEasingArray
static ServoEasing * ServoEasingArray[MAX_EASING_SERVOS]
Definition: ServoEasing.h:663
MAX_EASING_SERVOS
#define MAX_EASING_SERVOS
Definition: ServoEasing.h:157
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:963
ServoEasing::QuadraticEaseIn
static float QuadraticEaseIn(float aPercentageOfCompletion)
The simplest non linear easing function.
Definition: ServoEasing.hpp:2528
setEaseToDForAllServos
bool setEaseToDForAllServos(uint_fast16_t aMillisForMove)
Sets target position using content of ServoEasingNextPositionArray and use aMillisForMove instead of ...
Definition: ServoEasing.hpp:2355
ServoEasing::UserDataPointer
void * UserDataPointer
Definition: ServoEasing.h:600
START_UPDATE_BY_INTERRUPT
#define START_UPDATE_BY_INTERRUPT
Definition: ServoEasing.h:408
ServoEasing::SineEaseIn
static float SineEaseIn(float aPercentageOfCompletion)
Take half of negative cosines of first quadrant Is behaves almost like QUADRATIC.
Definition: ServoEasing.hpp:2544
ServoEasing::mOperateServoReverse
bool mOperateServoReverse
Reverse means, that values for 180 and 0 degrees are swapped by: aValue = mServo180DegreeMicroseconds...
Definition: ServoEasing.h:633
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:662
synchronizeAllServosStartAndWaitForAllServosToStop
void synchronizeAllServosStartAndWaitForAllServosToStop()
Synchronize and blocking wait until all servos are stopped.
Definition: ServoEasing.hpp:2466
writeAllServos
void writeAllServos(int aTargetDegreeOrMicrosecond)
Definition: ServoEasing.hpp:2278
ServoEasing::mDeltaMicrosecondsOrUnits
int mDeltaMicrosecondsOrUnits
end - start
Definition: ServoEasing.h:590
ServoEasing::setEaseToD
bool setEaseToD(int aTargetDegreeOrMicrosecond, uint_fast16_t aDegreesPerSecond)
Sets easing parameter, but does not start.
Definition: ServoEasing.hpp:1211
ServoEasing::mServoIndex
uint8_t mServoIndex
Index in sServoArray or INVALID_SERVO if error while attach() or if detached.
Definition: ServoEasing.h:619
ServoEasing::mCurrentMicrosecondsOrUnits
volatile int mCurrentMicrosecondsOrUnits
Internally only microseconds (or units (= 4.88 us) if using PCA9685 expander) and not degree are used...
Definition: ServoEasing.h:587
ServoEasing::setSpeed
void setSpeed(uint_fast16_t aDegreesPerSecond)
Definition: ServoEasing.hpp:687
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:1645
ServoEasing::write
void write(int aTargetDegreeOrMicrosecond)
Definition: ServoEasing.hpp:759
resumeWithoutInterruptsAllServos
void resumeWithoutInterruptsAllServos()
Definition: ServoEasing.hpp:2406
updateAllServos
bool updateAllServos()
Definition: ServoEasing.hpp:2417
ServoEasing::CubicEaseIn
static float CubicEaseIn(float aPercentageOfCompletion)
Definition: ServoEasing.hpp:2532
ServoEasing::easeTo
void easeTo(int aTargetDegreeOrMicrosecond)
Definition: ServoEasing.hpp:1028
ServoEasing::ElasticEaseIn
static float ElasticEaseIn(float aPercentageOfCompletion)
see: https://easings.net/#easeInOutElastic and https://github.com/warrenm/AHEasing/blob/master/AHEasi...
Definition: ServoEasing.hpp:2570
ServoEasing::QuarticEaseIn
static float QuarticEaseIn(float aPercentageOfCompletion)
Definition: ServoEasing.hpp:2536
ServoEasing::setEasingType
void setEasingType(uint_fast8_t aEasingType)
Definition: ServoEasing.hpp:736