VarSpeedServo - Board Compatibility

Hello to all arduino users,

I have checked a topic here, on the Arduino forum, regarding the VarSpeedServo library, a modified version of the Servo library that allows the control of a servo speed with an additional speed parameter on the write function. I have an ongoing project where its required to vary the speed of the servo at a specific period. Unfortunately, the “original” Servo library does not allow the control of the speed. :slightly_frowning_face:
Because of that, I started using the VarSpeedServo library as soon as I found it.

I have started the project with an Arduino Nano board, just for the first beta tests, in which the library works perfectly. Although, the final board for this project is not an Arduino board but a “compatible” one with an ARM Cortex-M3, an integrated 3-Axis accelerometer and 3-Axis gyroscope. Sadly, after I tried the test code I have made with the Arduino board I understood that the library was not compatible with the "final" board. :angry:

My question now is, is the incompatibility due to the processor or some control differences between the board? I could replace the board for a Genuino 101 for example, but I would need some confirmation that the library will work with this board. It also has an integrated accelerometer and gyroscope like the “compatible” one, two requirements I will definitely need at some point.
In conclusion, could you please confirm me if the library is compatible with other Arduino boards besides the Nano and Uno? Does anyone have used it with an Genuino 101 already?
Will I be able to implement it in a 32-bit board like the Genuino 101? Any chance to easily adapt the code for other boards?

Besides the compatibility, is there any alternative to control the servo speed? Any other library I could use? I know it would be possible to use some “for” cycles to control the speed, but that’s not really a good approach.
I would be grateful with any suggestion you may have for this issue.

Thanks in advance for your assistance :wink:

Have you looked at what the library does?
It does not tell the motor in the servo to go slower.

I got slower servo movement by slicing up the movement into smaller pieces, telling the servo to go there (which it does at full speed, the only thing it can do) and then wait for the slice period to end. Then tell the servo to move to the next position and wait.

I am quite sure that this is the same thing the VarSpeedServo library does.

Thanks for your help vinceherman.

I have tried to understand what the library does exactly but I did not get it properly. That's why I decided to open a topic here in the forum to reach for some support.

Here is the write function from the library with the speed parameter:

void VarSpeedServo::write(int value, uint8_t speed) {
	// This fuction is a copy of write and writeMicroseconds but value will be saved
	// in target instead of in ticks in the servo structure and speed will be save
	// there too.

  int degrees = value;

	if (speed) {
		if (value < MIN_PULSE_WIDTH) {
			// treat values less than 544 as angles in degrees (valid values in microseconds are handled as microseconds)
      		// updated to use constrain instead of if, pva
      		value = constrain(value, 0, 180);
      		value = map(value, 0, 180, SERVO_MIN(),  SERVO_MAX());    
		}
		// calculate and store the values for the given channel
		byte channel = this->servoIndex;
		if( (channel >= 0) && (channel < MAX_SERVOS) ) {   // ensure channel is valid
      		// updated to use constrain instead of if, pva
      		value = constrain(value, SERVO_MIN(), SERVO_MAX());

			value = value - TRIM_DURATION;
			value = usToTicks(value);  // convert to ticks after compensating for interrupt overhead - 12 Aug 2009

			// Set speed and direction
			uint8_t oldSREG = SREG;
			cli();
			servos[channel].target = value;  
			servos[channel].speed = speed;  
			SREG = oldSREG;   
		}
	} 
	else {
		write (value);
	}
}

What it seems to me is that the library changes the clock cycles withing a microsecond allowing the control of the servo during the pulse input. Am I right?

As for your suggestion regarding the movement, I believe that's the option I mentioned in my first message where I said I could use some "for" cycles to control the movement.
What you are suggesting is use "write" between the range I want with some delay between the funcion calls, correct? Although, as you said, the servo will always move at full speed and I want to avoid that. What I would need is some smooth movement with the control speed, exactly as I am being able with the VarSpeedServo library.

Doesn't anyone have any experience with this library in any boards besides the Uno and the Nano? A confirmation of compatibility with a Genuino 101 board would be great. :slight_smile:

Thanks for your attention!

Look at this video of my hexapod.

You can see smooth movement of the gate. And then at the end of the step, the feet 'jerk' up or down.
That jerk is a full speed movement.
The smooth step is a series of full speed movements. Just small steps. So it looks smooth.

My hexapod showing smooth movement and jerky movement

Servos do not provide any way of changing the motor speed. VarSpeedServo does exactly what vinceherman describes, moving many small steps to make up the whole movement. The end result looks smooth but is actually a series of small full-speed steps.

But I've only used it on 8-bit Nanos and ProMinis so don't know about your compatibility problems, sorry.

Steve

