GOduino II = Arduino + L293D Variable Speed Motor Controller

NTRODUCTION

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.

GOduino_II_pcb__14_.jpg


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.

GOduino_II_pcb__20_.jpg


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.

l293d-to-atmega328.jpg



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...

GOduino_II_pcb__34_.jpg

 

GOduino_II_pcb__29_.jpg



REFERENCES

GOduino: The Arduino Uno + Motor Driver clone
http://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
http://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

 

https://www.youtube.com/watch?v=seQ-r3Kdp0w?version=3

Cost of the build

Bitar, you have done an awesome job in developing the GoDuino and GoDuino II. This is pretty helpful material but the cost to build is a bit deceptive. Following your article in instructibles, I decided to make an arduino with a motor board (GoDuino 1) as my first MCU but the estimated cost of the project was over $30 so that I had to scrap the project and buy an arduino for myself. Please change the cost to atleast $25 which is more realistic.

One option you might have to save money

is to lose the crystal and caps, and, make adjustments to use the internal oscillator. Save money and get two more pins too. :slight_smile:

hackaday had an article about removing the crystal and caps to gain a pair of pins. mogul is working on using the internal oscillator and programming as an arduino also.

Link to the actual article: http://www.spikenzielabs.com/blog/?p=434

Futurlec < $12

Thanks!  Try buying the parts from Futurlec.com My total was came out to $12 plus shipping. See list below. So now you can make 2 GOduinos :slight_smile:

I have cut and paste a cart with all the parts:

 

ITEM NAME ITEM DESCRIPTION QUANTITY PRICE AMOUNT
ATMEGA328P-AU ATMega328 32-Pin 20MHz 32kb 8-bit Microcontroller $ 3.30 $ 3.30
L293 L293 Push-Pull 4-Channel Driver IC (L293D) $ 2.90 $ 2.90
C022PC 22pF 50V Ceramic Capacitors $ 0.05 $ 0.10
CRY16.000 16.000MHz Crystal $ 0.30 $ 0.30
C010U16E 10uF 16V Radial Electrolytic Capacitor $ 0.05 $ 0.10
C100U16E 100uF 16V Radial Electrolytic Capacitor $ 0.10 $ 0.10
7805T 7805T - 5V 1A Positive Regulator (LM7805) $ 0.25 $ 0.25
ICS16 16 Pin IC Socket $ 0.07 $ 0.07
ICS28 28 Pin IC Socket $ 0.12 $ 0.12
LED10R Red 10mm Round LED $ 0.20 $ 0.40
R220K14W 220kohm 1/4W 5% Carbon Film Resistor $ 0.10 $ 0.20
R010KMF 10kohm 1/4W 1% Metal Film Resistor $ 0.20 $ 0.20
TACT004 Black Standard Tactile Switch $ 0.30 $ 0.30
HEADS20 20 Pin .100 Straight Male Headers $ 1.50 $ 1.50
C100UC 0.1uF 50V Ceramic Capacitors $ 0.10 $ 0.20
EXPBRD Experimenters Board $ 1.50 $ 1.50
Subtotal: $ 11.54
Total price: $ 11.54

savings

Thanks birdmun. Will try and update for my next revision of GOduino.

CORRECTION: 220ohm not 220Kohm

I have accidently included two 220Kohm resistors when they should be 220Ohm only. So just replace this: 

R220K14W 220kohm 1/4W 5% Carbon Film Resistor

with this:

R220R14W 220ohm 1/4W 5% Carbon Film Resistor

Very clean design. However,

Very clean design. However, much to big for my last project. Try to get the size down to a minimum. 

I “invented” my version with an AtTiny for my last project EL2ISA2. It’s a very basic design (and even lower costs of total 3US$) with just the AtTiny and the L293 on board but it’s the right form factor for this robot. 

Please go ahead and keep creating. I am sure you will inspire me and many other LMRians with your concept.

The internal clock works up

The internal clock works up to 8MHz. If you select the board as Arduino Pro 8MHz/3.3V you can use it as a regular Arduino and everything works. This is what I’ve done for my uBipediono robot. Oh, you also need to load the 8MHz bootloader and set the proper fuses…

Re-mapping the 2 digital pins that were used by the crystal is not that easy, you need to edit the files in Arduino, or call the pin registers directly. 

