Giter Site home page Giter Site logo

netlabtoolkit / varspeedservo Goto Github PK

View Code? Open in Web Editor NEW
286.0 36.0 127.0 41 KB

Arduino library for servos that extends the standard servo.h library with the ability to set speed, and wait for position to complete

License: GNU Lesser General Public License v2.1

C++ 100.00%

varspeedservo's Introduction

VarSpeedServo.h

NOTE: This library is no longer maintained due to hardware dependencies and wide variety of devices to support. As an alternative, I have created VarSpeedPython, which is a module that can be used on any python platform (e.g. CircuitPython or MicroPython) or any implementation of Python. VarSpeedPython is does not have any hardware dependencies, and is designed to be called from within an event loop (and therefore does not block).

VarSpeedPython provides the ability to move from one position to another over a period of time, and with a specified number of steps, and with an easing function for the move. It can be applied to Servos, LEDs, any other actuator or output that needs to change from one value to another over time.

Please give it a try if your project can run on a Python platform.


The VarSpeedServo.h Arduino library allows the use of up to 8 servos moving asynchronously (because it uses interrupts). In addition, you can set the speed of a move, optionally wait (block) until the servo move is complete, and create sequences of moves that run asynchronously.

This code is an adaptation of the standard Arduino Servo.h library, which was first adapted by Korman and posted on the Arduino forum to add the speed capability. Philip van Allen updated it for Arduino 1.0 + and added the ability to to wait for the move to complete.

  • Supports up to 8 servos
  • Allows simultaneous, asynchronous movement of all servos
  • The speed of a move can be set
  • The write() function initiates a move and can optionally wait for completion of the move before returning
  • A servo can be sent a sequence of moves (where each move has a position and speed)

Sample Code - one servo moving, wait for first movement to finish, then execute another movement


#include <VarSpeedServo.h> 
 
VarSpeedServo myservo;    // create servo object to control a servo 
 
void setup() {
  myservo.attach(9);  // attaches the servo on pin 9 to the servo object 
} 
 
void loop() {
  myservo.write(180, 30, true);        // move to 180 degrees, use a speed of 30, wait until move is complete
  myservo.write(0, 30, true);        // move to 0 degrees, use a speed of 30, wait until move is complete
}

Sample Code - two servo moving in the same time with different speed, wait for both to finish and do another move

#include <VarSpeedServo.h> 

// create servo objects
VarSpeedServo myservo1;
VarSpeedServo myservo2;
 
void setup() {
  myservo1.attach(9);
  myservo2.attach(8);
} 
 
void loop() {
  
  int LEF = 0;
  int RIG = 180;
  
  int SPEED1 = 160;
  int SPEED2 = 100;
  
  myservo1.write(LEF, SPEED1);     
  myservo2.write(LEF, SPEED2);
  myservo1.wait(); // wait for servo 1 to finish
  myservo2.wait();  // wait for servo 2 to finish
    
  myservo1.write(RIG, SPEED1);     
  myservo1.wait(); // wait for S1
  
  myservo1.write(LEF, SPEED1); 
  myservo2.write(RIG, SPEED2);  
  myservo1.wait();
  myservo2.wait();    
        
  myservo1.write(RIG, SPEED1);     
  myservo1.wait();
      
  delay(1000);
  
}

Additional examples are included in the distribution and are available in the Arduino Examples section.

Class methods

A servo is activated by creating an instance of the Servo class passing the desired pin to the attach() method. The servos are pulsed in the background using the value most recently written using the write() method

VarSpeedServo - Class for manipulating servo motors connected to Arduino pins. Methods:

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  

write(value)     - Sets the servo angle in degrees.  (invalid angle that is valid as pulse in microseconds is treated as microseconds)
write(value, speed) - speed varies the speed of the move to new position 0=full speed, 1-255 slower to faster
write(value, speed, wait) - wait is a boolean that, if true, causes the function call to block until move is complete

writeMicroseconds() - Sets the servo pulse width in microseconds 
read()      - Gets the last written servo pulse width as an angle between 0 and 180. 
readMicroseconds()  - Gets the last written servo pulse width in microseconds. (was read_us() in first release)
attached()  - Returns true if there is a servo attached. 
detach()    - Stops an attached servos from pulsing its i/o pin. 

slowmove(value, speed) - The same as write(value, speed), retained for compatibility with Korman's version

stop() - stops the servo at the current position

sequencePlay(sequence, sequencePositions); // play a looping sequence starting at position 0
sequencePlay(sequence, sequencePositions, loop, startPosition); // play sequence with number of positions, loop if true, start at position
sequenceStop(); // stop sequence at current position
wait(); // wait for movement to finish
isMoving()  // return true if servo is still moving

