Car does not go backwards

I am using an arduino uno r4 wifi and the RemoteXY app.
I have two tt motors connected to an H-Bridge driver.
It seems to work fine until I try to go backwards.


/*
   -- New project --
   
   To compile this code using RemoteXY library 4.1.8 or later version 
   download by link http://remotexy.com/en/library/
   To connect using RemoteXY mobile app by link http://remotexy.com/en/download/                   
     - for ANDROID 4.18.03 or later version;
     - for iOS 1.14.1 or later version;
    
   To interact with the GUI, please refer to the manual: 
   https://remotexy.com/ru/help/code/interaction/

   This source code was automatically generated by the RemoteXY editor and 
   is an example for the RemoteXY library. 
   Licensed under the MIT License. See the LICENSE file in the RemoteXY library
   root (https://github.com/RemoteXY/RemoteXY-Arduino-library) for full license 
   details.             
*/

//////////////////////////////////////////////
//        RemoteXY include library          //
//////////////////////////////////////////////

// you can enable debug logging to Serial at 115200
//#define REMOTEXY__DEBUGLOG

// RemoteXY select connection mode and include library
#define REMOTEXY_MODE__WIFI_POINT

#include <WiFiS3.h>
#include <HCSR04.h>

// RemoteXY connection settings
#define REMOTEXY_WIFI_SSID "unor4"
#define REMOTEXY_WIFI_PASSWORD "11111111"
#define REMOTEXY_SERVER_PORT 6377


#include <RemoteXY.h>

// RemoteXY GUI configuration
#pragma pack(push, 1)
uint8_t const PROGMEM RemoteXY_CONF_PROGMEM[] =  // 89 bytes V19
  { 255, 3, 0, 4, 0, 82, 0, 19, 0, 0, 0, 0, 31, 1, 106, 200, 1, 1, 5, 0,
    5, 5, 90, 95, 95, 32, 2, 26, 31, 129, 3, 52, 56, 12, 64, 24, 104, 101, 97, 100,
    108, 105, 103, 104, 116, 115, 0, 10, 66, 42, 32, 32, 48, 4, 26, 31, 79, 78, 0, 31,
    79, 70, 70, 0, 67, 253, 13, 107, 13, 78, 2, 26, 2, 129, 2, 15, 38, 10, 64, 2,
    100, 105, 115, 116, 97, 110, 99, 101, 0 };

// this structure defines all the variables and events of your control interface
struct {

  // input variables
  int8_t joystick_01_x;   // from -100 to 100
  int8_t joystick_01_y;   // from -100 to 100
  uint8_t pushSwitch_01;  // =1 if state is ON, else =0, from 0 to 1

  // output variables
  float value_01;

  // other variable
  uint8_t connect_flag;  // =1 if wire connected, else =0

} RemoteXY;
#pragma pack(pop)

/////////////////////////////////////////////
//           END RemoteXY include          //
/////////////////////////////////////////////

UltraSonicDistanceSensor distanceSensor(3, 2);  // Initialize sensor that uses digital pins 13 and 12.
unsigned long lastSensorTime = 0;

void setup() {
  RemoteXY_Init();  // initialization by macros
  pinMode(6, OUTPUT);
  pinMode(9, OUTPUT);
  pinMode(10, OUTPUT);
  pinMode(11, OUTPUT);
  pinMode(LED_BUILTIN, OUTPUT);

  // TODO you setup code

  digitalWrite(6, 0);
  analogWrite(9, 150);
  digitalWrite(10, 0);
  analogWrite(11, 150);
  delay(200);
}

