Remote control car with sensor and arduino

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 for 2secs and then move forward again.

However, the result is the car moves forward (for few seconds) and reverse (for another few seconds) without any obstacle in front of the sensor, but it reverses full-time 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;
}

I don’t see anything obvious in the code that would result in that behavior. I would suggest putting in a couple of print statements for duration and inches and putting the vehicle up on “bricks”. Then experiment as you did before, putting your hand in front of the sensor. My guess is you’re getting erratic readings and sometimes detecting an obstacle when there is none. There could be several reasons for this but I recall a case where the power supply wasn’t up to the task of supplying the peak current required by the sensor. IIRC adding a big cap next to the sensor helped.

WRG to the code … I don’t know about your controller but I notice the code never turns off the drive level (PWM signal), even when braking. Is this OK ?

frankly the above code is not done by me (it’s copied from an online tutorial) as I’m not familiar with C programming. 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 again and again? Anyway to test it?

simon_h:
Anyway to test it?

I think the code is OK. I would put a print statement after the conversion of ping time to inches and send those inches to the serial monitor. I would put the vehicle up on blocks so the wheels can turn but the car doesn’t move (thus is can be connected to the PC w/o having to follow the car around). Then see what kind of readings you’re getting with nothing in front of the car. Perhaps you are getting false detections/readings.