Installation

  • Download the .zip file from the releases section of GitHub
  • In Arduino, select SKETCH>IMPORT LIBRARY...>ADD LIBRARY... and find the .zip file
  • This will install the library in your My Documents (Windows) or Documents (Mac) folder under Arduino/libraries
  • You can also unzip the file, and install it in the above libraries folder manually
  • See arduino.cc/en/Guide/Libraries for more info on libraries

varspeedservo's People

Contributors

ebranda avatar gillhawk avatar per1234 avatar pvanallen avatar sapics 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  avatar  avatar  avatar  avatar  avatar  avatar  avatar

varspeedservo's Issues

Library update for Arduino Nano 33 IoT and 33 BLE?

Hallo,
The new Arduino Nano’s (Every, 33 IoT, 33 BLE and 33 BLE Sense) are using new MCU’s and are not compadeble with the current VarSpeedServo library. Will there be an update anytime soon?

Thanks

sequencePlay function only playing 1st position point

First time I have tested the sequencePlay function:

With an own program but also with the original example "ServoSequence" the sequencePlay function only plays the first position point, then does nothing else.
Is there a way around it?

add support for Raspberry Pico

/root/Arduino/libraries/VarSpeedServo/VarSpeedServo.cpp: In function 'void handle_interrupts(timer16_Sequence_t, volatile uint16_t*, volatile uint16_t*)':
/root/Arduino/libraries/VarSpeedServo/VarSpeedServo.cpp:148:16: warning: conversion from 'unsigned int' to 'uint16_t' {aka 'short unsigned int'} changes value from '332500' to '4820' [-Woverflow]
  148 |       *OCRnA = (unsigned int)usToTicks(REFRESH_INTERVAL);
      |                ^
/root/Arduino/libraries/VarSpeedServo/VarSpeedServo.cpp: At global scope:
/root/Arduino/libraries/VarSpeedServo/VarSpeedServo.cpp:158:8: error: expected constructor, destructor, or type conversion before '(' token
  158 | SIGNAL (TIMER1_COMPA_vect)
      |        ^
/root/Arduino/libraries/VarSpeedServo/VarSpeedServo.cpp: In function 'void initISR(timer16_Sequence_t)':
/root/Arduino/libraries/VarSpeedServo/VarSpeedServo.cpp:206:5: error: 'TCCR1A' was not declared in this scope
  206 |     TCCR1A = 0;             // normal counting mode
      |     ^~~~~~
/root/Arduino/libraries/VarSpeedServo/VarSpeedServo.cpp:207:5: error: 'TCCR1B' was not declared in this scope
  207 |     TCCR1B = _BV(CS11);     // set prescaler of 8
      |     ^~~~~~
/root/Arduino/libraries/VarSpeedServo/VarSpeedServo.cpp:207:18: error: 'CS11' was not declared in this scope
  207 |     TCCR1B = _BV(CS11);     // set prescaler of 8
      |                  ^~~~
/root/Arduino/libraries/VarSpeedServo/VarSpeedServo.cpp:207:14: error: '_BV' was not declared in this scope
  207 |     TCCR1B = _BV(CS11);     // set prescaler of 8
      |              ^~~
/root/Arduino/libraries/VarSpeedServo/VarSpeedServo.cpp:208:5: error: 'TCNT1' was not declared in this scope
  208 |     TCNT1 = 0;              // clear the timer count
      |     ^~~~~
/root/Arduino/libraries/VarSpeedServo/VarSpeedServo.cpp:214:5: error: 'TIFR1' was not declared in this scope
  214 |     TIFR1 |= _BV(OCF1A);     // clear any pending interrupts;
      |     ^~~~~
/root/Arduino/libraries/VarSpeedServo/VarSpeedServo.cpp:214:18: error: 'OCF1A' was not declared in this scope
  214 |     TIFR1 |= _BV(OCF1A);     // clear any pending interrupts;
      |                  ^~~~~
/root/Arduino/libraries/VarSpeedServo/VarSpeedServo.cpp:215:5: error: 'TIMSK1' was not declared in this scope
  215 |     TIMSK1 |=  _BV(OCIE1A) ; // enable the output compare interrupt
      |     ^~~~~~
/root/Arduino/libraries/VarSpeedServo/VarSpeedServo.cpp:215:20: error: 'OCIE1A' was not declared in this scope
  215 |     TIMSK1 |=  _BV(OCIE1A) ; // enable the output compare interrupt
      |                    ^~~~~~
