Wheels not going backwards

Hello, I made a robot but am encountering issues with it. My wheels don’t go backwards and my robot does avoid obstacles like it’s supposed to. I attached my diagram and code below.


#include <Servo.h>

// Define pin numbers
const int trigPin = 8;
const int echoPin = 9;
const int servoPin = 10;
const int motor1Pin1 = 2;
const int motor1Pin2 = 3;
const int motor2Pin1 = 4;
const int motor2Pin2 = 5;
const int enaPin = 6;
const int enbPin = 7;

// Create servo object
Servo myservo;

void setup() {
  // Initialize serial communication
  Serial.begin(9600);
  
  // Initialize pins
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
  pinMode(servoPin, OUTPUT);
  pinMode(motor1Pin1, OUTPUT);
  pinMode(motor1Pin2, OUTPUT);
  pinMode(motor2Pin1, OUTPUT);
  pinMode(motor2Pin2, OUTPUT);
  pinMode(enaPin, OUTPUT);
  pinMode(enbPin, OUTPUT);

  // Attach servo to pin
  myservo.attach(servoPin);
}

void loop() {
  if (obstacleDetected()) {
    stopMotors();
    lookAround();
  } else {
    moveForward();
  }
}

bool obstacleDetected() {
  long duration, distance;
  
  // Send pulse to trigger pin
  digitalWrite(trigPin, LOW);
  delayMicroseconds(2);
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);
  
  // Read echo pin
  duration = pulseIn(echoPin, HIGH);
  
  // Calculate distance
  distance = duration * 0.034 / 2;
  
  // Print distance
  Serial.print("Distance: ");
  Serial.println(distance);
  
  // Check if obstacle is detected
  return distance < 20; // Adjust threshold as needed
}

void moveForward() {
  // Move forward
  digitalWrite(motor1Pin1, HIGH);
  digitalWrite(motor1Pin2, LOW);
  digitalWrite(motor2Pin1, HIGH);
  digitalWrite(motor2Pin2, LOW);
  analogWrite(enaPin, 200);
  analogWrite(enbPin, 200);
}

void stopMotors() {
  // Stop motors
  digitalWrite(motor1Pin1, LOW);
  digitalWrite(motor1Pin2, LOW);
  digitalWrite(motor2Pin1, LOW);
  digitalWrite(motor2Pin2, LOW);
}

void lookAround() {
  // Perform full sweep with servo motor
  for (int angle = 0; angle <= 180; angle += 5) {
    myservo.write(angle);
    delay(50);
  }
  for (int angle = 180; angle >= 0; angle -= 5) {
    myservo.write(angle);
    delay(50);
  }
}

You have:

void moveForward() {
  // Move forward
. . .
}

Where is:

void moveReverse() {
  // Move backward 
. . .
}

i updated my code but still encountering the issue of it not moving backwards

#include <Servo.h>

// Define pin numbers
const int trigPin = 8;
const int echoPin = 9;
const int servoPin = 10;
const int motor1Pin1 = 2;
const int motor1Pin2 = 3;
const int motor2Pin1 = 4;
const int motor2Pin2 = 5;
const int enaPin = 6;
const int enbPin = 7;

// Create servo object
Servo myservo;

void setup() {
 // Initialize serial communication
 Serial.begin(9600);
 
 // Initialize pins
 pinMode(trigPin, OUTPUT);
 pinMode(echoPin, INPUT);
 pinMode(servoPin, OUTPUT);
 pinMode(motor1Pin1, OUTPUT);
 pinMode(motor1Pin2, OUTPUT);
 pinMode(motor2Pin1, OUTPUT);
 pinMode(motor2Pin2, OUTPUT);
 pinMode(enaPin, OUTPUT);
 pinMode(enbPin, OUTPUT);

 // Attach servo to pin
 myservo.attach(servoPin);
}

