H-bridge problem: one of the motors is working only in one direction

Hi everyone!

Before I get to my problem and other thinks, I want you to warn you that I’am begginer.

Let me tell you first what I want my code to do and what I am building:

I have Arduino Mega 2560 and I decided to build a robot. Which I could control using IR remote. The robot (construction) is working fine, so the problem needs to be in the code, I know it because I used some DEMO codes from the internet to that robot and they were working 100%. The robot is basic tricycle with two DC motors, these are controlled through H-bridge. Then I added some ultrasonic sensors. The code should just control the robot - nothink more :slight_smile:

Here is the code:

#include "IRremote.h"

int enA = 10;
int in1 =40;
int in2 = 38;

int enB = 11;
int in3 = 36;
int in4 = 34;

float spd=255,spdc=spd,Rtrim=1,Ltrim=1;

float distance;
float distance1;
float distance2;
float distance3;
float distance4;

int ch=0;

int pamet=2;

/*************************/
int ECHOPIN1=2;       // front
int TRIGPIN1=3;

int ECHOPIN2=4;       // left side
int TRIGPIN2=5;

int ECHOPIN3=6;       // right side
int TRIGPIN3=7;

int ECHOPIN4=8;       // back
int TRIGPIN4=9;
/*************************/

int RECV_PIN=12;

IRrecv irrecv(RECV_PIN);
decode_results results;

void setup() {
  pinMode(enA, OUTPUT);
  pinMode(enB, OUTPUT);
  pinMode(in1, OUTPUT);
  pinMode(in2, OUTPUT);
  pinMode(in3, OUTPUT);
  pinMode(in4, OUTPUT);
/**********************************/
  pinMode(ECHOPIN1, INPUT); 
  pinMode(TRIGPIN1, OUTPUT);
  
  pinMode(ECHOPIN2, INPUT); 
  pinMode(TRIGPIN2, OUTPUT);
  
  pinMode(ECHOPIN3, INPUT); 
  pinMode(TRIGPIN3, OUTPUT);
  
  pinMode(ECHOPIN4, INPUT); 
  pinMode(TRIGPIN4, OUTPUT);
/*********************************/
  
  irrecv.enableIRIn();

}

/* MY FUNCTIONS (front, right etc...)*/
 
void front()
{
  analogWrite(enA, (spd*Rtrim));
  analogWrite(enB, (spd*Ltrim));
  digitalWrite(in1, HIGH);
  digitalWrite(in2, LOW);
  digitalWrite(in3, HIGH);
  digitalWrite(in4, LOW);
}

void left()
{
  analogWrite(enA, (spd*0.5*Rtrim));
  analogWrite(enB, (spd*0.5*Ltrim));
  digitalWrite(in1, LOW);
  digitalWrite(in2, HIGH);
  digitalWrite(in3, HIGH);
  digitalWrite(in4, LOW); 
}

void right()
{  
  analogWrite(enA, (spd*0.5*Rtrim));
  analogWrite(enB, (spd*0.5*Ltrim));
  digitalWrite(in1, HIGH);
  digitalWrite(in2, LOW);
  digitalWrite(in3, LOW);
  digitalWrite(in4, HIGH);
}
void backwards()
{ 
  analogWrite(enA, (spd*0.7*Rtrim));
  analogWrite(enB, (spd*0.7*Ltrim));
  digitalWrite(in1, LOW);
  digitalWrite(in2, HIGH);
  digitalWrite(in3, LOW);
  digitalWrite(in4, HIGH);
}
void Cstop()
{
  digitalWrite(in1, LOW);
  digitalWrite(in2, LOW);  
  digitalWrite(in3, LOW);
  digitalWrite(in4, LOW);
}

void minusSpd()
{
  spdc=spd;
  if(!((spdc-25.5)<0))spd=spd-25.5;
  if((spdc-25.5)<0)spd=0;
  analogWrite(enA, (spd*Rtrim));
  analogWrite(enB, (spd*Ltrim));          
}

void plusSpd()
{
  spdc=spd;
  if(!((spdc+25.5)>255))spd=spd+25.5;
  if((spdc+25.5)>255)spd=255;
  analogWrite(enA, (spd*Rtrim));
  analogWrite(enB, (spd*Ltrim));             
}

