9-18V (up to 4A) DC motors + arduino

Hi everyone

I am trying to help a couple students with a project that involves controlling some DC motors with propellers attached.

Initially we were going to use this

But no luck in getting it to work.

Now, I do have a lab power supply and the effect we can get with pushbuttons would suffice. Would I be able to use a sensors instead to turn motors on an off? Putting it in another words...is there a way i can wire this up such that via software i can control if power is driven to the motors or not?

Thanks in advance.

But no luck in getting it to work.

Well you'll need to elaborate on what that means.... does the code compile?- if not what are the errors?... if it does compile, what happens when it runs that shouldn't happen or doesn't happen that should?

You'll need to post your code, and also a schematic of the circuit would help.

To answer your other question...

Putting it in another words...is there a way i can wire this up such that via software i can control if power is driven to the motors or not?

.... well the answer there is a definite yes: you use the value of the sensor in you code, as input on which you base a decision which outputs the value to the motor. Let's say your sensor measures distance to an object. You could say, well, the object is >1m, I'll drive the motors full tilt. Or oops, it's between 0.5 m and 1m, so better only go half-speed. Or lastly, oh-oh, less than 0.5m better stop.

Exactly how you hook up and read a sensor, depends on the actual sensor of course, but if you get them from an "Arduino-friendly" source like Sparkfun or adafruit, they usually come with some sample Arduino code.

The sample code provided compiles fine, but not even following the datasheet wiring diagram for steppers produced any output which may or may not indicate a faulty shield

This was the code for steppers:

#include <ShiftStepper.h>

#define DATPIN    13  
#define SCLPIN    12
#define LATPIN    7
#define MRPIN     8  
#define INDPIN     2

// Set up the step sequence for a random motor...
static const uint8_t stepSequence[4] = {0x2, 0x4, 0x1, 0x8};
// Set up channel combinations for the motors...
static const uint8_t motChans0[__channelsPerMotor__] = {0,2,3,1};
static const uint8_t motChans1[__channelsPerMotor__] = {4,5,6,7};
static const uint8_t motChans2[__channelsPerMotor__] = {11,9,10,8};
static const uint8_t motChans3[__channelsPerMotor__] = {15,14,13,12};

// Declare some required globals

shiftChain *myChain = 0; // initializes so everyone can see it, but doesn't call the constructor
shiftStepMotor motor0(__channelsPerMotor__, stepSequence, motChans0);
shiftStepMotor motor1(__channelsPerMotor__, stepSequence, motChans1);
shiftStepMotor motor2(__channelsPerMotor__, stepSequence, motChans2);
shiftStepMotor motor3(__channelsPerMotor__, stepSequence, motChans3);
shiftDevice *motors[4] = {&motor0, &motor1, &motor2, &motor3};
shiftSixteen board0(4, motors);
shiftBoard *boards[1] = {&board0};
shiftChain storeChain(1, boards, DATPIN, SCLPIN, LATPIN, MRPIN, INDPIN);

/* ISR functions to shift it all out */

ISR (TIMER2_OVF_vect)
{
  myChain->doTick();
}

void setup (void) 
{
  myChain = &storeChain;
  Serial.begin(57600); 
  Serial.println("I live!"); 
  myChain->startTimer(__preScaler32__, 0, 2);
  Serial.println("Timer started"); 
  ((shiftStepMotor*)myChain->getBoard(0)->getDev(0))->doSteps(-1,1);  // set motor for continuous rotation
  ((shiftStepMotor*)myChain->getBoard(0)->getDev(1))->doSteps(-1,-1); // set motor for continuous rotation
  ((shiftStepMotor*)myChain->getBoard(0)->getDev(2))->doSteps(-1,1);  // set motor for continuous rotation
  ((shiftStepMotor*)myChain->getBoard(0)->getDev(3))->doSteps(-1,-1); // set motor for continuous rotation
}