My guess on the incompatibility is in how VarSpeedServo sets up interrupts. But that is only a guess, not based on any real world evidence other than the fact that I do see VarSpeedServo setting up interrupts.

Question is, will the servos work with the 101s 3.3 volt outputs?

vinceherman:
Look at this video of my hexapod.

You can see smooth movement of the gate. And then at the end of the step, the feet 'jerk' up or down.
That jerk is a full speed movement.
The smooth step is a series of full speed movements. Just small steps. So it looks smooth.

My hexapod showing smooth movement and jerky movement

Dear vinceherman,

Thanks for your help and for your video :slight_smile:
The movements seems really smooth tbh, even with the steps. How exactly have you done the code? Have you put the movement inside a "for" cycle without delays? How much were your step values?

The only problem I see is this approach, is the program will be stuck inside the "for" cycle until the entire movement is completed right? That's not exactly what I need, I need the servo to move freely with a specific speed once a need value is received from the serial COM, even if the previous movement is not completed.
Any other way to implement this without a cycle? :-\

slipstick:
Servos do not provide any way of changing the motor speed. VarSpeedServo does exactly what vinceherman describes, moving many small steps to make up the whole movement. The end result looks smooth but is actually a series of small full-speed steps.

But I've only used it on 8-bit Nanos and ProMinis so don't know about your compatibility problems, sorry.

Steve

Thanks for your help slipstick.
So, like I said before, the VarSpeedServo does not use delays on the movement but smaller or bigger steps to smooth the motion, is that it?
Yeah, I have also tested the library with a Nano and Uno boards, but I would like some confirmation for the 101 too.

vinceherman:
My guess on the incompatibility is in how VarSpeedServo sets up interrupts. But that is only a guess, not based on any real world evidence other than the fact that I do see VarSpeedServo setting up interrupts.

Yes, I believe that's the problem too. During the compiling, most of the erros come from the interrupts section. Do you know if the 101 board have similiar interrupts settings as the Uno?

756E6C:
Question is, will the servos work with the 101s 3.3 volt outputs?

That's not a problem. I am using 12V servos, so I am powering them up externally. :slight_smile:

That particular gate had 200 individual slices. 100 moving backward, down on the floor, and 100 moving forward one inch above the floor.
A newer version added 20 or so slices to smooth out the end step where the foot previously jerked up or down the entire inch in a single slice.

No, there was no 'for loop' during the running of the step. No delays. Delays are evil except in setup if you have to wait for a piece of hardware to initilize.

In setup, I calculated the foot positions of each of the 200 slices in the step.
In loop, I mostly do nothing except watch the millis. After 20 millis, call a routine moves each foot to the next slice of the step.
The foot position is then run through reverse kinematics logic to set the angles of the 3 servos for a leg.
Then it writes those angles to the 3 servos for that particular leg.

In later versions I added an RC receiver to send commands. Fun with interrupts!

vinceherman:
That particular gate had 200 individual slices. 100 moving backward, down on the floor, and 100 moving forward one inch above the floor.
A newer version added 20 or so slices to smooth out the end step where the foot previously jerked up or down the entire inch in a single slice.

No, there was no 'for loop' during the running of the step. No delays. Delays are evil except in setup if you have to wait for a piece of hardware to initilize.

In setup, I calculated the foot positions of each of the 200 slices in the step.
In loop, I mostly do nothing except watch the millis. After 20 millis, call a routine moves each foot to the next slice of the step.
The foot position is then run through reverse kinematics logic to set the angles of the 3 servos for a leg.
Then it writes those angles to the 3 servos for that particular leg.

In later versions I added an RC receiver to send commands. Fun with interrupts!

Okay, thanks for your help vince :slight_smile:
I think I am getting the general ideia, but I stil have some questions regarding those slices.
On those slices you are basically choosing a new position for the servo, only that? But how much are your increments? You can only pass integer values on the "write" function right? So if you have 200 slices, you would use 200º of the servo at best, but I believe that is not what is happening on the video.

That's a doubt I still have, for example, if I have a 60º servo and I would want to go from 0 to 20º at a certain speed, with increments I will be limited to 20 increments because the function only accepts integer values. But from 0 to 60º for example I could get 60 increments. I am thinking this the wrong way? How are you exactly doing this motion?
Would be much to ask for a simple sample code? I just need the approach for one servo, just that.

Also, you said you didn't used any "for" loop but you have used for the foot positions on the setup function correct? You declared an array of positions to save the correct values?

Thanks for your assistance!

Best Regards

A few things:
Use servo.writemicroseconds rather than servo.write
This gives you finer resolution in your commands to the servo.
Writemicroseconds lets you pass a number between 1000 and 2000, where 1500 is centered, 1000 is full rotation one way and 2000 is full rotation the other way.
Go look at the library servo.write. It simply maps the degrees you pass in to microseconds and then calls writemicrosecondes.