void loop() {
  int speed = 0;
  int left = 0;
  int right = 0;

  RemoteXYEngine.handler();

  if (!RemoteXY.connect_flag) {
    digitalWrite(LED_BUILTIN, 1);
    RemoteXYEngine.delay(600);
    digitalWrite(LED_BUILTIN, 0);
    RemoteXYEngine.delay(600);
  }
  // sample the HC-SR04 every 60ms
  if (millis() - lastSensorTime >= 60) {
    RemoteXY.value_01 = 12;  //distanceSensor.measureDistanceCm();
    digitalWrite(LED_BUILTIN, RemoteXY.pushSwitch_01);
    lastSensorTime = millis();
  }

  if (RemoteXY.joystick_01_y > 50) {
    if (RemoteXY.value_01 >= 12) {
      if (RemoteXY.joystick_01_y > 90) {
        speed = 255;
      } else {
        speed = 150;
      }
    }
  } else if (RemoteXY.joystick_01_y < -70) {
    speed = -150;
  }
  //
  if (RemoteXY.joystick_01_y == 0 && RemoteXY.joystick_01_x == 0) {
    digitalWrite(6, 0);
    digitalWrite(9, 0);
    digitalWrite(10, 0);
    digitalWrite(11, 0);
    speed = 0;
    left = 0;
    right = 0;
  }

  if (RemoteXY.joystick_01_x > 50) {
    left = 150;
  } else {
    left = 0;
  }
  if (RemoteXY.joystick_01_x < -50) {
    right = 150;
  } else {
    right = 0;
  }


  if (speed > 1) {//forward
    if (RemoteXY.value_01 >= 12) {
      digitalWrite(6, 0);
      analogWrite(9, min((speed + left), 255));
      digitalWrite(10, 0);
      analogWrite(11, min((speed + right), 255));
    }
  } else if (speed < -1) {//back
    analogWrite(6, abs(speed));
    analogWrite(9, 0);
    analogWrite(10, abs(speed));
    analogWrite(11, 0);
  } else {//still
    digitalWrite(6, 0);
    analogWrite(9, left);
    digitalWrite(10, 0);
    analogWrite(11, right);
  }
  // TODO you loop code
  // use the RemoteXY structure for data transfer
  // do not call delay(), use instead RemoteXYEngine.delay()
}
int limit(int value) {
  if (value > 255) {
    value = 255;
  }

  if (value < 0) {
    value = 0;
  }

  return value;
}

Thanks for the help (i hope it is not a stupid bug :roll_eyes:)

I have tried different H-Bridge drivers and motors.

Can you write and run a simkle sketch that just demonstrates that you have wired the H bridge correctly and that yourmotor(s) follow all commands as expected?

a7

Please create and post schematics. A datasheet link for the motors might be useful.

Why do you have

digitalWrite(6, 0);
analogWrite(9, min((speed + left), 255));
digitalWrite(10, 0);
analogWrite(11, min((speed + right), 255));

for going forwards but

analogWrite(6, abs(speed));
analogWrite(9, 0);
analogWrite(10, abs(speed));
analogWrite(11, 0);

for going backwards?

Did you mean min((speed + left), 255) and min((speed + right), 255) on pins 6 and 10 for going backwards instead of abs(speed)?

Here is a "basic steering" sketch... verify the pins for right-forward, right-reverse, left-forward and left-reverse, AND enable A and enable B.

// L298N steering

const byte LF = 6, LR = 9, RF = 10, RR = 11, EA = 8, EB = 12;

void setup() {
  Serial.begin(115200);
  pinMode(LF, OUTPUT); // left fwd
  pinMode(EA, OUTPUT); // enable A
  pinMode(LR, OUTPUT); // left rev
  pinMode(RF, OUTPUT); // right fwd
  pinMode(EB, OUTPUT); // enable B
  pinMode(RR, OUTPUT); // right rev
  pinMode(LED_BUILTIN, OUTPUT); // LED

  digitalWrite(EA, HIGH); // ENABLE motor A
  digitalWrite(EB, HIGH); // ENABLE motor B
}

void loop() {
  fwd();     stop();
  rev();     stop();
  rotater(); stop();
  rotatel(); stop();
  skidrf();  stop();
  skidlf();  stop();
  skidrr();  stop();
  skidlr();  stop();
}

void fwd() {
  Serial.println("FORWARD");
  movemotors(HIGH, LOW, HIGH, LOW);
}
void rev() {
  Serial.println("REVERSE");
  movemotors(LOW, HIGH, LOW, HIGH);
}
void rotater() {
  Serial.println("ROTATE RIGHT");
  movemotors(LOW, HIGH, HIGH, LOW);
}
void rotatel() {
  Serial.println("ROTATE LEFT");
  movemotors(HIGH, LOW, LOW, HIGH);
}
void skidrf() {
  Serial.println("SKID RIGHT FORWARD");
  movemotors(HIGH, LOW, LOW, LOW);
}
void skidrr() {
  Serial.println("SKID RIGHT REVERSE");
  movemotors(LOW, LOW, LOW, HIGH);
}
void skidlf() {
  Serial.println("SKID LEFT FORWARD");
  movemotors(LOW, LOW, HIGH, LOW);
}
void skidlr() {
  Serial.println("SKID LEFT REVERSE");
  movemotors(LOW, HIGH, LOW, LOW);
}
void stop() {
  Serial.println("STOP");
  movemotors(LOW, LOW, LOW, LOW);
}