void distancef(int a, int b){      //A is ECHOPIN
                                   //B is TRIGPIN
    digitalWrite(b, LOW);
    delayMicroseconds(2); 
    digitalWrite(b, HIGH);
    delayMicroseconds(10); 
    digitalWrite(b, LOW); 
    distance = pulseIn(a, HIGH); 
    distance= distance*0.017315f;  
}

void distanceall(){
  
    distancef(2,3);
    distance1=distance;
    distancef(4,5);
    distance2=distance;
    distancef(6,7);
    distance3=distance;
    distancef(8,9);
    distance4=distance;  
}

void translate() 
{
  switch(results.value)
  {
  case 0xFF38C7: Cstop();ch=0;break;                                                       // stop
  case 0xFF18E7: front();ch=0;break;                                                       // move forwards
  case 0xFF10EF: left();ch=0;break;                                                        // rotate left
  case 0xFF5AA5: right();ch=0;break;                                                       // rotate right
  case 0xFF4AB5: backwards();ch=0;break;                                                   // move backwards
  case 0xFFE01F: minusSpd();ch=ch;break;                                                   // minus spd
  case 0xFFA857: plusSpd();ch=ch;break;                                                    // plus spd
  case 0xFFE21D: ch++;if(ch>2)ch=0;break;                                                  //ch+
  case 0xFFA25D: ch--;if(ch<0)ch=2;break;                                                  //ch-
  case 0xFF22DD: if(Ltrim!=1){Ltrim=Ltrim+0.02;}if(Rtrim!=0){Rtrim=Rtrim-0.02;} break;     //prev
  case 0xFF02FD: if(Rtrim!=1){Rtrim=Rtrim+0.02;}if(Ltrim!=0){Ltrim=Ltrim-0.02;} break;     //next
  }
}

void IRsignal(){

  if (irrecv.decode(&results)){
  translate();
  irrecv.resume();
}

}

void loop() {
  /*MANUAL*/
  if(ch==0)
    IRsignal();
  /*AUTOMATIC*/
  if(ch==1){
    distanceall();
  }
  if(ch==2){
    distanceall();  
  }
IRsignal(); 
}

And here’s my problem:

When I send IR command to move FORWARD it works fine. But when I send IR command to move BACKWARDS the motor, using in1,in2 and enbA pins, isn’t responding. The same problem appear when I use rotate function.
Basically, the motor rotates just forward not conversely.

-I tried to find solution, but I couldn’t find any + I don’t know how to name this problem.
-H-bridge is working fine, the code I used to test it is in attechments.
-If the problem is obviouse I’am sorry for wasting your time, but could you please tell me where? As I said before I’am begginer.
-The code isn’t completed yet, but I think it shouldn’t affect the motors.
-If you have any questions, ask freely :slight_smile:

I wish you a good day, and thank you for any future advices :slight_smile:

H-bridge.ino (1.95 KB)

You don't seem to have any debugging code to show you what IR codes are actually being received or which function is actually being called.

Add some Serial.println() commands so you can see how the program is working.

...R

Well I was thinking about this too at first BUT it seems that if I have my arduino connected to pc and at the same time my motors are connected to the battery it doesn't work good :confused: So I Don't know how to connect my robot (turned on) to pc and have this feedback As print function.

JacobSzlaur:
Well I was thinking about this too at first BUT it seems that if I have my arduino connected to pc and at the same time my motors are connected to the battery it doesn't work good

That seems strange - I would not expect any problem.

What exactly do you mean by "it doesn't work good"?

Are you, by any chance using Pins 0 and 1 for something other than communicating with the PC?

...R

Sorry for the bad expression before :smiley:

But I did figure out that problem with PC connection! I don't know why but I connected the "+5V"from H-bridge to Arduino Board "Vin", while power the Arduino fom the PC too... So the arduino had two power sorces, hope I didn't brake it!

Now I will try the "Print function" tactic and hope I will find the problem :slight_smile:

I’am so sorry for late answer.

I tried to apply the Serial.printf function into my code:

switch(digitalRead(in1))
{
case HIGH: Serial.println(“in1: HIGH”);break;
case LOW: Serial.println(“in1: LOW”);break;
}

1)I did this to every “in” pin (in1 … in4), and I read the values - they were all fine, all low because I didn’t send any IR signal to robor yet. And I found somethink really strange: when I send IR signal to move frontwards it normally goes frontwards and print the pin values to my serial monitor, so the front function works fine. Then I tried stop function, no problem there too. But if I try any other function with that one motor going another way (then front) it completly crushes and doesn’t respond to any next IR signals I send to it.

