Simple code moving forward

Hi Forum,

I'm mentoring someone with his project. The goal is rather simple: let a robot move forward and get around obstacles. We wrote some complicated code and it did not work at all. Currently we're working on calibrating the hardware but meanwhile we're wondering if anyone can take some time and give us some feedback with our code.

We're using 4 continuous servos and 1 dis-continuous servo with an ultrasound sensor taped to it.

Here's the "dummy" code that I wrote, just to let the robot move and turn:

#include <TinkerKit.h>
#include <Servo.h>

//constants
Servo motorFL;                   
Servo motorFR;
Servo motorBL;
Servo motorBR;
Servo mount;
float inches;
float duration;
const int servoPin = 9;
const int pingPin = 7;


//setup
void setup(){
  Serial.begin(9600);
  motorFL.attach(O0);
  motorFR.attach(O1);
  motorBL.attach(O2);
  motorBR.attach(O3);
  mount.attach(servoPin);
}

//loop
void loop(){
  //detecting object
  pinMode(pingPin, OUTPUT);          // Set pin to OUTPUT
  digitalWrite(pingPin, LOW);        // Ensure pin is low
  delayMicroseconds(2);
  digitalWrite(pingPin, HIGH);       // Start ranging
  delayMicroseconds(5);              //   with 5 microsecond burst
  digitalWrite(pingPin, LOW);        // End ranging
  pinMode(pingPin, INPUT);           // Set pin to INPUT
  duration = pulseIn(pingPin, HIGH); // Read echo pulse
  inches = duration / 74 / 2;   
	
  //if encounters objects 
  if(inches < 2){
    motorFL.write(90);
  	motorFR.write(90);
  	motorBL.write(90);
  	motorBR.write(90);
  	delay(200);
  	
    motorFL.write(180);
  	motorFR.write(180);
  	motorBL.write(0);
  	motorBR.write(0);
  	delay(2000);
  	
    motorFL.write(180);
  	motorFR.write(180);
  	motorBL.write(180);
  	motorBR.write(180);
  	delay(1000);
  	
  	motorFL.write(0);
  	motorFR.write(0);
  	motorBL.write(180);
  	motorBR.write(180);
  	delay(1000);
  	return; 
  }
  //keeps going
  else if (inches >= 2){
  	motorFL.write(180);
  	motorFR.write(180);
  	motorBL.write(180);
  	motorBR.write(180);
  }
}

Here's a slightly more complicated version that involves turning the discontinuous servo that's attached to the sensor. The idea is to let the sensor follow the obstacle after turning until it's out of sight.

#include <TinkerKit.h>
#include <Servo.h>

//sets up motors
Servo motorFL;                    
Servo motorFR;
Servo motorBL;
Servo motorBR;
Servo mount;
const int servoPin = 9;
const int pingPin = 7;
float inches;
float duration;
boolean findObject;


void detectObject(){
  //detects object
  pinMode(pingPin, OUTPUT);          // Set pin to OUTPUT
  digitalWrite(pingPin, LOW);        // Ensure pin is low
  delayMicroseconds(2);
  digitalWrite(pingPin, HIGH);       // Start ranging
  delayMicroseconds(5);              //   with 5 microsecond burst
  digitalWrite(pingPin, LOW);        // End ranging
  pinMode(pingPin, INPUT);           // Set pin to INPUT
  duration = pulseIn(pingPin, HIGH); // Read echo pulse
 
 
  inches = duration / 74 / 2;      	 // Convert to inches
  									
  Serial.println(inches);            // Display result
  delay(200);		                 // Short delay

  if (inches >= 5)
    findObject = false;
  if (inches < 5)
    findObject = true;
}


void setup(){
  //attach the motors for wheels
  motorFL.attach(O0);
  motorFR.attach(O1);
  motorBL.attach(O2);
  motorBR.attach(O3);
  //attach mount motor
  mount.attach(servoPin);

}

void loop(){
 //makes sure sensor is facing forward 
 motor.write(0);
 delay(1000);
 
 //look for obstacles 
 detectObject();
 
 //if none are found, move forward while still looking 
 while(findObject == false){
    motorFL.write(180);
    motorBL.write(180);
    motorFR.write(180);
    motorBR.write(180);
    detectObject();
 }
  
  //if found
 else if(findObject){
 	
  //stop all wheels
  motorFL.write(90);
  motorBL.write(90);
  motorBR.write(90);
  motorFR.write(90);

  //giving it time to turn (CHECK DELAYS)
  mount.write(90); 
  motorFR.write(180);
  motorBR.write(180);
  motorFL.write(0);
  motorBL.write(0);
  delay(3000);     
  
  while(findObject){
    motorFL.write(180);
    motorBL.write(180);
    motorFR.write(180);
    motorBR.write(180);
    detectObject();
    
    if(findObject == false){
     motorFR.write(0);
     motorBR.write(0);
     motorFL.write(180);
     motorBL.write(180);
     delay(2000);
    }
    
  }
}
}

Any suggestions will be appreciated as I don't have too much experience with the arduino platform.

Delays block the code from doing anything else until they are done, so I would highly recommend you take the delays out and take a look at the example sketch Blink Without Delay. Learn how that sketch works and incorporate it into your code.

We wrote some complicated code and it did not work at all.

Exactly what didn't work? You can also use the serial monitor to see your distance readings and other values to see where the problem(s) occur.

