diff --git a/.github/workflows/LibraryBuild.yml b/.github/workflows/LibraryBuild.yml
index 6c4f77e..e391226 100644
--- a/.github/workflows/LibraryBuild.yml
+++ b/.github/workflows/LibraryBuild.yml
@@ -112,7 +112,7 @@ jobs:
- arduino-boards-fqbn: esp32:esp32:featheresp32:FlashFreq=80
platform-url: https://dl.espressif.com/dl/package_esp32_index.json
- sketches-exclude: QuadrupedControl,RobotArmControl # Comma separated list of (unique substrings of) example names to exclude in build
+ sketches-exclude: QuadrupedControl,RobotArmControl # Comma separated list of example names to exclude in build
build-properties:
PCA9685_Expander: -DUSE_PCA9685_SERVO_EXPANDER
PCA9685_ExpanderAndServo: -DUSE_PCA9685_SERVO_EXPANDER -DUSE_SERVO_LIB
diff --git a/README.md b/README.md
index cb28a94..bd6eeb6 100644
--- a/README.md
+++ b/README.md
@@ -18,15 +18,18 @@ This is a library for smooth servo movements. It uses the standard Arduino Servo
As an alternative to the Arduino Servo library, ServoEasing can be used with a [PCA9685 servo expander](https://learn.adafruit.com/16-channel-pwm-servo-driver?view=all) using the Arduino Wire library or a compatible one (and their restrictions).
For **ESP32** you need to install the Arduino ESP32Servo library.
For **AVR**, if you need only one or two servos, you may want to use the included [Lightweight Servo library](https://github.com/ArminJo/LightweightServo) instead of the Arduino Servo library because it uses only the internal Timer1 with no software overhead and has no problems with interrupt blocking libraries like SoftwareSerial, Adafruit_NeoPixel and DmxSimple.
-For instructions how to enable these alternatives see [Modifying library properties](#modifying-library-properties)
+For instructions how to enable these alternatives see [Compile options / macros](#compile-options--macros)
### Features
- **Linear** and 9 other ease movements are provided.
- All servos can move **synchronized** or **independently**.
- **Non blocking** movements are enabled by using **startEaseTo\* functions** by reusing the interrupts of the servo timer Timer1 or using a dedicated timer on other platforms. This function is not available for all platforms.
-- Trim value for each servo may be set.
-- Reverse operation of servo is possible eg. if it is mounted head down.
-- Allow to specify an arbitrary mapping between degrees and microseconds by `attach(int aPin, int aMicrosecondsForServoLowDegree, int aMicrosecondsForServoHighDegree, int aServoLowDegree, int aServoHighDegree)`
+- **Trim** value for each servo may be set.
+- **Reverse operation** of servo is possible eg. if it is mounted head down.
+- Allow to specify an arbitrary mapping between degrees and microseconds by `attach(int aPin, int aMicrosecondsForServoLowDegree, int aMicrosecondsForServoHighDegree, int aServoLowDegree, int aServoHighDegree)`.
+- **Servo speed** can be specified in **degree per second** or **milliseconds** for the complete move.
+
+## [API](https://github.com/ArminJo/ServoEasing/blob/master/src/ServoEasing.h#L428)
## Usage
Just call **myServo.startEaseTo()** instead of **myServo.write()** and you are done. Or if you want to wait (blocking) until servo has arrived, use **myServo.easeTo()**.
@@ -68,7 +71,7 @@ Just call **myServo.startEaseTo()** instead of **myServo.write()** and you are d
Digital Servos have a **deadband of approximately 5 µs / 0.5 degree** which means, that you will see a **stuttering movement** if the moving speed is slow.
If you control them with a PCA9685 expander it may get worse, since one step of 4.88 µs can be within the deadband, so it takes 2 steps to move the servo from its current position.
-# Compile options / macros
+# Compile options / macros for this library
To customize the software to different car extensions, there are some compile options / macros available.
Modify it by commenting them out or in, or change the values if applicable. Or define the macro with the -D compiler option for gobal compile (the latter is not possible with the Arduino IDE, so consider to use [Sloeber](https://eclipse.baeyens.it).
| Option | Default | File | Description |
@@ -80,14 +83,14 @@ Modify it by commenting them out or in, or change the values if applicable. Or d
| `PRINT_FOR_SERIAL_PLOTTER` | disabled | ServoEasing.h | Generate serial output for Arduino Plotter. |
| `USE_LEIGHTWEIGHT_SERVO_LIB` | disabled | ServoEasing.h | Makes the servo pulse generating immune to other libraries blocking interrupts for a longer time like SoftwareSerial, Adafruit_NeoPixel and DmxSimple. See below. Saves up to 742 bytes FLASH and 42 bytes RAM. |
-# Modifying library properties
-### Modifying library properties with Arduino IDE
+# Modifying compile options
+### Modifying compile options with Arduino IDE
First use *Sketch/Show Sketch Folder (Ctrl+K)*.
If you did not yet stored the example as your own sketch, then you are instantly in the right library folder.
Otherwise you have to navigate to the parallel `libraries` folder and select the library you want to access.
In both cases the library files itself are located in the `src` directory.
-### Modifying library properties with Sloeber IDE
+### Modifying compile options with Sloeber IDE
If you are using Sloeber as your IDE, you can easily define global symbols with *Properties/Arduino/CompileOptions*.
![Sloeber settings](https://github.com/ArminJo/ServoEasing/blob/master/pictures/SloeberDefineSymbols.png)
diff --git a/src/LightweightServo.cpp b/src/LightweightServo.cpp
index 3c153a4..5b7e79e 100644
--- a/src/LightweightServo.cpp
+++ b/src/LightweightServo.cpp
@@ -31,10 +31,6 @@
#if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega328__)
#include "LightweightServo.h"
-/*
- * Commenting out this saves 70 bytes flash memory. You must then use the init function initLightweightServoPin9And10() manually.
- */
-//#define DISABLE_SERVO_TIMER_AUTO_INITIALIZE
/*
* Variables to enable adjustment for different servo types
* 544 and 2400 are values compatible with standard arduino values
@@ -103,12 +99,12 @@ void deinitLightweightServoPin9_10(bool aUsePin9) {
* If aUsePin9 is false, then Pin10 is used
* 236 / 186(without auto init) bytes code size
*/
-int writeLightweightServo(int aValue, bool aUsePin9, bool aUpdateFast) {
- if (aValue <= 180) {
- aValue = DegreeToMicrosecondsLightweightServo(aValue);
+int writeLightweightServo(int aDegree, bool aUsePin9, bool aUpdateFast) {
+ if (aDegree <= 180) {
+ aDegree = DegreeToMicrosecondsLightweightServo(aDegree);
}
- writeMicrosecondsLightweightServo(aValue, aUsePin9, aUpdateFast);
- return aValue;
+ writeMicrosecondsLightweightServo(aDegree, aUsePin9, aUpdateFast);
+ return aDegree;
}
void writeMicrosecondsLightweightServo(int aMicroseconds, bool aUsePin9, bool aUpdateFast) {
@@ -153,8 +149,8 @@ void setLightweightServoPulseMicrosFor0And180Degree(int aMicrosecondsForServo0De
/*
* Pin 9 / Channel A. If value is below 180 then assume degree, otherwise assume microseconds
*/
-void write9(int aValue, bool aUpdateFast) {
- writeLightweightServo(aValue, true, aUpdateFast);
+void write9(int aDegree, bool aUpdateFast) {
+ writeLightweightServo(aDegree, true, aUpdateFast);
}
void writeMicroseconds9(int aMicroseconds, bool aUpdateFast) {
@@ -171,8 +167,8 @@ void writeMicroseconds9Direct(int aMicroseconds) {
/*
* Pin 10 / Channel B
*/
-void write10(int aValue, bool aUpdateFast) {
- writeLightweightServo(aValue, false, aUpdateFast);
+void write10(int aDegree, bool aUpdateFast) {
+ writeLightweightServo(aDegree, false, aUpdateFast);
}
void writeMicroseconds10(int aMicroseconds, bool aUpdateFast) {
@@ -189,12 +185,12 @@ void writeMicroseconds10Direct(int aMicroseconds) {
/*
* Conversion functions
*/
-int DegreeToMicrosecondsLightweightServo(int aValueDegree) {
- return (map(aValueDegree, 0, 180, sMicrosecondsForServo0Degree, sMicrosecondsForServo180Degree));
+int DegreeToMicrosecondsLightweightServo(int aDegree) {
+ return (map(aDegree, 0, 180, sMicrosecondsForServo0Degree, sMicrosecondsForServo180Degree));
}
-int MicrosecondsToDegreeLightweightServo(int aValueMicros) {
- return map(aValueMicros, sMicrosecondsForServo0Degree, sMicrosecondsForServo180Degree, 0, 180);
+int MicrosecondsToDegreeLightweightServo(int aMicroseconds) {
+ return map(aMicroseconds, sMicrosecondsForServo0Degree, sMicrosecondsForServo180Degree, 0, 180);
}
#endif
diff --git a/src/LightweightServo.h b/src/LightweightServo.h
index fe94c42..e84b39b 100644
--- a/src/LightweightServo.h
+++ b/src/LightweightServo.h
@@ -32,6 +32,11 @@
#include
+/*
+ * Commenting out this saves 70 bytes flash memory. You must then use the init function initLightweightServoPin9And10() manually.
+ */
+//#define DISABLE_SERVO_TIMER_AUTO_INITIALIZE
+
#define ISR1_COUNT_FOR_20_MILLIS 40000 // you can modify this if you have servos which accept a higher rate
/*
@@ -45,20 +50,20 @@ void deinitLightweightServoPin9_10(bool aUsePin9);
void setLightweightServoPulseMicrosFor0And180Degree(int aMicrosecondsForServo0Degree, int a180DegreeValue);
void setLightweightServoRefreshRate(unsigned int aRefreshPeriodMicroseconds);
-int writeLightweightServo(int aValue, bool aUsePin9, bool aUpdateFast = false);
+int writeLightweightServo(int aDegree, bool aUsePin9, bool aUpdateFast = false);
void writeMicrosecondsLightweightServo(int aMicroseconds, bool aUsePin9, bool aUpdateFast = false);
-void write9(int aValue, bool aUpdateFast = false); // setLightweightServoPulsePin9 Channel A
+void write9(int aDegree, bool aUpdateFast = false); // setLightweightServoPulsePin9 Channel A
void writeMicroseconds9(int aMicroseconds, bool aUpdateFast = false);
void writeMicroseconds9Direct(int aMicroseconds);
-void write10(int aValue, bool aUpdateFast = false); // setLightweightServoPulsePin10 Channel B
+void write10(int aDegree, bool aUpdateFast = false); // setLightweightServoPulsePin10 Channel B
void writeMicroseconds10(int aMicroseconds, bool aUpdateFast = false);
void writeMicroseconds10Direct(int aMicroseconds);
// convenience functions
-int DegreeToMicrosecondsLightweightServo(int aValueDegree);
-int MicrosecondsToDegreeLightweightServo(int aValueMicros);
+int DegreeToMicrosecondsLightweightServo(int aDegree);
+int MicrosecondsToDegreeLightweightServo(int aMicroseconds);
#endif // AVR_ATmega328
#endif // LIGHTWEIGHT_SERVO_H_
diff --git a/src/ServoEasing.h b/src/ServoEasing.h
index d7d71cd..192f989 100644
--- a/src/ServoEasing.h
+++ b/src/ServoEasing.h
@@ -329,12 +329,12 @@
* Values for provided EaseTypes
* The call style is coded in the upper 3 bits
*/
-#define CALL_STYLE_DIRECT 0x00 // == IN
-#define CALL_STYLE_OUT 0x20
-#define CALL_STYLE_IN_OUT 0x40
+#define CALL_STYLE_DIRECT 0x00 // == IN
+#define CALL_STYLE_OUT 0x20
+#define CALL_STYLE_IN_OUT 0x40
#define CALL_STYLE_BOUNCING_OUT_IN 0x60 // Bouncing has double movement, so double time (half speed) is taken for this modes
-#define CALL_STYLE_MASK 0xE0 // for future extensions
+#define CALL_STYLE_MASK 0xE0 // for future extensions
#define EASE_TYPE_MASK 0x0F
#define EASE_LINEAR 0x00 // No bouncing available
@@ -389,15 +389,15 @@
// some PCA9685 specific constants
#define PCA9685_GENERAL_CALL_ADDRESS 0x00
-#define PCA9685_SOFTWARE_RESET 6
-#define PCA9685_DEFAULT_ADDRESS 0x40
-#define PCA9685_MAX_CHANNELS 16 // 16 PWM channels on each PCA9685 expansion module
-#define PCA9685_MODE1_REGISTER 0x0
-#define PCA9685_MODE_1_RESTART 7
-#define PCA9685_MODE_1_AUTOINCREMENT 5
-#define PCA9685_MODE_1_SLEEP 4
-#define PCA9685_FIRST_PWM_REGISTER 0x06
-#define PCA9685_PRESCALE_REGISTER 0xFE
+#define PCA9685_SOFTWARE_RESET 6
+#define PCA9685_DEFAULT_ADDRESS 0x40
+#define PCA9685_MAX_CHANNELS 16 // 16 PWM channels on each PCA9685 expansion module
+#define PCA9685_MODE1_REGISTER 0x0
+#define PCA9685_MODE_1_RESTART 7
+#define PCA9685_MODE_1_AUTOINCREMENT 5
+#define PCA9685_MODE_1_SLEEP 4
+#define PCA9685_FIRST_PWM_REGISTER 0x06
+#define PCA9685_PRESCALE_REGISTER 0xFE
#define PCA9685_PRESCALER_FOR_20_MS ((25000000L /(4096L * 50))-1) // = 121 / 0x79 at 50 Hz