void movemotors(bool lf, bool lr, bool rf, bool rr) {
  digitalWrite(LF, lf);
  digitalWrite(LR, lr);
  digitalWrite(RF, rf);
  digitalWrite(RR, rr);
  delay(1000);
}

I was trying alot of stuff at this point and I figured that turning while going backwards was not necessary.

Here's @xfpd's sketch with some global editing. I got confused reading FR, RL, LF and so forth. I used back-to-back LEDs as proxies for the motors. Green is CW, red is CCW. Try it here:

I note that the enable inputs on the motor controller go unused. Those are the inputs @mappleorchard can use for the injection of PWM speed control.

the code
// L298N steering
// https://wokwi.com/projects/472342292263993345
// https://forum.arduino.cc/t/car-does-not-go-backwards/1455849

const byte leftFront   = 6;
const byte leftRear    = 9;
const byte leftEnable  = 8;

const byte rightFront  = 10;
const byte rightRear   = 11;
const byte rightEnable = 12;

void setup() {
  Serial.begin(115200);

  pinMode(leftFront, OUTPUT);
  pinMode(leftRear, OUTPUT);
  pinMode(leftEnable, OUTPUT);

  pinMode(rightFront, OUTPUT);
  pinMode(rightRear, OUTPUT);
  pinMode(rightEnable, OUTPUT);

  pinMode(LED_BUILTIN, OUTPUT);

  digitalWrite(leftEnable, HIGH);
  digitalWrite(rightEnable, HIGH);
}

void loop() {
  forward();          stop();
  reverse();          stop();
  rotateRight();      stop();
  rotateLeft();       stop();
  skidRightForward(); stop();
  skidLeftForward();  stop();
  skidRightReverse(); stop();
  skidLeftReverse();  stop();
}

void forward() {
  Serial.println("FORWARD");
  moveMotors(HIGH, LOW, HIGH, LOW);
}

void reverse() {
  Serial.println("REVERSE");
  moveMotors(LOW, HIGH, LOW, HIGH);
}

void rotateRight() {
  Serial.println("ROTATE RIGHT");
  moveMotors(LOW, HIGH, HIGH, LOW);
}

void rotateLeft() {
  Serial.println("ROTATE LEFT");
  moveMotors(HIGH, LOW, LOW, HIGH);
}

void skidRightForward() {
  Serial.println("SKID RIGHT FORWARD");
  moveMotors(HIGH, LOW, LOW, LOW);
}

void skidRightReverse() {
  Serial.println("SKID RIGHT REVERSE");
  moveMotors(LOW, LOW, LOW, HIGH);
}

void skidLeftForward() {
  Serial.println("SKID LEFT FORWARD");
  moveMotors(LOW, LOW, HIGH, LOW);
}

void skidLeftReverse() {
  Serial.println("SKID LEFT REVERSE");
  moveMotors(LOW, HIGH, LOW, LOW);
}

void stop() {
  Serial.println("STOP");
  moveMotors(LOW, LOW, LOW, LOW);
}

void moveMotors(bool leftFrontState, bool leftRearState,
                bool rightFrontState, bool rightRearState) {
  digitalWrite(leftFront, leftFrontState);
  digitalWrite(leftRear, leftRearState);
  digitalWrite(rightFront, rightFrontState);
  digitalWrite(rightRear, rightRearState);

  delay(777);
}

HTH

a7

I tested @alto777 's code. It worked. Then I ran this

/*
/\*

  -- New project --

  

  To compile this code using RemoteXY library 4.1.8 or later version 

  download by link http://remotexy.com/en/library/

  To connect using RemoteXY mobile app by link http://remotexy.com/en/download/                   

    - for ANDROID 4.18.03 or later version;

    - for iOS 1.14.1 or later version;

   

  To interact with the GUI, please refer to the manual: 

  https://remotexy.com/ru/help/code/interaction/



  This source code was automatically generated by the RemoteXY editor and 

  is an example for the RemoteXY library. 

  Licensed under the MIT License. See the LICENSE file in the RemoteXY library

  root (https://github.com/RemoteXY/RemoteXY-Arduino-library) for full license 

  details.             

\*/