I did use for loops in setup to initialize the foot position array. Then during the loop, when it is time to move the foot, I call a function to calculate the servo positions that put the foot there. It uses reverse kinematics. Google that and read up about it.

I will be glad to help you through some pseudo code for this. You need more than one servo per leg. I had 3 per leg. This permits steps that keep the body smooth. With only 2 servos per leg, the body bobs around during the step.

Have you purchased any hardware yet?

Oh, other thoughts:
My work resulted in the ability to walk forward. It would be trivial to also include a gait that rotated the pod.
It would need to complete the forward step and then start doing the rotate step.
I thought this was a bit clunky. I did intend to change this algorithm from a fixed array of slices for the step to one where I calculate the next foot position on the fly based on current directional input.
I never got that far before other shiny things took my attention elsewhere. (I started dating I think)

I should ask what your goals are with this project. What are you trying to do?
Make a device that can walk around and look cool? (this is as far as I got)
Make a mobile platform for some other project? (this was the original goal, we wanted a mobile platform for video processing, not on the arduino)

If you have 3 servos, you can start working on the hardware.
For proper support of the servo when bearing the weight of the pod, you want a servo holder with a bearing on the bottom.
But for just running test to wave the foot around in the air, you can use pieces of wood screwed to the servo horns.

vinceherman:
A few things:
Use servo.writemicroseconds rather than servo.write
This gives you finer resolution in your commands to the servo.
Writemicroseconds lets you pass a number between 1000 and 2000, where 1500 is centered, 1000 is full rotation one way and 2000 is full rotation the other way.
Go look at the library servo.write. It simply maps the degrees you pass in to microseconds and then calls writemicrosecondes.

I did use for loops in setup to initialize the foot position array. Then during the loop, when it is time to move the foot, I call a function to calculate the servo positions that put the foot there. It uses reverse kinematics. Google that and read up about it.

I will be glad to help you through some pseudo code for this. You need more than one servo per leg. I had 3 per leg. This permits steps that keep the body smooth. With only 2 servos per leg, the body bobs around during the step.

Have you purchased any hardware yet?

Thanks for your help vince :slight_smile:

Okay, so regarding the "writemicroseconds" the best advantage is I will have better resolution than with "write" correct? With write I will be limited by the angle of the servo (for example 180 increments) but with writemicroseconds I will have 500 increments for each side, I am right?
The only problem is I will have a lot of increments that you not have any change on the position of the servo, but it will not be noticeable due to the number of slices, correct?

Regarding the pseudo code, the application will not be the same, not even close tbh. I will have no legs and it's just one servo per mass. It's pretty straightforward, it's just a circular mass where I will vary the angle with one servo, just this. But like I said, this movement should be done with different speed values of the servo at specific times.

So, in conclusion, for this approach I should vary the increments depending on the speed I want to achieve.
For example, if I want to move the servo from 0º to 90º at full speed I just need to call the function writeMicroseconds(1500) but if I want to change the speed of the movement, I can call the function writeMicroseconds(aux) where I make increments of 5 for example until the position value, in this case until 1500 with increments of 5.

I am thinking this the proper way now?

vinceherman:
Oh, other thoughts:
My work resulted in the ability to walk forward. It would be trivial to also include a gait that rotated the pod.
It would need to complete the forward step and then start doing the rotate step.
I thought this was a bit clunky. I did intend to change this algorithm from a fixed array of slices for the step to one where I calculate the next foot position on the fly based on current directional input.
I never got that far before other shiny things took my attention elsewhere. (I started dating I think)

I should ask what your goals are with this project. What are you trying to do?
Make a device that can walk around and look cool? (this is as far as I got)
Make a mobile platform for some other project? (this was the original goal, we wanted a mobile platform for video processing, not on the arduino)

If you have 3 servos, you can start working on the hardware.
For proper support of the servo when bearing the weight of the pod, you want a servo holder with a bearing on the bottom.
But for just running test to wave the foot around in the air, you can use pieces of wood screwed to the servo horns.

Like I explained before, the application does not have anything to do with pods.
I will have 4 individual masses with one servo each for the variation of the angle. Although, the movement will be independent from each other, there is not "communication" between them.
Just imagine a mass with a servo connected to the shaft and consider each mass and servo as a isolated system.

Thanks for your assistance, I really appreciate it :slight_smile:

the application does not have anything to do with pods.

Hah! In my excitement over the subject matter, I wan injecting too much of my previous project into yours.

with writemicroseconds I will have 500 increments for each side, I am right?

Yes, you got it. And you are correct, some slices may see no new position given for a particular servo. But the overall effect will be as smooth as the resolution of the servo signal allows.

I am thinking this the proper way now?

Much better.

Throw some code at it. See if you can get behavior close to what you want.