Variable speed & angle asynchronous servo control

Arduino library to provide complete, flexible control of servo motors.

Similar projects worth following
While there are many programs (call 'em sketches if you like) for the Arduino that use the Servo library to exercise a servo motor or two (sometimes more), they nearly all act the same: they move the servo(s) to a new position instantly, or at least as fast as possible. While useful, this behaviour is often not as desirable as it might be.

This project will present a library that defines a Sweeper object that addresses the shortcomings of existing servo control schemes. The purpose of the Sweeper library is to provide the ability to move a Servo to a desired position at a desired rate. Not only can desired movement angle and time be specified, but arrays can be used for control permitting coordinated group movements, as well as individual movements.

Impatient? Here's the short take.
- Provide suitable power to your servos See Hardware Interface..
- Download and install the Sweeper Library.
- Start with the example sketches provided, experiment and learn. See the video to see them in action.
- Read more when you need to know more.

Hardware Interface
- Servos need independent power! Initially, I used a 6V, 1A wall wart. Ran 6 SG-5010 and 2 SG90 servos simultaneously for a few minutes and the wall wart was just barely warm. I didn't try to find the limits of this setup. It worked for testing. Servos are really happiest (most of them) with 5V, not 6V. So I'm now using a 5V, 2A switching supply. If you use a lot of motors (more than 4 to 6 or so?) you may need a beefier supply. YMMV. If your motors are loaded heavily, obviously you'll need more power. Test your system by running a single motor, then add more one at a time. If the motors stop moving reliably, then you should increase the power available. The worst case is likely to be when several motors all need to move rapidly at the same time.
- I built a simple board to connect power and the control signals. The schematic and a picture of it are attached. (See ServoIntrf.png and ServoInterface.pdf.) Doesn't get much simpler. The two big caps are there to smooth out surges during servo motion. But if you aren't into building hardware,  simply search Ebay for "Sensor Shield Digital Analog Module Servo Motor for Arduino UNO R3". The file ServoBoard.jpg shows a picture. For about five bucks with shipping, this is a good way to go.

Installing the Sweeper Library is the zipped Sweeper library. To install library, download the zip, open the Arduino IDE, go to Sketch > Include Library > Add .ZIP Library, and then select the Sweeper zip file that you just downloaded. No need to restart Arduino, the Sweeper Library will now be available. Note that you must also install the Servo library, if it's not already done, to use the Sweeper library. The elapsedMillis library must be installed to run the demos. These can be installed with the Library Manager.

Read more »

Zipped version of the Sweeper Library with examples.

Zip Archive - 16.18 kB - 02/14/2021 at 01:30



The Servo Interface board for Uno offered on Ebay.

JPEG Image - 328.01 kB - 02/14/2021 at 01:27



The servo interface board I built.

JPEG Image - 149.50 kB - 03/12/2017 at 01:38



Simple Servo Interface board schematic.

Adobe Portable Document Format - 26.85 kB - 03/12/2017 at 00:48


  • The Right Answer

    doctek02/14/2021 at 01:33 0 comments

    So I looked into this project again recently and came to the sudden realization that I had not taken the next obvious step and put the Sweeper class into an independent library, like the Servo library! Wishing to learn from the excellent examples that exist, I spent some quality time digging into the Servo library. After some careful consideration, I devised a way to create a Sweeper class that could be a separate library - just what I wanted! Then I modified a couple of sketches to test out my shiny new library. A few tweaks later and it works great.

    This led to an extensive revision of this project! Reading back over the entries I made for it, I now realize that most of it is moot. It just explained the process I went through to develop the library. The important point is that a Sweeper library has been created. Examples will show how to use it. Since I can't delete or modify the build logs, I will use to them mainly for the history of the development of the Sweeper Library. Very little more needs to be said about that. Note that the sketches I developed along the way using an inline Sweeper class definition are now gone. I have replaced these by examples which use the Sweeper Library. These examples are included with the Sweeper Library.

  • Class Improvements and Helper Functions

    doctek04/02/2017 at 19:37 0 comments

    OK! Except for some tiding up, the desired functions are working. Uh, sort of. Now it's time to make the Sweeper class easier to use and to add some helper functions to do interesting things - like group moves perhaps. For those playing along at home, this will be the useful version!

    Step 1: Fix the Sweeper class so that no arguments are required to instantiate a Sweeper object. Why? Because an array of Sweepers can now be created. This keeps the code for creating, initializing, and updating the servos nice and clean.

    Step 2: Add some useful class functions. The code to initialize a move with destination and time is now separate from the function that enables the move. Doing this allows several moves to be set up, then all started at the same time, for a group move. Now it is likely that this is not necessary in most cases, but I thought it would be nice to have and would eliminate worries caused by starting moves at staggered times.

    Step 3: Create a "group move" function. The idea here is to allow a group of servos to be easily defined (as an array), along with a corresponding array of target angles and an allowed time for the move.

    Step 4: Time the worst case operation. Suppose all the Sweepers need to move on the same tick. Will there be time or will there be a timing conflict?

    Still coming: video of a simple demo. Bonus: Lego link: Gear and Mount.

  • Modifications for More Control

    doctek03/12/2017 at 00:57 0 comments

    The first (Adafruit) version of the code simply swept two servos back and forth over their full range at independent rates. While that makes a nice demo, it's not really what I wanted. So time to start hacking the code. As a first step, I wanted a servo to move to a specified position at the programmed rate, then stop until directed to a new position. A few simple changes to the Sweeper class, a bit of code in loop() to excerise it, and it was working. The results are shown in T2MultiServo2.ino.

    If we can specify the desired position to sweep to, what else do we need? That's right, programmable sweep time. The Sweeper class functions need to know the time interval between incremental moves. But that's not really what I wanted to specify. I'd like to specify the time for the full move. So that's what I implemented! The code is in T2MultiServo3.ino. Again, the change is pretty straight-forward.

  • Inspiration and First Steps

    doctek03/12/2017 at 00:38 0 comments

    The seminal idea for this project came from a discussion at an Arduino Interest Group meeting in San Diego. One person mentioned that he had a kinetic sculpture and wanted to animate it with servo motors. He asked if anyone knew how to control the servos with an Aduino. We discussed his project needs and I said I'd see if I could find any useful info. When I started googling, I realized the problem didn't really have a good solution that I could find. Reason enough to see what I might come up with. Goal: Control 9 (min) to 12 (limit of Servo library) stepper motors independently to sweep to a desired position in a given time. Allow other functions to run simultaneously, if possible. Use minimal external components.

    While I found no complete solution, I did discover a huge step in the right direction! Bill Earl at Adafruit shows how to create an Arduino program to sweep two servos back and forth (0 to 180 degrees) at a programmed rate. His program is interrupt driven so the sweep rates are independent. This struck me as the perfect place to start!

View all 4 project logs

Enjoy this project?



doctek wrote 07/23/2017 at 04:25 point

Amazing and ambitious projects! I like the idea of using paper structurally to make robot bodies and limbs.

Your approach to servo control is also interesting. Continually sending commands from a central controller is a good way to partition motion control and allow multiple units for motion and sensing. Since I don't plan such a complex control system, I used the interrupt scheme to keep the loop() open for other tasks without impacting timing of the servo actions. I don't like trying to coordinate synchronous actions with asynchronous communications if I can avoid it. Too many "moving parts" makes me crazy! I think the control structures I use could be constructed on the fly from input commands, but I haven't tried that yet.

To deal with the problem of initial position and motion limits, I've written a program that allows one servo at a time to be addressed and exercised. I've considered the idea of putting the results into EEPROM, but so far that hasn't been needed. More future work?

  Are you sure? yes | no

Morning.Star wrote 07/23/2017 at 11:20 point

Interestingly enough, I got the idea looking at two consecutive servo signals on my scope and noticed how the interrupt system interleaved the PWM to produce what I was seeing. My first thought was to modify the interrupt code to pull in the sequence from the buffer directly, but I couldnt see how to sync that with an unknown number of servos and had to let the interrupts handle the switching. I built a structure to interface with the buffer and pinched it off in loop() because thats all the chip had to do; demux asynchronous commands into a synchronous buffer. Decal's supercontroller would be a multithreaded nightmare if I tried to put it on one die, which is why its built the way it is. AIMos is fully multi-threaded and the semaphore made my brain hurt as it was, trying to pipeline it for serial meant I had to implement a command structure because even at 115200bps the lag between servos 1 and 12 starting is noticeable, more audibly than visibly but still... Complex motions like accelerations are easy enough with one servo, but sending 12 parallel streams over serial proved notchy, so I abstracted them into commands that control a parallel structure which runs a lot faster than the serial does and is a lot smoother as a result. The problem is with the serial link, it really needs to be parallel and faster for an AI to control many servos over it. ;-)

Any thoughts on the problem I'm having with the ADC on my chips? They behave like digital ports, reading either 0 or 1023 unless floating, then they read variable and react to my finger touching the pin. It's really p*ing me off...

  Are you sure? yes | no

doctek wrote 07/25/2017 at 00:46 point

Your need to have an unknown and changeable number of servos connected kind of kills my scheme - although you could just design for a maximum of 12 servos, I think. But if what you have works, then why try to fix it?

Regarding your ADC, is that on the AVR? I don't see the code to run it implemented in the program you pointed to. Did I miss that part? I'll be glad to take a look at it if you like. I've used the AVR's ADC many times.

  Are you sure? yes | no

Morning.Star wrote 07/26/2017 at 06:25 point

I'll log the trouble I had when I cool off lol. I discovered that both of my Unos have failed, on one the 117 regulator is dead, and it has another unknown problem that prevents the ADC working. The other one has a broken trace somewhere but I never noticed til now as the digitals work fine. I also have a Mega2560 that the FTDI failed on, it wont talk to USB anymore but works otherwise. And then I also discovered the new IDE's Plotter crashes Inkscape on a multi-monitor setup and lost a bunch of foot template drawings. <pumps shotgun>

Chips work just great in my board... Thanks for answering tho. :-)

  Are you sure? yes | no

Morning.Star wrote 07/22/2017 at 09:27 point

Interesting approach. :-) I did something similar which I'm now reusing in Decal ( I called it a Servo Sequencer... What it does is accept a packet over serial that contains an angle and a speed, plus a start time in ticks and then execute the motion synchronously out of a rolling buffer containing the positions of all the servos. The code is documented in #AIMOS and posted in #Cardware if you're interested how I went about it.

  Are you sure? yes | no

Similar Projects

Does this project spark your interest?

Become a member to follow this project and never miss any updates