Thanks lumi, Ro-Bot-X for

Thanks lumi, Ro-Bot-X for the suggestions and tips.

SN754410 or L293D

Amazing work Bitar, Only thing I wasn’t sure about is the use of the L293D.

For me the SN754410 is almost 1/2 the price (digi-key) and can take almost double the current. 1A per motor and 2A peak.

Good news is they work in exactly the same way.

Thanks for getting me thinking again :wink:

 

 

**SN754410 **

Thanks, SkeptiKalYes the SN754410 is a good substitute. I picked the L293d because of its flyback diodes. It offers reasonable protection against spikes and reduces circuit complexity. The tradeoff seems to be the lower current ceiling of the L293D. For my own purposes, I would use the SN754410 

Legend or not?

I have seen so much discussion about wether SN754410 has flyback diodes or not. I compared the datasheets of these two drivers and the schematics and for me it looks very much like it has clamp diodes built in, acutally it is said on front page of datasheet. Somebody read the datasheets and correct if i’m wrong.

for ESD protection

 

I researched this a while ago and came across this tidbit on Ladyada’s website:

“On using the SN754410: Some people use the SN754410 motor driver chip because it is pin-compatible, has output diodes and can provide 1A per motor, 2A peak. After careful reading of the datasheet and discussion with TI tech support and power engineers it appears that the output diodes were designed for ESD protection only and that using them as kickback-protection is a hack and not guaranteed for performance. For that reason the kit does not come with the SN754410 and instead uses the L293D with integrated kickback-protection diodes. If you’re willing to risk it, and need the extra currrent, feel free to buy SN754410’s and replace the provided chips.”

http://www.ladyada.net/make/mshield/use.html

Then I came across this on the TI website but nothing official.

http://e2e.ti.com/support/applications/motor_drivers/f/38/t/110876.aspx

 I guess implementers should decide based on their level of comfort. 

 

I guess it all depends on

I guess it all depends on what motors you are using and at what voltage. The idea is to stay in the range of the internal diodes of the SN754410, even if they were designed for other purposes. I have never burned one and I used a lot of them. But, I never had a stalled motor on a small robot, always the motors were below the 1A current rating and I did not use too high voltages. Usually 6V, sometimes 7.4V. Oh, one more thing, it’s always a good protection measure to stop the motor in software before reversing direction. I am selling the SN754410 in all my kits and no one has complained that hey burned their chip. It all depends if you work within the limits or not.

Here is an idea I had to test out the motor’s back EMF voltage. Best to use an oscilloscope, but a DMM will work too, but it may be too slow to show the peak value. Hook up your DMM or scope to measure the voltage on the motor, connect the motor to 6V, the DMM will show you the exact voltage on the motor. Now disconnect the power. The DMM will show a negative voltage that is the back EMF generated. Since it dies fast, the DMM may not catch it, that’s why it is best to use a scope. If you short the leads on the motor, the back EMF goes back to the motor. In an H-bridge circuit, that back EMF voltage is channeled to the battery through the clamping diodes. If the back EMF voltage is over the diodes max ratings, they will burn and the H-bridge chip will be destroyed. But if you brake the motor (it’s like shorting the leads), the back EMF goes back to the motor, or at least most of it, so you are reducing the chances that the internal diodes wil get burned.

In my kits, I am using the 2 pin motor control where the Enable is tied High and one of the direction pins sets the direction and the other direction pin is used for the PWM signal. The PWM signal quickly alternates between High and Low, and the amount of time the signal is High determines the voltage that results because of the inductance load (the motor). If the direction pin is Low, when the PWM signal is on a Low alternance, the motor is braked and when the signal is on a High alternance, the motor runs. Because of the braking part, any back EMF voltage is shorted through the motor and does not affect the SN754410 chip. Only if the Enable is tied Low you have to be carefull because the motor is “disconnected” from the control circuit, but the current still runs through the SN754410 chip, so while the motor is coasting to a stop, it generates back EMF that needs to be dealt with. We use geared motors that are innefficient and there is also the weight load on the motors that slows them down fast to a stop, so even without external protection diodes, the SN754410 does a good job at dealing with the back EMF.

 

Nice kits

I checked out your kits. Nice job.