Friday, June 18, 2010

Arduino's and Motors (using SN75441)

Arduino's and Motors (using SN75441)


I am very fortunate that I have the Internet available to me as there is so much available information available on so many subjects.  I like to think that once the user has a command or understanding of how search engines work that they have access to nearly limitless information resources.  For example, ITP Physical Computing has put together an Arduino class online that is available to the world.  Thank you very much!

Anyways, at this point I have had some experience with an Arduino motor shield that I used to test and control some small motors.  But, like anything, you can learn so much more by actually building the circuit instead of just using a ready-made solution, so I decided to do so.  I found that I had greater control over the motors and that I could put similar functionality in a smaller circuit than that which the motor shield offered, although initially the wiring would look scary.

I made a change to the original circuit suggested by ITP.  That change to the circuit was supplying SN75441  pin 8 (Vcc2) with power from a secondary battery instead of the 5v that the Arduino offered.  My reason for doing this is because powering the motors from the Arduino 5v would reset the Arduino.  I decided to relieve the stress on the Arduino and use an external battery to allow for more power to the motors. I also changed the code to allow for independent motor control via serial and I changed the use of the switch to an on/off switch for the motors.  The code is at the bottom of this post. 

Once I wired up the SN75441 motor driver IC to the Arduino and the individual motors from the dual-gearbox (bought from Sparkfun.com) I ran into a problem.  The problem was that even with only one motor on, both motors would spin which is obviously a serious problem for steering.  Sparkfun user "AdamBaba" commented that "You are only supposed to do 1 side for differential drive."  So, I removed the allen screw from the other hex nut, tested the Arduino code and found that his solution worked. 


REFERENCES:
http://itp.nyu.edu/physcomp/Labs/DCMotorControl
http://www.sparkfun.com/commerce/product_info.php?products_id=319
http://www.ecs.umass.edu/ece/m5/tutorials/H-Bridge_tutorial.html


ARDUINO CODE:  (copy and paste)

// Basic H-Bridge Motor Driver Control 
// Author:          Nickolas Andersen
// Original Date:   06/14/2010
//                            Version 1
// Very modified version of "DC Motor Control Using an H-Bridge" from ITP Physical Computing
// http://itp.nyu.edu/physcomp/Labs/DCMotorControl

/*
  High Level Operation:
  User:     Uses serial terminal, PS2 gamepad to send commands.
  Arduino:  Accepts serial commands, PS2 gamepad commands.
  Arduino:  Controls the SN75441 Dual H-Bridge Motor Driver IC.
*/

// The switchPin allows or disallows motor control.
// The motor's "EN" pin on and set with a value. (on a PWM pin.)
// Motor1A/Motor2A (and Motor3A/4A) can be set HIGH or LOW each so that polarity (spin direction) is set.

// Global Variables
  const int switchPin = 2;    // switch input

  const int motorEN12 = 9;   
  const int motor1A   = 3;
  const int motor2A   = 4;

  const int motorEN34 = 10;
  const int motor3A   = 11;
  const int motor4A   = 12;

  const int ledPin = 13;      // LED

  char SerialValue;

  int speedvalueA = 0 ; 
  int speedvalueB = 0 ; 

void setup() {

  Serial.begin(57600);
  pinMode(switchPin, INPUT); // set the switch as an input:

  // Set Motor pins as output
  pinMode(motorEN12, OUTPUT);
  pinMode(motor1A, OUTPUT);
  pinMode(motor2A, OUTPUT);

  pinMode(motorEN34, OUTPUT);
  pinMode(motor3A, OUTPUT);
  pinMode(motor4A, OUTPUT);

  pinMode(ledPin, OUTPUT);
}

void loop()
  {
  if (Serial.available() > 0)  { Check4SerialCOMMANDS() ; }

  if (digitalRead(switchPin) == HIGH)
    {
    analogWrite(motorEN12, speedvalueA);
    digitalWrite(motor1A, HIGH);
    digitalWrite(motor2A, LOW);
   
    analogWrite(motorEN34, speedvalueB);
    digitalWrite(motor3A, HIGH);
    digitalWrite(motor4A, LOW);
    }
  else
    {
    digitalWrite(motorEN12, LOW);
    digitalWrite(motorEN34, LOW);
    digitalWrite(motor1A, LOW); 
    digitalWrite(motor2A, LOW); 
    digitalWrite(motor3A, LOW); 
    digitalWrite(motor4A, LOW); 
    }
  }