//////////////////////////////////////////////

//        RemoteXY include library          //

//////////////////////////////////////////////



// you can enable debug logging to Serial at 115200

//#define REMOTEXY__DEBUGLOG



// RemoteXY select connection mode and include library

#define REMOTEXY_MODE__WIFI_POINT



#include <WiFiS3.h>



// RemoteXY connection settings

#define REMOTEXY_WIFI_SSID "unoR4"

#define REMOTEXY_WIFI_PASSWORD ""

#define REMOTEXY_SERVER_PORT 6377




#include <RemoteXY.h>



// RemoteXY GUI configuration

#pragma pack(push, 1)

uint8_t const PROGMEM RemoteXY_CONF_PROGMEM\[\] =  // 113 bytes V19

 { 255, 7, 0, 0, 0, 106, 0, 19, 0, 0, 0, 117, 110, 111, 114, 52, 0, 31, 2, 106,

   200, 200, 84, 1, 1, 6, 0, 1, 247, 19, 57, 57, 144, 3, 24, 24, 0, 2, 31, 0,

   1, 247, 124, 57, 57, 144, 56, 24, 24, 0, 2, 31, 0, 1, 234, 67, 57, 57, 115, 28,

   24, 24, 0, 2, 31, 0, 1, 13, 67, 57, 57, 171, 28, 24, 24, 0, 2, 31, 0, 2,

   71, 64, 23, 52, 82, 69, 36, 14, 0, 2, 26, 31, 31, 79, 78, 0, 79, 70, 70, 0,

   5, 12, 21, 143, 143, 6, 8, 69, 69, 32, 2, 26, 31 };

// this structure defines all the variables and events of your control interface

struct {



 // input variables

 uint8_t button_01;     // =1 if button pressed, else =0, from 0 to 1

 uint8_t button_02;     // =1 if button pressed, else =0, from 0 to 1

 uint8_t button_03;     // =1 if button pressed, else =0, from 0 to 1

 uint8_t button_04;     // =1 if button pressed, else =0, from 0 to 1

 uint8_t switch_01;     // =1 if switch ON and =0 if OFF, from 0 to 1

 int8_t joystick_01_x;  // from -100 to 100

 int8_t joystick_01_y;  // from -100 to 100



 // other variable

 uint8_t connect_flag;  // =1 if wire connected, else =0



} RemoteXY;

#pragma pack(pop)



/////////////////////////////////////////////

//           END RemoteXY include          //

/////////////////////////////////////////////




const byte leftFront = 6;

const byte leftRear = 9;

const byte leftEnable = 8;



const byte rightFront = 10;

const byte rightRear = 11;

const byte rightEnable = 12;



void setup() {

 RemoteXY_Init();  // initialization by macros



 pinMode(leftFront, OUTPUT);

 pinMode(leftRear, OUTPUT);

 pinMode(leftEnable, OUTPUT);



 pinMode(rightFront, OUTPUT);

 pinMode(rightRear, OUTPUT);

 pinMode(rightEnable, OUTPUT);



 pinMode(LED_BUILTIN, OUTPUT);

 // TODO you setup code

}



void loop() {

 RemoteXYEngine.handler();



 if (!RemoteXY.connect_flag) {

   digitalWrite(LED_BUILTIN, HIGH);

   RemoteXYEngine.delay(200);

   digitalWrite(LED_BUILTIN, LOW);

   RemoteXYEngine.delay(200);

 }



 digitalWrite(LED_BUILTIN, RemoteXY.switch_01);



 if (RemoteXY.joystick_01_y > 80) {

   forward();

   RemoteXYEngine.delay(30);

 } else if (RemoteXY.joystick_01_y < -80) {

   reverse();

   RemoteXYEngine.delay(30);

 } else if (RemoteXY.joystick_01_x > 80) {

   rotateLeft();

   RemoteXYEngine.delay(30);

 } else if (RemoteXY.joystick_01_x < -80) {

   rotateRight();

   RemoteXYEngine.delay(30);

 } else if (RemoteXY.button_01) {

   forward();

   RemoteXYEngine.delay(30);

 } else if (RemoteXY.button_02) {

   reverse();

   RemoteXYEngine.delay(30);

 } else if (RemoteXY.button_03) {

   rotateLeft();

   RemoteXYEngine.delay(30);

 } else if (RemoteXY.button_04) {

   rotateRight();

   RemoteXYEngine.delay(30);

 } else {

   stop();

 }

 // TODO you loop code

 // use the RemoteXY structure for data transfer

 // do not call delay(), use instead RemoteXYEngine.delay()

}




