GithubHelp home page GithubHelp logo

arduino-libraries / servo Goto Github PK

View Code? Open in Web Editor NEW
231.0 29.0 250.0 233 KB

Servo Library for Arduino

Home Page: http://arduino.cc/

License: GNU Lesser General Public License v2.1

C++ 89.73% C 10.27%

servo's Introduction

servo's People

Contributors

aentinger avatar aethaniel avatar agdl avatar alfran avatar alranel avatar cmaglie avatar damellis avatar dcuartielles avatar dependabot[bot] avatar eric-wieser avatar facchinm avatar fede85 avatar feilipu avatar iabdalkader avatar kurte avatar madacol avatar matteosuppo avatar olaffilies avatar per1234 avatar pnndra avatar sebromero avatar shfitz avatar tigoe avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

servo's Issues

Compiling error with Adafruit Metro M4 Grand Central

I am getting following error while compiling servo library on Adafruit Metro M4 Grand Central

/home/Downloads/arduino-1.8.9/libraries/Servo/src/samd/Servo.cpp: In function 'void Servo_Handler(timer16_Sequence_t, Tc*, uint8_t, uint8_t)': /home/Downloads/arduino-1.8.9/libraries/Servo/src/samd/Servo.cpp:44:60: error: 'volatile struct TC_STATUS_Type::<anonymous>' has no member named 'SYNCBUSY' #define WAIT_TC16_REGS_SYNC(x) while(x->COUNT16.STATUS.bit.SYNCBUSY); ^ /home/Downloads/arduino-1.8.9/libraries/Servo/src/samd/Servo.cpp:64:9: note: in expansion of macro 'WAIT_TC16_REGS_SYNC' WAIT_TC16_REGS_SYNC(tc) ^ /home/Downloads/arduino-1.8.9/libraries/Servo/src/samd/Servo.cpp: In function 'void _initISR(Tc*, uint8_t, uint32_t, IRQn_Type, uint8_t, uint8_t)': /home/Downloads/arduino-1.8.9/libraries/Servo/src/samd/Servo.cpp:123:11: error: 'struct Gclk' has no member named 'CLKCTRL' GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID(gcmForTimer)); ^ /home/Downloads/arduino-1.8.9/libraries/Servo/src/samd/Servo.cpp:123:37: error: 'GCLK_CLKCTRL_CLKEN' was not declared in this scope GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID(gcmForTimer));

Is there a way to change the Timers used?

I need to disable and/or change the sequence in which timers are used.

I know how to modify the library to do it, but it's really bothersome to carry a copy of the modified library wherever I go.

I think it's possible to make the Timers opt-out by specifying in the .ino file something like #define doNotUseTimer5 before including the library, and use a #ifndef doNotUseTimer5 to omit lines where Timer5 is defined.

I may do the Pull Request I just described, but I don't know if there already exist something to disable a specific timer, because I see this defined in the source #define _useTimer5 but I don't know how it works or how to use it outside of the library to disable a timer

bug in SAMD implementation, SAMD51 support

There is a bug in the SAMD implementation of the servo library.

Steps to reproduce
Use a SAMD21-based board (Arduino Zero, Adafruit Feather M0, ...)
Create 12 servos objects. According to specs, up to 12 servos are allowed.
Attach all servos to different pins.
Set the pulse width for each servo to at least 1850 μs. This value is a perfectly normal pulse width for hobby servos.

Expected result
All pulse width are as configured and the pulse repetition rate is about 50 Hz (i.e. the spacing between the rising edges of the pulses is about 20 ms) on any configured pin.

Observed result
The pulse widths are ok, but the pulse spacing for all servos is way off. The pulse spacing is about 41 ms, corresponding to a repetition rate of less than 24 Hz. This can be clearly seen on an oscilloscope. Although the repetition rate for servos is said to be not that critical, those large pulse spacings are problematic.

Detailed bug analysis
The bug is caused by the unintentional overflow of the 16 bit counter of the SAMD Timer/Counter (TC) instance. The TC is clocked by a scaled down CPU clock. The CPU clock is 48 MHz (on SAMD21, i.e. Arduino Zero & friends) and the prescaler is 16, resulting in an effective clock speed of 3 MHz for the TC peripheral. 3 MHz correspond to 3 clock ticks per microsecond, or 60000 clock ticks for the desired 20 ms repetition rate (50 Hz). The TC counter is used in 16 bit mode and wraps back to 0 after 2^16 = 65536 clock ticks, so counting to 60000 with a 16-bit-counter is perfectly ok. 65536 clock ticks correspond to 21.845 ms. Trying to count longer than that causes the internal counter to overflow and start from zero again. This is what happens here. When configuring many servos and/or long servo pulses, the total sum of the pulse width cannot be multiplexed (i.e. "squeezed") into the 20 ms interval required for 50 Hz repetition rate. If the total sum of pulse widths is bigger than 20 ms, but still smaller than 21.845 ms, not much happens. The repetition rate only gets slightly longer (21.845 ms correspond to about 45.8 Hz). I would already consider this a bug, although most servos could probably handle 45 Hz just fine. However, "really bad things" happen when longer pulse widths cause the counter to roll over (see example above: 12 * 1850 μs = 22.2 ms --> rollover happens before last pulse has finished). Due to unsigend integer arithmetic, the pulse widths are still ok, even the for the pulse(s) after rollover. The start of the first pulse of the next "multiplexing cycle" is always scheduled to occur when the counter reaches 60000 (again). When counter rollover happened, the total delay between pulses on any given pin is thus not 60000 clock cycles = 20 ms, but 65536+60000 clock cycles = 41.845 ms.

Possible solutions
Let's call the fact that pulse repetition rate gets slightly larger for total pulse duration between 20 ms and 21.845 ms "consequence A"
Let's call the doubling of the repetition rate due to counter rollover "consequence B".

  • Use a larger clock prescaler, e.g. 64 instead of 16 (note: there is no prescaler with value 32 on TC instances...). This would cause the clock to run slower. The wraparound would occur much later (i.e. not at all, realistically). However, the resolution would be decreased unnecessarily. "Consequence B" would be fixed, "consequence A" would still be present.
  • Decrease the number of maximum possible servos for SAMD. If we want to be able to handle up to 2400 μs per servo, we can squeeze up to eight back-to-back pulses into our 20 ms period. However, the 2400 μs limit is not that hard. Users could easily use even longer pulses (probably not healthy for their servos, but who knows what users will do...). To be safe, one should only allow seven or maybe even only six servos. In my opinion, this would be a shame. Users often use ARM Cortex-M based boards because the higher performance is needed for more complex projects. It would be sad if those boards supported much fewer servos than the "good old AVR boards".
  • Use both Capture/Compare registers of the TC instance. Right now, only one CC register is used. Every CC register can safely take care of only six servos, giving 12 servos per TC instance. However, to coordinate to CC registers with a single counter, a bit of book-keeping is necessary. This causes some code refactoring.