void Check4SerialCOMMANDS()
  {
  SerialValue = Serial.read() ;   // Do a serial data read.
    if (  (SerialValue==('0') or (SerialValue==(char(0)))))    {  speedvalueA = 0;   Serial.print("A="); Serial.print(speedvalueA); Serial.println(" "); return; } 
    if (  (SerialValue==('1') or (SerialValue==(char(1)))))    {  speedvalueA = 51;  Serial.print("A="); Serial.print(speedvalueA); Serial.println(" "); return; } 
    if (  (SerialValue==('2') or (SerialValue==(char(2)))))    {  speedvalueA = 102; Serial.print("A="); Serial.print(speedvalueA); Serial.println(" "); return; } 
    if (  (SerialValue==('3') or (SerialValue==(char(3)))))    {  speedvalueA = 153; Serial.print("A="); Serial.print(speedvalueA); Serial.println(" "); return; } 
    if (  (SerialValue==('4') or (SerialValue==(char(4)))))    {  speedvalueA = 204; Serial.print("A="); Serial.print(speedvalueA); Serial.println(" "); return; } 
    if (  (SerialValue==('5') or (SerialValue==(char(5)))))    {  speedvalueA = 255; Serial.print("A="); Serial.print(speedvalueA); Serial.println(" "); return; } 
   
    if (  (SerialValue==('p') or (SerialValue==(char('p')))))  {  speedvalueB = 0;   Serial.print("B="); Serial.print(speedvalueB); Serial.println(" "); return; } 
    if (  (SerialValue==('q') or (SerialValue==(char('q')))))  {  speedvalueB = 51;  Serial.print("B="); Serial.print(speedvalueB); Serial.println(" "); return; } 
    if (  (SerialValue==('w') or (SerialValue==(char('w')))))  {  speedvalueB = 102; Serial.print("B="); Serial.print(speedvalueB); Serial.println(" "); return; } 
    if (  (SerialValue==('e') or (SerialValue==(char('e')))))  {  speedvalueB = 153; Serial.print("B="); Serial.print(speedvalueB); Serial.println(" "); return; } 
    if (  (SerialValue==('r') or (SerialValue==(char('r')))))  {  speedvalueB = 204; Serial.print("B="); Serial.print(speedvalueB); Serial.println(" "); return; } 
    if (  (SerialValue==('t') or (SerialValue==(char('t')))))  {  speedvalueB = 255; Serial.print("B="); Serial.print(speedvalueB); Serial.println(" "); return; } 
  }


SN754410 Pinout:Function/Pin Function/Pin
1,2EN (1)    (16) Vcc1
1A    (2)    (15) 4A
1Y    (3)    (14) 4Y
GND   (4)    (13) GND
GND   (5)    (12) GND
2Y    (6)    (11) 3Y
2A    (7)    (10) 3A
Vcc2  (8)    (9)  3,4EN

Main Circuit Wiring: 
SN754410 to Arduino Hookups:
SN754410 1,2EN to  Arduino 9
SN754410 1A to Arduino 3
SN754410 1Y to Motor +
SN754410 GND to Circuit Ground
SN754410 GND to Circuit Ground
SN754410 2Y to Motor -
SN754410 2A to Arduino 4
SN754410 Vcc2 to External Battery
SN754410 3,4EN to Arduino 10
SN754410 3A to Arduino 11
SN754410 3Y to Motor +
SN754410 GND to Circuit Ground
SN754410 GND to Circuit Ground
SN754410 4Y to Motor -
SN754410 4A to Arduino12
SN754410 Vcc1 to Arduino

4 comments:

  1. Brilliant. Works a treat. Many thanks.
    Austin

    ReplyDelete
  2. I'm interested in details of the control input you mentioned.

    Your code comments say " Arduino: Accepts serial commands, PS2 gamepad commands".

    Is that serial OR a PS2 gamepad?
    A PS2 gamepad connected somehow to a serial port?

    How about some sort of sketch or schematic of some sort?

    ReplyDelete
  3. The project featured in this post actually supported control via the normal serial port AND PS2, although I did not demonstrate the PS2 control for this video. I have a test sketch that I use when I connect a PS2 gamepad to my projects. I plan on putting up a post on it in the future, probably in a week or two.

    ReplyDelete
  4. After I looked at the code, it became clear. Keyboard inputs, one set of key presses for one motor, the other set for the second motor.

    Yes, looking forward to the PS2 sketch. Repurposing a game controller for something USEFUL..I like that idea

    ReplyDelete

Keep it clean. :)