/root/Arduino/libraries/VarSpeedServo/VarSpeedServo.cpp: In member function 'void VarSpeedServo::writeMicroseconds(int)':
/root/Arduino/libraries/VarSpeedServo/VarSpeedServo.cpp:374:23: error: 'SREG' was not declared in this scope
  374 |     uint8_t oldSREG = SREG;
      |                       ^~~~
/root/Arduino/libraries/VarSpeedServo/VarSpeedServo.cpp: In member function 'void VarSpeedServo::write(int, uint8_t)':
/root/Arduino/libraries/VarSpeedServo/VarSpeedServo.cpp:422:22: error: 'SREG' was not declared in this scope
  422 |    uint8_t oldSREG = SREG;
      |                      ^~~~

Using library VarSpeedServo in folder: /root/Arduino/libraries/VarSpeedServo (legacy)
Using library Wire at version 1.0 in folder: /root/.arduino15/packages/rp2040/hardware/rp2040/3.1.1/libraries/Wire
Using library MPU6050 at version 0.6.0 in folder: /root/Arduino/libraries/MPU6050

Ardunio.uno 1.65

Having Trouble with using VarSpeedServo
error code produced :-
Third-party platform.txt does not define compiler.path. Please report this to the third-party hardware maintainer.
VarSpeedServoAeduinoOnly.ino:4:20: fatal error: stdlib/h: No such file or directory
compilation terminated.
Error compiling.
Invalid library found in E:\arduino 1.54\libraries\Audio: 'arch' folder is no longer supported! See http://goo.gl/gfFJzU for more information
Invalid library found in E:\arduino 1.54\libraries\EEPROM: 'arch' folder is no longer supported! See http://goo.gl/gfFJzU for more information
Invalid library found in E:\arduino 1.54\libraries\Ethernet: 'arch' folder is no longer supported! See http://goo.gl/gfFJzU for more information
Invalid library found in E:\arduino 1.54\libraries\GSM: 'arch' folder is no longer supported! See http://goo.gl/gfFJzU for more information
Invalid library found in E:\arduino 1.54\libraries\Robot_Control: 'arch' folder is no longer supported! See http://goo.gl/gfFJzU for more information
Invalid library found in E:\arduino 1.54\libraries\Servo: 'arch' folder is no longer supported! See http://goo.gl/gfFJzU for more information
Invalid library found in E:\arduino 1.54\libraries\SoftwareSerial: 'arch' folder is no longer supported! See http://goo.gl/gfFJzU for more information
Invalid library found in E:\arduino 1.54\libraries\SPI: 'arch' folder is no longer supported! See http://goo.gl/gfFJzU for more information
Invalid library found in E:\arduino 1.54\libraries\WiFi: 'arch' folder is no longer supported! See http://goo.gl/gfFJzU for more information
Invalid library found in E:\arduino 1.54\libraries\Audio: 'arch' folder is no longer supported! See http://goo.gl/gfFJzU for more information
Invalid library found in E:\arduino 1.54\libraries\EEPROM: 'arch' folder is no longer supported! See http://goo.gl/gfFJzU for more information
Invalid library found in E:\arduino 1.54\libraries\Ethernet: 'arch' folder is no longer supported! See http://goo.gl/gfFJzU for more information
Invalid library found in E:\arduino 1.54\libraries\GSM: 'arch' folder is no longer supported! See http://goo.gl/gfFJzU for more information
Invalid library found in E:\arduino 1.54\libraries\Robot_Control: 'arch' folder is no longer supported! See http://goo.gl/gfFJzU for more information
Invalid library found in E:\arduino 1.54\libraries\Servo: 'arch' folder is no longer supported! See http://goo.gl/gfFJzU for more information
Invalid library found in E:\arduino 1.54\libraries\SoftwareSerial: 'arch' folder is no longer supported! See http://goo.gl/gfFJzU for more information
Invalid library found in E:\arduino 1.54\libraries\SPI: 'arch' folder is no longer supported! See http://goo.gl/gfFJzU for more information
Invalid library found in E:\arduino 1.54\libraries\WiFi: 'arch' folder is no longer supported! See http://goo.gl/gfFJzU for more information

New feature 🙂- Arduino Simulation pages for the examples

Hi there

Thank you for the Servo library examples, first of all. I have used it and have created a few permanent simulation pages. You can use this for free, modify it as you wish.

Having the simulation pages helps the user to get a feel of the examples without having it wait for the hardware setup to be done. This also gives a clear idea of what the examples and the library is capable of. This will be helpful for the readers.

