Avatar
H-bridge RC control
Feb 11th, 2020 | by: Rick Sanchez | Views 4424
Views 4424
Read the signal from a PWM radio receiver with the Arduino. Then control the speed adn direction of a DC motor with another PWM signal. This is basic, but you can change the code and add more parts. 
The code

The code will read the PWM inputs on D8 adn D10 with values from 1000 to 2000us. Then we map those values to 0 to 255 for the analogWrite function. If one channel is higher than the other we spin the motor. If now we stop the motor. If both channels are high or low, we stop the motor sow e won't make a short circuit. 


//Variables
//We create variables for the time width values of each PWM input signal
unsigned long counter_1, counter_2, current_count;
//We create variables to stopre the previous value of the input signal (if LOW or HIGH)
byte last_CH1_state, last_CH2_state;
//To store the 1000us to 2000us value we create variables and store each channel
int input_CH1, input_CH2;      //In this example channel 1 of the receiver at pin D8 of the Arduino

/////////////////////////////////////////////////////////////////////////////////////
//Edit here if you have different signal from yout radio reciver
int min_value = 1000;             //min PWM value from receiver in us, usually 1000us
int max_value = 2000;             //max PWM value from receiver in us, usually 2000us
/////////////////////////////////////////////////////////////////////////////////////

//Inputs/outputs
int motor_CW = 6;
int motor_CCW = 9;

void setup() {
  PCICR |= (1 << PCIE0);    //enable PCMSK0 scan 
  PCMSK0 |= (1 << PCINT0);  //Set pin D8 trigger an interrupt on state change for CH1.                                               
  PCMSK0 |= (1 << PCINT2);  //Set pin D10 trigger an interrupt on state change.
  pinMode(motor_CW,OUTPUT);
  pinMode(motor_CCW,OUTPUT)
}

void loop() {
  int PWM_motor_CW = map(input_CH1, min_value, max_value, 0, 255);
  int PWM_motor_CCW = map(input_CH2, min_value, max_value, 0, 255);

  //Rotate CCW
  if(PWM_motor_CW > 5 && PWM_motor_CCW < 5)
  {
    analogWrite(motor_CW, LOW);
    analogWrite(motor_CCW, PWM_motor_CCW);
  }

  //Rotate CW
  if(PWM_motor_CW < 5 && PWM_motor_CCW > 5)
  {
    analogWrite(motor_CW, PWM_motor_CW);
    analogWrite(motor_CCW, LOW);
  }
  
  //if both are LOW, we stop both dirrections
  if(PWM_motor_CW < 5 && PWM_motor_CCW < 5)
  {
    analogWrite(motor_CW, LOW);
    analogWrite(motor_CCW, LOW);
  }
  //if both are HIGH, we stop both dirrections in order to not make short circuit
  if(PWM_motor_CW > 5 && PWM_motor_CCW > 5)
  {
    analogWrite(motor_CW, LOW);
    analogWrite(motor_CCW, LOW);
  }  
}

//This is the interruption routine
//----------------------------------------------

ISR(PCINT0_vect){
//First we take the current count value in micro seconds using the micros() function  
  current_count = micros();
  ///////////////////////////////////////             //Channel 1
  if(PINB & B00000001)                                //We make an AND with the pin state register, We verify if pin 8 is HIGH???
  {                               
    if(last_CH1_state == 0)                           //If the last state was 0, then we have a state change...
    {                                                 
      last_CH1_state = 1;                             //Store the current state into the last state for the next loop
      counter_1 = current_count;                      //Set counter_1 to current value.
    }
  }
  else if(last_CH1_state == 1)
  {                                                   //If pin 8 is LOW and the last state was HIGH then we have a state change      
    last_CH1_state = 0;                               //Store the current state into the last state for the next loop
    input_CH1 = current_count - counter_1;            //We make the time difference. Channel 1 is current_time - timer_1.
  }

  ///////////////////////////////////////Channel 2
  if(PINB & B00000100 )
  {                              //pin D10 - B00000100                                         
    if(last_CH2_state == 0)
    {                                             
      last_CH2_state = 1;                                                  
      counter_2 = current_count;                                               
    }
  }
  else if(last_CH2_state == 1)
  {                                             
    last_CH2_state = 0;                                                    
    input_CH2 = current_count - counter_2;                   
  }
}


3 Comments

  • Noob 1884

    about 4 years ago

    Hello! is it possible to use this project together with this one? https://www.youtube.com/watch?v=aztm_8qGVfc I would like to control a DC motor in this way using the X axis of the left transmitter joystick described in the video. Moving upwards to go forward and moving downwards to go backwards. Thanks

  • Noob 1884

    about 4 years ago

    Y Axis*

  • Noob 1997

    about 4 years ago

    is it possible to further develop this project/topic, for example for 2 DC motors? I would like to know where the wires go when I connected 2 motors to the H bridge? how many DC motors can be connected in series on one side? if this is a beginners page it would be nice if someone gave functional examples. one more question is there somewhere a paid version of such electronic schemes based on Arduino because it seems that this knowledge is covered with great mystery and is rarely revealed to the uninitiated. The problem is that I would like to know before I buy components and stay with them without anything useful. I don't want to stay again with a pile of rubbish for which I spent money just because I thought I could do it seeing only a fragment of the electronic diagram that I do not quite understand.

Login or Sign Up to post comments on this tutorial.