Introduction: GOduino II = Arduino + L293D Variable Speed Motor Controller

About: Did I unplug the solder iron?
UPDATES

GOduino II was featured on dangerousprototypes.com

04/07/2012  I have added a budget slide for those readers who were wondering where I got my < $20 budget for the GOduino II. 

INTRODUCTION

The GOduino II is a self-contained programmable controller for wheel-based robots. It's an Arduino Uno clone plus an L293D motor driver for under $20. It controls both motor direction and speed. The prototype predecessor to this is the GOduino, a basic version of this controller on a breadboard. I will maintain updates to this guide both here and on my blog http://techbitar.blogspot.com



BACKGROUND

I have designed a few basic robots using the Arduino Uno and motor shields. Both are great for prototyping. But I found myself taking my robots apart every time I needed to build another robot. It's not cost effective to buy more Arduino microcontrollers and motor shields for every new robot project.

Also in countries like Jordan where the average monthly income is about $300 and an outrageously high tariff code that's hostile to technology, it becomes a necessity for students and makers to seek locally assembled low cost, repairable alternatives to imported electronic circuits.

FUNCTIONALITY

The GOduino II works for 2 motors only, and leaves plenty of Arduino pins available for sensors. This is also my first from-scratch pcb adventure. If you look at the back of the GOduino II, you will see all sort of clues to my inexperience. And yes, I am a software guy so this is all relatively new to me. You will note that some of my headers have buck teeth. I had a few accidents while soldering. My next version will be neater.

This may not be state of the art stuff but it does the job for me and my protospace members. If it helps anyone out there, please send me a link. As always, if you see any flaws or have suggestions that can make this a better design, please share your thoughts.

CREDIT

This project is based on the works of so many good folks. Please see References section at the bottom for some of the projects that provided the foundation for this modest PCB project.

PARTS LIST

ITEM    QTY
Atmega328p w/Opti bootloader 1
L293D h-bridge 1
16Mhz crystal 1
PCB  1
22pf caps 2
100uF cap 1
10uF cap 2
0.1uF cap 4
T7805 5V DC regulator 1
DIP sockets 28-pin 1
DIP socket 16-pin 1
Headers 1
Jumper wires 10
LED 2
Resistors 220 Ohms 2
Resistor 10K Ohms 1
Push button 1

I have estimated the total cost of the GOduino II around $20 + shipping & handling.

As for the Arduino IDE 1.0, it can be downloaded for free
http://arduino.cc/en/Main/Software

MAPPING L293D PINS TO ATMEGA328P (ARDUINO UNO)

The bullet numbers below corresponds to the L293D pins. This pin mapping works with my test Arduino sketch. But you can change it to suit your purposes.

1. Enable/disable Motor 1. Also used to control speed of Motor 1. Arduino digital PWM pin 9. ATmega328 pin 15.
2. Connect to Arduino to control direction of Motor 1 rotation. Arduino digital pin 3. ATmega328 pin 5.
3. Connect to Motor 1 first pole.
4. Connect to Ground.
5. Connect to Ground.
6. Connect to Motor 1 second pole.
7. Connect to Arduino to control direction of Motor 1 rotation.  Arduino digital pin 2. Atmega328 pin 4.
8. Connect to power supply which will power both motors. This may or may not be regulated.
9. Enable/Disable for Motor 2. Also used to control speed of Motor 2. Connect to Arduino PWM pin 10. ATmega328 pin 16 .
10. Connect to Arduino to control direction of rotation for Motor 2. Arduino pin 7. ATmega328 pin 13.
11. Connect to Motor 2 - first pole.
12. Connect to Ground.
13. Connect to Ground.
14. Connect to Motor 2 - second pole.
15. Connect to Arduino to control direction of rotation for Motor 2. Arduino pin 8. ATmega328 pin 14.
16. Connect to regulated 5V DC.

PCB NOTES

Why did I use male headers to expose the pins of both the ATmega328p and the L293d? You can use Arduino style headers instead but I had plenty of male headers and plenty of female jumper wires. But for my next GOduino II build, I will use Arduino style headers. I feel safer with fewer IC pins exposed.

L293D CURRENT 

The L293D in the GOduino II can handle sustained current of 600 mA per motor. There seems to be some misconception about this ICs ability to handle 1.2A peak current per motor.  The L293D datasheet says it does but for a fraction of a second  (100 µs). This is not enough to support a motor operating at peak/stall current which may last for seconds or minutes.

But the good news is that you can double the 600mA per motor support by piggybacking another L293D. At its simplest, this means soldering one L293D on top of another while matching the pins.

L293D VOLTAGE

The L293D needs to be powered in two ways. It needs 5V DC for its logic circuits (pin 16) and power from 4.5V to 36V for the motors (pin 8). Check your motor datasheet to find its voltage. 
I found out that by controlling the PWM signals from the ATmega328p wired to the enable pins of the L293D I managed to change the voltage supplied to the motor. So even though I supply 7.2V to my motors via the L293D, I can reduce it by manipulating the values in the analogWrite function in my Arduino sketch.

BRUSHED DC MOTORS

