Pages: [1]   Go Down
Author Topic: Glitches with Arduino and servo control  (Read 841 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 3
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Code:
//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
« Last Edit: May 20, 2012, 10:48:23 pm by Tripacer » Logged

0
Offline Offline
Tesla Member
***
Karma: 141
Posts: 9470
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

A typical newbie mistake is trying to power the servos from the arduino instead of a seperate power supply.
Logged

Consider the daffodil. And while you're doing that, I'll be over here, looking through your stuff.   smiley-cool

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 291
Posts: 25898
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

...and another is to forget to have common grounds.
Logged

"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 601
Posts: 48569
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

And a third is to assume that serial data transmission is guaranteed to result in all data being transferred.

And a fourth is this classic:
Code:
  if (Serial.available() > 0 )
  {
   
    TankVal[0] = Serial.read();
    TankVal[1] = Serial.read();
See if there is at least one byte available, then read both of them. For this, you need to whack yourself with a clue-by-four.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 3
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.

Thanks again smiley
Logged

UK
Offline Offline
Shannon Member
****
Karma: 223
Posts: 12579
-
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


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.
Logged

I only provide help via the forum - please do not contact me for private consultancy.

Offline Offline
Newbie
*
Karma: 0
Posts: 3
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Code:
//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
Logged

0
Offline Offline
Tesla Member
***
Karma: 141
Posts: 9470
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.

Code:
// 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="";
  }
}

Logged

Consider the daffodil. And while you're doing that, I'll be over here, looking through your stuff.   smiley-cool

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 601
Posts: 48569
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
  while (Serial.available() != 0 )
  {
      TankVal[i] = Serial.read();
      i++; 
   }
Suppose you read two characters.

Code:
    LeftTankReadVal = 0;
    LeftTankReadVal = LeftTankReadVal + TankVal[0];
    RightTankReadVal = 0;
    RightTankReadVal = RightTankReadVal + TankVal[1];
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.

Code:
    LeftTank.write(LeftTankVal);
    delay(10);
    RightTank.write(RightTankVal);
    delay(10);
Why are you delaying BETWEEN moving one side and moving the other side?
Logged

Pages: [1]   Go Up
Jump to: