Hello,
I'm currently working on an obstacle avoiding robot using an Arduino Uno. The robot is built and I though I had the programming correct, but it has to drive wheels which are continuous rotation servos. Everything seems to be working fine, until it's supposed to go in a straight line, then one servo will spin in one direction and the other will spin in the other direction, making it just do circles.
Here is the code:
#include //include Servo library
const int RForward = 0;
const int RBackward = 180;
const int LForward = RBackward;
const int LBackward = RForward;
const int RNeutral = 90;
const int LNeutral = 90; //constants for motor speed
const int pingPin = 7;
const int dangerThresh = 10; //threshold for obstacles (in cm)
int leftDistance, rightDistance; //distances on either side
Servo panMotor;
Servo leftMotor;
Servo rightMotor; //declare motors
long duration; //time it takes to recieve PING))) signal
void setup() {
rightMotor.attach(11);
leftMotor.attach(10);
panMotor.attach(6); //attach motors to proper pins
panMotor.write(90); //set PING))) pan to center
}
void loop() {
int distanceFwd = ping();
if (distanceFwd > dangerThresh) //if path is clear
{
leftMotor.write(LForward);
rightMotor.write(RForward); //move forward
delay(100);
} else //if path is blocked
{
leftMotor.write(LNeutral);
rightMotor.write(RNeutral);
panMotor.write(0);
delay(500);
rightDistance = ping(); //scan to the right
delay(500);
panMotor.write(180);
delay(700);
leftDistance = ping(); //scan to the left
delay(500);
panMotor.write(90); //return to center
delay(100);
compareDistance();
}
}
void compareDistance() {
if (leftDistance > rightDistance) //if left is less obstructed
{
leftMotor.write(LBackward);
rightMotor.write(RForward); //turn left
delay(500);
} else if (rightDistance > leftDistance) //if right is less obstructed
{
leftMotor.write(LForward);
rightMotor.write(RBackward); //turn right
delay(500);
} else //if they are equally obstructed
{
leftMotor.write(LForward);
rightMotor.write(RBackward); //turn 180 degrees
delay(1000);
}
}
long ping() {
// Send out PING))) signal pulse
pinMode(pingPin, OUTPUT);
digitalWrite(pingPin, LOW);
delayMicroseconds(2);
digitalWrite(pingPin, HIGH);
delayMicroseconds(5);
digitalWrite(pingPin, LOW);
//Get duration it takes to receive echo
pinMode(pingPin, INPUT);
duration = pulseIn(pingPin, HIGH);
//Convert duration into distance
return duration / 29 / 2;
}
I've tried to do my best with showing this code. As far as I knew, I had to highlight it all and then click the button, which I did. So hopefully that's all good.
The right side continuous rotation server (right side as you're in the vehicle) is connected to pin 10.
The left side continuous rotation server is connected to pin 11
The pan motor servor (which the PING sensor is attached to) is connected to pin 6
The PING sensor is connected to pin 7
I don't know if this will help, but I've included a very shrewd representation of the connection;
I'm trying my best to make this as apporpritate for this forum as possible. If I've made any mistakes, please just let me know and I will try to fix it.
The main thing I'm looking for is to see if anyone can look at the code and see why both of the continuous servos would be operating in differnt directions when they're supposed to be going straight.
Hmmmm. I can see NO attempt you have made to debug your program. I am looking for places where you have serial.Print() the variable values used in your logic, but do not see any such code.
Best to try to debug your own program before asking someone else to do it, don;t you think?
If it came across as me trying to get others to do my work for me, I apologize. That was not the intent. I'm very new to this so there is a lot I don't know and I'm trying to teach myself. So I'm only trying to get helpful suggestions about the correct course to take.
The only method of debugging I know is to click on the "verify" tab. When I do that I get the message:
Exit status 1
Compilation error: #include expects "FILENAME" or .
So now I have two questions, if you don't mind answering them. What does the above error mean.
My second questions is when you stated "I am looking for places where you have serial.Print() the variable values used in your logic, but do not see any such code"
What do you mean by that and what can I do to remedy that?
Welcome to our forum.
Thank you for posting your code properly. Good job.
Continuous servos use the servo signal to control the speed and direction of a gear motor. Ideally a pulse duration of 1500us (90 degrees) will stop the servo, a pulse width of 2000us (180 degrees) will make the motor rotate forward at full speed and a pulse width of 1000us (0 degrees) will make the motor rotate backward at full speed.
Most servos will have a stop number near 1500us (90 degrees) but not exactly. Usually one will need to find the number (near 1500us or 90 degrees) that stops the servo by experimentation.
So to have the motors drive a robot one motor must rotate forward and the other in reverse as one is mirrored by the one on the other side. A way to do that is to have a speed variable add that to the right motor stop number and subtract from the left motor stop number.
So, something like:
speed = 50;
rightServo.write(rightStopNumber + speed);
leftServo.write(leftStopNumber - speed);
If you use the include keyword the compiler expects that something be included. In the case where you are using servos, you need to include the Servo library.
#include <Servo.h>
The best debugging tool that you have is the serial print. Insert serial prints in the code to monitor program execution and variable values to see if things are happening as you expect.
To do that you need to open the serial port. In the setup() function open the port with:
Serial.begin(115200);
Then insert some serial prints with labels.
I inserted a few to illustrate. See the // ********************
#include <Servo.h> //include Servo library
const int RForward = 0;
const int RBackward = 180;
const int LForward = RBackward;
const int LBackward = RForward;
const int RNeutral = 90;
const int LNeutral = 90; //constants for motor speed
const int pingPin = 7;
const int dangerThresh = 10; //threshold for obstacles (in cm)
int leftDistance, rightDistance; //distances on either side
Servo panMotor;
Servo leftMotor;
Servo rightMotor; //declare motors
long duration; //time it takes to recieve PING))) signal
void setup()
{
// open the serial port
Serial.begin(115200); // ********************************
rightMotor.attach(11);
leftMotor.attach(10);
panMotor.attach(6); //attach motors to proper pins
panMotor.write(90); //set PING))) pan to center
}
void loop()
{
int distanceFwd = ping();
Serial.print("distance is "); // print the distance with a label
Serial.println(distanceFwd); // ********************************
if (distanceFwd > dangerThresh) //if path is clear
{
Serial.println("Moving forward"); // ************************
leftMotor.write(LForward);
rightMotor.write(RForward); //move forward
delay(100);
}
else //if path is blocked
{
Serial.println("Path blocked"); // ****************************
leftMotor.write(LNeutral);
rightMotor.write(RNeutral);
panMotor.write(0);
delay(500);
rightDistance = ping(); //scan to the right
delay(500);
panMotor.write(180);
delay(700);
leftDistance = ping(); //scan to the left
delay(500);
panMotor.write(90); //return to center
delay(100);
compareDistance();
}
}
void compareDistance()
{
if (leftDistance > rightDistance) //if left is less obstructed
{
leftMotor.write(LBackward);
rightMotor.write(RForward); //turn left
delay(500);
}
else if (rightDistance > leftDistance) //if right is less obstructed
{
leftMotor.write(LForward);
rightMotor.write(RBackward); //turn right
delay(500);
}
else //if they are equally obstructed
{
leftMotor.write(LForward);
rightMotor.write(RBackward); //turn 180 degrees
delay(1000);
}
}
long ping()
{
// Send out PING))) signal pulse
pinMode(pingPin, OUTPUT);
digitalWrite(pingPin, LOW);
delayMicroseconds(2);
digitalWrite(pingPin, HIGH);
delayMicroseconds(5);
digitalWrite(pingPin, LOW);
//Get duration it takes to receive echo
pinMode(pingPin, INPUT);
duration = pulseIn(pingPin, HIGH);
//Convert duration into distance
return duration / 29 / 2;
}
When you open the serial monitor to see your prints, make sure that the baud rate is set to match the begin() function (15200 in this case).
Hi @ranelr2138
I recommend that you
Take a look into this tutorial:
Arduino Programming Course
It is easy to understand and has a good mixture between explaining important concepts and example-codes to get you going. So give it a try and report your opinion about this tutorial.
From your code you have defined constants that have opposite values
This means if the servos are mounted in a "mirror"-way this should work.
If your servos for leftwheel / rightwheel are mounted in the same position
(=not "mirrored") The code works exactly as the code is written.
Write a short testprogram that does nothing more than make the left servo move forward and the right servo move forward
and use serial printing to print the values to the serial monitor.
And then compare the values that were used in the
leftMotor.write() / rightMotor.write() function-calls
with wheel-rotation direction
If the wheel rotate in a way that your robot circles instead of moving straight forward you can conclude that you have to reverse one value
best regards Stefan