I need help and insight to design a way to control several servo's through the Arduino chip. I found this code and it's been quite useful to me. The code allows me to input numbers 0-9 through the Serial Monitor and moves the servo (unless I've completely misunderstood the code, which I most likely did :P). However it doesn't seem to allow me to control more than servo. What I'm aiming at is getting a setup that would control several servo's individually, but just like how the posted code did (Pressing 0-9 and moving the servo to a certain positions. My programming skills are horrifying (in the bad way), so any suggestions or help would be fantastic.
I'm currently using the Arduino's 5v port to power the Servo
I have tried to use an external power supply, but it makes the Servo unresponsive.
The external power supply outputted about 5v as well
OS: Windows 7
/* Servo Motors
* ------------
*
* This program controls 2 servo motors through sending commands over
* the serial port. The motors will be connected to pins 2 and 3. It
* motors will be controlled with a single byte. The first nibble will
* control the motor, while the second will control the postion. Thus
* each motor will have 16 positions.
*
*
* (cleft) 2006 David Cuartielles for K3, Sweden
* http://www.arduino.cc
*
* @idea: T. Igoe, J. Gray
* @code: T. Igoe, J. Gray, D. Cuartielles
* @PD patch: D. Cuartielles
*
*/
int servoPinL = 2; // Control pin for servo motor - L
int servoPinR = 3; // Control pin for servo motor - R
int pulseL = 0; // Amount to pulse the servoL
int pulseR = 0; // Amount to pulse the servoR
int delayValueMax = 20000; // the 2 millisecond maxiumum pulse range for the servo
int delayValue = 20000; // the actual value the code should wait, determined later
int analogValue = 0; // the value returned from the analog sensor
int analogPin = 0; // the analog pin that the sensor's on
char c, servoNumber, servoValue;
void setup(void)
{
pinMode(servoPinL, OUTPUT); // Set servo pins as an output pins
pinMode(servoPinR, OUTPUT);
pulseL = 1000; // Set the motor position values to the minimum
pulseR = 1000;
Serial.begin(9600);
}
void loop(void)
{
c = Serial.read();
if (c != -1)
{
servoNumber = (c & 0xF0) >> 4; // servo ID is in high nibble
servoValue = (c & 0x0F); // servo angle is in low nibble
if (servoNumber%2 == 0) pulseL = (servoValue*62) + 1000; // make a pulse 1000-2000 us
else if (servoNumber%2 == 1) pulseR = (servoValue*62) + 1000; // make a pulse 1000-2000 us
// print values on the screen
// for a terminal window
//printString("\n\r Numer: ");
//printInteger(servoNumber%2);
//printString(" - Value: ");
//printInteger(servoValue);
// print values on the screen
// for debugging in PD
Serial.write(c);
}
digitalWrite(servoPinL, HIGH); // Turn the L motor on
delayMicroseconds(pulseL); // Length of the pulse sets the motor position
digitalWrite(servoPinL, LOW); // Turn the L motor off
digitalWrite(servoPinR, HIGH); // Turn the R motor on
delayMicroseconds(pulseR); // Length of the pulse sets the motor position
digitalWrite(servoPinR, LOW); // Turn the R motor off
delayValue = delayValueMax - pulseL - pulseR; // determine how much time you have before the 20 ms is over...
delayMicroseconds(delayValue); // 20 millisecond delay is needed between pulses to keep the servos in sync
}
You need to connect the ground of the external supply to the ground of the arduino.
Worked successfully
You need to send two numbers, the first one gives the servo number and the second the position.
Correct me if I'm wrong, but should I be using the Serial monitor to input the numbers? I've tried entering in two numbers on the same line like "39", "35", or with a space in between like "2 1", but both motors move into the last corresponding digit. For example when I input "38" both servos move to position 8.
Franky that servo code is over five years old. The servo library that is distributed with Arduino can control up to 12 servos on a standard board. This is a test sketch you can use to control any of the servos attached:
/*
* Servo serial tester
*
* Command a servo by entering a numeric value for the angle followed by a letter to identify the servo
* where 'a' is the first servo, 'b' the second and so on
* '*' commands all servos
* '+' sweeps all servos in one direction and '-' sweeps then in the other direction
*/
#include <Servo.h>
const int NBR_SERVOS = MAX_SERVOS; // the number of servos, up to 48 for Mega, 12 for other boards
const int FIRST_SERVO_PIN = 2;
Servo Servos[NBR_SERVOS] ; // max servos is 48 for mega, 12 for other boards
void setup()
{
Serial.begin(9600);
for(int i=0; i < NBR_SERVOS; i++)
Servos[i].attach(FIRST_SERVO_PIN +i);
delay(2000);
Serial.print(" Initialized ");
Serial.print(NBR_SERVOS,DEC);
Serial.println(" Servos");
}
void loop()
{
static int pos = 0;
if ( Serial.available())
{
char ch = Serial.read();
if(ch >= '0' && ch <= '9') // is ch a number?
pos = pos * 10 + ch - '0'; // yes, accumulate the value
else if(ch >= 'a' && ch <= 'a'+ NBR_SERVOS) // is ch a letter for one of our servos?
{
Servos[ch - 'a'].write(pos); // yes, save the position in the position array
pos = 0;
int channel = ch - 'a';
int angle = Servos[channel].read();
Serial.print("Servo on pin ");
Serial.print(FIRST_SERVO_PIN + channel, DEC);
Serial.print(": angle = ");
Serial.println(angle,DEC);
}
else if (ch == '*')
{
// position all the servos
for(int i=0; i < NBR_SERVOS; i++)
Servos[i].write(pos);
pos = 0;
}
else if (ch == '+')
{
// sweep all servos from 0 to 180
for(int angle = 0;angle < 180; )
{
for(int i=0; i < NBR_SERVOS; i++)
{
Servos[i].write(angle);
}
Serial.print("Angle = ");
Serial.println(angle,DEC);
++angle;
delay(20);
}
pos = 0;
}
else if (ch == '-')
{
// sweep all servos from 180 to 0
for(int angle = 180;angle >= 0; )
{
for(int i=0; i < NBR_SERVOS; i++)
{
Servos[i].write(angle);
}
angle = Servos[0].read();
Serial.print("Angle = ");
Serial.println(angle,DEC);
--angle;
delay(20);
}
pos = 0;
}
}
}
If the servos don't work, check that you have the grounds connected correctly and are suppllying enough power for all the servos.
Your code worked perfectly mem, thank you so much! Is it possible to macro angle commands or write up something in your code that would allow me to macro angle positions for the servo's? Just like the sweep function that was included?