The GOduino II works with up to 2 brushed DC motors within the range of 4.5V to 36V with peak load of 600mA for each motor. These motors generate plenty of electrical noise that can cause all sorts of issues from poor sensor reading (if you have sensors attached to your GOduino II) to constant IC resets. To deal with this, I always place a 0.1uF ceramic capacitor across the poles of each motor.

MOTOR ROTATION

The direction of your motor rotation is a subjective call.  In my code, I use the words forward and back to describe some of my functions. In reality, the way you wire your motors and pins determines when the rotation of a motor is forward or backward or clockwise vs counter-clockwise. Keep in mind that motors on opposite sides of a robot platform spin opposite of one another. If your motors don't rotate the way you want them, often times the fix can be in your code without resorting to rewiring.

PROGRAMMING GODUINO II

So how do you program the ATmega328p on the GOduino II? A computer with a serial port should do nicely. But without a serial port, here are the alternatives.


1)  If you have an Arduino Uno DIP model you can just load your sketch from the Arduino IDE 1.0 the way you typically do. Then remove the ATmega328p from your Arduino Uno and insert it into the GOduino II IC socket. That's it. I ordered a few ATmega328p ICs (DIP) pre loaded with the Arduino Uno bootloader so I can use them in this manner.

2) Or you can use the Arduino Uno to program an ATmega328p. SparkFun has a good tutorial on how to do this. See article Reinstalling your Arduino bootloader and Using an Arduino to Program an AVR  in the references section.

3) Or you can use an inline programmer like the ones sold by Sparkfun, LadyAda, or Pololu to load Arduino  sketches directly from the Arduino IDE into the ATmega328p without removing it from the GOduino II PCB socket. See link in references section to the article by David A. Mellis on how to build and program an Arduino Uno on a breadboard. You can save a dollar or two by buying the 328p blank then burning the bootloader yourself if you have the gear and know how.

THE ARDUINO TEST SKETCH

The Arduino 1.0 test sketch below seems like a long program but it's mostly repeating blocks of code to spin the motors and to ensure the pins and motor poles are connected properly. I have written 4 functions that can handle most robot locomotion tasks but feel free to change it so long as the L293D enable pins (1,9) are connected to PWM pins on the Arduino/ATmega328p and the code below is updates to reflect any rewiring of pins.

/*
REMIXED BY: TECHBITAR / HAZIM BITAR

DATE: APRIL 3, 2012

PROJECT: GOduino II TEST

FUNCTION: This sketch is an Arduino 1.0 IDE test program for the GOduino II PCB  board. The GOduino II is an integrated "runtime" Arduino Uno and L293D h-bridge aka motor driver which allows forward and  reverse movement of motors as well as variable speed.  This test code assumes two motors (each  < 600mA in peak current ) are attached to the GOduino II

This sample sketch calls the following three functions with variable motornum = 1 or 2 to   signify Motor 1 and Motor 2.

- motorforward(int motornum)
- motorback(int motornum)
- motorstop(int motornum)
- motorspeed(int motor1, int motor2)

LICENSE: This is shareware but please give credit. 

WEBSITE: http://techbitar.blogspot.com

EMAIL: techbitar AT gmail DOT com

*/

// map motor poles to Arduino pins
#define motor1pole1 2 
#define motor1pole2 3
#define motor2pole1 7
#define motor2pole2 8

// map L293d motor enable pins to Arduino pins
#define enablePin1 9
#define enablePin2 10

#define M1_MAX_SPEED 100
#define M2_MAX_SPEED 100

#define motordelay 30
#define debugmotorsec 3000

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

  // set mapped L293D motor1 and motor 2 enable pins on Arduino to output (to turn on/off motor1 and motor2 via L293D)
  pinMode(enablePin1, OUTPUT);
  pinMode(enablePin2, OUTPUT);

  // set mapped motor poles to Arduino pins (via L293D)
  pinMode( motor1pole1 , OUTPUT);
  pinMode( motor1pole2, OUTPUT);
  pinMode( motor2pole1, OUTPUT);
  pinMode( motor2pole2 , OUTPUT);
  motorspeed(0, 0);
}

int mspeed = 100;  // pick a starting speed up to 255