Here are the links. Please let me know If I can create a PR to update the links in the ReadMe file.

ServoSequence
https://wokwi.com/arduino/projects/300614891113284109

VarSpeedServoTest
https://wokwi.com/arduino/projects/300615166523867657

Sweep two Servos
https://wokwi.com/arduino/projects/300615326711677450

I will be glad to answer your questions if any. ALso, kindly share your feedback on the simulator, we will appreciate it.

Thank you :)
matititam

Motor Reset when I use attach function.

My servo comes to 0 when I use attach function.

Here is the code I used:

#include <VarSpeedServo.h>

VarSpeedServo test;

void setup() {
// put your setup code here, to run onc
test.attach(2);
}

void loop() {
// put your main code here, to run repeatedly:
}

High-resolution servo support.

Looking at the code, it seems the range is hard-coded to 0-180 and pulse-widths are limited to multiples of 4us. However, modern digital/programmable servos allow programming the travel-range to increase the resolution (i.e. same pulse-widths, fewer degrees). It's not uncommon to have 0-120 or 0-90 servos. Also, I think this suggests new overloadedwrite() methods that accept degree-fractions (or radians), or centi-degrees.

What do you think are the challenges involved in removing the 4us multiple (for all servos) and allowing to specify angle constraints per-servo (or all servos)?

(I'm willing to help if you think the goal is possible)

Servo not waiting until move complete before executing another move

The code below sets up and initiates a move from 20 degrees to 170 degrees and then back to 20 degrees all at full speed waiting for each move to complete before starting the next:

`VarSpeedServo servo1;
servo1.attach(5);
servo1.write(20, 0);
servo1.wait();

servo1.write(170, 0);
servo1.wait();

servo1.write(20, 0);
servo1.wait();`

However the servo is not completing the move to 170 degrees before returning to 20 degrees.

Starting point

I am trying to use this library to slow down robot arm, because the fast speed could destroy servo gear coupling, due to inertia force.
The problem is that the library sets the motor starting point to 90 degrees only, and I cannot seem to be able to change this. Since my starting point, for the arm at resting position is a different value (20 degrees) the system results in giving a jerk to set the 90 degrees before starting positioning, and this is a problem.
Can we have a possibility to set a different starting point ?
Regards, Giorgio

wait for the end of the movement of two servo?

Hi,

I've two servo(basically mounted as a tower, one is for X one for Y).

I've some new coordinates to go(like go to the angle 50° in X, 60 in Y).

The issue that I've is that if I only wait on the second instruction, maybe y has to go from 59 to 60, and x from 0 to 90, and in this case the movement is not finish when the next steps are solved, any idea how to solve this?

To wait on the end of the two servos, which will not have the same duration?

acceleration/deacceleration

Hi There !

Nice Lib. How can I manage to move to a position with acceleration or deacceleration?
For example move from full right to full left with an acceleration from speed 30 to speed 100 ?

Kind regards

Different ATmega speeds

I want to run my ATmega328p using the 8MHz internal oscillator rather than the 16MHz Xtal (to gain extra I/O).
Does varspeedservo run independent of the chip's clock speed, or do I need to alter the varspeedservo code somewhere?

gcc - warning: comparison is always true

Just FYI ...

VarSpeedServo.cpp @ 364
VarSpeedServo.cpp @ 414
if( (channel >= 0) && (channel < MAX_SERVOS) ) // ensure channel is valid
. . . . . . . . . . ^
VarSpeedServo.cpp:364:16: warning: comparison is always true due to limited range of data type [-Wtype-limits]

A byte value is 0 ... 255 and in this case GCC is right AFAIKT.

servo.wait() method not working

Here is a simple example of this issue:

#include <VarSpeedServo.h>
VarSpeedServo servo;

void setup() {
  servo.attach(10);
  servo.write(90);
  servo.wait();
  servo.detach();

}
void loop(){}

In this example, the servo doesn't move at all because it is detached before it can move despite the method wait() being called before detach(). I want to detach my servos after movement to keep them from jittering. Is there any way I can do that?

Motor won't change direction when using VarSpeedServo.h

Hello,

I'm trying to use this library in my program which is basically just a remote controlled robot that stops when the sensor detects an object. The problem is that when the servo is sweeping, the robot has difficulty receiving commands from the IR remote control.

I'll try to include my program here but, it isn't finished and I couldn't clean it since I'm still working on the code to make the servo sweep. This is the code just at it is.

Please help if you can.

My IR Controlled Robot.txt

I am very new to this

I have the ELEGOO MEGA2560 R3. Will this varspeedservo work with it or just the actual arduino

isMoving implementation

The documentation implies this exists but it is a "To Do" in the code. I made a simple implementation of this function if you are interested. Added an argument to make it easier. Mimics the code under "write" with wait=true.

bool VarSpeedServo::isMoving(int value) {
if (value < MIN_PULSE_WIDTH) {
if (read() != value) return(true);
} else {
if (readMicroseconds() != value) return(true);
}
return(false);
}

Update for SAMD21

I need a version of this that works on the SAMD21 processor for a project of mine. I'm working on an update for that processor and will contribute back when complete.

sequencePlay

I think i found a bug in the sequencePlay function.
It works well if it is run for the first time and does not stop.
If it is triggered some time after the first run it will not start. I also tried to stop the squence if it was stuck somewhere but it wont make a difference. Example:

if(digitalRead(pin) == LOW)
{
myservo1.sequencePlay(test, 3);
}

runs fine, but the arduino has to be reset to work again. I also used some different conditions than this pin state to test it out.

isMoving can't return "false"

The "isMoving" function misses a return "false" if the conditions for "true" are not met.

"Flowing off the end of a value-returning function (except main) without a return statement is undefined behavior." source

Please add "return false;" at the end of the function and it should work like expected.

bool VarSpeedServo::isMoving() {
  byte channel = this->servoIndex;
  int value = servos[channel].value;
  
  if (value < MIN_PULSE_WIDTH) {
    if (read() != value) {
      return true;
    }
  } else {
    if (readMicroseconds() != value) {
      return true;
    }
  }
  
  return false;
}

Not an Issue but an Example suggestion --> Multi-Serial Position and Speed

Wrote this to control testing servo(s) on the fly -- thought maybe it would be a great addition to the examples for your AWESOME library.

Side note --> thx for the library!

// Multi Serial to VarSpeedServo --> Vije Miller
// https://github.com/netlabtoolkit/VarSpeedServo

/*
  Type: Servo No. + Position + . + Speed
  Keypad Friendly Position and Speed Testing
  Example: 290.120 (Servo 2 Position 90 Speed 120)
  10 to 1180 + .0 to .255 Speed for Servo 1
*/

#include <VarSpeedServo.h>

// Name Servos
VarSpeedServo one;
VarSpeedServo two;
VarSpeedServo three;
VarSpeedServo four;
VarSpeedServo five;

// Set Values
String input;
String also;
String then;
int also_int;
int then_pos;
int then_int;

// Default Position and Speed
const int start = 90;
const int set_speed = 50;

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

  // Assign Pins
  one.attach(2);
  two.attach(3);
  three.attach(4);
  four.attach(5);
  five.attach(6);

  // Default Position and Speed
  one.write(start, set_speed, true);
  two.write(start, set_speed, true);
  three.write(start, set_speed, true);
  four.write(start, set_speed, true);
  five.write(start, set_speed, true);
}

