Arduino 2WD Robot Car - Obstacle Avoidance Code Not Working Properly

Hi everyone,

I built an Arduino-based 2WD robot car and programmed it to autonomously navigate and avoid obstacles using an ultrasonic sensor and a servo motor. However, I’m facing several issues:

  1. Movement Pattern Issue: My robot currently moves in small circles. When it detects an obstacle, it either stops, moves backward, and resumes circling or just stops in front of the obstacle without continuing. I would like the robot to move in larger circles and actively avoid obstacles rather than getting stuck.
  2. Servo Motor Issue: The servo motor doesn't move at all, while the ultrasonic sensor works fine. This prevents the sensor from scanning different directions for obstacles.

I've attached my wiring diagram as a picture and included my current code below. Any suggestions for improvements or debugging would be greatly appreciated!

Thank you in advance for your help!

#include <Servo.h>
#include <avr/wdt.h>  // Watchdog timer for auto reset

// Define ultrasonic sensor pins
#define TRIG 4
#define ECHO 5

// Define motor driver pins (L298N)
#define MOTOR_R_F 6  // Right motor forward
#define MOTOR_R_B 7  // Right motor backward
#define MOTOR_L_F 8  // Left motor forward
#define MOTOR_L_B 9  // Left motor backward

// Define servo pin
#define SERVO_PIN 10

// Create Servo object
Servo myServo;

// Function to measure distance using ultrasonic sensor
long getDistance() {
    digitalWrite(TRIG, LOW);
    delayMicroseconds(2);
    digitalWrite(TRIG, HIGH);
    delayMicroseconds(10);
    digitalWrite(TRIG, LOW);

    long duration = pulseIn(ECHO, HIGH);
    long distance = duration * 0.034 / 2;  // Convert to cm
    if (distance > 200) return 200;  // Limit to 200 cm max
    return distance;
}

// Function to move the robot forward
void moveForward() {
    digitalWrite(MOTOR_R_F, HIGH);
    digitalWrite(MOTOR_R_B, LOW);
    digitalWrite(MOTOR_L_F, HIGH);
    digitalWrite(MOTOR_L_B, LOW);
}

// Function to move the robot backward
void moveBackward() {
    digitalWrite(MOTOR_R_F, LOW);
    digitalWrite(MOTOR_R_B, HIGH);
    digitalWrite(MOTOR_L_F, LOW);
    digitalWrite(MOTOR_L_B, HIGH);
}

// Function to turn left
void turnLeft() {
    digitalWrite(MOTOR_R_F, HIGH);
    digitalWrite(MOTOR_R_B, LOW);
    digitalWrite(MOTOR_L_F, LOW);
    digitalWrite(MOTOR_L_B, HIGH);
}

// Function to turn right
void turnRight() {
    digitalWrite(MOTOR_R_F, LOW);
    digitalWrite(MOTOR_R_B, HIGH);
    digitalWrite(MOTOR_L_F, HIGH);
    digitalWrite(MOTOR_L_B, LOW);
}

// Function to stop the robot
void stopRobot() {
    digitalWrite(MOTOR_R_F, LOW);
    digitalWrite(MOTOR_R_B, LOW);
    digitalWrite(MOTOR_L_F, LOW);
    digitalWrite(MOTOR_L_B, LOW);
}

void setup() {
    Serial.begin(9600);
    wdt_enable(WDTO_8S); // Enable auto-reset if frozen for 8 seconds

    // Initialize motor pins
    pinMode(MOTOR_R_F, OUTPUT);
    pinMode(MOTOR_R_B, OUTPUT);
    pinMode(MOTOR_L_F, OUTPUT);
    pinMode(MOTOR_L_B, OUTPUT);

    // Initialize ultrasonic sensor pins
    pinMode(TRIG, OUTPUT);
    pinMode(ECHO, INPUT);

    // Attach servo to pin
    myServo.attach(SERVO_PIN);
    myServo.write(90);  // Center position
    delay(1000);
}

void loop() {
    wdt_reset();  // Prevent watchdog timer reset if running correctly

    long frontDistance = getDistance();
    Serial.print("Front Distance: ");
    Serial.print(frontDistance);
    Serial.println(" cm");

    if (frontDistance > 20) {  
        moveForward();  // Move forward if path is clear
    } else {  
        stopRobot();
        Serial.println("Obstacle detected! Scanning...");
        delay(500);

        // Scan left
        myServo.write(150);
        delay(500);
        long leftDistance = getDistance();
        Serial.print("Left Distance: ");
        Serial.print(leftDistance);
        Serial.println(" cm");

        // Scan right
        myServo.write(30);
        delay(500);
        long rightDistance = getDistance();
        Serial.print("Right Distance: ");
        Serial.print(rightDistance);
        Serial.println(" cm");

        // Reset servo to center
        myServo.write(90);
        delay(500);

        // Decide turning direction
        if (leftDistance > rightDistance) {
            Serial.println("Turning LEFT...");
            turnLeft();
            delay(800);
        } else {
            Serial.println("Turning RIGHT...");
            turnRight();
            delay(800);
        }

        stopRobot();  // Stop after turning
        delay(500);

        moveForward();  // Ensure robot moves forward after turning
    }

    delay(200);  // Prevent excessive serial flooding
}

Can You post real schematics? The positions on the boards tells nothing.

Powering that motor looking thing from the controller might not be good.

This says "turn left only when LEFT distance is greater than RIGHT distance"... if the obstacle is the same distance on both sides, why turn?

Changing the radius of the steering circle with this configuration (without the ENABLE pin connected on the L298N for both motors) will adding new steering methods. Currently, when you turn right (for example), the left motor is moved forward and the right motor is moved backwards.

One new steering method is called "skid steer." There are two forms of skid steer. The one skid steer method is "forward skid steer." For the "right turn" this method will require the left motor to be moved forward and the right motor to be stopped. That will drive the car to the right with the left wheel creating a larger arch. The left, forward, skid steer requires the right motor to move forward while the left motor is stopped.

If you want a wider turn, you will need to make a variable-drive steering method using PWM. Read the L298N data about the ENABLE pins and PWM signals. This steering method is similar to the forward skid steer, but moving the "stopped" motor slightly while the "moving" motor drives around the arc.

Hi ecunhaa,
from the sketch point of view it should not circle at all, when there is free space in front.
Turning always left schould be a mechanical or motor issue.
Since you have no feedback loop and regulation of the motors, it would be nearly strange if it would be able to really go strait.

Have you tested the motors and motors control? E.g. with a sketch wich is only calling the moving functions one after another with some delay of 2 seconds. Are the motors moving forward and backwards like expected?

Are you looking at the serial output? What does it show, when it stucks?

Beside of that, when the servo isn´t moving, then this is another part to be isolated looked at. Make a sketch, where in the loop is only the servo moving part to analyze the problem. Is it the right pin? Is the servo ok? Have you something to measure the signal for the servo?

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.