Code problem?

Hi guys, I’ve faced an obstacle in my project. I’m using a remote control car, an Arduino Uno R3, motor shield and Ping ultrasonic sensor to make an auto obstacle-avoidance car. My plan is when my car senses an obstacle, it will reverse and turn left (to change direction from the obstacle) and then move forward again.

However, my car currently can only move forward and doesn’t react to any obstacle. I’ve checked that the sensor is in good working condition as well as the arduino board. I’ve done everything similarly according to an online tutorial here: http://www.instructables.com/id/RC-Car-to-Robot/step19/Wire-it-up/ where the only difference is the car I’m using if compared to the tutorial. Do you guys have any idea what is wrong with my project?

Uploaded with ImageShack.us

Here is the code I used from the online tutorial:

/*
RC Car to Robot Conversion
by Randy Sarafan

Used to convert an RC car into a robot that uses a PING sensor to avoid obstacles,
and an Arduino motor shield for motor control.

For more information see:
http://www.instructables.com/id/RC-Car-to-Robot/

Built atop Ping example code by Tom Igoe
*/

// this constant won't change.  It's the pin number
// of the sensor's output:
const int pingPin = 7;

void setup() {
  
  //establish motor direction toggle pins
  pinMode(12, OUTPUT); //drive motor -- HIGH = forwards and LOW = backwards
  pinMode(13, OUTPUT); //turn motor -- HIGH = left and LOW = right
  
  //establish motor brake pins
  pinMode(9, OUTPUT); //brake (disable) the drive motor
  pinMode(8, OUTPUT); //brake (disable) the turn motor

  //Turns brake off for drive motor
  digitalWrite(9, LOW); 

  //Turns brake on for turn motor
  digitalWrite(8, HIGH); 

  //Sets initial speed of drive motor
  analogWrite(3, 200);
  
  //Sets initial direction of drive motor
  digitalWrite(12, HIGH);
}

void loop()
{
  // establish variables for duration of the ping, 
  // and the distance result in inches and centimeters:
  long duration, inches, cm;

  // The PING))) is triggered by a HIGH pulse of 2 or more microseconds.
  // Give a short LOW pulse beforehand to ensure a clean HIGH pulse:
  pinMode(pingPin, OUTPUT);
  digitalWrite(pingPin, LOW);
  delayMicroseconds(2);
  digitalWrite(pingPin, HIGH);
  delayMicroseconds(5);
  digitalWrite(pingPin, LOW);

  // The same pin is used to read the signal from the PING))): a HIGH
  // pulse whose duration is the time (in microseconds) from the sending
  // of the ping to the reception of its echo off of an object.
  pinMode(pingPin, INPUT);
  duration = pulseIn(pingPin, HIGH);

  // convert the time into a distance
  inches = microsecondsToInches(duration);

  //
  //if objects are less than 12 inches away
  //the robot reverses and turns to the right
  //for 2 seconds
  //
  
  if (inches < 12){
    
    //brake drive motor and pause 1/10 second
    digitalWrite(9, HIGH);
    delay(100);

    //
    //setting turn motor
    //
    
    //turn off brake for turn motor 
    digitalWrite(8, LOW);

    //set turn motor direction
    digitalWrite(13, HIGH);

    //activate turn motor
    analogWrite(11, 255);
    
    //
    //setting drive motor
    //
    
    //turn off brake of drive motor
    digitalWrite(9, LOW); 
    
    //set drive motor backwards direction
    digitalWrite(12, LOW);
    
    //activate the drive motor
    analogWrite(3, 200);

    
    //backup for 2 seconds
    delay(2000);
    
    //
    //stopping
    //
    
    //brake both motors
    digitalWrite(8, HIGH);
    digitalWrite(9, HIGH);
    
    
  }
  
  //
  //when nothing is within 12" 
  //the robot simply drives forwards
  //
  
  else{
    
    //
    //Setting drive motor
    //
    
    //set drive motor forward direction
    digitalWrite(12, HIGH);
    
    //turn off brake of drive motor
    digitalWrite(9, LOW);    
    
    //activate drive motor
    analogWrite(3, 200);
  
  
  }
  
  delay(100);
}

long microsecondsToInches(long microseconds)
{
  // According to Parallax's datasheet for the PING))), there are
  // 73.746 microseconds per inch (i.e. sound travels at 1130 feet per
  // second).  This gives the distance travelled by the ping, outbound
  // and return, so we divide by 2 to get the distance of the obstacle.
  // See: http://www.parallax.com/dl/docs/prod/acc/28015-PING-v1.3.pdf
  return microseconds / 74 / 2;
}

The code looks OK so the problem is likely a hardware problem. You might want to use the LED on pin 13 to indicate when the ping sensor detects a distance < 12. The LED should come ON if the distance is < 12 and turn OFF if the distance is > 12. If you can’t get the light to go on and off by moving the car near a wall you have a problem with the distance sensor.

  //
  //when nothing is within 12" 
  //the robot simply drives forwards
  //
  else {
/////////////////// Add this line: ///////////// 
      digitalWrite(13, LOW);  // Turn off the LED

    //
    //Setting drive motor
    //
    
    //set drive motor forward direction
    digitalWrite(12, HIGH);
    
    //turn off brake of drive motor
    digitalWrite(9, LOW);    
    
    //activate drive motor
    analogWrite(3, 200);
  }

It's interesting that microsecondsToInches() is a function, but EVERYTHING else happens in loop.