Suggested solution
Personally, I am a strong believer in "when you fix it, fix it properly", so I am in favor of the third option. Accordingly, I have already created some code and would be grateful for review and feedback before I submit a pull request.

Important note on the history of my suggested fix
The bug came to my attention because of different behavior between SAMD21 and SAMD51 based boards. SAMD51 uses a different clock frequency and different prescaler, which means the bug is present, but does not show up because rollover happens much later. I use(d) the Adafruit fork of the ArduinoCore-samd repository for my projects (using Adafruit Feather M0/M4 boards) which comes with a local/forked version of the servo library. I started out fixing the bug there and only realized later, that there is still no SAMD51 support in the "official" Arduino servo library and the bug is also present upstream (i.e. in the Arduino servo library).

This is why my code "as is" incidentally also introduces SAMD51 support into the servo library (tested on Adafruit Feather M4 Express), in addition to fixing the present bug. If this is too much to swallow at once, I can take out the SAMD51 specific portions of the code and open a separate issue for also including SAMD51 code later. There actually is already an open issue (#21) and a matching pull request (#34, pending as of today) for adding SAMD51 support, but this code still contains the bug.

Please let me know what you think.

Add support for 8-bit timers like Timer2

Sometimes it might me necessary to use Time1 for other purposes so the Servo library has to use a 8 bit timer like the Timer0 or Timer2.
Please add support for 8 bit timers and make it configurable which timer has to be used.

MAX_SERVOS limit when testing

Is it possible to have a destructor for Servo that removes the motor from static list of Servos? The reason for asking is that I am artificially hitting the MAX_SERVOS limit when running unit tests for my solution. I have a test suite that initializes motors which contain Servos and then destructs the Motor to move on to the next test. See example below. B/c the Servo constructor adds to the static list of servos and caps it out at 48 (for the Mega 2560) after so many tests, the servos will stop attaching. Seems to me like there should be a destructor that does the cleanup for what the constructor is doing.

RUN_TEST(test_One);
RUN_TEST(test_Three);
RUN_TEST(test_RunTwoMotorsAsync);
RUN_TEST(test_ManualMotorReset);         
RUN_TEST(test_InitializeTwentyTwoMotors);
RUN_TEST(test_InitializeTwentyTwoMotorsAndMoveTwo);

Merge PWMServo library (hardware servo control on pins 9 and 10) into Servo library. [imported]

From @cmaglie on November 15, 2012 18:42

This is Issue 631 moved from a Google Code project.
Added by 2011-09-08T21:06:25.000Z by [email protected].
Please review that bug for more context and additional comments, but update this bug.

Original labels: Type-Enhancement, Priority-Medium, Component-Core

Original description

It would be cool if the Servo library could use either of two strategies: hardware PWM control if the servos are on pins 9 or 10, and software if not. This would basically be combining the old servo library with the new one. See also PWMServo (http://arduiniana.org/libraries/pwmservo/) for an alternative version of the old (hardware-control) servo library.

Copied from original issue: arduino/Arduino#631

servo not working on nano 33 ble sense

i cant compile my code, even if there is nothing in it and the library is just included.
I get this message:

C:\Program Files\WindowsApps\ArduinoLLC.ArduinoIDE_1.8.42.0_x86__mdqgnx93n4wtt\libraries\Servo\src\mbed\Servo.cpp:7:11: error: 'DigitalOut' in namespace 'mbed' does not name a type
mbed::DigitalOut *pin;
^~~~~~~~~~
C:\Program Files\WindowsApps\ArduinoLLC.ArduinoIDE_1.8.42.0_x86__mdqgnx93n4wtt\libraries\Servo\src\mbed\Servo.cpp:8:11: error: 'Timeout' in namespace 'mbed' does not name a type
mbed::Timeout timeout; // calls a callback once when a timeout expires
^~~~~~~
C:\Program Files\WindowsApps\ArduinoLLC.ArduinoIDE_1.8.42.0_x86__mdqgnx93n4wtt\libraries\Servo\src\mbed\Servo.cpp:9:11: error: 'Ticker' in namespace 'mbed' does not name a type
mbed::Ticker ticker; // calls a callback repeatedly with a timeout
^~~~~~
C:\Program Files\WindowsApps\ArduinoLLC.ArduinoIDE_1.8.42.0_x86__mdqgnx93n4wtt\libraries\Servo\src\mbed\Servo.cpp: In constructor 'ServoImpl::ServoImpl(PinName)':
C:\Program Files\WindowsApps\ArduinoLLC.ArduinoIDE_1.8.42.0_x86__mdqgnx93n4wtt\libraries\Servo\src\mbed\Servo.cpp:13:7: error: 'pin' was not declared in this scope
pin = new mbed::DigitalOut(_pin);
^~~
C:\Program Files\WindowsApps\ArduinoLLC.ArduinoIDE_1.8.42.0_x86__mdqgnx93n4wtt\libraries\Servo\src\mbed\Servo.cpp:13:7: note: suggested alternative: 'min'
pin = new mbed::DigitalOut(_pin);
^~~
min
C:\Program Files\WindowsApps\ArduinoLLC.ArduinoIDE_1.8.42.0_x86__mdqgnx93n4wtt\libraries\Servo\src\mbed\Servo.cpp:13:17: error: expected type-specifier
pin = new mbed::DigitalOut(_pin);
^~~~
C:\Program Files\WindowsApps\ArduinoLLC.ArduinoIDE_1.8.42.0_x86__mdqgnx93n4wtt\libraries\Servo\src\mbed\Servo.cpp: In destructor 'ServoImpl::~ServoImpl()':
C:\Program Files\WindowsApps\ArduinoLLC.ArduinoIDE_1.8.42.0_x86__mdqgnx93n4wtt\libraries\Servo\src\mbed\Servo.cpp:17:9: error: 'ticker' was not declared in this scope
ticker.detach();
^~~~~~
C:\Program Files\WindowsApps\ArduinoLLC.ArduinoIDE_1.8.42.0_x86__mdqgnx93n4wtt\libraries\Servo\src\mbed\Servo.cpp:17:9: note: suggested alternative: 'time'
ticker.detach();
^~~~~~
time
C:\Program Files\WindowsApps\ArduinoLLC.ArduinoIDE_1.8.42.0_x86__mdqgnx93n4wtt\libraries\Servo\src\mbed\Servo.cpp:18:9: error: 'timeout' was not declared in this scope
timeout.detach();
^~~~~~~
C:\Program Files\WindowsApps\ArduinoLLC.ArduinoIDE_1.8.42.0_x86__mdqgnx93n4wtt\libraries\Servo\src\mbed\Servo.cpp:18:9: note: suggested alternative: 'timer_t'
timeout.detach();
^~~~~~~
timer_t
C:\Program Files\WindowsApps\ArduinoLLC.ArduinoIDE_1.8.42.0_x86__mdqgnx93n4wtt\libraries\Servo\src\mbed\Servo.cpp:19:16: error: 'pin' was not declared in this scope
delete pin;
^~~
C:\Program Files\WindowsApps\ArduinoLLC.ArduinoIDE_1.8.42.0_x86__mdqgnx93n4wtt\libraries\Servo\src\mbed\Servo.cpp:19:16: note: suggested alternative: 'min'
delete pin;
^~~
min
C:\Program Files\WindowsApps\ArduinoLLC.ArduinoIDE_1.8.42.0_x86__mdqgnx93n4wtt\libraries\Servo\src\mbed\Servo.cpp: In member function 'void ServoImpl::start(uint32_t)':
C:\Program Files\WindowsApps\ArduinoLLC.ArduinoIDE_1.8.42.0_x86__mdqgnx93n4wtt\libraries\Servo\src\mbed\Servo.cpp:24:7: error: 'ticker' was not declared in this scope
ticker.attach(mbed::callback(this, &ServoImpl::call), 0.02f);
^~~~~~
C:\Program Files\WindowsApps\ArduinoLLC.ArduinoIDE_1.8.42.0_x86__mdqgnx93n4wtt\libraries\Servo\src\mbed\Servo.cpp:24:7: note: suggested alternative: 'time'
ticker.attach(mbed::callback(this, &ServoImpl::call), 0.02f);
^~~~~~
time
C:\Program Files\WindowsApps\ArduinoLLC.ArduinoIDE_1.8.42.0_x86__mdqgnx93n4wtt\libraries\Servo\src\mbed\Servo.cpp: In member function 'void ServoImpl::call()':
C:\Program Files\WindowsApps\ArduinoLLC.ArduinoIDE_1.8.42.0_x86__mdqgnx93n4wtt\libraries\Servo\src\mbed\Servo.cpp:28:9: error: 'timeout' was not declared in this scope
timeout.attach(mbed::callback(this, &ServoImpl::toggle), duration / 1e6);
^~~~~~~
C:\Program Files\WindowsApps\ArduinoLLC.ArduinoIDE_1.8.42.0_x86__mdqgnx93n4wtt\libraries\Servo\src\mbed\Servo.cpp:28:9: note: suggested alternative: 'timer_t'
timeout.attach(mbed::callback(this, &ServoImpl::toggle), duration / 1e6);
^~~~~~~
timer_t
C:\Program Files\WindowsApps\ArduinoLLC.ArduinoIDE_1.8.42.0_x86__mdqgnx93n4wtt\libraries\Servo\src\mbed\Servo.cpp: In member function 'void ServoImpl::toggle()':
C:\Program Files\WindowsApps\ArduinoLLC.ArduinoIDE_1.8.42.0_x86__mdqgnx93n4wtt\libraries\Servo\src\mbed\Servo.cpp:33:8: error: 'pin' was not declared in this scope
*pin = !*pin;
^~~
C:\Program Files\WindowsApps\ArduinoLLC.ArduinoIDE_1.8.42.0_x86__mdqgnx93n4wtt\libraries\Servo\src\mbed\Servo.cpp:33:8: note: suggested alternative: 'min'
*pin = !*pin;
^~~
min
In file included from C:\Users\Alex Stedman\Documents\ArduinoData\packages\arduino\hardware\mbed\1.1.6\variants\ARDUINO_NANO33BLE/pins_arduino.h:3:0,
from C:\Users\Alex Stedman\Documents\ArduinoData\packages\arduino\hardware\mbed\1.1.6\cores\arduino/Arduino.h:86,
from C:\Program Files\WindowsApps\ArduinoLLC.ArduinoIDE_1.8.42.0_x86__mdqgnx93n4wtt\libraries\Servo\src\mbed\Servo.cpp:3:
C:\Program Files\WindowsApps\ArduinoLLC.ArduinoIDE_1.8.42.0_x86__mdqgnx93n4wtt\libraries\Servo\src\mbed\Servo.cpp: In member function 'uint8_t Servo::attach(int, int, int)':
C:\Users\Alex Stedman\Documents\ArduinoData\packages\arduino\hardware\mbed\1.1.6\cores\arduino/macros.h:28:40: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
#define digitalPinToPinName(P) (P >= PINS_COUNT ? NC : g_APinDescription[P].name)
C:\Program Files\WindowsApps\ArduinoLLC.ArduinoIDE_1.8.42.0_x86__mdqgnx93n4wtt\libraries\Servo\src\mbed\Servo.cpp:64:44: note: in expansion of macro 'digitalPinToPinName'
servos[this->servoIndex] = new ServoImpl(digitalPinToPinName(pin));
^~~~~~~~~~~~~~~~~~~
exit status 1
Error compiling for board Arduino Nano 33 BLE.

Whats the issue?

Attach with Min Max bug

There seems to be an issue witihin the library for values of min and max in the attach(pin, min, max) function.
I am using an official Arduino Uno R3 and IDE version 1.8.19, Servo library version 1.1.8.
I am reading values back using the readMicrosecond function through Serial.

When using the overloaded attach function, min values above 1059 and max values below about 1900 do not work. Instead the library acts as no limits, my serial prints even reach up to 2800 microseconds. Please see details below:

Smallest microsecond range (works perfectly):

int min = 1059;
  int max = 1900;
  Servo2.write(0);
  Serial.println(Servo2.attach(servo2Pin, min, max));
  tftText("Servo 2");

'Unlimited' range after higher min:

int min = 1060
  int max = 1900;
  Servo2.write(0);
  Serial.println(Servo2.attach(servo2Pin, min, max));
  tftText("Servo 2");

'Unlimited' range after higher max:

int min = 1060
  int max = 1850;
  Servo2.write(0);
  Serial.println(Servo2.attach(servo2Pin, min, max));
  tftText("Servo 2");

Higher range reaches up to about 2865:
image

Edit 23:40 18/07/2022: Wrong value for max, fixed now.

ATmega328PB

For the AVR I added the ATmega328PB. It has 3 16bit timers. Could address 22 servos. But I limited it to 20 servos, because I only need 20 servos . At TimerServos.h add I the 328PB

#elif defined(__AVR_ATmega328PB__) || defined(__AVR_ATmega128__) || defined(__AVR_ATmega1281__) || defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega2561__)
#define _useTimer3
#define _useTimer1
typedef enum { _timer3, _timer1, _Nbr_16timers } timer16_Sequence_t;

In servo.h define I the Atmega328PB with 10 servos on one timer.

#if defined(__AVR_ATmega328PB__)
#define SERVOS_PER_TIMER       10     // the maximum number 10 of servos controlled by one timer at the ATmega328PB
#else
#define SERVOS_PER_TIMER       12	 // the maximum number 12 of servos controlled by one timer
#endif

More than 11 servos on a timer makes no sense and everyone should ask themselves how many servos can be accommodated on a timer maximum because of the frame rate. 11 servos means already in the worst case 22ms or more frame rate or 45 Hz or less repetition rate.

Arduino wifi rev2, ticks / us

Hi,

At now, the counter ticks/us is 0.25. Would it be possible to change the prescaler to have it at 1 ticks/us?

Thanks.

warning for mbed_nano architecture

i have been using this library with an Arduino Nano 33 BLE Sense,
and Arduino released a new core for it, where the architecture is named mbed_nano
so now i have a warning that says
"
WARNING: library Servo claims to run on avr, megaavr, sam, samd, nrf52, stm32f4, mbed architecture(s) and may be incompatible with your current board which runs on mbed_nano architecture(s).
"

Servo write() vs writeMicroseconds()

Moved from arduino/Arduino#10160 by @kreinkens

Both write() and writeMicroseconds() commands should be able to control both position and continuous rotation servos, given appropriate inputs.

I discovered that they are unable to act equally in controlling the continuous rotation servos. I was working in MATLAB which apparently used only the write() command as the basis for servo control.
Returning to Arduino environment, I configured the servo, attach(12,1400,1600). I measured the delivered signals. Although the midpoint pulse width of 1500 was valid, the min/max values were closer to 375 and 2620 respectively. The result is that it is not possible to vary the speed of the continuous rotation servo using the write() command.

Not a problem in Arduino, since writeMicroseconds() is available to create variable speed control.
However, MATLAB has not included a similar command in the support for Arduino Hardware. I have made this request, but thought that addressing this in the Arduino write() command might be another strategy to solve this.

Servo control or console output (serial) : with UNO WiFi Rev2, you must choice !

Servo library allows to control a servo by sending pulses to the servo. Using the library with UNO R3 gives correct results : a constant pulse duration in myservo.write (int) gives a stable servo position. Using the library with UNO WiFi Rev2 gives correct duration in 95% of time but random duration in 5% of time. So, the servo does random position jumps.

After a couple of days of research, I understand the issue is linked to simultaneous usage of Serial and Servo. Uncomment Serial.begin(115200) makes the issue disappear. This issue is blocking.

My environnement :

  • IDE 1.8.8
  • Servo library 1.1.3
  • Card type declared in IDE : Arduino Uno WiFi Rev2
  • Registers emulation: none (ATMEGA4809)
  • Pin D2 used to send pulses

test sketch :

#include <Wire.h>        // for communication with a Sharp device
#include <Servo.h>     
#define  POS_MIN 550 
#define  POS_MAX 2250 
#define  servo_pin  2    // servo pulses pin

Servo my_servo;

void setup() 
{
  my_servo.attach(servo_pin, POS_MIN, POS_MAX); 
  my_servo.write(POS_MIN); 

//********************************************************************

//  Serial.begin(115200); => uncomment this line makes the issue visible with a scope
/*
  delay(2000);
  Serial.println("   ");
  Serial.println("UnoWiFi_basic_test");
*/
//********************************************************************

  Wire.begin();
}
void loop() 
{                    
    process_test();  
}  
void process_test()       
{
    int angle = 675;
    mon_servo.write(angle); 
    Serial.print(" ");
    Serial.println (angle);
    delay(20); 
}   

Issue when running the writeMicroseconds method with FeeTech motor driver

When running the following example with Nano Every the FeeTech motor driver will not work, I assume it is because of the servo not providing pulses with an accurate enough output. Have made the following video to document it: https://vimeo.com/359635766 pass: oniudra.

See the following code to replicate the video:

//#define USESERVO

#ifdef USESERVO
  #include <Servo.h>
#endif

const int motorApin = 9;
const int motorBpin = 10;

const int MIN = 500;
const int MAX = 2500;

int motorSpeed = 127; // min speed 0, max speed 255
long motorSpeedUs = 1500;
int serVal = 0;

#ifdef USESERVO
  Servo motorA;
  Servo motorB;
#endif

void setup() {
  Serial.begin(9600);

#ifdef USESERVO
  motorA.attach(motorApin, MIN, MAX);
  motorB.attach(motorBpin);
#endif
}

void loop() {
  if (Serial.available()) {
    serVal = Serial.read();

    switch (serVal) {
      case '+':
        motorSpeed += 10;
        if (motorSpeed >= 255) motorSpeed = 255;
        motorSpeedUs = map(motorSpeed, 0, 255, MIN, MAX);
        Serial.print("Speed: ");
        Serial.println(motorSpeedUs);
        break;
      case '-':
        motorSpeed -= 10;
        if (motorSpeed <= 0) motorSpeed = 0;
        motorSpeedUs = map(motorSpeed, 0, 255, MIN, MAX);
        Serial.print("Speed: ");
        Serial.println(motorSpeedUs);
        break;
      case 's':
        motorSpeed = 127;
        motorSpeedUs = map(motorSpeed, 0, 255, MIN, MAX);
        Serial.println("Stop");
        break;
    }

#ifdef USESERVO
    motorA.writeMicroseconds(motorSpeedUs);
    motorB.writeMicroseconds(1500);
#endif

#ifndef USESERVO
    analogWrite(motorApin, motorSpeed);
    analogWrite(motorBpin, 0);
#endif
  }
}

PWM signal sporadically inverted on Portenta H7

Sometimes the Servo PWM signal is inverted aka instead of 1.5 ms HI it is 1.5 ms LO. It only happens ~1 in 4 times after reset. I'm able to reproduce it with the supplied sketch. It is possible that the problem lies by the mbed guys, but since your Library is affected, I thought to post it here first.

Steps to reproduce:

  1. Upload sketch to Portenta H7
  2. Measure PWM output with oscilloscope
  3. Press reset button a few times, should be able to see, the signal is sometimes inverted

Libraries used:

  • Servo 1.1.8
  • Arduino_PortentaBreakout 1.0.1
  • mbed_portenta 2.8.0

Servo.zip

Add support for ATtiny85

Have tried using the versions above with an Attiny85 but got a few errors comeback:

.pio\libdeps\attiny85\Servo\src\avr\Servo.cpp:82:44: error: cannot convert 'volatile uint8_t* {aka volatile unsigned char*}' to 'volatile uint16_t* {aka volatile unsigned int*}' for argument '2' to 'void handle_interrupts(timer16_Sequence_t, volatile uint16_t*, volatile uint16_t*)'

.pio\libdeps\attiny85\Servo\src\avr\Servo.cpp:128:5: error: 'TCCR1A' was not declared in this scope

.pio\libdeps\attiny85\Servo\src\avr\Servo.cpp:129:5: error: 'TCCR1B' was not declared in this scope

.pio\libdeps\attiny85\Servo\src\avr\Servo.cpp:136:5: error: 'TIFR1' was not declared in this scope

.pio\libdeps\attiny85\Servo\src\avr\Servo.cpp:137:5: error: 'TIMSK1' was not declared in this scope

Was just wondering if these are an easy fix, or if it's something I'm missing?!

Regards,
George M.

Raspberry Pico Compatibility; servo read response

When I use servo.read on a Pico, the result returned seems to be two or three degrees wrong versus the last request to servo.write.

In the Arduino documentation it states; "Read the current angle of the servo (the value passed to the last call to write())."

Problem when using Nano Every at 20MHz

Servo positioning is incorrect when using Servo library with a Nano Every running at 20MHz. The calculation in Servo.cpp to adapt to the clock frequency is dropping the fractional part and producing an incorrect result.

In the file Servo/src/megaavr/Servo.cpp, line 6 is as follows:

#define usToTicks(_us)    ((clockCyclesPerMicrosecond() / 16 * _us) / 4)                 // converts microseconds to tick

clockCyclesPerMicrosecond() / 16 is rounding off to 1 before multiplying by _us, producing an incorrect result.

Changing the line to the following seems to correct the problem:

#define usToTicks(_us)    (((int32_t)clockCyclesPerMicrosecond() * _us / 16) / 4 )                 // converts microseconds to tick

Raspberry Pico Compatibility; attach parameters

When using an AVR based board, I usually initiate servo with the following;-

  radar_servo.attach(RADAR_SERVO_POSITION_PIN,500,2360);  // NANO attaches the servo on pin 9 to the servo object

When migrating to Pico I found those parameters send the servo crazy, and instead simply using the following worked;-

  radar_servo.attach(RADAR_SERVO_POSITION_PIN);  // PICO attaches the servo on pin 9 to the servo object

Bugg in servo library with detach(), after can't use analogWrite on pin 9 or 10

From @JLP69 on September 24, 2015 15:31

I'm using the Servo library, and I've finding that detach() method doesn't work as in the reference. I've reading some post about it. It seems that the timers aren't reseted by this method for using PWM output on the pins 9 and 10.
And I've found something in the library code to be changed.
In the Servo.cpp, in the finISR function (that is used for disable the timer) there is no code for doing that for Arduino board.

#else
//For arduino - in future: call here to a currently undefined function to reset the timer
TCCR1B = 0;
TCCR1B=_BV(CS11);
TCCR1B=_BV(CS10);
TCCR1A=_BV(WGM10);
TIMSK1=0;
#endif

After few trials, it seems working. I think it may be included in source code.

Copied from original issue: arduino/Arduino#3860

Absence of examples of some methods

While browsing through the codebase, I came to know that examples of some functionality in the Servo library are not available. Below are the methods for which examples are needed.
-> servo.writeMicroseconds()
-> servo.read()
-> servo.attached()
-> servo.detach()

Incomplete samd51 implementation

Hi,

The implementation for the samd servo library doesn't work on samd51.

The syncbusy bit and clock management are different on this new chip so the code here need to be adapted for samd51.

For example when I try to compile the sweep example for the Feather M4 I get this :

Build options changed, rebuilding all
/home/silvanosky/Arduino/libraries/Servo/src/samd/Servo.cpp: In function 'void Servo_Handler(timer16_Sequence_t, Tc*, uint8_t, uint8_t)':
/home/silvanosky/Arduino/libraries/Servo/src/samd/Servo.cpp:44:60: error: 'volatile struct TC_STATUS_Type::<anonymous>' has no member named 'SYNCBUSY'
 #define WAIT_TC16_REGS_SYNC(x) while(x->COUNT16.STATUS.bit.SYNCBUSY);
                                                            ^
/home/silvanosky/Arduino/libraries/Servo/src/samd/Servo.cpp:64:9: note: in expansion of macro 'WAIT_TC16_REGS_SYNC'
         WAIT_TC16_REGS_SYNC(tc)
         ^
/home/silvanosky/Arduino/libraries/Servo/src/samd/Servo.cpp:44:60: error: 'volatile struct TC_STATUS_Type::<anonymous>' has no member named 'SYNCBUSY'
 #define WAIT_TC16_REGS_SYNC(x) while(x->COUNT16.STATUS.bit.SYNCBUSY);
                                                            ^
/home/silvanosky/Arduino/libraries/Servo/src/samd/Servo.cpp:81:9: note: in expansion of macro 'WAIT_TC16_REGS_SYNC'
         WAIT_TC16_REGS_SYNC(tc)
         ^
/home/silvanosky/Arduino/libraries/Servo/src/samd/Servo.cpp:44:60: error: 'volatile struct TC_STATUS_Type::<anonymous>' has no member named 'SYNCBUSY'
 #define WAIT_TC16_REGS_SYNC(x) while(x->COUNT16.STATUS.bit.SYNCBUSY);
                                                            ^
/home/silvanosky/Arduino/libraries/Servo/src/samd/Servo.cpp:84:9: note: in expansion of macro 'WAIT_TC16_REGS_SYNC'
         WAIT_TC16_REGS_SYNC(tc)
         ^
/home/silvanosky/Arduino/libraries/Servo/src/samd/Servo.cpp:44:60: error: 'volatile struct TC_STATUS_Type::<anonymous>' has no member named 'SYNCBUSY'
 #define WAIT_TC16_REGS_SYNC(x) while(x->COUNT16.STATUS.bit.SYNCBUSY);
                                                            ^
/home/silvanosky/Arduino/libraries/Servo/src/samd/Servo.cpp:91:9: note: in expansion of macro 'WAIT_TC16_REGS_SYNC'
         WAIT_TC16_REGS_SYNC(tc)
         ^
/home/silvanosky/Arduino/libraries/Servo/src/samd/Servo.cpp:44:60: error: 'volatile struct TC_STATUS_Type::<anonymous>' has no member named 'SYNCBUSY'
 #define WAIT_TC16_REGS_SYNC(x) while(x->COUNT16.STATUS.bit.SYNCBUSY);
                                                            ^
/home/silvanosky/Arduino/libraries/Servo/src/samd/Servo.cpp:99:9: note: in expansion of macro 'WAIT_TC16_REGS_SYNC'
         WAIT_TC16_REGS_SYNC(tc)
         ^
/home/silvanosky/Arduino/libraries/Servo/src/samd/Servo.cpp: In function 'void resetTC(Tc*)':
/home/silvanosky/Arduino/libraries/Servo/src/samd/Servo.cpp:44:60: error: 'volatile struct TC_STATUS_Type::<anonymous>' has no member named 'SYNCBUSY'
 #define WAIT_TC16_REGS_SYNC(x) while(x->COUNT16.STATUS.bit.SYNCBUSY);
                                                            ^
/home/silvanosky/Arduino/libraries/Servo/src/samd/Servo.cpp:112:5: note: in expansion of macro 'WAIT_TC16_REGS_SYNC'
     WAIT_TC16_REGS_SYNC(TCx)
     ^
/home/silvanosky/Arduino/libraries/Servo/src/samd/Servo.cpp:44:60: error: 'volatile struct TC_STATUS_Type::<anonymous>' has no member named 'SYNCBUSY'
 #define WAIT_TC16_REGS_SYNC(x) while(x->COUNT16.STATUS.bit.SYNCBUSY);
                                                            ^
/home/silvanosky/Arduino/libraries/Servo/src/samd/Servo.cpp:116:5: note: in expansion of macro 'WAIT_TC16_REGS_SYNC'
     WAIT_TC16_REGS_SYNC(TCx)
     ^
/home/silvanosky/Arduino/libraries/Servo/src/samd/Servo.cpp: In function 'void _initISR(Tc*, uint8_t, uint32_t, IRQn_Type, uint8_t, uint8_t)':
/home/silvanosky/Arduino/libraries/Servo/src/samd/Servo.cpp:123:11: error: 'struct Gclk' has no member named 'CLKCTRL'
     GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID(gcmForTimer));
           ^
/home/silvanosky/Arduino/libraries/Servo/src/samd/Servo.cpp:123:37: error: 'GCLK_CLKCTRL_CLKEN' was not declared in this scope
     GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID(gcmForTimer));
                                     ^
