Controlling Robot Wheels
Last week, we figured out how to control a motor with a H-bridge. We expanded this to controlling a pair of wheels using the H-bridge. Above is a photo of the hardware. The wiring of the H-bridge is:
- H-bridge [+] and [-] are connected to a 9V battery
- H-bridge [IN1] to [IN4] is connected to Arduino Pins 6, 7, 8, 9
- H-bridge [Motor A] and [Motor B] pins are connected directly to the two motors
Below is Arduino code by Hackers member Luke to control this.
// Luke Madden, CoderDojo Athenry // Control motors using a H Bridge // The H bridge has 4 input pins: in1-in4 #define in1 6 #define in2 7 #define in3 8 #define in4 9 int fast = 150;// range 1-255 int slow = 80;// slower speed int hyperspeed = 255;// hits the hyperdrive void setup() { pinMode(in1, OUTPUT); pinMode(in2, OUTPUT); pinMode(in3, OUTPUT); pinMode(in4, OUTPUT); Serial.begin(9600); } void loop() { drive(); } void drive() { // Test the functions Serial.println("move forward"); forward(); delay(2000); Serial.println("hit the hyperdrive"); hyperdrive(); delay(2000); Serial.println("go backwards"); backwards(); delay(2000); } void forward() { //makes motor go forwards analogWrite(in1, fast); analogWrite(in2, 0); analogWrite(in3, fast); analogWrite(in4, 0); } void hyperdrive() { //hits the hyperdrive analogWrite(in1, hyperspeed); analogWrite(in2, 0); analogWrite(in3, hyperspeed); analogWrite(in4, 0); } void backwards() { //makes motor go backwards analogWrite(in1, 0); analogWrite(in2, fast); analogWrite(in3, 0); analogWrite(in4, fast); } void stopping(){ //makes it stop analogWrite(in1, 0); analogWrite(in2, 0); analogWrite(in3, 0); analogWrite(in4, 0); }
Handling Interrupts in Arduino
In Arduino, you can set up special functions that are a called depending on the state of some digital pins – these are called Interrupt Service Routines (ISRs). These routines are called separately from the main loop() that is always running, even if the main loop() is in the middle of another operation.
For controlling our robots, our Arduino might receive a signal on a pin, and if we want the robot to react quickly, an ISR can handle it. The ISR can send a signal on a different pin or change the state of a variable.
This code is simple and correctly-working demonstration of how interrupts work. Note that you don’t need to build any circuitry to try this out. A built-in LED on the Arduino, at pin 13, turns on/off depending on whether Pin 2 is connected/disconnected from the the GROUND pin.
There are three main tasks:
- Define the ISR function: this is a function declared as void with no arguments: for example, our ISR is called changed and is defined as:
void changed() { … }
In our code, it sets the value of a variable called controlState and it turns the LED on/off. Note that the value of controlState is printed out repeatedly in the main program loop, showing how the ISR can change a variable that is used elsewhere. - In the setup() function, set the pin mode of the control pin to INPUT or INPUT_PULLUP (see below for the difference). For example, we have defined the variable control to have value 2 and are setting its mode like this:
pinMode(controlPin, INPUT_PULLUP); - In setup(), attach the ISR to the pin:
attachInterrupt(digitalPinToInterrupt(controlPin), changed, CHANGE);
One extra note about the above line of code: all pins have numbers and all interrupts have numbers, and these are not (necessarily) the same numbers. The function digitalPinToInterrupt() returns the interrupt number corresponding to a given digital pin.
Some other things to note:
- The Interrupt Service Routine (ISR) should be short and run fast: delay() calls are ignored and print() can cause problems.
- You can’t attach two interrupts to the one pin: use CHANGE and then test pin state
- If you initiate the pin with INPUT_PULLUP, it is triggered by connecting it to GROUND; otherwise, if you initiate it with INPUT, you need a circuit with 10k resistor.
- On an Uno, can only attach interrupts to pins 2 and 3.
- If you are changing a variable in the ISR and need to use it elsewhere, declare it as volatile.
Here is the full Arduino code:
// Michael Madden, CoderDojo Athenry // // Test a pin interrupt to which an interrupt service routine (ISR) is attached. // When the control pin is connected to GROUND, the LED on the board is turned on. // Things we have figured out: // * The interrupt service routine (ISR) is a function declared as void with no arguments. // * It should be short and run fast: delay() calls are ignored and print() can cause problems. // * You can't attach two interrupts to the one pin: use CHANGE and then test pin state // * If you initiate the pin with INPUT_PULLUP, it is triggered by connecting it to GROUND; // * otherwise, with INPUT, you need a circuit with 10k resistor. // * On an Uno, can only attach interrupts to pins 2 and 3. // * If you are changing a variable in the ISR and need to use it elsewhere, declare it as volitile. const byte controlPin = 2; // Want to react when this pin is triggered const byte ledPin = 13; // no circuit needed: there is a built in LED on 13 volatile int controlState = 0; // will change this value in ISR void setup() { pinMode(ledPin, OUTPUT); pinMode(controlPin, INPUT_PULLUP); attachInterrupt(digitalPinToInterrupt(controlPin), changed, CHANGE); Serial.begin(9600); } void loop() { // The main loop does not do much, it just prints out the value of the // control pin's state every 2 seconds. Serial.print("Current value of control pin = "); Serial.println(controlState); delay(2000); } void changed() { // This is our interrupt service routine. // It is triggered when the control pin changes, // so we check its state and turn on/off the LED. // controlState = digitalRead(controlPin); if(controlState > 0) { digitalWrite(ledPin, HIGH); } else { digitalWrite(ledPin, LOW); } }
Pingback: Hackers – How to Control a Robot’s Wheel Motors Based on Joystick Movements | CoderDojo Athenry
Pingback: How to Steer a Robot Car based on Joystick Input or Object Tracking | galweejit