void loop() {
 if (obstacleDetected()) {
   stopMotors();
   lookAround();
   moveReverse();
   stopMotors();
   lookAround();
 } else {
   moveForward();
 }
}

bool obstacleDetected() {
 long duration, distance;
 
 // Send pulse to trigger pin
 digitalWrite(trigPin, LOW);
 delayMicroseconds(2);
 digitalWrite(trigPin, HIGH);
 delayMicroseconds(10);
 digitalWrite(trigPin, LOW);
 
 // Read echo pin
 duration = pulseIn(echoPin, HIGH);
 
 // Calculate distance
 distance = duration * 0.034 / 2;
 
 // Print distance
 Serial.print("Distance: ");
 Serial.println(distance);
 
 // Check if obstacle is detected
 return distance < 20; // Adjust threshold as needed
}

void moveForward() {
 // Move forward
 digitalWrite(motor1Pin1, HIGH);
 digitalWrite(motor1Pin2, LOW);
 digitalWrite(motor2Pin1, HIGH);
 digitalWrite(motor2Pin2, LOW);
 analogWrite(enaPin, 200);
 analogWrite(enbPin, 200);
}

void moveReverse() {
 // Move reverse
 digitalWrite(motor1Pin1, LOW);
 digitalWrite(motor1Pin2, HIGH);
 digitalWrite(motor2Pin1, LOW);
 digitalWrite(motor2Pin2, HIGH);
 analogWrite(enaPin, 200);
 analogWrite(enbPin, 200);
}

void stopMotors() {
 // Stop motors
 digitalWrite(motor1Pin1, LOW);
 digitalWrite(motor1Pin2, LOW);
 digitalWrite(motor2Pin1, LOW);
 digitalWrite(motor2Pin2, LOW);
}

void lookAround() {
 // Perform full sweep with servo motor
 for (int angle = 0; angle <= 180; angle += 5) {
   myservo.write(angle);
   delay(50);
 }
 for (int angle = 180; angle >= 0; angle -= 5) {
   myservo.write(angle);
   delay(50);
 }
}


The robot is doing exactly what it was coded to do.

The function moveReverse() takes at most 50 microseconds to execute, then stopMotors() is called. How far would you expect the robot to move in 50 microseconds?

When testing motion control, test each part of the control individually, for long enough to see how the robot behaves, without mixing in sensors, other motions, etc.

Note: do not instantaneously reverse motors, as that burns out motor drivers. When going forward, stop the robot completely before executing reverse, and vice-versa.

This is not a PWM pin. It will only be HIGH/255 or LOW/0.

Using your pin numbers (use pin 7 as DIO and replace the PWM with a good pin), try this motors-only sketch. The first four sections test one motor in one direction. The second four motors test two motors in all directions. Watch the Serial Monitor for descriptions.

// Motor steering simulating Arduino Cars with L298N style motor driver boards
// NOT for LAFVIN car (LDR, IR, SONAR, line follow, IRremote) 

// LEFT motor
int IN1 = 8; // LEFT motor forward, DIO pin, only HIGH or LOW
int IN2 = 7; // LEFT REVERSE, DIO pin, only HIGH or LOW
int ENA = 6; // ENABLE (and disable) left motor, PWM pin, speed = 0 - 255

// RIGHT motor
int IN3 = 2; // RIGHT motor forward, DIO pin, only HIGH or LOW
int IN4 = 4; // RIGHT motor reverse, DIO pin, only HIGH or LOW
int ENB = 3; // ENABLE (and disable) right motor, PWM pin, speed = 0 - 255

// adjustable PWM, range 0 (no speed) - 255 (full speed)
// useful factors of 255 = 1, 3, 5, 15, 17, 51, 85...
int speed =  51; // slow
// int speed = 127; // medium
// int speed = 255; // maximum

int ON  = speed;
int OFF = 0;

int thisDelay = 3000; // delay during motor movement