2)Next strange think I recognized was that if I restart the Serial Monitor Window it completly changes the values on the pins and start writing: in1: LOW, in2: LOW and so on…

-one motor still doesn’t work in one direction, even if the Serial monitor prints that it should work

I realy don’t know where the problem can be.
One more time sorry for late answer.

The delay does not matter except that I have forgotten all about this. Please post the latest version of your program.

...R

Here you go:

#include "IRremote.h"

int i=0;

int enA = 10;
int in1 =40;
int in2 = 38;

int enB = 11;
int in3 = 36;
int in4 = 34;

float spd=255,spdc=spd,Rtrim=1,Ltrim=1;

float distance;
float distance1;
float distance2;
float distance3;
float distance4;

int ch=0;

int pamet=2;

/*************************/
int ECHOPIN1=2;       // front
int TRIGPIN1=3;

int ECHOPIN2=4;       // left side
int TRIGPIN2=5;

int ECHOPIN3=6;       // right side
int TRIGPIN3=7;

int ECHOPIN4=8;       // back
int TRIGPIN4=9;
/*************************/

int RECV_PIN=12;

IRrecv irrecv(RECV_PIN);
decode_results results;

void setup() {
  pinMode(enA, OUTPUT);
  pinMode(enB, OUTPUT);
  pinMode(in1, OUTPUT);
  pinMode(in2, OUTPUT);
  pinMode(in3, OUTPUT);
  pinMode(in4, OUTPUT);
/**********************************/
  pinMode(ECHOPIN1, INPUT); 
  pinMode(TRIGPIN1, OUTPUT);
  
  pinMode(ECHOPIN2, INPUT); 
  pinMode(TRIGPIN2, OUTPUT);
  
  pinMode(ECHOPIN3, INPUT); 
  pinMode(TRIGPIN3, OUTPUT);
  
  pinMode(ECHOPIN4, INPUT); 
  pinMode(TRIGPIN4, OUTPUT);
/*********************************/
  
  irrecv.enableIRIn();
  Serial.begin(9600);

}

/* MY FUNCTIONS (front, right etc...)*/
 
void front()
{
  analogWrite(enA, (spd*Rtrim));
  analogWrite(enB, (spd*Ltrim));
  digitalWrite(in1, HIGH);
  digitalWrite(in2, LOW);
  digitalWrite(in3, HIGH);
  digitalWrite(in4, LOW);
}

void left()
{
  analogWrite(enA, (spd*0.5*Rtrim));
  analogWrite(enB, (spd*0.5*Ltrim));
  digitalWrite(in1, LOW);
  digitalWrite(in2, HIGH);
  digitalWrite(in3, HIGH);
  digitalWrite(in4, LOW); 
}

void right()
{  
  analogWrite(enA, (spd*0.5*Rtrim));
  analogWrite(enB, (spd*0.5*Ltrim));
  digitalWrite(in1, HIGH);
  digitalWrite(in2, LOW);
  digitalWrite(in3, LOW);
  digitalWrite(in4, HIGH);
}
void backwards()
{ 
  analogWrite(enA, (spd*0.7*Rtrim));
  analogWrite(enB, (spd*0.7*Ltrim));
  digitalWrite(in1, LOW);
  digitalWrite(in2, HIGH);
  digitalWrite(in3, LOW);
  digitalWrite(in4, HIGH);
}
void Cstop()
{
  digitalWrite(in1, LOW);
  digitalWrite(in2, LOW);  
  digitalWrite(in3, LOW);
  digitalWrite(in4, LOW);
}

void minusSpd()
{
  spdc=spd;
  if(!((spdc-25.5)<0))spd=spd-25.5;
  if((spdc-25.5)<0)spd=0;
  analogWrite(enA, (spd*Rtrim));
  analogWrite(enB, (spd*Ltrim));          
}

void plusSpd()
{
  spdc=spd;
  if(!((spdc+25.5)>255))spd=spd+25.5;
  if((spdc+25.5)>255)spd=255;
  analogWrite(enA, (spd*Rtrim));
  analogWrite(enB, (spd*Ltrim));             
}