void loop (void) {
  char in = 0;        // input character
  static int16_t speedSetting = 1;  // speed 
  if (Serial.available() > 0) {
    in = Serial.read();
    switch (in) {
      case '+':
        speedSetting++;
        ((shiftStepMotor*)myChain->getBoard(0)->getDev(0))->setSpeed(speedSetting);
        ((shiftStepMotor*)myChain->getBoard(0)->getDev(1))->setSpeed(-speedSetting);
        ((shiftStepMotor*)myChain->getBoard(0)->getDev(2))->setSpeed(speedSetting);
        ((shiftStepMotor*)myChain->getBoard(0)->getDev(3))->setSpeed(-speedSetting);
        Serial.print("Speed setting: ");
        Serial.print(speedSetting, DEC);
        Serial.print(" Forward speed: ");
        Serial.print(((shiftStepMotor*)myChain->getBoard(0)->getDev(0))->getSpeed(), DEC);
        Serial.print(" Reverse speed: ");
        Serial.println(((shiftStepMotor*)myChain->getBoard(0)->getDev(1))->getSpeed(), DEC);
        break;
      case '-':
        speedSetting--;
        ((shiftStepMotor*)myChain->getBoard(0)->getDev(0))->setSpeed(speedSetting);
        ((shiftStepMotor*)myChain->getBoard(0)->getDev(1))->setSpeed(-speedSetting);
        ((shiftStepMotor*)myChain->getBoard(0)->getDev(2))->setSpeed(speedSetting);
        ((shiftStepMotor*)myChain->getBoard(0)->getDev(3))->setSpeed(-speedSetting);
        Serial.print("Speed setting: ");
        Serial.print(speedSetting, DEC);
        Serial.print(" Forward speed: ");
        Serial.print(((shiftStepMotor*)myChain->getBoard(0)->getDev(0))->getSpeed(), DEC);
        Serial.print(" Reverse speed: ");
        Serial.println(((shiftStepMotor*)myChain->getBoard(0)->getDev(1))->getSpeed(), DEC);
        break;
    }
  }
  delay(10);
}

as per controlling the dc motors via arduino i was just suggested either using a dual chip h-bridge (which I am not sure i could get one that would allow the peak to go up to 4A or close to that value) or a transistor.

I have never worked with transistors but can anyone recommend one that would work for me? I did a bit of research and came across this one
http://www.fairchildsemi.com/ds/TI/TIP120.pdf

but might as well ask! thanks

I'm a bit confused now, because in your first post you didn't mention steppers, just DC motors, but then provide code for steppers....

4A is a lot... are you sure that's what the motors draw?- Checkd the data sheet? Easy to test by putting ammeter in series with motor and measuring the current under no-load and under some load or other, like trying to stop the motor by grabbing the spindle somehow. (Normal safety measures apply....)

Others wiser than I will need to advise on what parts are needed to drive those high current motors, if that's what they are.

Edit... you only need a bridge for a dc motor if you need it bi-directional. Otherwise, a meaty enough transistor will do the trick, as shown here

And further confusion, along with the stepper thing... the shield to which you link, is capable of that current, but then it's not the one in your photo. You're not actually making it easy for us to help you.

thanks again for the fast response

the indicated shield should suffice:
5A at up to 30V

My motors are indeed 9-18v, 24000rpm, 4.2A draw at maximum efficiency (guess it will never go that high with just propellers)

As for the code...I definitely couldn't get the shield to work with DC's so I tested with a stepper, since the documentation and example code provided uses a stepper...hope that clarifies it

Lastly...i only need it to spin in one direction!

I definitely couldn't get the shield to work with DC's

But which shield are you using for your test?- the red one in the photo or the big 5A one in the link?

If you're using the red one then check its specification- it might not be able to provide the current.

In either case, you should post your code and a schematic.

my bad...the stepper driver was just sitting on the breadboard, i used the one i provided link for....

as up now i was trying this code and wiring

(probably there is something wrong with the wiring, i was just trying to get voltage variation on the multimeter but no luck. if i set latchpin to 8, multimeter is at 0, if i use any other pin it gets the power supply voltage

/************************************************************************************************************************************
 * ShiftPWM non-blocking RGB fades example, (c) Elco Jacobs, updated August 2012.
 *
 ************************************************************************************************************************************/

// You can choose the latch pin yourself.
const int ShiftPWM_latchPin=8;


// If your LED's turn on if the pin is low, set this to true, otherwise set it to false.
const bool ShiftPWM_invertOutputs = false;

const bool ShiftPWM_balanceLoad = false;

#include <ShiftPWM.h>   // include ShiftPWM.h after setting the pins!

unsigned char maxBrightness = 255;
unsigned char pwmFrequency = 75;
int numRegisters = 6;
int numOutputs = numRegisters*8;
int numRGBLeds = numRegisters*8/3;
int fadingMode = 0; //start with all LED's off.

unsigned long startTime = 0; // start time for the chosen fading mode

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

  // Sets the number of 8-bit registers that are used.
  ShiftPWM.SetAmountOfRegisters(numRegisters);

  // SetPinGrouping allows flexibility in LED setup. 
  // If your LED's are connected like this: RRRRGGGGBBBBRRRRGGGGBBBB, use SetPinGrouping(4).
  ShiftPWM.SetPinGrouping(1); //This is the default, but I added here to demonstrate how to use the funtion
  
  ShiftPWM.Start(pwmFrequency,maxBrightness);
  printInstructions();
}



