How to save pins in feature rich Arduino Uno based Robots

The challenge

The Arduino robot that I am building is going to be feature rich. It is based on Arduino Uno. I am going to put in 2.4GHz RF communication, Ultrasonic distance sensor, VGA camera, WiFi, Gyroscope, Accelerometer and of course motors.

If you check out the parts list in my robot kit, you will see that it comes with a motor shield. In my previous articles, I mentioned how to control the motors with the motor shield. It wasn’t too difficult to make it run. Most people would be happy with the simplicity and library support with the motor shield. However, it is a nightmare for my robot because I run out of pins!

Arduino Motor Shield uses 10 pins (pin 3-12). This doesn’t leave much pins for anything else. In particular, it overlaps with the SPI interface (10-13) and SPI is used by the 2.4GHz RF module. I have 5 options

1. drop the RF module. If I do that, it reduces the max distance that I can have between my base station and the robot dramatically. According to the spec, with RF, the max distance is 100 meter. It could be longer if I use better antenna.

2. Cut off some of the pins on the motor shield. The pins usage of the motor shield are as follows:

dc motor 1 pin 11
dc motor 2 pin 3
dc motor 3 pin 5
dc motor 4 pin 6
shift register pins 4, 7, 8, 12
servo 1 pin 9
servo 2 pin 10

If I take this option, that means I have to cripple DC motor1 (pin11), servo2 (pin10) and shift register (pin 12). The last one (pin 12) is fatal if I cut it off. So, this is not a option.

3. Replace Arduino Uno with Arduino Mega 2560. This would be a easy fix. However, it is not desirable because I sold the parts to my members in my robotic club to build the same robot. Anyways, I decided to use Arduino Mega 2560 for the future purchases if my member wants to buy the parts from me. For my own robot, I am not taking this option.

4. Use I2C motor shield. This would be an easy fix as well. However, I don’t like it because I want to use what I already have.

5. Use only one L293D motor driver (from the motor shield). This is what I end up going with. I like this option because:

  • It only takes 4 pins to control the 2 DC motors in the chassis.
  • It is a learning experience for me to directly control the motor driver
  • I get to use the prototyping shield that comes with the kit

 Driving L293D directly using Arduino Uno

This is how my solution look like

driving_l293d_motor_driver_directly_with_arduino_uno_2

In the picture, it shows that the L293D motor driver IC (from the motor shield) is soldered down to the prototype shield. I am using header pins and Dupont cables to make the connections.

The schematic is shown below (click to enlarge):

l293d_proto_schem

Basically, I am only using digital pins 4-7 to control 2 DC motors. I also added two large capacitors (470uF each) to reduce power supply noise caused by the motors. I haven’t tried to determine what the minimum size to use. It turns out that the motors run pretty well with those.

Here is the basic code to control the motors:

 

// pins controller motors
#define motor1_pos 4
#define motor1_neg 5
#define motor2_pos 6
#define motor2_neg 7

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

  // set the pin directions
  pinMode(motor1_pos,OUTPUT);
  pinMode(motor1_neg,OUTPUT);
  pinMode(motor2_pos,OUTPUT);
  pinMode(motor2_neg,OUTPUT);
}


void loop() { 

  robotForward(1000);
  Serial.println("Forward");

  robotBackward(1000);
  Serial.println("Backward");

  robotLeft(1000);
  Serial.println("Left");
  
  robotRight(1000);
  Serial.println("Right");
 
  robotStop(1000);
  Serial.println("Stop");
}



void robotStop(int ms){
  digitalWrite(motor1_pos, LOW); 
  digitalWrite(motor1_neg, LOW); 
  digitalWrite(motor2_pos, LOW); 
  digitalWrite(motor2_neg, LOW); 
  delay(ms);
}

void robotForward(int ms){
  digitalWrite(motor1_pos, HIGH); 
  digitalWrite(motor1_neg, LOW); 
  digitalWrite(motor2_pos, HIGH); 
  digitalWrite(motor2_neg, LOW); 
  delay(ms);
}

void robotBackward(int ms){
  digitalWrite(motor1_pos, LOW); 
  digitalWrite(motor1_neg, HIGH); 
  digitalWrite(motor2_pos, LOW); 
  digitalWrite(motor2_neg, HIGH); 
  delay(ms);
}
void robotLeft(int ms){
  digitalWrite(motor1_pos, LOW); 
  digitalWrite(motor1_neg, HIGH); 
  digitalWrite(motor2_pos, HIGH); 
  digitalWrite(motor2_neg, LOW); 
  delay(ms);
}

void robotRight(int ms){
  digitalWrite(motor1_pos, HIGH); 
  digitalWrite(motor1_neg, LOW); 
  digitalWrite(motor2_pos, LOW); 
  digitalWrite(motor2_neg, HIGH); 
  delay(ms);
}