void loop() {

// set speed of motor 1 and 2 to same speed
  motorspeed(mspeed, mspeed);

// spin motor 1 only in one direction
  Serial.print("MOTOR 1 FORWARD @ SPEED: ");  
  Serial.println(mspeed);
  motorforward(1);
  delay(debugmotorsec);
  motorstop(1);

  // spin motor 2 only in one direction
  Serial.print("MOTOR 2 FORWARD @ SPEED: ");  
  Serial.println(mspeed);
  motorforward(2);
  delay(debugmotorsec);
  motorstop(2);

  // spin motor 1 only in opposite direction
  Serial.print("MOTOR 1 BACK @ SPEED: ");  
  Serial.println(mspeed);
  motorback(1);
  delay(3000);
  motorstop(1);

// spin motor 2 only in opposite direction
  Serial.print("MOTOR 2 BACK @ SPEED: ");   
  Serial.println(mspeed);
  motorback(2);
  delay(debugmotorsec);
  motorstop(2);

// stop both motors 1 and 2
  Serial.println("BOTH MOTORS STOP FOR 2 SEC.");
  motorstop(1);
  motorstop(2);
  delay(2000);

// spin both motors in one direction
  Serial.print("BOTH MOTORS FORWARD @ SPEED: ");
  Serial.println(mspeed);
  motorforward(1);
  motorforward(2);
  delay(debugmotorsec);

// stop both motors
  Serial.println("BOTH MOTORS STOP FOR 2 SEC."); 
  motorstop(1);
  motorstop(2);

  delay(2000);
// spin both motors in opposite direction
  Serial.print("BOTH MOTORS BACK @ SPEED: ");
  Serial.println(mspeed);
  motorback(1);
  motorback(2);
  delay(debugmotorsec);

// stop both motors
  Serial.println("BOTH MOTORS STOP FOR 2 SEC.");
  motorstop(1);
  motorstop(2);
  delay(2000);


// spin both motors but in opposite directions
  Serial.print("MOTOR1 FORWARD | MOTOR2 BACK @ SPEED: "); 
  Serial.println(mspeed);
  motorforward(1);
  motorback(2);
  delay(debugmotorsec);

// stop both motors
  Serial.println("BOTH MOTORS STOP FOR 2 SEC.");
  motorstop(1);
  motorstop(2);
  delay(2000);

// spin both motors in the other opposite direction
  Serial.print("MOTOR1 BACK | MOTOR2 FORWARD @ SPEED: ");
  Serial.println(mspeed);
  motorback(1);
  motorforward(2);
  delay(debugmotorsec);

// stop both motors
  Serial.println("BOTH MOTORS STOP FOR 2 SEC.");
  motorstop(1);
  motorstop(2);
  delay(2000);

  mspeed += 50;  // add 50 to speed of motor spin. Max speed 255

// set speed of motor 1 and 2 to same new speed
  motorspeed(mspeed,mspeed);

}

// MOTOR FUNCTIONS

void motorstop(int motornum){
  delay(motordelay);
  if (motornum == 1) {
    digitalWrite(motor1pole1, LOW);
    digitalWrite(motor1pole2, LOW);
  }
  else if (motornum == 2) {

    digitalWrite(motor2pole1, LOW);
    digitalWrite(motor2pole2, LOW);
  }
  delay(motordelay);
}

void motorforward(int motornum){
  if (motornum == 1) {
    digitalWrite(motor1pole1, HIGH);
    digitalWrite(motor1pole2, LOW);
  }
  else if (motornum == 2) {

    digitalWrite(motor2pole1, LOW);
    digitalWrite(motor2pole2, HIGH);
  }
  delay(motordelay);
}

void motorback(int motornum){
  if (motornum == 1) {
    digitalWrite(motor1pole1, LOW);
    digitalWrite(motor1pole2, HIGH);
  } 
  else if (motornum == 2) {
    digitalWrite(motor2pole1, HIGH);
    digitalWrite(motor2pole2, LOW);
  }
  delay(motordelay);
}

void motorspeed(int motor1speed, int motor2speed) {
  if (motor1speed > M1_MAX_SPEED ) motor1speed = M1_MAX_SPEED; // limit top speed
  if (motor2speed > M2_MAX_SPEED ) motor2speed = M2_MAX_SPEED; // limit top speed
  if (motor1speed < 0) motor1speed = 0; // keep motor above 0
  if (motor2speed < 0) motor2speed = 0; // keep motor speed above 0
  analogWrite(enablePin1, motor1speed);
  analogWrite(enablePin2, motor2speed);
}

// ====================================

FINAL NOTES

I will continue to evolve the GOduino II while looking for better alternatives that are high on the repairability and hackability score. A $30 Arduino Uno could end up costing $60 after tariffs and shipping in Jordan. And if something goes wrong with it, you might as well throw it away since no local facility exists to replace and repair smd components. Since basic electronic parts are readily available locally, it should be easy and inexpensive to build and repair the GOduino II. DIP lives on...

BUDGET

A few readers wondered where to buy the parts to stay within budget. I order my parts from Futurlec.com The whole GOduino adds up to less than $12 If you don't have an Arduino UNO DIP microcontroller and don't wish to buy one, you will need an FTDI USB-serial programmers. You can buy those for about $15 

Futurlec is not my sponsor and I don't get commission or discounts for mentioning them.


REFERENCES

GOduino: The Arduino Uno + Motor Driver clone
https://www.instructables.com/id/GOduino-The-Arduino-Uno-Motor-Driver-clone

Building an Arduino on a Breadboard by David A. Mellis
http://arduino.cc/en/Main/Standalone

Control your motors with L293D and Arduino by Guilherme Martins
https://www.instructables.com/id/Control-your-motors-with-L293D-and-Arduino

Control a DC motor with Arduino and L293D chip
http://luckylarry.co.uk/arduino-projects/control-a-dc-motor-with-arduino-and-l293d-chip

Reinstalling your Arduino bootloader
http://www.sparkfun.com/tutorials/247

Using an Arduino to Program an AVR
http://www.sparkfun.com/tutorials/200