void loop()
{    
  if(Serial.available()){
    if(Serial.peek() == 'l'){
      // Print information about the interrupt frequency, duration and load on your program
      ShiftPWM.PrintInterruptLoad();
      Serial.flush();
    }
    else{
      fadingMode = Serial.parseInt(); // read a number from the serial port to set the mode
      Serial.print("Mode set to "); 
      Serial.print(fadingMode); 
      Serial.print(": ");
      startTime = millis();
      switch(fadingMode){
      case 0:
        Serial.println("All LED's off");
        break;
      case 1:
        Serial.println("Fade in and out one by one");
        break;
      case 2:
        Serial.println("Fade in and out all LED's");
        break;                
      default:
        Serial.println("Unknown mode!");
        break;
      }
    } 
  }
  unsigned char brightness;
  switch(fadingMode){
  case 0:
    // Turn all LED's off.
    ShiftPWM.SetAll(0);
    break;
  case 1:
    oneByOne();
    break;
  case 2:
    inOutAll();
    break;
  
  default:
    Serial.println("Unknown Mode!");
    delay(1000);
    break;
  }
}

void oneByOne(void){ // Fade in and fade out all outputs one at a time
  unsigned char brightness;
  unsigned long fadeTime = 500;
  unsigned long loopTime = numOutputs*fadeTime*2;
  unsigned long time = millis()-startTime;
  unsigned long timer = time%loopTime;
  unsigned long currentStep = timer%(fadeTime*2);

  int activeLED = timer/(fadeTime*2);

  if(currentStep <= fadeTime ){
    brightness = currentStep*maxBrightness/fadeTime; ///fading in
  }
  else{
    brightness = maxBrightness-(currentStep-fadeTime)*maxBrightness/fadeTime; ///fading out;
  }
  ShiftPWM.SetAll(0);
  ShiftPWM.SetOne(activeLED, brightness);
}

void inOutTwoLeds(void){ // Fade in and out 2 outputs at a time
  unsigned long fadeTime = 500;
  unsigned long loopTime = numOutputs*fadeTime;
  unsigned long time = millis()-startTime;
  unsigned long timer = time%loopTime;
  unsigned long currentStep = timer%fadeTime;

  int activeLED = timer/fadeTime;
  unsigned char brightness = currentStep*maxBrightness/fadeTime;

  ShiftPWM.SetAll(0);
  ShiftPWM.SetOne((activeLED+1)%numOutputs,brightness);
  ShiftPWM.SetOne(activeLED,maxBrightness-brightness);
}

void inOutAll(void){  // Fade in all outputs
  unsigned char brightness;
  unsigned long fadeTime = 2000;
  unsigned long time = millis()-startTime;
  unsigned long currentStep = time%(fadeTime*2);

  if(currentStep <= fadeTime ){
    brightness = currentStep*maxBrightness/fadeTime; ///fading in
  }
  else{
    brightness = maxBrightness-(currentStep-fadeTime)*maxBrightness/fadeTime; ///fading out;
  }
  ShiftPWM.SetAll(brightness);
}

void alternatingColors(void){ // Alternate LED's in 6 different colors
  unsigned long holdTime = 2000;
  unsigned long time = millis()-startTime;
  unsigned long shift = (time/holdTime)%6;
  for(int led=0; led<numRGBLeds; led++){
    switch((led+shift)%6){
    case 0:
      ShiftPWM.SetRGB(led,255,0,0);    // red
      break;
    case 1:
      ShiftPWM.SetRGB(led,0,255,0);    // green
      break;
    case 2:
      ShiftPWM.SetRGB(led,0,0,255);    // blue
      break;
    case 3:
      ShiftPWM.SetRGB(led,255,128,0);  // orange
      break;
    case 4:
      ShiftPWM.SetRGB(led,0,255,255);  // turqoise
      break;
    case 5:
      ShiftPWM.SetRGB(led,255,0,255);  // purple
      break;
    }
  }
}