void setup() {
  Serial.begin(9600); // for Serial Monitor

  pinMode(ENA, OUTPUT); // configure ENABLE pins for output
  pinMode(ENB, OUTPUT);

  pinMode(IN1, OUTPUT); // configure MOTOR DRIVER pins for output
  pinMode(IN2, OUTPUT);
  pinMode(IN3, OUTPUT);
  pinMode(IN4, OUTPUT);

  digitalWrite(ENA, speed); // PWM speed control, 0 - 255
  digitalWrite(ENB, speed);

  eightSteeringModes();
}

void loop() {
}

void basicSteering() {
  enableMotors(ON);
  forward(); delay(1000); allStop();
  reverse(); delay(1000); allStop();
  rotateLeft(); delay(1000); allStop();
  rotateRight(); delay(1000); allStop();
  enableMotors(OFF);
}

void eightSteeringModes () {
  enableMotors(ON);
  allStop();
  // single motor
  forwardSkidLeft();
  reverseSkidRight();// placed this out of order to keep car stationary
  forwardSkidRight();
  reverseSkidLeft();
  // double motors
  rotateLeft();
  rotateRight();
  forward();
  reverse();
  allStop();
  enableMotors(OFF);
}

//**************************************************
// L298N MOTOR DIRECTIONS
//**************************************************
//  ENA   ENB   IN1   IN2   IN3   IN4
//  HIGH  HIGH  HIGH  LOW   LOW   HIGH  forward - left forward, right forward
//  HIGH  HIGH  LOW   HIGH  HIGH  LOW   reverse - left reverse, right reverse
//  HIGH  HIGH  LOW   HIGH  LOW   HIGH  face left - left reverse, right forward
//  HIGH  HIGH  HIGH  LOW   HIGH  LOW   face right - left forward, right reverse
//  HIGH  HIGH  HIGH  LOW   LOW   LOW   skid left - stop left, forward right
//  HIGH  HIGH  LOW   LOW   LOW   LOW   stop - all LOW
//  HIGH  HIGH  HIGH  HIGH  HIGH  HIGH  brake - all HIGH - do not use, over current
//  LOW   LOW   N/A   N/A   N/A   N/A   stop - both ENABLE LOW
//
// *** LEFT motor and RIGHT motor are facing opposite directions ***
// *** LEFT motor will use HIGH, LOW to go forward ***
// *** RIGHT motor will use LOW, HIGH to go forward ***

//**************************************************
// MOTOR FUNCTIONS
//**************************************************
void driveMotor(bool p1, bool p2, bool p3, bool p4) {
  digitalWrite(IN1, p1);
  digitalWrite(IN2, p2);
  digitalWrite(IN3, p3);
  digitalWrite(IN4, p4);
  delay(thisDelay);
}

void enableMotors(int enab) {
  if (enab) {
    Serial.print("Enable motors... ");
    delay(thisDelay / 2);
  }
  else
    Serial.print("... Disable motors.");
  digitalWrite(ENA, enab);
  digitalWrite(ENB, enab);
}

void allStop() {
  Serial.print("All motors Stop. (L STOP R STOP)");
  driveMotor(LOW, LOW, LOW, LOW);
  delay(thisDelay / 2); // allow motor to be stopped
}

void forwardSkidLeft() {
  Serial.print("\n\tForward Skid-Left.  (L STOP R FWD)");
  digitalWrite(ENA, 0);
  digitalWrite(ENB, speed);
  driveMotor(LOW, LOW, LOW, HIGH); // left motor stop, right motor forward
}

void forwardSkidRight() {
  Serial.print("\tForward Skid-Right. (L FWD R STOP)");
  digitalWrite(ENA, speed);
  digitalWrite(ENB, 0);
  driveMotor(HIGH, LOW, LOW, LOW); // left motor forward, right motor off
}

