I am trying to control two servos with an Arduino Duemilanove with servos connected to pins 8 & 9.
I have a driver program written in Visual Basic that sends two byte via the serial port to the Arduino. The values range from 0 to 100. The attached Arduino code reads the values and moves the servos to the correct position. One function of the driver program send one single pair of values (50,50) and the servos respond with no problem. Another function sends two groups of 100 pairs of values with one value equal to 0 and the other varying from 100 down to 0. Randomly both servos will move rapidily out of the normal range of positions and then continue onwards. I have check the serial data stream with my oscilloscope and there appear to be no data problems. When I check the pulses coming out of the Arduino they vary normally until the random movement occurs, then return to normal expected values.
I have been struggling to no avail for the past week or so trying to diagnose this bug and correct it. I would appreciate any help.
Thanks, Tripacer
//Fuel Tank Control program version 2 : FuelTankControl2.ino
// external program. Values range from 0 to 100
// which represents the range of tanks values from empty to full.
// Values are sent in two byte pairs; left tank first followed by right tank.
#include <Servo.h>
Servo LeftTank; // Create a seervo object to control a servo
Servo RightTank;
int angle; // variable to store servo position
int LeftTankVal;
int RightTankVal;
int LeftTankReadVal; // Converted int value
int RightTankReadVal;
int LeftTankMin = 30; // Left tank minimum value
int LeftTankMax = 125; // Left tank maximum value
int RightTankMin = 30; // Right tank minimum value
int RightTankMax = 125; // Right tank maximum value
char CommandVal; // Input command value
byte TankVal[2]; // Left and right tank input values
int LeftTankRange; // Left tank Min to Max servo movement range
int RightTankRange; // Range for right tank
int i; // Array index
void setup()
{
LeftTank.attach(8); // attach the servo to pin 9 to the servo object
RightTank.attach(9); // attach the servo to pin 10
// Set initial servo positions **** if possible in setup block ****
LeftTank.write(LeftTankMin);
RightTank.write(RightTankMin);
LeftTankRange = LeftTankMax - LeftTankMin; // Calculate range value
RightTankRange = RightTankMax - RightTankMin;
Serial.begin(9600); // Start and configure servial communications
}
void loop()
{
if (Serial.available() > 0 )
{
TankVal[0] = Serial.read();
TankVal[1] = Serial.read();
// This section zeros the value and converts byte value to int
LeftTankReadVal = 0;
LeftTankReadVal = LeftTankReadVal + TankVal[0];
RightTankReadVal = 0;
RightTankReadVal = RightTankReadVal + TankVal[1];
}
// End data read
// Calculate servo positions - rounds to integer value
LeftTankVal = (LeftTankRange * LeftTankReadVal) / 100;
RightTankVal = (RightTankRange * RightTankReadVal) / 100;
// Move servo to new position
LeftTank.write(LeftTankVal);
RightTank.write(RightTankVal);
delay(20); // waits 20ms between servocommands
} // end of program
Thanks for the suggestions and comments. However, I have always powered the servos form a separate external power supply with the power supply and the Arduino grounds connect to a common bus. This has no effect on the problem.
Also reading the data via a while loop or as outlined in the code above does not change the problem. Watching the output for the servo signal coming from an Arduino pin shows that a larger time pulse is sent to the servo for positioning.
The data sending programing is displaying the values sent to the serial port, and the glitches randomly occur at different points in the sequence. I suspect some type of timing issue but cannot seem to run it down.
Tripacer:
Also reading the data via a while loop or as outlined in the code above does not change the problem.
If you've changed your sketch to correct the serial port handling issue that PaulS pointed out, I suggest you post your updated sketch; it's just conceivable that it isn't perfect yet.
Sorry about that. Here is the current code. Still no difference. I have even tried to change the delay values in the loop. Does anyone know if the servo.write function automatically refresh the servoe signal every 25 ms? Where can I find more documentation about that library other than on Arduino.cc?
Thanks, Tripacer
//Fuel Tank Control program version 2a : FuelTankControl2a.ino
// Input values come from external program. Values range from 0 to 100
// which represents the range of tanks values from empty to full.
// Values are sent in two byte pairs; left tank first followed by right tank.
#include <Servo.h>
Servo LeftTank; // Create a seervo object to control a servo
Servo RightTank;
int LeftTankVal;
int RightTankVal;
int LeftTankReadVal; // Converted int value
int RightTankReadVal;
int LeftTankMin = 30; // Left tank minimum value
int LeftTankMax = 125; // Left tank maximum value
int RightTankMin = 30; // Right tank minimum value
int RightTankMax = 125; // Right tank maximum value
char CommandVal; // Input command value
byte TankVal[2]; // Left and right tank input values
int LeftTankRange; // Left tank Min to Max servo movement range
int RightTankRange; // Range for right tank
int i; // Array index
void setup()
{
LeftTank.attach(8); // attach the servo to pin 9 to the servo object
RightTank.attach(9); // attach the servo to pin 10
// Set initial servo positions **** if possible in setup block ****
LeftTank.write(LeftTankMin);
RightTank.write(RightTankMin);
LeftTankRange = LeftTankMax - LeftTankMin; // Calculate range value
RightTankRange = RightTankMax - RightTankMin;
Serial.begin(9600); // Start and configure servial communications
}
void loop()
{
i = 0; // Initialize index counter and read both values
while (Serial.available() != 0 )
{
TankVal[i] = Serial.read();
i++;
}
// End data read loop
// This section zeros the value and converts byte value to int
LeftTankReadVal = 0;
LeftTankReadVal = LeftTankReadVal + TankVal[0];
RightTankReadVal = 0;
RightTankReadVal = RightTankReadVal + TankVal[1];
// Calculate servo positions
LeftTankVal = (LeftTankRange * LeftTankReadVal) / 100;
RightTankVal = (RightTankRange * RightTankReadVal) / 100;
// Move servo to new position
LeftTank.write(LeftTankVal);
delay(10);
RightTank.write(RightTankVal);
delay(10);
// delay(20); // waits 20ms between servocommands -
// Does Servo library automatically refresh the servo signal every 25ms?
} // end of program
simple servo test code for the serial monitor for two servos. You can try this and see if the servos still operate in an erratic manner.
// zoomkat 12-13-11 serial servo (2) test
// for writeMicroseconds, use a value like 1500
// for IDE 1.0
// Powering a servo from the arduino usually DOES NOT WORK.
// two servo setup with two servo commands
// send eight character string like 15001500 or 14501550
// use serial monitor to test
#include <Servo.h>
String readString, servo1, servo2;
Servo myservo1; // create servo object to control a servo
Servo myservo2;
void setup() {
Serial.begin(9600);
myservo1.attach(6); //the pin for the servo control
myservo2.attach(7);
Serial.println("two-servo-test-1.0"); // so I can keep track of what is loaded
}
void loop() {
while (Serial.available()) {
delay(3); //delay to allow buffer to fill
if (Serial.available() >0) {
char c = Serial.read(); //gets one byte from serial buffer
readString += c; //makes the string readString
}
}
if (readString.length() >0) {
Serial.println(readString); //see what was received
// expect a string like 07002100 containing the two servo positions
servo1 = readString.substring(0, 4); //get the first four characters
servo2 = readString.substring(4, 8); //get the next four characters
Serial.println(servo1); //print to serial monitor to see parsed results
Serial.println(servo2);
int n1 = servo1.toInt();
int n2 = servo2.toInt();
Serial.println("the numbers are :");
Serial.println(n1); //print to serial monitor to see number results
Serial.println(n2);
myservo1.writeMicroseconds(n1); //set servo position
myservo2.writeMicroseconds(n2);
readString="";
}
}
Now, why you feel it necessary to set the value to 0 and then add a new value to it escapes me, but you did not read two ints from the serial port. You read two characters.