void distancef(int a, int b){      //A is ECHOPIN
                                   //B is TRIGPIN
    digitalWrite(b, LOW);
    delayMicroseconds(2); 
    digitalWrite(b, HIGH);
    delayMicroseconds(10); 
    digitalWrite(b, LOW); 
    distance = pulseIn(a, HIGH); 
    distance= distance*0.017315f;  
}

void distanceall(){
  
    distancef(2,3);
    distance1=distance;
    distancef(4,5);
    distance2=distance;
    distancef(6,7);
    distance3=distance;
    distancef(8,9);
    distance4=distance;  
}

void translate() 
{
  switch(results.value)
  {
  case 0xFF38C7: Cstop();ch=0;break;                                                       // stop
  case 0xFF18E7: front();ch=0;break;                                                       // move forwards
  case 0xFF10EF: left();ch=0;break;                                                        // rotate left
  case 0xFF5AA5: right();ch=0;break;                                                       // rotate right
  case 0xFF4AB5: backwards();ch=0;break;                                                   // move backwards
  case 0xFFE01F: minusSpd();ch=ch;break;                                                   // minus spd
  case 0xFFA857: plusSpd();ch=ch;break;                                                    // plus spd
  case 0xFFE21D: ch++;if(ch>2)ch=0;break;                                                  //ch+
  case 0xFFA25D: ch--;if(ch<0)ch=2;break;                                                  //ch-
  case 0xFF22DD: if(Ltrim!=1){Ltrim=Ltrim+0.02;}if(Rtrim!=0){Rtrim=Rtrim-0.02;} break;     //prev
  case 0xFF02FD: if(Rtrim!=1){Rtrim=Rtrim+0.02;}if(Ltrim!=0){Ltrim=Ltrim-0.02;} break;     //next
  }
}

void IRsignal(){

  if (irrecv.decode(&results)){
  translate();
  irrecv.resume();
  }

  delay(1);
  i=i+1;
  if(i==1000){
  switch(digitalRead(in1))
  {
    case HIGH: Serial.println("in1: HIGH");break;
    case LOW: Serial.println("in1: LOW");break;
  }
      switch(digitalRead(in2))
  {
    case HIGH: Serial.println("in2: HIGH");break;
    case LOW: Serial.println("in2: LOW");break;
  }
    switch(digitalRead(in3))
  {
    case HIGH: Serial.println("in3: HIGH");break;
    case LOW: Serial.println("in3: LOW");break;
  }
    switch(digitalRead(in4))
  {
    case HIGH: Serial.println("in4: HIGH");break;
    case LOW: Serial.println("in4: LOW");break;
  }
  i=0;
  }
  

  
}

void loop() {
  /*MANUAL*/
  if(ch==0)
    IRsignal();
  /*AUTOMATIC*/
  if(ch==1){
    distanceall();
  }
  if(ch==2){
    distanceall();  
  }
IRsignal(); 
}

The last part isn’t completed yet, but I think it should not have any imapct on effectiveness of the code.

Could you possibly make life easier for my brain and provide all the information at the same time, or at least on the same day, so I don't forget and have to read it all again. It is also a big help if you respond to a Reply quickly.

Your code is very hard to read because you have multiple statements on one line all over the place. I don't know if the AutoFormat tool will sort that out for you - but it would be worth trying.

My suggestion would be to take a lot of stuff out of the program (comment it out) and then add things back piece by piece to identify where the problem is.

Personally I avoid this style of code analogWrite(enA, (spd0.7Rtrim)); because it is impossible to view the value before it is used by analogWrite(). I would calculate the value on one line and use it on the next line.

I also try very hard not to use floating point maths. It is very slow. And, in any case, analogWrite() is expecting an whole number (byte) value.

...R

I'am sorry but I don't have that much freetime this days, but I will try my best in the future.

1)Okey so don't have multiple statements on one line, gonna try it out.

2)Alright, and also I though I will try sending commands to the robot by PC and see if it's working good, if it would, then the problem would be in the IR part of the code.

3)I felt little bit unsure about this too to be honest.

4)Wow I didn't know that about analogWrite function - but how can I then make motors work at 50% for example? If I'am right you can't multiply and divide INT values, so that the result was decimal, or it will round the values automatically?

JacobSzlaur:
but how can I then make motors work at 50% for example?

Very simple. analogWrite(pin, 128);

RTFM

...R