void reverseSkidLeft()  {
  Serial.print("\tReverse Skid-Left.   (L REV R STOP)\n");
  digitalWrite(ENA, speed);
  digitalWrite(ENB, 0);
  driveMotor(LOW, HIGH, LOW, LOW); // left motor reverse, right motor stop
}

void reverseSkidRight() {
  Serial.print("\tReverse Skid-Right.  (L STOP R REV)\n");
  digitalWrite(ENA, 0);
  digitalWrite(ENB, speed);
  driveMotor(LOW, LOW, HIGH, LOW); // left motor off, right motor reverse
}

void rotateLeft() {
  Serial.print("\tRotate Left.\t    (L REV R FWD)");
  digitalWrite(ENA, speed);
  digitalWrite(ENB, speed);
  driveMotor(LOW, HIGH, LOW, HIGH); // left motor reverse, right motor forward
}

void rotateRight() {
  Serial.print("\tRotate Right.\t     (L FWD R REV)\n");
  digitalWrite(ENA, speed);
  digitalWrite(ENB, speed);
  driveMotor(HIGH, LOW, HIGH, LOW); // left motor forward, right motor reverse
}

void forward() {
  Serial.print("\tForward.\t    (L FWD R FWD)");
  digitalWrite(ENA, speed);
  digitalWrite(ENB, speed);
  driveMotor(HIGH, LOW, LOW, HIGH); // left motor forward, right motor forward
}

void reverse() {
  Serial.print("\tReverse.\t     (L REV R REV)\n");
  digitalWrite(ENA, speed);
  digitalWrite(ENB, speed);
  driveMotor(LOW, HIGH, HIGH, LOW ); // left motor reverse, right motor reverse
}

void pwmDrive() {
  // Move motor with changing speed
  int dutyCycle;
  forward();
  while (dutyCycle <= 255) {
    digitalWrite(ENA, dutyCycle);
    dutyCycle += 51; // useful factors of 255 = 1, 3, 5, 15, 17, 51, 85
    delay(250);
  }
  reverse();
  while (dutyCycle > 0) {
    digitalWrite(ENA, dutyCycle);
    dutyCycle -= 51;
    delay(250);
  }
}

so i updated my code and now my robot can go backwards but it doesn’t seem to be able to turn directions when it sense obstacles in front of it, here’s my schematic and updated code


#include <Servo.h>

// Define pin numbers
const int trigPin = 8;
const int echoPin = 9;
const int servoPin = 10;
const int enaPin = 6;
const int enbPin = 7;

// Create servo object
Servo myservo;

void setup() {
  // Initialize serial communication
  Serial.begin(9600);
  
  // Initialize pins
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
  pinMode(servoPin, OUTPUT);
  pinMode(enaPin, OUTPUT);
  pinMode(enbPin, OUTPUT);

  // Attach servo to pin
  myservo.attach(servoPin);
}

void loop() {
  if (obstacleDetected()) {
    stopMotors();
    lookAround();
    moveReverse();
    turnToClearPath();
    moveForward();
  } else {
    moveForward();
  }
}

bool obstacleDetected() {
  long duration, distance;
  
  // Send pulse to trigger pin
  digitalWrite(trigPin, LOW);
  delayMicroseconds(2);
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);
  
  // Read echo pin
  duration = pulseIn(echoPin, HIGH);
  
  // Calculate distance
  distance = duration * 0.034 / 2;
  
  // Print distance
  Serial.print("Distance: ");
  Serial.println(distance);
  
  // Check if obstacle is detected
  return distance < 20; // Adjust threshold as needed
}

void moveForward() {
  // Move forward
  digitalWrite(enaPin, HIGH);
  digitalWrite(enbPin, HIGH);
  digitalWrite(3, HIGH);  // Motor 1 forward
  digitalWrite(4, LOW);   // Motor 1 forward
  digitalWrite(5, HIGH);  // Motor 2 forward
  digitalWrite(6, LOW);   // Motor 2 forward
}

