loading
 
Oscillations
Dave West from United States  [16 posts]
7 years
I've found a RR script that sends a balls COGX serially to an Arduino controlling a Sabertooth in RC/Microcontroller mode. I'm not using the Sabertooth module because I need the Arduino to process other inputs.
Anyway, the robot is getting the blobs x position, and works somewhat, but oscillates around 0 and never settles. I've tried increasing the offset, but don't want to bring ti too high. My camera seems fast enough about@ 25 fps. This is the Arduino sketch:

#include <Servo.h> // Include the servo library

Servo myServo; // Create a new servo object
char incomingData[4] = {
  0, 0, 0, 0}; // A buffer to store the ASCII value read in from the serial port
int distance = 0; // The distance of the object from the center of the screen
int currentAngle = 90; // The current angle of the servo
int i = 0; // counter

void setup(){
  Serial.begin(9600); // Open the serial port with a 9600 baud rate
  Serial.println("Serial port ready"); // Print on screen
  myServo.attach(9); // Attach the servo signal line to pin 9
  myServo.write(currentAngle); // Set the starting angle at 90 degrees
}

void loop(){
  // Wait for data to become available at the serial port
  if (Serial.available()){
    // Get the data coming through the serial port and store it in the buffer
    while (i < 4){
      incomingData[i] = Serial.read(); // Assign the input value to the incomingData buffer
      i++; // Increment the counter
    }

    distance = atoi(incomingData); // Convert ASCII to Int

    // If the distance is negative then add 15 to the currentAngle and update the servo, and vise versa to combat oscillation
    if (distance < -15){
      currentAngle++;
      currentAngle = constrain(currentAngle, 83, 97); // Constrain the value of currentAngle to within 83-97degrees. Keeps motors slow for now
      myServo.write(currentAngle);
    }
    else if (distance > 15){
      currentAngle--;
      currentAngle = constrain(currentAngle, 83, 97); // Constrain the value of currentAngle to within 0-180 degrees
      myServo.write(currentAngle);
    }
  }

  i = 0; // Reset the counter
  delay(5);
}

Thanks for looking.

Dave
Anonymous 7 years
Dave,

Do you mean that the robot tries to move such that the X coordinate goes to 0 but it never quite gets there? If so, then that is perfectly normal. It is very unlikely that most robots can move with such precision as to change the image by 1 pixel. And even if it did the COG module result will depend on the cameras input which will NEVER give you exactly (and I mean pixel to pixel) the same image even with a completely steady scene. If you look closely you will see pixels are still slightly changing even in a steady scene. Thus you will always have some error from the camera sampling of the scene and the lack of precision of the robot moving. Or am I not understanding your question correctly?

STeven.
Dave West from United States  [16 posts] 7 years
STeven,


My screen is 160x120. I've got a VB script that takes the COGX and converts it to a -80 to 80 range. This new variable is sent to the Arduino and converted to an int called 'distance'. I've given it a 30 pixel deadzone, -15 to 15 so these values around the center are treated as 0 and the motors should stop. This is not the case. If the target moves from -80 to center (0), robot continues to turn until it reaches +15, and then reverses direction and will continue until -15 when it reverses again. It never settles.
RR correctly sends a 0 when the target is centered. I'm thinking this is an Arduino programming problem. This video may explain better...
http://www.youtube.com/watch?v=URaHDTsQk2Y

Thanks,

Dave
Anonymous 7 years
Dave,

Ah,ok, so you are having issues with the Arduino code instead ... in order to get the effect that you are looking for you will have to replace the code with

// If the distance is negative then add 15 to the currentAngle and update the servo, and vise versa to combat oscillation
    if (distance < -15){
      currentAngle++;
      currentAngle = constrain(currentAngle, 83, 97); // Constrain the value of currentAngle to within 83-97degrees. Keeps motors slow for now
      myServo.write(currentAngle);
    }
    else if (distance > 15){
      currentAngle--;
      currentAngle = constrain(currentAngle, 83, 97); // Constrain the value of currentAngle to within 0-180 degrees
      myServo.write(currentAngle);
    }
    else
      myServo.write(90);
  

Basically add the last 'else' statement onto that conditional. Right now the code only changes when the distance is + or -  15 and the servo will not change its heading unless told to. When you write the 90 after the two angle checks that should tell the servo to now go straight.

(Watch the }'s when pasting this code over what you have.)

STeven.
Dave West from United States  [16 posts] 7 years
Steven,

Thanks so much! That did it. I've been scratching my head for a few days on that one. It jerks and lurches a bit when turning, but it does stay straight when centered. One more question. Now I'd like to add forward and backward movement depending on COG_BOX_SIZE. After I add the variable to the serial module to send, I'm at a loss at how to separate it from the COGX on the Arduino end (COGX info goes on 1 Sabertooth input and BOX_SIZE goes on the other.).

Thanks again,
Dave
Anonymous 7 years
Dave,

Note that we are not arduino experts here and these kinds of posts are best left to other forums.

In a nutshell, you would use the value of COG_BOX_SIZE to determine if you will send negative or positive values to the sabertooths. I.e. if COG_BOX_SIZE is > say 20 then move backwards, otherwise move forward. In terms of your previous script that would be sending a -90 as apposed to a 90. (we are making a big assumption about what you have connected to pin 9 and what the servo class in the arduino is doing ... again we don't program that platform!)

I'm also not sure why you are directly sending COGX and COG_BOX_SIZE directly to the sabertooth as I can't imagine they would really be meaningful to do so. Your arduino program has to interpret those values and then either convert them or assign new values to actually send to the sabertooth. Just as your above script is doing.

STeven.
Dave West from United States  [16 posts] 7 years
Steven,

Sorry if I simplified too much. As I did with RR's COG_X data, I will have to convert it into terms the Sabertooth can deal with. I'll research a bit more and ask on the Arduino forum if need be.

I'll post a link when everythings working.

Thanks,

Dave

This forum thread has been closed due to inactivity (more than 4 months) or number of replies (more than 50 messages). Please start a New Post and enter a new forum thread with the appropriate title.

 New Post   Forum Index