/home/silvanosky/Arduino/libraries/Servo/src/samd/Servo.cpp:123:58: error: 'GCLK_CLKCTRL_GEN_GCLK0' was not declared in this scope
     GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID(gcmForTimer));
                                                          ^
/home/silvanosky/Arduino/libraries/Servo/src/samd/Servo.cpp:123:110: error: 'GCLK_CLKCTRL_ID' was not declared in this scope
     GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID(gcmForTimer));
                                                                                                              ^
/home/silvanosky/Arduino/libraries/Servo/src/samd/Servo.cpp:124:18: error: 'struct Gclk' has no member named 'STATUS'
     while (GCLK->STATUS.bit.SYNCBUSY);
                  ^
/home/silvanosky/Arduino/libraries/Servo/src/samd/Servo.cpp:134:30: error: 'TC_CTRLA_WAVEGEN_NPWM' was not declared in this scope
     tc->COUNT16.CTRLA.reg |= TC_CTRLA_WAVEGEN_NPWM;
                              ^
/home/silvanosky/Arduino/libraries/Servo/src/samd/Servo.cpp:44:60: error: 'volatile struct TC_STATUS_Type::<anonymous>' has no member named 'SYNCBUSY'
 #define WAIT_TC16_REGS_SYNC(x) while(x->COUNT16.STATUS.bit.SYNCBUSY);
                                                            ^
/home/silvanosky/Arduino/libraries/Servo/src/samd/Servo.cpp:141:5: note: in expansion of macro 'WAIT_TC16_REGS_SYNC'
     WAIT_TC16_REGS_SYNC(tc)
     ^
/home/silvanosky/Arduino/libraries/Servo/src/samd/Servo.cpp:44:60: error: 'volatile struct TC_STATUS_Type::<anonymous>' has no member named 'SYNCBUSY'
 #define WAIT_TC16_REGS_SYNC(x) while(x->COUNT16.STATUS.bit.SYNCBUSY);
                                                            ^
/home/silvanosky/Arduino/libraries/Servo/src/samd/Servo.cpp:145:5: note: in expansion of macro 'WAIT_TC16_REGS_SYNC'
     WAIT_TC16_REGS_SYNC(tc)
     ^
/home/silvanosky/Arduino/libraries/Servo/src/samd/Servo.cpp:44:60: error: 'volatile struct TC_STATUS_Type::<anonymous>' has no member named 'SYNCBUSY'
 #define WAIT_TC16_REGS_SYNC(x) while(x->COUNT16.STATUS.bit.SYNCBUSY);
                                                            ^
/home/silvanosky/Arduino/libraries/Servo/src/samd/Servo.cpp:159:5: note: in expansion of macro 'WAIT_TC16_REGS_SYNC'
     WAIT_TC16_REGS_SYNC(tc)
     ^