void moveReverse() {
  // Move reverse
  digitalWrite(enaPin, HIGH);
  digitalWrite(enbPin, HIGH);
  digitalWrite(3, LOW);   // Motor 1 reverse
  digitalWrite(4, HIGH);  // Motor 1 reverse
  digitalWrite(5, LOW);   // Motor 2 reverse
  digitalWrite(6, HIGH);  // Motor 2 reverse
}

void stopMotors() {
  // Stop motors
  digitalWrite(enaPin, LOW);
  digitalWrite(enbPin, LOW);
}

void lookAround() {
  // Perform full sweep with servo motor
  for (int angle = 0; angle <= 180; angle += 5) {
    myservo.write(angle);
    delay(50);
  }
  for (int angle = 180; angle >= 0; angle -= 5) {
    myservo.write(angle);
    delay(50);
  }
}

void turnToClearPath() {
  // Turn to clear path (assuming object-free direction is to the right)
  myservo.write(90); // Center servo
  delay(500); // Wait for servo to center
  digitalWrite(3, HIGH);  // Motor 1 forward
  digitalWrite(4, LOW);   // Motor 1 forward
  digitalWrite(5, LOW);   // Motor 2 reverse
  digitalWrite(6, HIGH);  // Motor 2 reverse
  delay(500); // Adjust turn duration as needed
  stopMotors();
}

i changed the ENB to the correct pin but now it doesn't move straight, i reworked my dc motors to my l298n motor to give it the ability to turn and now all it does is move clockwise

Progress! You know your two motors work!

Your "lookAround()" function really does nothing but rotate a servo. You should include the "obstacleDetected()" function inside the "lookAround()" function and do this...

  1. Look left and record the distance.
  2. Look forward and record the distance.
  3. Look right and record the distance.
  4. Steer to the best direction (largest distance)
  5. Move in that direction

Does that make sense, both "lookAround" doing nothing and how to determine where to send the vehicle?

so i changed my code to this, is this what you meant?

#include <Servo.h>

// Define pin numbers
const int trigPin = 8;
const int echoPin = 9;
const int servoPin = 10;
const int motor1Pin1 = 2;
const int motor1Pin2 = 3;
const int motor2Pin1 = 4;
const int motor2Pin2 = 5;
const int enaPin = 6;
const int enbPin = 11;

// Create servo object
Servo myservo;

void setup() {
  // Initialize serial communication
  Serial.begin(9600);
  
  // Initialize pins
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
  pinMode(servoPin, OUTPUT);
  pinMode(enaPin, OUTPUT);
  pinMode(enbPin, OUTPUT);

  // Attach servo to pin
  myservo.attach(servoPin);
}

void loop() {
  if (obstacleDetected()) {
    stopMotors();
    int direction = lookAround();
    steer(direction);
    moveForward();
  } else {
    moveForward();
  }
}

bool obstacleDetected() {
  long duration, distance;
  
  // Send pulse to trigger pin
  digitalWrite(trigPin, LOW);
  delayMicroseconds(2);
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);
  
  // Read echo pin
  duration = pulseIn(echoPin, HIGH);
  
  // Calculate distance
  distance = duration * 0.034 / 2;
  
  // Print distance
  Serial.print("Distance: ");
  Serial.println(distance);
  
  // Check if obstacle is detected
  return distance < 20; // Adjust threshold as needed
}

int lookAround() {
  int distanceLeft, distanceForward, distanceRight;
  
  // Look left
  myservo.write(0);
  delay(500);
  distanceLeft = measureDistance();
  
  // Look forward
  myservo.write(90);
  delay(500);
  distanceForward = measureDistance();
  
  // Look right
  myservo.write(180);
  delay(500);
  distanceRight = measureDistance();
  
  // Determine best direction
  if (distanceLeft > distanceForward && distanceLeft > distanceRight) {
    return -1; // Left
  } else if (distanceRight > distanceForward && distanceRight > distanceLeft) {
    return 1; // Right
  } else {
    return 0; // Forward
  }
}

