How create a detailed motor controller using an arduino motor shield with the uno?

Hi, i'm new here and new to the arduino. I am using an arduino motor sheild and the uno board to contol a 4v dc motor. I want to be able to make the motor spin forward as well as reverse the polarity and make it spin in the opposite direction. Also using four inputs, preferrably push buttons, I need it to increase the motor speed by 5%, decrease the motor speed by 5%, make the motor speed 25% of max speed and make the motor speed 50% of max speed. Code examples would be really helpful. Your time and help are greatly appreciated.

sort by: active | newest | oldest
maewert5 years ago
Have you reviewed the various motor shield tutorials? Here is one: https://www.instructables.com/id/Arduino-Motor-Shield-Tutorial/
beginnerbot (author)  maewert5 years ago
Thanks for the reply. I actually have reviewed that tutorial. Its what led me to this website initially.

That tutorial is only a looped progragram, it has no inputs, whereas am using 4 inputs that will change the state of the motor. And they all need to be able to check what the previous state was in order to proceed. I'm not 100% sure on how to do that.

P.S. its just one motor.
Adding four buttons is not too difficult.  We can put them on pins 4,5,6, and 7.  Wire them so that the Normally Open push button grounds the pin when it is pressed.  We then define the buttons as INPUTS.  Even though they are inputs we then do a digital write to them setting them HIGH, this turns on an internal pull-up resistor on the pins so the pins read HIGH when the buttons are not being pressed.

Note that all of the Arduino programs are looped.  You probably want to define a variable to hold the current motor state, then read the pins and change the motor state based on what pins are pressed.