exit status 1
Error compiling for board Adafruit Feather M4 Express (SAMD51).

Add TIMERB3 to megaavr

With the additional timer TIMERB3 the servo library also works for MegaCorex and ATMega4809.
Advantage over the MegaCorex Servo library with this library is the setting of the frame rate works.
To ServoTimers.h add

#if defined(SERVO_USE_TIMERB3)
  &TCB3;
#endif

Servo.cpp add

#elif defined(SERVO_USE_TIMERB3)
ISR(TCB3_INT_vect)

Inverted pulse

Hello,

I made a minor add to the Servo library (and at that time only for AVR) to output an inverted pulse (the output signal is at rest at VCC and the pulse is at GND). The goal is to drive a 6V powered servo, the pulse being amplified and inverted by a NPN transistor. 2 methods are added to the servo class: setInvertedPulse and isInvertedPulse. If you are interested in the add, I can extend it to the other supported platforms and I can do a PR.

Let me now.

Best regards

An error occurs

Hello.
When I try to include the Servo.h file, I get an error like this:
#error "This library only supports boards with an AVR, SAM, SAMD, NRF52 or STM32F4 processor."
The one I'm using is an Arduino compatible.
Arduino uses AVR, so you can't get such an error.
I think it's a bug, so please fix it.
(This sentence was entered by automatic translation and may be incorrect.)

