1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-07-29 05:21:37 +03:00
This commit is contained in:
sticilface
2020-11-15 09:23:24 +00:00
15 changed files with 135 additions and 69 deletions

View File

@ -27,15 +27,15 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
uint32_t Servo::_servoMap = 0;
// similiar to map but will have increased accuracy that provides a more
// symetric api (call it and use result to reverse will provide the original value)
// symmetrical api (call it and use result to reverse will provide the original value)
int improved_map(int value, int minIn, int maxIn, int minOut, int maxOut)
{
const int rangeIn = maxIn - minIn;
const int rangeOut = maxOut - minOut;
const int deltaIn = value - minIn;
// fixed point math constants to improve accurancy of divide and rounding
const int fixedHalfDecimal = 1;
const int fixedDecimal = fixedHalfDecimal * 2;
constexpr int fixedHalfDecimal = 1;
constexpr int fixedDecimal = fixedHalfDecimal * 2;
return ((deltaIn * rangeOut * fixedDecimal) / (rangeIn) + fixedHalfDecimal) / fixedDecimal + minOut;
}
@ -46,9 +46,9 @@ int improved_map(int value, int minIn, int maxIn, int minOut, int maxOut)
Servo::Servo()
{
_attached = false;
_valueUs = DEFAULT_PULSE_WIDTH;
_minUs = MIN_PULSE_WIDTH;
_maxUs = MAX_PULSE_WIDTH;
_valueUs = DEFAULT_NEUTRAL_PULSE_WIDTH;
_minUs = DEFAULT_MIN_PULSE_WIDTH;
_maxUs = DEFAULT_MAX_PULSE_WIDTH;
}
Servo::~Servo() {
@ -58,10 +58,15 @@ Servo::~Servo() {
uint8_t Servo::attach(int pin)
{
return attach(pin, MIN_PULSE_WIDTH, MAX_PULSE_WIDTH);
return attach(pin, DEFAULT_MIN_PULSE_WIDTH, DEFAULT_MAX_PULSE_WIDTH);
}
uint8_t Servo::attach(int pin, uint16_t minUs, uint16_t maxUs)
{
return attach(pin, minUs, maxUs, _valueUs);
}
uint8_t Servo::attach(int pin, uint16_t minUs, uint16_t maxUs, int value)
{
if (!_attached) {
digitalWrite(pin, LOW);
@ -76,7 +81,7 @@ uint8_t Servo::attach(int pin, uint16_t minUs, uint16_t maxUs)
_maxUs = max((uint16_t)250, min((uint16_t)3000, maxUs));
_minUs = max((uint16_t)200, min(_maxUs, minUs));
write(_valueUs);
write(value);
return pin;
}
@ -85,20 +90,20 @@ void Servo::detach()
{
if (_attached) {
_servoMap &= ~(1 << _pin);
startWaveform(_pin, 0, REFRESH_INTERVAL, 1);
delay(REFRESH_INTERVAL / 1000); // long enough to complete active period under all circumstances.
stopWaveform(_pin);
_attached = false;
digitalWrite(_pin, LOW);
_valueUs = DEFAULT_NEUTRAL_PULSE_WIDTH;
}
}
void Servo::write(int value)
{
// treat values less than 544 as angles in degrees (valid values in microseconds are handled as microseconds)
if (value < _minUs) {
// treat any value less than 200 as angle in degrees (values equal or larger are handled as microseconds)
if (value < 200) {
// assumed to be 0-180 degrees servo
value = constrain(value, 0, 180);
// writeMicroseconds will contrain the calculated value for us
// for any user defined min and max, but we must use default min max
value = improved_map(value, 0, 180, _minUs, _maxUs);
}
writeMicroseconds(value);
@ -106,6 +111,7 @@ void Servo::write(int value)
void Servo::writeMicroseconds(int value)
{
value = constrain(value, _minUs, _maxUs);
_valueUs = value;
if (_attached) {
_servoMap &= ~(1 << _pin);
@ -117,8 +123,7 @@ void Servo::writeMicroseconds(int value)
int Servo::read() // return the value as degrees
{
// read returns the angle for an assumed 0-180, so we calculate using
// the normal min/max constants and not user defined ones
// read returns the angle for an assumed 0-180
return improved_map(readMicroseconds(), _minUs, _maxUs, 0, 180);
}

View File

@ -27,9 +27,9 @@
//
// Servo - Class for manipulating servo motors connected to Arduino pins.
//
// attach(pin ) - Attaches a servo motor to an i/o pin.
// attach(pin, min, max ) - Attaches to a pin setting min and max values in microseconds
// default min is 544, max is 2400
// attach(pin) - Attaches a servo motor to an i/o pin.
// attach(pin, min, max) - Attaches to a pin setting min and max values in microseconds
// default min is 1000, max is 2000
//
// write() - Sets the servo angle in degrees. (invalid angle that is valid as pulse in microseconds is treated as microseconds)
// writeMicroseconds() - Sets the servo pulse width in microseconds
@ -44,13 +44,17 @@
#include <Arduino.h>
// the following are in us (microseconds)
//
#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 DEFAULT_PULSE_WIDTH 1500 // default pulse width when servo is attached
#define REFRESH_INTERVAL 20000 // minumim time to refresh servos in microseconds
#define MAX_SERVOS 12
// The following values are in us (microseconds).
// Since the defaults can be overwritten in the new attach() member function,
// they were modified from the Arduino AVR defaults to be in the safe range
// of publically available specifications. While this implies that many 180°
// servos do not operate the full 0° to 180° sweep using these, it also prevents
// unsuspecting damage. For Arduino AVR, the same change is being discussed.
#define DEFAULT_MIN_PULSE_WIDTH 1000 // uncalibrated default, the shortest duty cycle sent to a servo
#define DEFAULT_MAX_PULSE_WIDTH 2000 // uncalibrated default, the longest duty cycle sent to a servo
#define DEFAULT_NEUTRAL_PULSE_WIDTH 1500 // default duty cycle when servo is attached
#define REFRESH_INTERVAL 20000 // classic default period to refresh servos in microseconds
#define MAX_SERVOS 9 // D0-D8
#if !defined(ESP8266)
@ -63,8 +67,16 @@ class Servo
public:
Servo();
~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, uint16_t min, uint16_t max); // as above but also sets min and max values for writes.
// attach the given pin to the next free channel, sets pinMode, returns channel number or 0 if failure.
// returns channel number or 0 if failure.
uint8_t attach(int pin);
// attach the given pin to the next free channel, sets pinMode, min, and max values for write().
// returns channel number or 0 if failure.
uint8_t attach(int pin, uint16_t min, uint16_t max);
// attach the given pin to the next free channel, sets pinMode, min, and max values for write(),
// and sets the initial value, the same as write().
// returns channel number or 0 if failure.
uint8_t attach(int pin, uint16_t min, uint16_t max, int value);
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