Skip to content

Commit

Permalink
Documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
ArminJo committed Nov 23, 2020
1 parent a52c079 commit be94356
Show file tree
Hide file tree
Showing 5 changed files with 48 additions and 44 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/LibraryBuild.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
19 changes: 11 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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).<br/>
For **ESP32** you need to install the Arduino ESP32Servo library.<br/><br/>
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.<br/>
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()**.<br/>
Expand Down Expand Up @@ -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.<br/>
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).<br/>
| Option | Default | File | Description |
Expand All @@ -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)*.<br/>
If you did not yet stored the example as your own sketch, then you are instantly in the right library folder.<br/>
Otherwise you have to navigate to the parallel `libraries` folder and select the library you want to access.<br/>
In both cases the library files itself are located in the `src` directory.<br/>

### 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*.<br/>
![Sloeber settings](https://github.com/ArminJo/ServoEasing/blob/master/pictures/SloeberDefineSymbols.png)

Expand Down
30 changes: 13 additions & 17 deletions src/LightweightServo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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) {
Expand All @@ -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) {
Expand All @@ -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
Expand Down
15 changes: 10 additions & 5 deletions src/LightweightServo.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@

#include <stdint.h>

/*
* 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

/*
Expand All @@ -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_
Expand Down
26 changes: 13 additions & 13 deletions src/ServoEasing.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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

Expand Down

0 comments on commit be94356

Please sign in to comment.