void steer(int direction) {
  // Steer based on direction
  if (direction == -1) { // Left
    // Steer left
    digitalWrite(enaPin, HIGH);
    digitalWrite(enbPin, HIGH);
    digitalWrite(2, LOW);  // Motor 1 reverse
    digitalWrite(3, HIGH); // Motor 1 reverse
    digitalWrite(4, HIGH); // Motor 2 forward
    digitalWrite(5, LOW);  // Motor 2 forward
    delay(500); // Adjust turn duration as needed
  } else if (direction == 1) { // Right
    // Steer right
    digitalWrite(enaPin, HIGH);
    digitalWrite(enbPin, HIGH);
    digitalWrite(2, HIGH); // Motor 1 forward
    digitalWrite(3, LOW);  // Motor 1 forward
    digitalWrite(4, LOW);  // Motor 2 reverse
    digitalWrite(5, HIGH); // Motor 2 reverse
    delay(500); // Adjust turn duration as needed
  } else { // Forward
    // No steering needed
  }
}

void moveForward() {
  // Move forward
  digitalWrite(enaPin, HIGH);
  digitalWrite(enbPin, HIGH);
  digitalWrite(2, HIGH);  // Motor 1 forward
  digitalWrite(3, LOW);   // Motor 1 forward
  digitalWrite(4, HIGH);  // Motor 2 forward
  digitalWrite(5, LOW);   // Motor 2 forward
}

void stopMotors() {
  // Stop motors
  digitalWrite(enaPin, LOW);
  digitalWrite(enbPin, LOW);
}

int measureDistance() {
  long duration;
  
  // Send pulse to trigger pin
  digitalWrite(trigPin, LOW);
  delayMicroseconds(2);
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);
  
  // Read echo pin
  duration = pulseIn(echoPin, HIGH);
  
  // Calculate distance
  return duration * 0.034 / 2;
}

But now my motor 2 will not move, i connected the motor 2 directly to a power source and it spun around but now evern with the simplest code only motor 1 spinds, imunsure where to go form here seeing as this project is due tmrw

This initializes "direction" inside "loop()" meaning the scope of this "direction" is only valid inside "loop()"...

"lookAround" only returns a value with a range of 0 to 255, but not a "best direction to move with the farthest obstacles" then "steer(direction);" tries to use "direction" from the return of "lookAround()".

You have two motors with forward, backward and variable speed. Which motor, direction and speed is "42?"

You can use global variables to help the problem of scope, but to return many data points (direction of obstacle or which motor, which direction, which speed) from a function, you will need to pass a structure. I think you should start with using global variables before tackling structures.

Not my problem. I don't care.

The logic of "loop()" looks good, but "lookAround()" needs to give your "steer(direction)" more information (which motor, which direction, what speed).

Here is my "worst program, evAr" which shows the mis-use of one variable name, showing scope as "global" and "local," and the many levels of "local."

Never code like this...

// The many layers of variable scope shown on the Serial Monitor output.

int a = 9600; // global "a"
void setup() {
  Serial.begin(a); // using the global variable value of "a"
  Serial.println(a); // global "a"

  int a = 2; // this new "a" is locally defined here, in "setup()"

  for (int a = 7; a < 9; a++) { // this new "a" is local only inside "for"
    Serial.println(a); // this "a" is local to "for"
  }

  Serial.println(a); // this "a" is local from the definition inside "setup"
}
void loop() {
  Serial.println(a); // this is the global "a"
  while(1);
}

Your motors look like they can use the same method as the TB6612FNG motor driver - IN1, IN2, ENA for each motor. This forum page has TEN motor tests that begin by testing one motor in one direction and end in both motors in both directions at varying speeds. When on the page, search "motors" and see "1 of 10" through "10 of 10" tests.

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