void forward() {

 Serial.println("FORWARD");

 moveMotors(170, LOW, 170, LOW);

}



void reverse() {

 Serial.println("REVERSE");

 moveMotors(LOW, 170, LOW, 170);

}



void rotateRight() {

 Serial.println("ROTATE RIGHT");

 moveMotors(LOW, 170, 170, LOW);

}



void rotateLeft() {

 Serial.println("ROTATE LEFT");

 moveMotors(170, LOW, LOW, 170);

}



void skidRightForward() {

 Serial.println("SKID RIGHT FORWARD");

 moveMotors(170, LOW, LOW, LOW);

}



void skidRightReverse() {

 Serial.println("SKID RIGHT REVERSE");

 moveMotors(LOW, LOW, LOW, 170);

}



void skidLeftForward() {

 Serial.println("SKID LEFT FORWARD");

 moveMotors(LOW, LOW, 170, LOW);

}



void skidLeftReverse() {

 Serial.println("SKID LEFT REVERSE");

 moveMotors(LOW, 170, LOW, LOW);

}



void stop() {

 Serial.println("STOP");

 moveMotors(LOW, LOW, LOW, LOW);

}



void moveMotors(byte leftFrontState, byte leftRearState,

               byte rightFrontState, byte rightRearState) {

 digitalWrite(leftFront, leftFrontState);

 digitalWrite(leftRear, leftRearState);

 digitalWrite(rightFront, rightFrontState);

 digitalWrite(rightRear, rightRearState);

}

It worked. I don't know what was wrong. Next I will add back in the ultrasonic sensor.

Thank you everyone. It works!

If you mean now that you've added the ultrasound functions, post the code you ended up with.

These calls are nonsense, or misleading:

moveMotors(170, LOW, 170, LOW);

The only arguments that make sense are LOW and HIGH.

What you wrote works because anything other than zero eventually means HIGH. Whatever you were going for by writing 170 (or 42 (or 212)) is not happening. The motors are full on or off.

If you want to change the speed, as seemed to be the case in your original sketch, you can use PWM on the motor controller enable input. Those are currently not used.

And it's @xfpd's code gift, I just did some text editing!

a7

@mappleorchard

In the sketch in post #8, the ENABLE inputs are leftEnable and rightEnable... and are set HIGH (full ON) in the sketch. To use PWM on the "enable" pins, set the direction of each motor (forward or backward... or stop) and give leftEnable or rightEnable or both a PWM value from 0 to 255 (for the TT motors, minimum starts at about 55 and goes to 255).

I changed moveMotors() to accept bytes instead of bools. What I meant by "I don't know what was wrong" is that I don't know why my original code did not work. Thanks to everyones help I have fixed the problem.

Some of my motor driver boards do not have enable pins, so I set the pins that would be HIGH to a pwm signal. Why do you think that is somehow wrong?

I am not certain of the reference, but if your sketch works, that is good.

:+1:

This looks more like an H-bridge control issue than a RemoteXY joystick problem. Your speed = -150 logic is being reached, but I’d first verify the H-bridge input mapping and whether pins 6/9 and 10/11 are actually the correct direction/PWM pairs for your specific driver.

Also, try testing each motor independently with a very simple forward/reverse sketch. If both motors reverse correctly there, then the issue is likely in the control logic. One thing that stands out is that your forward code uses digitalWrite() for the direction pins and analogWrite() for the PWM pins, while reverse swaps those roles. Depending on the H-bridge, that may not be the correct way to drive the inputs.

I’d confirm the driver’s truth table and then make the forward/reverse functions explicitly set direction and PWM for each motor. That should make the problem much easier to isolate.