ServoEasing: smooth servo movements with easing curves
The Servo library’s write() jumps a servo to an angle as fast as the motor can go. That is fine for a pointer and harsh for a robot arm, a puppet’s eyes or a camera pan, where the sudden start and stop shakes the whole build. ServoEasing by Armin Joachimsmeyer moves the servo in many small steps instead, at a speed you choose in degrees per second, and shapes the motion with an easing curve so it starts and stops gently.
Built in on Mokxi: #include <ServoEasing.hpp> and it builds, with nothing to install. Free, and no account needed.
What ServoEasing does
A ServoEasing object is a drop-in for a Servo object: attach() it to a pin, with a starting angle, and it moves there at once. easeTo() then moves to a new angle and returns when it arrives. startEaseTo() starts the same move and returns at once, and the sketch checks isMoving() until it is done, which lets several servos or other code run alongside. The curves include linear, quadratic, cubic, sine, bounce and more, each with in, out and in-out forms.
The example attaches a servo on pin 9 at 45 degrees, eases it to 135 at 90 degrees a second with a cubic in-out curve, then starts a move back to 90 and polls until it finishes. Upstream moves a started servo from a timer interrupt; in Mokxi it moves each time the sketch calls isMoving() or update(), as the library’s non-blocking examples do anyway. The PCA9685 servo board constructors are not here.
| Library Manager name | ServoEasing |
|---|---|
| Author | Armin Joachimsmeyer |
| Include | #include <ServoEasing.hpp>#include <ServoEasing.h> |
| Boards | every board Mokxi compiles for but ATtiny85 |
| In the simulator | Runs, with a gap the note below names. |
| Parts it drives | Hobby servo |
Install it
It builds on every board Mokxi compiles for but ATtiny85.
In Mokxi it is built in: #include <ServoEasing.hpp> and the sketch compiles, with no download, no zip and no Library Manager.
On a real board, install "ServoEasing" by Armin Joachimsmeyer from the Arduino IDE’s Library Manager (Sketch, Include Library, Manage Libraries), or add ServoEasing to lib_deps in PlatformIO. Mokxi follows the calls of release 3.6.0, so a sketch written here builds there too.
What to know in the simulator: Upstream advances a started move from a timer interrupt; here it advances when the sketch calls isMoving() or update(), as the library’s non-blocking examples do. The PCA9685 constructors are not here.
- ESP32-C3
- Arduino Uno
- Arduino Nano
- Arduino Mega 2560
- Arduino Leonardo
- SparkFun Pro Micro
- Arduino Micro
- ESP32-C6
- WCH CH32V003
- Raspberry Pi Pico
- Raspberry Pi Pico W
- Seeed XIAO SAMD21
- STM32
- STM32 Nucleo-F411RE
- STM32 Blue Pill
- micro:bit V2
- Arduino Uno R4
- ESP32 DevKit
- ESP32-S3-DevKitC-1
- ESP8266 NodeMCU
- Arduino Pro Mini 3.3 V
- Seeed XIAO ESP32-C3
- ESP32-C3 SuperMini
- Seeed XIAO ESP32-C6
- ESP32-DevKitC V4
- LOLIN32 Lite
- Wemos D1 R32
- Cheap Yellow Display
- TTGO T-Display
- Seeed XIAO ESP32-S3
- Arduino Nano ESP32
- Arduino Nano RP2040 Connect
- Seeed XIAO RP2040
- Waveshare RP2040-Zero
- Arduino Uno R4 WiFi
The calls you will use
In the order a sketch meets them.
ServoEasing Servo1
One servo. Include ServoEasing.hpp in the main sketch file only; other files include ServoEasing.h.
Servo1.attach(9, 45)
Attaches to pin 9 and moves straight to 45 degrees, so the first eased move has a known start.
Servo1.setEasingType(EASE_CUBIC_IN_OUT)
The curve for the following moves. EASE_LINEAR is a constant speed; the IN_OUT forms speed up and slow down.
Servo1.easeTo(135, 90)
Moves to 135 degrees at 90 degrees a second and returns when it gets there.
Servo1.startEaseTo(90, 45)
Starts the move and returns at once. Use it when the sketch has other work to do while the servo moves.
Servo1.startEaseTo(90, 45);
while (Servo1.isMoving()) {
// read buttons, update a display
}Servo1.isMoving()
True until the started move is finished. Here it also advances the move, so call it often.
Servo1.setSpeed(60)
The default speed in degrees a second for moves that do not name one.
synchronizeAllServosStartAndWaitForAllServosToStop()
After setEaseTo() on several servos, starts them together so they all arrive at the same moment.
Example: A servo eased across, then started and polled
On the Arduino Uno R3. It runs in the browser exactly as printed.
#include <ServoEasing.hpp>
ServoEasing Servo1;
void setup() {
Serial.begin(9600);
Servo1.attach(9, 45);
Servo1.setEasingType(EASE_CUBIC_IN_OUT);
Servo1.easeTo(135, 90); // 90 degrees at 90 a second: one second, and it waits
Serial.print("at ");
Serial.println(Servo1.read());
Servo1.startEaseTo(90, 45);
unsigned long started = millis();
while (Servo1.isMoving()) {
}
Serial.print("back at ");
Serial.print(Servo1.read());
Serial.print(" after ");
Serial.print((millis() - started + 50) / 100 * 100);
Serial.println(" ms");
}
void loop() {}Wiring
- Arduino Uno R3 9 to Hobby servo PWM
- Arduino Uno R3 5V to Hobby servo VCC
- Arduino Uno R3 GND to Hobby servo GND
Common errors and how to fix them
multiple definition of ServoEasing functions
ServoEasing.hpp was included in more than one .cpp or .ino tab. It holds the code itself, so include it in exactly one file and use ServoEasing.h everywhere else.
The servo jumps at power on before easing
A hobby servo goes to its last commanded angle as soon as it gets a signal. Pass the position it is likely already at as attach()’s second argument, so the first move starts from there.
startEaseTo() starts but the servo never finishes the move
Nothing is calling isMoving() or update() in Mokxi, or on a real board the timer interrupt is disabled. Poll isMoving() in loop() until it returns false.
Questions and answers
Which calls move a started servo in Mokxi?
Any of isMoving(), update(), updateAllServos() or isOneServoMoving(). Call one of them in loop() after startEaseTo() and the move advances each time.
Keep going
Parts
Try ServoEasing without installing anything
Open the example, change the sketch, and keep your version in a free account.