Create some more functions. One for pinging. Call that function to get the distance.

Create one for braking. Create one for backing. Create one for going forward.

It's a lot easier to debug code when you can see that the correct function gets called. Then, it's a matter of determining whether that function is operating correctly. And, that is easy to test.

Comment out all the code in loop(), except for a call to the function to back up. Does the car go backwards? Yes, the function (and hardware) are good. No? Then, you might have a hardware problem or a software problem, but, at least you have a better idea.

Serial.begin() in setup() and Serial.print() in loop() and other functions will go a long way towards answering your questions.

If I were you I’d split the problem up and write a sketch that does nothing but interface to the ping sensor and show that you can get a sensible distance reading from it.

Then put that aside and write a sketch that just controls the motor and prove you can make it go forwards and backwards at the speed you want.

Then write one that controls the steering and make sure you can control that.

Then start bringing these together and get the whole sketch working.

I suggest that you encapsulate these different bits of code in functions so that when you come to combine them into a sketch you can just add in the relevant function and call it in the right place, to minimise the work involved in moving them between sketches.

Ok, to simplify my project, I’ve made some modification where I removed the front steer motor function. What I want now is to make the car go forward, reverse for 2 seconds when the sensor detects an obstacle at a distance lesser than 15", and then move forward again.

However, my result is totally opposite! It moves forward and reverse without any obstacle in front of the sensor, but it only moves forward when there is an obstacle!

Here’s my code, anyone mind telling me where is the error? Thanks :slight_smile:

/*
RC Car to Robot Conversion
by Randy Sarafan

Used to convert an RC car into a robot that uses a PING sensor to avoid obstacles,
and an Arduino motor shield for motor control.

For more information see:
http://www.instructables.com/id/RC-Car-to-Robot/

Built atop Ping example code by Tom Igoe
*/

// this constant won't change.  It's the pin number
// of the sensor's output:
const int pingPin = 7;

void setup() {
  
  //establish motor direction toggle pins
  pinMode(12, OUTPUT); //drive motor -- HIGH = forwards and LOW = backwards
  
  //establish motor brake pins
  pinMode(9, OUTPUT); //brake (disable) the drive motor

  //Turns brake off for drive motor
  digitalWrite(9, LOW); 

  //Sets initial speed of drive motor
  analogWrite(3, 200);
  
  //Sets initial direction of drive motor
  digitalWrite(12, HIGH);
}

void loop()
{
  // establish variables for duration of the ping, 
  // and the distance result in inches and centimeters:
  long duration, inches, cm;

  // The PING))) is triggered by a HIGH pulse of 2 or more microseconds.
  // Give a short LOW pulse beforehand to ensure a clean HIGH pulse:
  pinMode(pingPin, OUTPUT);
  digitalWrite(pingPin, LOW);
  delayMicroseconds(2);
  digitalWrite(pingPin, HIGH);
  delayMicroseconds(5);
  digitalWrite(pingPin, LOW);

  // The same pin is used to read the signal from the PING))): a HIGH
  // pulse whose duration is the time (in microseconds) from the sending
  // of the ping to the reception of its echo off of an object.
  pinMode(pingPin, INPUT);
  duration = pulseIn(pingPin, HIGH);

  // convert the time into a distance
  inches = microsecondsToInches(duration);

  //
  //if objects are less than 15 inches away
  //the robot reverses for 2 seconds
  //
  
  if (inches < 15){
    
    //brake drive motor and pause 1/10 second
    digitalWrite(9, HIGH);
    delay(100);

    //
    //setting drive motor
    //
    
    //turn off brake of drive motor
    digitalWrite(9, LOW); 
    
    //set drive motor backwards direction
    digitalWrite(12, LOW);
    
    //activate the drive motor
    analogWrite(3, 200);

    
    //backup for 2 seconds
    delay(2000);
    
    //
    //stopping
    //
    
    //brake both motors
    digitalWrite(9, HIGH);
    
    
  }
  
  //
  //when nothing is within 12" 
  //the robot simply drives forwards
  //
  
  else{
    
    //
    //Setting drive motor
    //
    
    //set drive motor forward direction
    digitalWrite(12, HIGH);
    
    //turn off brake of drive motor
    digitalWrite(9, LOW);    
    
    //activate drive motor
    analogWrite(3, 200);
  
  
  }
  
  delay(100);
}

long microsecondsToInches(long microseconds)
{
  // According to Parallax's datasheet for the PING))), there are
  // 73.746 microseconds per inch (i.e. sound travels at 1130 feet per
  // second).  This gives the distance travelled by the ping, outbound
  // and return, so we divide by 2 to get the distance of the obstacle.
  // See: http://www.parallax.com/dl/docs/prod/acc/28015-PING-v1.3.pdf
  return microseconds / 74 / 2;
}

After checking, the ultrasonic sensor works fine. I suspect the code is the main culprit to my problem. The system somehow runs the forward and reverse code when there is no obstacle. Is the problem lies in the loop code? Maybe the system runs the loop code in the wrong way? Anyway to test it?

Is the motor shield up to the task of controlling the motor? Are you suffering voltage dips?

AWOL: Is the motor shield up to the task of controlling the motor? Are you suffering voltage dips?

yes the motor shield is working fine too, and mind explaining what voltage dips mean?

Suggest you disconnect and ignore the motors, add some code to print out the distance you're getting from the ping sensor, and see whether that's giving you sensible values.