void loop() {
  if (Serial.available() > 0)
  {
    // Assign Strings
    input = Serial.readString();
    also = input;
    then = also;

    // Get Servo Number
    input.remove(1);

    // Get Position
    also.remove(0, 1);
    also_int = also.toInt();

    // Get Speed
    then_pos = then.indexOf('.');
    then_pos = then_pos + 1;
    then = then.substring(then_pos);
    then_int = then.toInt();

    // Print Results
    Serial.print(input);
    Serial.print(" ");
    Serial.print(also_int);
    Serial.print(" ");
    Serial.println(then_int);

    // Run Results
    if (input == "1") {
      one.write(also_int, then_int, true);
    } else if (input == "2") {
      two.write(also_int, then_int, true);
    } else if (input == "3") {
      three.write(also_int, then_int, true);
    } else if (input == "4") {
      four.write(also_int, then_int, true);
    } else if (input == "5") {
      five.write(also_int, then_int, true);
    }
    delay(10);
  }
}

README.md out of date

The README.md appears to be out of date in regard to number of servos supported, it says:
"The VarSpeedServo.h Arduino library allows the use of up to 8 servos moving asynchronously (because it uses interrupts). In addition, you can set the speed of a move, optionally wait (block) until the servo move is complete, and create sequences of moves that run asynchronously."

and VarSpeedServo.cpp says:
"Timers are seized as needed in groups of 12 servos - 24 servos use two timers, 48 servos will use four."

default position

is there a way to disable the static void initISR() so that when i power up the unit it wont jump to the default pulse width of 1400 ?

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.