Add Atmega1284P support to Servo.h [imported]

From @cmaglie on November 15, 2012 18:59

This is Issue 984 moved from a Google Code project.
Added by 2012-07-14T13:09:37.000Z by [email protected].
Please review that bug for more context and additional comments, but update this bug.

Original labels: Type-Enhancement, Priority-Medium

Original description

What change would like to see? Please add Atmega1284P support to Servo.h. Though it can be done manually, it could be included in an official release.

Why? The 1284P is capable of 24 servos, but defaults to 12 with the current file.

Would this cause any incompatibilities with previous versions? If so, how
can these be mitigated? Unknown...

Copied from original issue: arduino/Arduino#984

Trouble compiling with vscode + platformio + STM32F407ZG

Hello! Thank you for all your hard work.

I am trying to use this library in platformio with the SKR PRO 1.2 (STM32F407ZG). I'm including
arduino-libraries/Servo@^1.1.7 in platformio. At first I get

#error "This library only supports boards with an AVR, SAM, SAMD, NRF52 or STM32F4 processor."

I see that it may require #define ARDUINO_ARCH_STM32F4. I tried to define this myself and then I get

.pio\libdeps\BIGTREE_SKR_PRO-Sixi3\Servo\src/stm32f4/ServoTimers.h:34:10: fatal error: types.h: No such file or directory