Here is an example (may not be completely what you're after):
/*************************************************************
Motor Shield 1-Channel DC Motor Demo
by Randy Sarafan
Updated for 4 buttons
*************************************************************/

int btn1 = 4; // for 25%
int btn2 = 5; // for 50%
int btn3 = 6; // for Increase
int btn4 = 7; // for Decrease

int speed = 0;
int direction = 0;

void setup() {
 
  //Setup Channel A
  pinMode(12, OUTPUT); //Initiates Motor Channel A pin
  pinMode(9, OUTPUT); //Initiates Brake Channel A pin
  digitalWrite(9, LOW);   //Disengage the Brake for Channel A
  pinMode(btn1, INPUT);
  pinMode(btn2, INPUT);
  pinMode(btn3, INPUT);
  pinMode(btn4, INPUT);
digitalWrite(btn1, HIGH);
digitalWrite(btn2, HIGH);
digitalWrite(btn3, HIGH);
digitalWrite(btn4, HIGH);
}

void loop(){
 
  // Lets set the motor speed and direction
  if (0 == direction)
  {
   digitalWrite(12, HIGH);
  }
  else
  {
   digitalWrite(12, LOW);
  }
  analogWrite(3, speed);


if (LOW == digitalRead(btn1))  // 25%
  speed = 1024 * .25;
if (LOW == digitalRead(btn2))  // 50%
  speed = 1024 * .5;
if (LOW == digitalRead(btn3))  // 5% increase
  speed = speed + (1024 * .05);
if (LOW == digitalRead(btn3))  // 5% decrease
  speed = speed - (1024 * .05);

speed = constrain(speed, 0, 1023); // this makes sure speed is between 0 and 1023

 
}
maewert maewert5 years ago
Opps, I see I forgot to change the Decrease line to use button #4.
Should read:
if (LOW == digitalRead(btn4)) // 5% decrease
speed = speed - (1024 * .05);
beginnerbot (author)  maewert5 years ago
I made a correction to the code, it didn't make sense to keep engaging the break.

int btn1 = 4; // for 25%
int btn2 = 5; // for 50%
int btn3 = 6; // for Increase
int btn4 = 7; // for Decrease

int speed = 0;
int direction = 0;

void setup() {

//Setup Channel A
pinMode(12, OUTPUT); //Initiates Motor Channel A pin
pinMode(9, OUTPUT); //Initiates Brake Channel A pin
digitalWrite(9, LOW); //Disengage the Brake for Channel A
pinMode(btn1, INPUT);
pinMode(btn2, INPUT);
pinMode(btn3, INPUT);
pinMode(btn4, INPUT);
digitalWrite(btn1, HIGH);
digitalWrite(btn2, HIGH);
digitalWrite(btn3, HIGH);
digitalWrite(btn4, HIGH);
}

void loop(){

// Lets set the motor speed and direction
digitalWrite(12, HIGH); //Establishes forward direction of Channel A
digitalWrite(9, LOW); //Disengage the Brake for Channel A
analogWrite(3, 10); //Spins the motor on Channel A at full speed

if (LOW == digitalRead(btn1)) // 25%
delay(15000);
speed = 255 * .25;
if (LOW == digitalRead(btn2)) // 50%
delay(15000);
speed = 255 * .50;
if (LOW == digitalRead(btn3)) // 5% increase
delay(15000);
speed = speed + (255 * .05);
if (LOW == digitalRead(btn3)) // 5% decrease
delay(15000);
speed = speed - (255 * .05);

speed = constrain(speed, 0, 255); // this makes sure speed is between 0 and 1023


}
I believe the IF statements are no longer correct:
Try this out:
===================================
if (LOW == digitalRead(btn1)) // 25%
speed = 255 * .25;
if (LOW == digitalRead(btn2)) // 50%
speed = 255 * .50;
if (LOW == digitalRead(btn3)) // 5% increase
speed = speed + (255 * .05);
if (LOW == digitalRead(btn3)) // 5% decrease
speed = speed - (255 * .05);

delay(15000);
===================================

The way IF statement work is the code following the IF is executed only if what's inside the '()' is true.  You added 'delay(15000);' after the IF statement breaking the code.  Lets 'play computer' and walk through what happens when no buttons are pressed:

We do the first IF statement:
if (LOW == digitalRead(btn1)) // 25%
delay(15000);

The button is not being pressed so we do NOT delay.

Then we see this statement and we execute it:
speed = 255 * .25;

So we are changing speed when we don't want to.

If you wnat to ONLY change the speed when the IF is true, then we need to add '{}' around the statements like so:

if (LOW == digitalRead(btn1)) // 25%
{delay(15000);
speed = 255 * .25;}
if (LOW == digitalRead(btn2)) // 50%
{delay(15000);
speed = 255 * .50;}
if (LOW == digitalRead(btn3)) // 5% increase
{delay(15000);
speed = speed + (255 * .05);}
if (LOW == digitalRead(btn3)) // 5% decrease
{delay(15000);
speed = speed - (255 * .05);}

Best Wishes
beginnerbot (author)  maewert5 years ago
Never mind the last question, human error. I mistakenly wired one of my grounds in th wrong place. I also had to tweak the numbers. Setting the constraint to a negative number instead of zero made the motor stop spinning and start again at a really high speed. Setting it to '0' sloved that. Now, I think i'll add another switch to decide whether or not I want the motor to spin in reverse.

Any suggestions on how I can make this device into/use it for something practical?

Thanks so much for the help. I'll try and write the code for this last switch myself. If there are any mishaps, I will let you know.
beginnerbot (author)  maewert5 years ago
The motor spins constantly and does not respond to the inputs. Are pins 4,5,6,7 pwm pins? Does it matter/make a difference?
beginnerbot (author)  maewert5 years ago
Hi,

There is only one pin for channel that allows pwm. Here is a new code, but the only thing that works is turning on the motor initially:

int btn1 = 4; // for 25%
int btn2 = 5; // for 50%
int btn3 = 6; // for Increase
int btn4 = 7; // for Decrease

int speed = 0;
int direction = 0;

void setup() {

//Setup Channel A
pinMode(12, OUTPUT); //Initiates Motor Channel A pin
pinMode(9, OUTPUT); //Initiates Brake Channel A pin
digitalWrite(9, LOW); //Disengage the Brake for Channel A
pinMode(btn1, INPUT);
pinMode(btn2, INPUT);
pinMode(btn3, INPUT);
pinMode(btn4, INPUT);
digitalWrite(btn1, HIGH);
digitalWrite(btn2, HIGH);
digitalWrite(btn3, HIGH);
digitalWrite(btn4, HIGH);
}

void loop(){

// Lets set the motor speed and direction
digitalWrite(12, HIGH); //Establishes forward direction of Channel A
digitalWrite(9, LOW); //Disengage the Brake for Channel A
analogWrite(3, 10); //Spins the motor on Channel A at full speed

if (LOW == digitalRead(btn1)) // 25%
digitalWrite(9, HIGH); //Eengage the Brake for Channel A
delay(15000);
speed = 255 * .25;
if (LOW == digitalRead(btn2)) // 50%
digitalWrite(9, HIGH); //Eengage the Brake for Channel A
delay(15000);
speed = 255 * .50;
if (LOW == digitalRead(btn3)) // 5% increase
digitalWrite(9, HIGH); //Eengage the Brake for Channel A
delay(15000);
speed = speed + (255 * .05);
if (LOW == digitalRead(btn3)) // 5% decrease
digitalWrite(9, HIGH); //Eengage the Brake for Channel A
delay(15000);
speed = speed - (255 * .05);

speed = constrain(speed, 0, 255); // this makes sure speed is between 0 and 1023


}
Try this:

/*************************************************************
Motor Shield 1-Channel DC Motor Demo
by Randy Sarafan
Updated for 4 buttons
*************************************************************/

int btn1 = 4; // for 25%
int btn2 = 5; // for 50%
int btn3 = 6; // for Increase
int btn4 = 7; // for Decrease

int speed = 0;

void setup() {

  //Setup Channel A
  pinMode(12, OUTPUT); //Initiates Motor Channel A pin
  pinMode(9, OUTPUT); //Initiates Brake Channel A pin
  digitalWrite(9, LOW);   //Disengage the Brake for Channel A
  pinMode(btn1, INPUT);
  pinMode(btn2, INPUT);
  pinMode(btn3, INPUT);
  pinMode(btn4, INPUT);
digitalWrite(btn1, HIGH);
digitalWrite(btn2, HIGH);
digitalWrite(btn3, HIGH);
digitalWrite(btn4, HIGH);
}

void loop(){


if (LOW == digitalRead(btn1))  // 25%
  speed = 1024 * .25;
if (LOW == digitalRead(btn2))  // 50%
  speed = 1024 * .5;
if (LOW == digitalRead(btn3))  // 5% increase
  speed = speed + (1024 * .05);
if (LOW == digitalRead(btn3))  // 5% decrease
  speed = speed - (1024 * .05);

// this makes sure speed is between -1023 and 1023
speed = constrain(speed, -1023, 1023);

// Lets set the motor speed and direction
  if (speed > 0)
  {
   digitalWrite(12, HIGH);
   analogWrite(3, speed);
  }
  else
  {
   digitalWrite(12, LOW);
   analogWrite(3, abs(speed)); 
  }
  delay(250);

}
beginnerbot (author) 5 years ago
Wow, thanks to both of you guys. This weekend I will hunker down and work on the code. I will keep you posted as to my progress.

bwrussell5 years ago
First take a look at the Arduino reference page. Lots of great examples.

Writing code is a little like building with Legos. There are lots of little building blocks that come from different sets that come together to make something new. What I'm trying to say is you probably won't find one example code just like you want it but you will find a bunch of different ones that each do something you want. Find an example for controlling a motor and another for working with inputs. Copy and paste the sections that you need and then stick them together into something new.
As for your specific questions:
The library for the motor shield should have a built in function for forward, backwards and stop, as well as one for setting speeds (via PWM) and braking.

To keep track of the previous input you simply need to create a variable that stores the previous push. Basically in the code where each button is pressed have it write '1', '2', '3', or '4' to a int variable (create this variable in the beginning and just overwrite it each time a button is pushed). The numbers represent each switch. When you need to check the state the code just reads the variable and reacts accordingly using a if...else if structure.

You may want to search "debouncing" for your switches if you start getting weird behavior.

And remember: Always comment your code as you write it! That way if you are still having trouble someone else can look at it and help you. If you don't comment it and you post it here with questions most people aren't willing to try and decipher uncommented code.