void hueShiftAll(){  // Hue shift all LED's
  unsigned long cycleTime = 10000;
  unsigned long time = millis()-startTime;
  unsigned long hue = (360*time/cycleTime)%360;
  ShiftPWM.SetAllHSV(hue, 255, 255); 
}

void randomColors(){  // Update random LED to random color. Funky!
  unsigned long updateDelay = 100;
  static unsigned long previousUpdateTime;
  if(millis()-previousUpdateTime > updateDelay){
    previousUpdateTime = millis();
    ShiftPWM.SetHSV(random(numRGBLeds),random(360),255,255);
  }
}

void fakeVuMeter(void){ // immitate a VU meter
  static int peak = 0;
  static int prevPeak = 0;
  static int currentLevel = 0;
  static unsigned long fadeStartTime = startTime;

  unsigned char brightness;
  unsigned long fadeTime = (currentLevel*2);// go slower near the top

  unsigned long time = millis()-fadeStartTime;
  unsigned long currentStep = time%(fadeTime);

  if(currentLevel==peak){
    // get a new peak value
    prevPeak = peak;
    while(abs(peak-prevPeak)<5){
      peak =  random(numRGBLeds); // pick a new peak value that differs at least 5 from previous peak
    }
  }

  if(millis()-fadeStartTime > fadeTime){
    fadeStartTime = millis();
    if(currentLevel<peak){ //fading in
      currentLevel++;
    }
    else{ //fading out
      currentLevel--;
    }
  }
  // animate to new top
  for(int led=0;led<numRGBLeds;led++){
    if(led<currentLevel){
      int hue = (numRGBLeds-1-led)*120/numRGBLeds; // From green to red
      ShiftPWM.SetHSV(led,hue,255,255); 
    }
    else if(led==currentLevel){
      int hue = (numRGBLeds-1-led)*120/numRGBLeds; // From green to red
      int value;
      if(currentLevel<peak){ //fading in        
        value = time*255/fadeTime;
      }
      else{ //fading out
        value = 255-time*255/fadeTime;
      }
      ShiftPWM.SetHSV(led,hue,255,value);       
    }
    else{
      ShiftPWM.SetRGB(led,0,0,0);
    }
  }
}

void rgbLedRainbow(unsigned long cycleTime, int rainbowWidth){
  // Displays a rainbow spread over a few LED's (numRGBLeds), which shifts in hue. 
  // The rainbow can be wider then the real number of LED's.
  unsigned long time = millis()-startTime;
  unsigned long colorShift = (360*time/cycleTime)%360; // this color shift is like the hue slider in Photoshop.

  for(int led=0;led<numRGBLeds;led++){ // loop over all LED's
    int hue = ((led)*360/(rainbowWidth-1)+colorShift)%360; // Set hue from 0 to 360 from first to last led and shift the hue
    ShiftPWM.SetHSV(led, hue, 255, 255); // write the HSV values, with saturation and value at maximum
  }
}

void printInstructions(void){
  Serial.println("---- ShiftPWM Non-blocking fades demo ----");
  Serial.println("");
  
  Serial.println("Type 'l' to see the load of the ShiftPWM interrupt (the % of CPU time the AVR is busy with ShiftPWM)");
  Serial.println("");
  Serial.println("Type any of these numbers to set the demo to this mode:");
  Serial.println("  0. All LED's off");
  Serial.println("  1. Fade in and out one by one");
  Serial.println("  2. Fade in and out all LED's");
  
  Serial.println("");
  Serial.println("Type 'm' to see this info again");  
  Serial.println("");
  Serial.println("----");
}

with this wiring...

That code is for fading a bunch of leds off and on, based on a keypress on the pc keyboard, as far as I can make out. And the wiring shows a stepper motor wired in far right with the dc motor lurking by the tool box....

breadboard hook-up wires won't take 4A or anything like that - often they have significant series resistance and I'd
keep them for low current use only. Also some of the croc-clip leads I've bought weren't even soldered to the clips
and had stupidly thin wires. If you want 4A to flow reliably you'll need better wiring and screw-terminals or soldered connections only.