FWIW my firmware is https://github.com/marginallyclever/makelangelo-firmware and I'm on the Sixi3 branch.
If you have some idea what I'm doing wrong, please let me know.

Make output frequency of the PWM signal adjustable.

It happens, that some servos or other motor controllers require the PWM signal to be outputted at a specific frequency. These frequency my be between 5 and 400 Hz.
It would be awesome to configure that output frequency on initialization of a single servo or on a global scale.

enlarge range for angle from 0 to 359

hello,
will it be possible to enlarge the range for angle e.g. from 0 to 359 or at least from 0 to 270?
The default servo max angle= 180 should be possible to be changed arbitrarily for that purpose.

Conflict with virtualwire.h library

It shows

\Servo.cpp.o (symbol from plugin): In function `ServoCount':
(.text+0x0): multiple definition of `__vector_11'

\VirtualWire\VirtualWire.cpp.o (symbol from plugin): first defined here
collect2.exe: error: ld returned 1 exit status
Multiple libraries were found for "Servo.h"

The problem is that both Servo.cpp and VirtualWire.cpp try to use the same interrupt vector. Arduino Uno has only a single 16-bit timer, and Servo.cpp library seems to want it. The problem is that VirtualWire library also wants to use the only 16-bit timer available.

attach(pin) returns 0

The documentation says that .attach(pin) should return the pin assigned or 0 in the case of a failure.

When I check the returned value it's always 0, regardless of failure:

#include <Servo.h>

Servo servo;

void setup() {
  Serial.begin(9600);
  byte b = servo.attach(2);
  while(!Serial) { ; }
  Serial.println("Ready\n=====");
  Serial.println("Pin attached:  " + String(b));
}

Output:

Ready=====
Pin attached: 0

problems with midi library

Hello, I'm not much of a programmer and I'm having problems with a project where I plan to control some things by reading midi (music to mechatronics). If I include <Servo.h> in my project, midi stops working (servo test procedures do work as expected). There's no compiler error, just midi messages like NoteON event don't come thru (just by including servo header and nothing more).

I'm bypassing the midi library (https://github.com/FortySevenEffects/arduino_midi_library) with reading and analyzing serial bytes, but I find that rather tedious. Is there any chance someone experienced could compare the two libraries and identify the culprit?

Servo compilation error in platform io

hey,
i'm using platform io IDE, and nodemcu.
and when im trying to compile the library i get this error message:
"This library only supports boards with an AVR, SAM, SAMD, NRF52 or STM32F4 processor."

there is something to do to fix it? it is very important.

thanks.

add extend documentation to say which timers are used

I was looking up the IRRemote-library and found very quickly information which hardware-timer is used.
And in which file to lookup how to modify the default-timer.

The servo-library often conflicts with IR. It would be very useful if the used timers would be named at a prominent and easy to find place in the documentation

Online simulator pages for Servo Library - New feature 😀

Hi there

Thank you very much for the most used and working library. We have been working on an Arduino simulator for the Arduino community ♥. It is free to use for all and needs no login or additional downloads. It runs right out of the browser.

We have created online simulation pages and we will be glad to create a PR to add the information about the simulation pages in the ReadMe file. I believe it will be interesting for the users of the library as well. Kindly give your kind feedback 😀

https://wokwi.com/arduino/libraries/Servo

you can find the simulations running in the below link
🙏

Best Regards
Puneeth

feature request: Servo class: servo.write(int angle, float rotationspeed)

feature request: Servo class: servo.write(int angle, float rotationspeed)

  • angle: degrees (endpoint)
  • rotationspeed: degrees per second

