Skip to content

Commit

Permalink
Fix arduino-libraries#3: Update min and max to sensible defaults
Browse files Browse the repository at this point in the history
R/C servos have a standard pulse width range of 1000 to 2000µs<sup name="a1">[1](#f1)</sup>, with the zero point between the two at 1500µs. Currently, Arduino's Servo library sets:

- [`#define MIN_PULSE_WIDTH 544`](https://github.com/arduino-libraries/Servo/blob/4970d615a13f4c0d08026ee361cc8a01974924a2/src/Servo.h#L80)
- [`#define MAX_PULSE_WIDTH 2400`](https://github.com/arduino-libraries/Servo/blob/4970d615a13f4c0d08026ee361cc8a01974924a2/src/Servo.h#L81)
- [`#define DEFAULT_PULSE_WIDTH 1500`](https://github.com/arduino-libraries/Servo/blob/4970d615a13f4c0d08026ee361cc8a01974924a2/src/Servo.h#L82)

This causes a lot of confusion<sup name="a2">[2](#f2)</sup>, especially since [the docs say `write(90)` should correspond to the mid-point] (https://www.arduino.cc/en/Reference/ServoWrite); in actuality, it results in a call to `writeMicroseconds(1472)`<sup name="a3">[3](#f3)</sup>.

This change adjusts the defaults to align with R/C standards. Specifically,

- `write(0)` now corresponds to the standard min pulse width of 1000µs.
- `write(90)` now corresponds to the standard zero point pulse width, and aligns with the library's `DEFAULT_PULSE_WIDTH` variable.
- `write(180)` now corresponds to the standard max pulse width of 2000µs.

Tested on an Arduino Uno with a [Tower Pro Micro Servo SG90](http://www.ee.ic.ac.uk/pcheung/teaching/DE1_EE/stores/sg90_datasheet.pdf), and a [Parallax Feedback 360° High-Speed Servo](https://parallax.com/sites/default/files/downloads/900-00360-Feedback-360-HS-Servo-v1.2.pdf).

---

<a name="f1" href="#a1">1</a>: For example, http://www.ee.ic.ac.uk/pcheung/teaching/DE1_EE/stores/sg90_datasheet.pdf

<a name="f2" href="#a2">2</a>: For instance:

 - julianduque/beaglebone-io#54
 - arduino-libraries#3
 - https://toolguyd.com/oscilloscope-arduino-servo-pwm-signal-mistakes/
 - https://makezine.com/2014/04/23/arduinos-servo-library-angles-microseconds-and-optional-command-parameters/

I also see a _lot_ of posts on https://forum.arduino.cc about this.

<a name="f3" href="#a3">3</a>: There is actually no way to set a standard servo to the zero-point using `write(angle)`; the closest you can get is `write(92)`, for a pulse of 1504µs.
  • Loading branch information
rileyjshaw committed Apr 5, 2019
1 parent 3c1373b commit 931445b
Show file tree
Hide file tree
Showing 6 changed files with 12 additions and 12 deletions.
8 changes: 4 additions & 4 deletions src/Servo.h
Expand Up @@ -77,8 +77,8 @@

#define Servo_VERSION 2 // software version of this library

#define MIN_PULSE_WIDTH 544 // the shortest pulse sent to a servo
#define MAX_PULSE_WIDTH 2400 // the longest pulse sent to a servo
#define MIN_PULSE_WIDTH 1000 // the shortest pulse (in us) sent to a servo
#define MAX_PULSE_WIDTH 2000 // the longest pulse (in us) sent to a servo
#define DEFAULT_PULSE_WIDTH 1500 // default pulse width when servo is attached
#define REFRESH_INTERVAL 20000 // minumim time to refresh servos in microseconds

Expand Down Expand Up @@ -106,8 +106,8 @@ class Servo
uint8_t attach(int pin); // attach the given pin to the next free channel, sets pinMode, returns channel number or 0 if failure
uint8_t attach(int pin, int min, int max); // as above but also sets min and max values for writes.
void detach();
void write(int value); // if value is < 200 its treated as an angle, otherwise as pulse width in microseconds
void writeMicroseconds(int value); // Write pulse width in microseconds
void write(int value); // if value is < the minimum pulse width it's treated as an angle, otherwise as pulse width in microseconds
void writeMicroseconds(int value); // Write pulse width in microseconds
int read(); // returns current pulse width as an angle between 0 and 180 degrees
int readMicroseconds(); // returns current pulse width in microseconds for this servo (was read_us() in first release)
bool attached(); // return true if this servo is attached, otherwise false
Expand Down
2 changes: 1 addition & 1 deletion src/avr/Servo.cpp
Expand Up @@ -264,7 +264,7 @@ void Servo::detach()
void Servo::write(int value)
{
if(value < MIN_PULSE_WIDTH)
{ // treat values less than 544 as angles in degrees (valid values in microseconds are handled as microseconds)
{ // treat values less than the minimum pulse width as angles in degrees (valid values in microseconds are handled as microseconds)
if(value < 0) value = 0;
if(value > 180) value = 180;
value = map(value, 0, 180, SERVO_MIN(), SERVO_MAX());
Expand Down
2 changes: 1 addition & 1 deletion src/megaavr/Servo.cpp
Expand Up @@ -157,7 +157,7 @@ void Servo::detach()

void Servo::write(int value)
{
// treat values less than 544 as angles in degrees (valid values in microseconds are handled as microseconds)
// treat values less than the minimum pulse width as angles in degrees (valid values in microseconds are handled as microseconds)
if (value < MIN_PULSE_WIDTH)
{
if (value < 0)
Expand Down
2 changes: 1 addition & 1 deletion src/sam/Servo.cpp
Expand Up @@ -228,7 +228,7 @@ void Servo::detach()

void Servo::write(int value)
{
// treat values less than 544 as angles in degrees (valid values in microseconds are handled as microseconds)
// treat values less than the minimum pulse width as angles in degrees (valid values in microseconds are handled as microseconds)
if (value < MIN_PULSE_WIDTH)
{
if (value < 0)
Expand Down
2 changes: 1 addition & 1 deletion src/samd/Servo.cpp
Expand Up @@ -243,7 +243,7 @@ void Servo::detach()

void Servo::write(int value)
{
// treat values less than 544 as angles in degrees (valid values in microseconds are handled as microseconds)
// treat values less than the minimum pulse width as angles in degrees (valid values in microseconds are handled as microseconds)
if (value < MIN_PULSE_WIDTH)
{
if (value < 0)
Expand Down
8 changes: 4 additions & 4 deletions src/stm32f4/ServoTimers.h
Expand Up @@ -75,8 +75,8 @@
#define MIN_ANGLE 0
#define MAX_ANGLE 180

#define MIN_PULSE_WIDTH 544 // the shortest pulse sent to a servo
#define MAX_PULSE_WIDTH 2400 // the longest pulse sent to a servo
#define MIN_PULSE_WIDTH 1000 // the shortest pulse (in us) sent to a servo
#define MAX_PULSE_WIDTH 2000 // the longest pulse (in us) sent to a servo

/** Class for interfacing with RC servomotors. */
class Servo {
Expand All @@ -103,12 +103,12 @@ class Servo {
* @param minPulseWidth Minimum pulse width to write to pin, in
* microseconds. This will be associated
* with a minAngle degree angle. Defaults to
* SERVO_DEFAULT_MIN_PW = 544.
* MIN_PULSE_WIDTH.
*
* @param maxPulseWidth Maximum pulse width to write to pin, in
* microseconds. This will be associated
* with a maxAngle degree angle. Defaults to
* SERVO_DEFAULT_MAX_PW = 2400.
* MAX_PULSE_WIDTH.
*
* @param minAngle Target angle (in degrees) associated with
* minPulseWidth. Defaults to
Expand Down

0 comments on commit 931445b

Please sign in to comment.