There's too many different ultrasonic sensors out there. Please post a vendor link or datasheet for the one your are using.
Also , are you trying to say the robot is supposed to be programmed to TRACK NEAREST OBJECT AND FOLLOW IT ?
We need a cell phone photo of a hand-drawn sketch of the physical layout of the servo mounting . If possible top view and side view. What's the SITREP on the sensor and standard 180 degree servo ? Any testing done on that ? Any success ? We need to know
the status of these . Can you measure distance ?(yes/no) Where are you getting your code ? Can you rotate the standard servo ?

Here's a top view of the servos.
FRONT

Dis Cont Servo
Cont Servo FL Cont Servo FR

ROBOT

Cont Servo BL Cont Servo BR

BACK

We taped the ultrasonic sensor on the dis cont servo and it looks in the forward direction.

The task is to avoid obstacles. We want to make the robot move forward while detecting for objects with the ultrasonic sensor. If the sensor reports back a float < a certain amount, then we will turn the robot and get around the obstacle.

The way we want to do it is as follows:
If object is detected, turn robot left, turn dis cont servo so sensor is facing the obstacle. Move forward as long as sensor is giving back a float < a certain amount. Once the float is > that amount(we moved pass the obstacle), turn right and continue moving forward.

I think the biggest problem we have is we don't understand how to move forward using the write() functions. Does Servo.write(180) tell the servo to go in the forward direction at full speed? How do you specify how long you want it to move int that direction for? We thought that was the purpose of the delay() function.

We are designing the field ourselves, so we can place the obstacles however we want.

Thanks for the warm response.

write()

Description

Writes a value to the servo, controlling the shaft accordingly. On a standard servo, this will set the angle of the shaft (in degrees), moving the shaft to that orientation. On a continuous rotation servo, this will set the speed of the servo (with 0 being full-speed in one direction, 180 being full speed in the other, and a value near 90 being no movement).

Continuous-rotation servos will respond to the writeMicrosecond function in an analogous manner to the write function.

servo.writeMicroseconds(uS)
Parameters

servo: a variable of type Servo
uS: the value of the parameter in microseconds (int)
Example

#include <Servo.h> 

Servo myservo;

void setup() 
{ 
  myservo.attach(9);
  myservo.writeMicroseconds(1500);  // set servo to mid-point
} 

void loop() {}

Hi, your pictures did not take to your post, use the Additonal Options below the editng box and attach the files for us thanks.
Hope to be of help, a picture of your project would be great and a circuit diag, either a CAD or picture of hand drawn circuit would be fine, in jpg, png or pdf.

Hope we can help. These are sort of project we like doing as it is helping yourself and your sage and by the looks of your code you have a good grasp on making it in modules to keep the debugging easy.

Tom..... :slight_smile:

With a continuous rotation servo the "angle" tells it how fast to go. Roughly speaking servo.write(90) will make it stop and 0 will may it go full speed in one direction, 180 will be full speed in the other direction. Every servo is different so you will need to experiment to find the exact values for your devices.

I recommend you use servo.writeMicroseconds() in place of servo.write(). Using writeMicroseconds() 1000 approximately corresponds to 0 deg, 1500 = 90 and 2000 = 180 - all approximate. The advantage of using writeMicroseconds() is that it gives you finer control and it allows you to give values below 1000 and above 2000 which may be useful with some servos.

I wonder why you have 4 drive wheels using 4 continuous rotation servos. I think it will be difficult to sync the speeds of all 4 and I suggest you start with 2 powered and 2 unpowered wheels.

As well as the BWOD sketch already recommended to you. you should read about the concept of a State Machine (or Finite State Machine). These are rather grand names for a simple concept of using variables to record the state of something - for example the speed setting for the left motor or the angle for the sensor servo.

Using this technique it is easy to separate the logic of "what the robot should be doing - the control logic" from the "operational code - the driving of the motors etc".

For example you can break the control logic into a function that collects and saves the sensor reading, another piece that updates the variables recording the motor states according to the sensor data, etc. Then, elsewhere, there is code that makes the motors do their stuff depending on the values saved by the control logic. This also means that each function will be short, only concerned with one activity and thus easy to debug or modify.

I wrote an extended demo of the BWOD technique in the first post in this Thread. I hope it gives a flavout of what I am talking about.

...R

Thanks for the response everyone.

@raschemmel The student I'm mentoring has the robot which is why I didn't post a picture of the actual layout. I'll supply that when I meet him soon.
We're using the same sensor as http://arduino.cc/en/Tutorial/Ping?from=Tutorial.UltrasoundSensor. We got the detection code from this link as well.
From the tests that I did with him last time, the ultrasonic sensor is functional but the motors would not sync and they seem to "self-correct" after calibration. I'll be taking @Robin2's suggestions and fix up my code to get around that problem.
Thanks for the documentation. If I'm understanding this correctly, I'd need to write my own function to control how long the continuous servos are operating at a certain speed? For example, if I want one to be moving at full speed for 10 seconds, I can't use delay() or other functions provided.

@TomGeorge Thanks for the advice. I wasn't 100% sure it was allowed on the arduino platform. I'll definitely try to break it up into different functions.

@Robin2 Thanks for the recommendations. Your suggestion's spot on - the servos were impossible to sync. We'll probably go with your suggestion and use 2 powered/2 unpowered.
And yes, I read your code I get what you mean. I'll be working with him on that when I see him.

Thanks for the clarifications! We'll work on the code and hopefully we'll be able to fix everything.

wrote some complicated code and it did not work at all

Never write complicated code.
Code may become complicated over time but you should never write more than about ten lines without testing. Only by building up the code and function can you ever hope to get it working. Debugging is easy as well because the fault is almost always in the code you have written since the last time you tested.
So concentrate on individual functions of the robot, write these as code functions and only then string them together.
Use of delay is fine as long as you know you can do nothing else until it is over. Most of the time however that is not the case.