e.g.,

servo.write(90); // let the servo move to position 90° immediately
delay(1000);
servo.write(180, 10.0); // moves the servo from the current position (90°) to position 180° by a rotation speed of 10°/sec

The function must not be blocking, so that a following command can be started immediately before the further movement has been finished (simultaneous movement)

servo1.write(180, 10.0);
servo2.write(45, 5.0);

No PWM output on PWM pins with Nano 33 Sense

I was trying to run some tests with servos on my Nano 33 Sense and I noticed that every time I loaded a test sketch (sweep sketch from the examples folder), My servo was unresponsive. I connected the Nano's PWM pin to a scope (pinout 21 or D3 in this case, but I had also tried the others as well) and I was getting nothing on the scope. I had hooked up and loaded the same sketch to an Arduino MEGA 2560 and I could see the pulse sweep on the scope. Any idea as to why my nano 33 sense would not be working correctly like the MEGA?

Disable homing of servo on attach (or slow down movement)

Is there a way to disable homing of servo when servo.attach()? In my use, it whip around so fast that pulls the device over on when the ESP8266 is powered on.

Either that or a way to slow down the movement so it doesn't move so fast.

Incorrect servo read values for Nano 33 BLE Sense with MBED 1.1.6

The read method of Servo returns incorrect values. If position 0 is written the read value is -1 and for 180 the returned value is ~ 177- 178.

The issue is not seen with SAM, SAMD, or AVR.

Please use the below sketch for reproducing the issue:

#include <Servo.h>

Servo myservo;  // create servo object to control a servo
// twelve servo objects can be created on most boards

int pos = 0;    // variable to store the servo position

void setup() {
  myservo.attach(9);  // attaches the servo on pin 9 to the servo object
  Serial.begin(9600);
}

void loop() {
  myservo.write(0);
  int currPos = myservo.read();
  Serial.println(currPos);
  delay(150);
  myservo.write(180);
  currPos = myservo.read();
  Serial.println(currPos);
  delay(150);
}

Update Servo library for more standard default pulse widths

From @bhuang10000 on December 23, 2014 19:33

The Servo library uses a default pulse width of 544 uS to 2400 uS -- with a zero/neutral position at 1472 uS?

This does not coincide with any standard servos that I've seen. Most servos (like HiTech or other generic ones) operate on a rage from 900 uS to 2100 uS with a neutral position (90 deg) at 1500 uS. The "default pulse width" is set to 1500, but this is not the same as 90 degrees on the servo.

Suggest changing the default settings to align with 900 uS and 2100 uS --

# define MIN_PULSE_WIDTH       900     // the shortest pulse sent to a servo
# define MAX_PULSE_WIDTH      2100     // the longest pulse sent to a servo
# define DEFAULT_PULSE_WIDTH  1500     // default pulse width when servo is attached

Copied from original issue: arduino/Arduino#2509

Does not work with NRF52 device

I am using @sandeepmistry 's Arduino Core for an nRF52 device. When I try to compile the "Sweep" example, it fails with the error message:

This library only supports boards with an AVR, SAM, SAMD, NRF52 or STM32F4 processor

Upon digging further into Servo.h, I find the following conditions:

#if defined(ARDUINO_ARCH_AVR)
#include "avr/ServoTimers.h"
#elif defined(ARDUINO_ARCH_SAM)
#include "sam/ServoTimers.h"
#elif defined(ARDUINO_ARCH_SAMD)
#include "samd/ServoTimers.h"
#elif defined(ARDUINO_ARCH_STM32F4)
#include "stm32f4/ServoTimers.h"
#elif defined(ARDUINO_ARCH_NRF52)
#include "nrf52/ServoTimers.h"
#else
#error "This library only supports boards with an AVR, SAM, SAMD, NRF52 or STM32F4 processor."
#endif

It is possible that the ARDUINO_ARCH_NRF52 is not defined in @sandeepmistry 's core. How can I use the Servo library for my nRF52 device?

Period improperly calculated in Servo library for megaavr microcontrollers (Arduino Nano Every)

This was submitted to the wrong area, so is being resubmitted here. Excuse me for lack of familiarity with GitHub.

The ServoHandler function in libraries/Servo/src/megaavr/Servo.cpp improperly calculates the wait time for the refresh period to expire. This certainly came about from the differences between ATmega328P and ATmega4809 Timer/Counters. The number of ticks into the period must be accumulated to calculate the new CCMP value necessary. This should have been done with the tcCounterValue variable, which I have done here. I'm providing my fix for consideration.

void ServoHandler(int timer)
{
	static uint16_t tcCounterValue = 0;
    if (currentServoIndex[timer] < 0) {
        // Write compare register
        _timer->CCMP = 0;
    } else {
        if (SERVO_INDEX(timer, currentServoIndex[timer]) < ServoCount && SERVO(timer, currentServoIndex[timer]).Pin.isActive == true) {
            digitalWrite(SERVO(timer, currentServoIndex[timer]).Pin.nbr, LOW);   // pulse this channel low if activated
        }
    }

    // Select the next servo controlled by this timer
    currentServoIndex[timer]++;

    if (SERVO_INDEX(timer, currentServoIndex[timer]) < ServoCount && currentServoIndex[timer] < SERVOS_PER_TIMER) {
        if (SERVO(timer, currentServoIndex[timer]).Pin.isActive == true) {   // check if activated
            digitalWrite(SERVO(timer, currentServoIndex[timer]).Pin.nbr, HIGH);   // it's an active channel so pulse it high
        }

        // Get the counter value
        tcCounterValue += (_timer->CCMP = (uint16_t) (SERVO(timer, currentServoIndex[timer]).ticks));
    }
    else {
        // finished all channels so wait for the refresh period to expire before starting over

        if (tcCounterValue + 4UL < usToTicks(REFRESH_INTERVAL)) {   // allow a few ticks to ensure the next OCR1A not missed
            _timer->CCMP = (uint16_t) usToTicks(REFRESH_INTERVAL) - tcCounterValue;
        }
        else {
            _timer->CCMP = (uint16_t) (4UL);   // at least REFRESH_INTERVAL has elapsed
        }
		tcCounterValue = 0;
        currentServoIndex[timer] = -1;   // this will get incremented at the end of the refresh period to start again at the first channel
    }

    /* Clear flag */
    _timer->INTFLAGS = TCB_CAPT_bm;
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.