Hi, I'm working on a project involving multiple servos which I would like to rotate back and forth at varying speeds and positions. I can use the write() and writeMicroseconds() commands for the positions (between 0 and 180) but I have no idea how to control the speed at which they will get to these positions. And I don't want to use a delay between movements. I know there are ways to control the speed of running motors but, not for servos. Can you help me? thanks much.
I know there are ways to control the speed of running motors but, not for servos. Can you help me? thanks much.
The specific servo is the only thing that can determine the fastest speed that it can move, say from 0-180 degrees. Some servos are faster then others and the amount of physical load on the servo can also effect it's maximum speed of movement. Servo speed is a specification often listed in a servo's datasheet.
What you can do under Arduino software control is slow down the servos speed, but only by making smaller moves with each analogWrite command and/or adding delays between analogWrite commands.
Hello I'm back to my arduino after assisting a photoshoot of the oil spill in the gulf...anyway I found this video which is pretty much exactly what I want to do. Sorry for the bad music, but you can see the servos here have varying speeds. Can I reproduce what this guy did with only the servo.write command?
I just came across this from Google. I'm working on figuring out a similar issue and was wondering if this solved the problem.
here is the code I currently have:
// Controlling a servo position using a temperature sensor
// by Michal Rinott <http://people.interaction-ivrea.it/m.rinott>
// edited 5-12-2010 by Will Lyon to include base setting for servo if voltage not detected on pin 7
// edited again 7-4-2010 by crenn to simplify the code a little
// edited yet again 7-5-2010 by crenn to add features
// edited again 7-21-2010 by Will Lyon - recalibrated servo positions
// edited again 10-15-2010 by crenn - slow down servo when computer is off
#include <Servo.h>
Servo myservo; // create servo object to control a servo
//Constants
const unsigned char CONTROL = 5; // digital pin used to detect if the system is on or off
const unsigned char TEMP_SENSOR = 0; // analog pin used to connect the temp sensor
const unsigned char MAX_SAMPLES = 10;
const unsigned char OFF_POSITION = 180;
const unsigned char LOW_POSITION = 160;
const unsigned char HIGH_POSITION = 80;
//Main global varibles
char trigger = 0; // varible used to store the control pin value
unsigned int val = OFF_POSITION; // variable to read the value from the analog pin
unsigned int updateAvgtemp(){
static int history[MAX_SAMPLES]={0};
static unsigned char lastHist=0;
static unsigned char numHist=0;
unsigned int temp=0;
unsigned char counter=0;
unsigned char arcount=0;
history[lastHist] = analogRead(TEMP_SENSOR);
if(numHist<MAX_SAMPLES)
++numHist;
arcount=lastHist;
++lastHist;
if(lastHist>=MAX_SAMPLES)
lastHist=0;
temp=0;
counter=0;
do{
temp+=history[arcount];
arcount--;
if(arcount>MAX_SAMPLES)
arcount=(MAX_SAMPLES-1);
counter++;
}while(counter < numHist);
return (temp/numHist);
}
void setup()
{
pinMode (CONTROL, INPUT); // sets the control pin to input
myservo.attach(9); // attaches the servo on pin 9 to the servo object
digitalWrite(CONTROL, LOW); // ensure internal pullup resistor is disabled.
}
void loop()
{
trigger = digitalRead(CONTROL); // read input of pin CONTROL and store it
if (trigger == HIGH){ // reads if pin CONTROL, if true, do this:
val = updateAvgtemp(); // read the value of the temp sensor (value with range of 1024)
val = map(val, 350, 700, LOW_POSITION, HIGH_POSITION); // scale it to use it with the servo (value between 160 and 80)
myservo.write(val); // sets the servo position according to the scaled value
}
else {
while(val<OFF_POSITION){
val++;
myservo.write(val);
delay(100);
}
myservo.write(OFF_POSITION); // sets servo position to 180 if above statment is false
}
delay(125); // wait 25ms for the servo to move to it's new position and also 100ms until it gets the new value
}
What I want, is at the end, when the value for control pin 5 is false, for the servo to slowly go to its off position (170). How could I introduce something similar to the above code to make this happen?
How slow do you want the servo to move and do you want it to move at a constant slow speed? How precise do the speed regulation need to be? The answers might be in your code, but I don't want to bother with working through it at the moment.
I want it to take approx. 30 seconds to go from it's full open position to the closed position. in this vid you can see what I've got this code running, and how fast it opens/closes:
Ok, I'll going to put up a modification of the standard Servo Library which adds a method slowmove, where you can add speed parameter. Then you just have to replace your myservo.write (xxx) with myservo.slowmove (xxx, speed).
I wanted to polish that library a little before publishing, but it might just do what you need in its current state.
I'll post a link once it's up - I hope it will be today.
I want it to take approx. 30 seconds to go from it's full open position to the closed position. in this vid you can see what I've got this code running, and how fast it opens/closes:
You should be able to incremental servo positioning like in the servo sweep demo sketch to slowly open and close the loovers.
Here's the VarSpeedServo library. It's a clone of the Servo Library with one additional function slowmove which is a replacement of write with an additional speed parameter.
Speed=0: Write is used, full speed
Speed=1: Slowest
Speed=255: Fastest. With the servos I have, above 127 I couldn't see any difference to write because the mechanical speed was the limiting factor.
Everything that works with Servo works with VarSpeedServo too. Important: Don't use Servo.h and VarSpeedServo.h at the same time, it will create conflicts.
// Controlling a servo position using a temperature sensor
// by Michal Rinott <http://people.interaction-ivrea.it/m.rinott>
// edited 5-12-2010 by Will Lyon to include base setting for servo if voltage not detected on pin 7
// edited again 7-4-2010 by crenn to simplify the code a little
// edited yet again 7-5-2010 by crenn to add features
// edited again 7-21-2010 by Will Lyon - recalibrated servo positions
// edited again 10-15-2010 by crenn - slow down servo when computer is off
// edited again 10-15-10 by Will Lyon, with new VarSpeedServo library to slow servo movement
// VarSpeedServo library from Korman on Arduino.cc forums
#include <VarSpeedServo.h>
VarSpeedServo myservo; // create variable speed servo object to control a servo
//Constants
const unsigned char CONTROL = 5; // digital pin used to detect if the system is on or off
const unsigned char TEMP_SENSOR = 0; // analog pin used to connect the temp sensor
const unsigned char MAX_SAMPLES = 10; // number of temp sensor samples to average
const unsigned char OFF_POSITION = 180; // position of servo when no voltage is detected on pin 5
const unsigned char LOW_POSITION = 155; // lowest servo position for lowest temp
const unsigned char HIGH_POSITION = 120; // highest servo position for highest temp
//Main global varibles
char trigger = 0; // varible used to store the control pin value
unsigned int val = OFF_POSITION; // variable to read the value from the analog pin
unsigned int updateAvgtemp(){
static int history[MAX_SAMPLES]={0};
static unsigned char lastHist=0;
static unsigned char numHist=0;
unsigned int temp=0;
unsigned char counter=0;
unsigned char arcount=0;
history[lastHist] = analogRead(TEMP_SENSOR);
if(numHist<MAX_SAMPLES)
++numHist;
arcount=lastHist;
++lastHist;
if(lastHist>=MAX_SAMPLES)
lastHist=0;
temp=0;
counter=0;
do{
temp+=history[arcount];
arcount--;
if(arcount>MAX_SAMPLES)
arcount=(MAX_SAMPLES-1);
counter++;
}while(counter < numHist);
return (temp/numHist);
}
void setup()
{
pinMode (CONTROL, INPUT); // sets the control pin to input
myservo.attach(9, HIGH_POSITION, LOW_POSITION); // attaches the servo on pin 9 to the servo object
digitalWrite(CONTROL, LOW); // ensure internal pullup resistor is disabled.
}
void loop()
{
trigger = digitalRead(CONTROL); // read input of pin CONTROL and store it
if (trigger == HIGH){ // reads if pin CONTROL, if true, do this:
val = updateAvgtemp(); // read the value of the temp sensor (value with range of 1024)
val = map(val, 350, 700, LOW_POSITION, HIGH_POSITION); // scale it to use it with the servo (value between 160 and 120)
myservo.slowmove(val, 255); // sets the servo position according to the scaled value
}
else {
while(val<OFF_POSITION){
val++;
myservo.slowmove(val, 255);
delay(100);
}
myservo.slowmove(OFF_POSITION, 1); // sets servo position to 180 if above statment is false, at slowest speed
}
delay(125); // wait 25ms for the servo to move to it's new position and also 100ms until it gets the new value
}
it works great, I just need to lube my hinges etc, they're a little sticky.
I also had to change the high position to 120 from 90, otherwise it wanted to open the vents too far and actually popped the pins out of the first 2 flaps lol.
I'll see tomorrow morning (when the room and computer have cooled off) about the general operation, but it definitely closes slower!
Instead of Speed 255 use either Speed 0 or myservo.write. Internally Speed 0 just calls write and doesn't do anything special. Those commands are more direct and tell the servo to go as fast as it can.
alright so after some recalibration (still not sure why it was needed)
this:
const unsigned char OFF_POSITION = 180; // position of servo when no voltage is detected on pin 5
const unsigned char LOW_POSITION = 155; // servo position for lowest temp
const unsigned char HIGH_POSITION = 120; // servo position for highest temp
is now this:
const unsigned char OFF_POSITION = 180; // position of servo when no voltage is detected on pin 5
const unsigned char LOW_POSITION = 160; // servo position for lowest temp
const unsigned char HIGH_POSITION = 135; // servo position for highest temp
but originally (before the "VarSpeedServo" library) it was this:
const unsigned char OFF_POSITION = 180; // position of servo when no voltage is detected on pin 5
const unsigned char LOW_POSITION = 160; // servo position for lowest temp
const unsigned char HIGH_POSITION = 90; // servo position for highest temp
:-?
and the current complete code:
// Controlling a servo position using a temperature sensor
// by Michal Rinott <http://people.interaction-ivrea.it/m.rinott>
// edited 5-12-2010 by Will Lyon to include base setting for servo if voltage not detected on pin 7
// edited again 7-4-2010 by crenn to simplify the code a little
// edited yet again 7-5-2010 by crenn to add features
// edited again 7-21-2010 by Will Lyon - recalibrated servo positions
// edited again 10-15-2010 by crenn - slow down servo when computer is off
// edited again 10-15-2010 by Will Lyon, with new VarSpeedServo library to slow servo movement
// VarSpeedServo library from Korman on Arduino.cc forums
#include <VarSpeedServo.h>
VarSpeedServo myservo; // create variable speed servo object to control a servo
//Constants
const unsigned char CONTROL = 5; // digital pin used to detect if the system is on or off
const unsigned char TEMP_SENSOR = 0; // analog pin used to connect the temp sensor
const unsigned char MAX_SAMPLES = 10; // number of temp sensor samples to average
const unsigned char OFF_POSITION = 180; // position of servo when no voltage is detected on pin 5
const unsigned char LOW_POSITION = 160; // servo position for lowest temp
const unsigned char HIGH_POSITION = 135; // servo position for highest temp
//Main global varibles
char trigger = 0; // varible used to store the control pin value
unsigned int val = OFF_POSITION; // variable to read the value from the analog pin
unsigned int updateAvgtemp(){
static int history[MAX_SAMPLES]={0};
static unsigned char lastHist=0;
static unsigned char numHist=0;
unsigned int temp=0;
unsigned char counter=0;
unsigned char arcount=0;
history[lastHist] = analogRead(TEMP_SENSOR);
if(numHist<MAX_SAMPLES)
++numHist;
arcount=lastHist;
++lastHist;
if(lastHist>=MAX_SAMPLES)
lastHist=0;
temp=0;
counter=0;
do{
temp+=history[arcount];
arcount--;
if(arcount>MAX_SAMPLES)
arcount=(MAX_SAMPLES-1);
counter++;
}while(counter < numHist);
return (temp/numHist);
}
void setup()
{
pinMode (CONTROL, INPUT); // sets the control pin to input
myservo.attach(9, HIGH_POSITION, LOW_POSITION); // attaches the servo on pin 9 to the servo object
digitalWrite(CONTROL, LOW); // ensure internal pullup resistor is disabled.
}
void loop()
{
trigger = digitalRead(CONTROL); // read input of pin CONTROL and store it
if (trigger == HIGH){ // reads if pin CONTROL, if true, do this:
val = updateAvgtemp(); // read the value of the temp sensor (value with range of 1024)
val = map(val, 350, 700, LOW_POSITION, HIGH_POSITION); // scale it to use it with the servo (value between 160 and 120)
myservo.slowmove(val, 0); // sets the servo position according to the scaled value
}
else {
while(val<OFF_POSITION){
val++;
myservo.slowmove(val, 0);
delay(100);
}
myservo.slowmove(OFF_POSITION, 1); // sets servo position to 180 if above statment is false, at slowest speed
}
delay(125); // wait 25ms for the servo to move to it's new position and also 100ms until it gets the new value
}
The degrees for write are always relative to the values you pass in the attach function. If you don't pass any values, the defaults of the library will be taken. So in this case, always pass them.
The values you use for attach are pure garbage if you're using a standard RC-servo. They should be the number of microseconds for the low and high positions (usually 1000 and 2000).
As an alternative, use microsecond values for write or slow-move. Those bypass the conversion magic an permit a better control. Usual values are from 1000 to 2000.