Pololu Robotics & Electronics
Menu
My account Comments or questions? About Pololu Contact Ordering information Distributors

HELP, Simple Motor running with DualVNH5019MotorShield and Uno3


#1

HI,
Im new to Arduino and Pololo but I’m needing to run a 6 amp x 12v fan motor over a time during the day.
Im having problems firstly getting the code for this and second changing the example code to work correctly.

Can someone point me in the right direction for code to drive a simple fan ( M1) forward speed at 50%.

What I need is:

  1. To run the fan 50% of the full speed as fan is too strong on full.
  2. To run the fan for 1 hour on and 1 hour off
  3. Run motor only during the day light hours as it has solar and battery to run off.

I have the shield and Uno mounted and wired with test fan to check works for now and will connect to 6amp fan once this works well.
Picture below of the setup and sheild to date.

Thanks Jason


#2

Hello.

The VNH5019 shield controls the speed of brushed DC motors by adjusting the duty cycle of the PWM signal on the motor outputs. Generally, the inductance of the motor connected smooths that output PWM into effectively an analog voltage. If your fan can be controlled in that way, you should be able to achieve speeds lower than your supply voltage using the functions in our VNH5019 Arduino library, which it sounds like you are trying to do. The setM1speed() takes a value between 0 and 400, with 0 corresponding to no rotation (supplying 0V) and 400 to full speed (supplying 100% of the voltage connected to VIN). So, to supply half of the motor supply voltage, you should write:

setM1speed(200);

There are many ways you can program your Arduino to run your fan like that. In general, you can use a function like delay() to pause your Arduino sketch. You can learn more about that on the Arduino web page for that function. The maximum length of time you can delay using delay() is about 30s, so to delay for longer periods of time using that functions, you will have to call it multiple times. This method is not very precise, so if you are interested in precision, let me know and I can go over another method.

If you want to ensure the fan is only on when daylight is available, you might consider adding a way to detect sunlight in your system. One simple way would be to use a photocell like this.

If you are not using a brushed DC motor, you could post a link to more details about it and I might be able to offer suggestions.

-Jon


#3

Thanks Jon,
Thanks for getting back to me, appreciate your time on this.

Understand what your thoughts are.

I’m needing something more precise as I need to stand the fan unit down for
1 hour and then run for 1hr approx so that the solar has a chance to cope
in marginal conditions.
If you could suggest another method would be great.

I’ll check now that the motor is brushed as I’m not sure about that.

Best regards
Jason


#4

Needing to run your motors for "1hr approx " makes it seem like inaccuracies of a few seconds should not be an issue, and I suspect delay() to have a much better accuracy than that (more like on the order of a few microseconds).

-Jon


#5

No I need to stop the motor for standdown of 1 hr not less as will chew up
my solar battery. Then on fur 1 hour.

I could make it 2 hrs hense why I say approx.

So I’m assuming delay () is for 0 to 30sec so this won’t work unless I can
say delay (3600000).

Best regards
Jason


#6

Like I mentioned earlier, you can just make multiple calls to delay() to pause your script for longer periods of time. For example, this for loop:

for (int i = 0; i < 10; n++) 
{
delay(30000);
}

waits for 30 seconds each time it iterates. Since there are a total of 10 iterations, this will wait for a total of 300 seconds.

-Jon


#7

Arrrr ha, got it. I’ll try this.
Thanks again for the help

Best regards
Jason


#8

HI Jon,

I’ve got the motor running and testing at present, I have used the standard
pololu driver code and cut it down for M1 only with the faults etc.

Below is the code I’m using but still need to start and stop the motor
every 60 mins approx, the delay (30000) at the end seems to delay the start
of the motor 30 seconds then it runs but doesn’t stop. I need to include a
stop parameter to stop it after running 60mins and delay for 60 mins and
start again.

I’m not having much luck with the code below, where am I going wrong please?

cheers Jason

#include "DualVNH5019MotorShield.h"

DualVNH5019MotorShield md;

void stopIfFault()
{
  if (md.getM1Fault())
  {
    Serial.println("M1 fault");
    while(1);
  }
  if (md.getM2Fault())
  {
    Serial.println("M2 fault");
    while(1);
  }
}

void setup()
{
  Serial.begin(115200);
  Serial.println("Dual VNH5019 Motor Shield");
  md.init();
}

void loop()
{
  for (int i = 0; i <= 400; i++) //jon can i set motor speed to 50% here??//
  {
    md.setM1Speed(i);
    stopIfFault();
    if (i%200 == 100)
    {
      Serial.print("M1 current: ");
      Serial.println(md.getM1CurrentMilliamps());
    }
    delay(30000); //startup delay//
  }
}

#9

Right now your modified version of our example code increases the short 2ms delay (delay(2)) to 30 seconds. This short delay is called each time the code iterates through the for loop, and is there so that the motor takes time to ramp up to the target duty cycle. By increasing it to 30 seconds, it will take 400*30 = 12000 seconds to ramp up to the target duty cycle, incrementally increasing the duty cycle by 1 every 30 seconds. This does not sound at all like what you want to do. So, as a first step you should change back the short delay to delay(2), and add delay(30000) outside of the for loop like:

void loop()
{
  for (int i = 0; i <= 200; i++) // I made the 400 a 200 so that this loop finishes with a duty cycle of 50% instead of 100%
  {
    md.setM1Speed(i);
    stopIfFault();
    if (i%200 == 100)
    {
      Serial.print("M1 current: ");
      Serial.println(md.getM1CurrentMilliamps());
    }
    delay(2); // this short delay exists so that the motor takes time to ramp up to the target duty cycle
  }
delay(30000);
}

That snippet of code ramps the motor up to the target duty cycle (I used a value of 200 so that the code ramps up to a 50% duty cycle instead of 100%, which is what a value of 400 does) and delays for 30 seconds. Now, since 30000 is pretty close to the maximum value you can delay for, to delay for any longer periods of time using that function, you could call it again by typing out the command again. For example:

void loop()
{
  for (int i = 0; i <= 200; i++) // I made the 400 a 200 so that this loop finishes with a duty cycle of 50% instead of 100%
  {
    md.setM1Speed(i);
    stopIfFault();
    if (i%200 == 100)
    {
      Serial.print("M1 current: ");
      Serial.println(md.getM1CurrentMilliamps());
    }
    delay(2); //  this short delay exists so that the motor takes time to ramp up to the target duty cycle
  }
delay(30000); // delay for 30 seconds
delay(30000); // delay for another 30 seconds
}

That snippet of code ramps the motor up to the target duty cycle and delays for 30 seconds twice for a total of 1 minute. You could call delay(30000) 120 times to delay for 60 minutes, but not is not really a good way to code. A more elegant method is to write a function to delay for a certain amount of time, and to make a for loop that calls that function as many times as you want. Here is what that would look like:

void loop()
{
  for (int i = 0; i <= 200; i++) // I made the 400 a 200 so that this loop finishes with a duty cycle of 50% instead of 100%
  {
    md.setM1Speed(i);
    stopIfFault();
    if (i%200 == 100)
    {
      Serial.print("M1 current: ");
      Serial.println(md.getM1CurrentMilliamps());
    }
    delay(2); //  this short delay exists so that the motor takes time to ramp up to the target duty cycle
  }
 customPause(60);
}

void customPause(int delayTimeInMinutes)
{
  int n = delayTimeInMinutes;
  for  (n; n >= 0; n--)
  { 
    delay(30000);
    delay(30000);
  }
}

-Jon


#10

Thanks Jon,
This makes total sense. I’ll upload and test.
I’ll get back to you with results and post code

Best regards
Jason


#11

HI Jon,
Just testing this now with 60mins set but
what tells the motor to turn OFF after a set time like 60mins?? What code would I use for this?

I presume the above delay code snippet

customPause(60);
}

void customPause(int delayTimeInMinutes)
{
  int n = delayTimeInMinutes;
  for  (n; n >= 0; n--)
  { 
    delay(30000);
    delay(30000);
  }
}

would then hold the motor off for 60mins then turn back on and repeat the loop over and over
cheers
jason


#12

Once the motor is moving, there are a couple ways to get the motor to stop. You can send a value of 0 to setM1Speed(), which corresponds to full coast. That results in power being removed from the motor, and the output shaft should continue to rotate until friction slows it to a complete stop. If you want to stop the motor more quickly, you can use setM1Brake(), and the value you pass into that function will determine how quickly the motor will brake. You can learn more about those functions and their parameters under the Documentation section of the VNH5019 Arduino library’s GitHub page.

-Jon


#14

HI Jon,

I changed to code to some I found on another forum to the below and changed they delays so that its 4mins on and 4 mins off and this works very well.

Is there a better way to delay this up to 60mins??
you suggested custompause(60); but would this still work in this prgram? and where?
cheers
jason

#include "DualVNH5019MotorShield.h"

DualVNH5019MotorShield md;

void setup()
{
  Serial.begin(115200);
  Serial.println("Dual VNH5019 Motor Shield");
  md.init();
}

void loop()
{
  //motor startup//
  Serial.println("M1 Speed 100% Forward");
  md.setM1Speed(400);
  Serial.print("M1 current: ");
  Serial.println(md.getM1CurrentMilliamps());
  delay(120000);//MS delay to stop = 2mins//
  delay(120000);//MS delay to stop = 2mins//
  
  //motor shutdown//
  Serial.println("M1 Speed 0%");
  md.setM1Speed(0);
  Serial.print("M1 current: ");
  Serial.println(md.getM1CurrentMilliamps());
  delay(120000);//MS delay to start = 2mins//
  delay(120000);//MS delay to start = 2mins//
}

#15

HI Jon,
2nd question
I have an LDR here and keen to control theVNH5019 with the LDR via a mapped pin into the VNH5019 input, what pin can I remap to turn ‘OFF’ the driver from the Arduino.

My code now looks like:

#include "DualVNH5019MotorShield.h"

DualVNH5019MotorShield md;

int sensorPin = A0;   // select the input pin for ldr, JON Need to find pin to turn off M1 motor Vcc//
int sensorValue = 0;  // variable to store the value coming from the sensor

void setup()
{
  Serial.begin(115200);
  Serial.println("Dual VNH5019 Motor Shield");
  md.init();
  pinMode(2, OUTPUT); //pin connected to the VNH5019//
}

void loop()
{
  // read the value from the sensor:
  sensorValue = analogRead(sensorPin);
  Serial.print("LDR light reading of ");    
  Serial.println(sensorValue); //prints the values coming from the sensor on the screen
  
  if(sensorValue < 300) //setting a threshold value
  digitalWrite(2,HIGH); //turn VNH5019 ON//
  
  else digitalWrite(2,LOW); //turn VNH5019 OFF//
  delay(100);
  
  //motor startup//
  Serial.println("M1 Speed 50% Forward");
  md.setM1Speed(200);
  Serial.print("M1 current: ");
  Serial.println(md.getM1CurrentMilliamps());
  delay(120000);//MS delay to stop = 2mins//
  delay(120000);//MS delay to stop = 2mins//

  // read the value from the sensor:
  sensorValue = analogRead(sensorPin);
  Serial.print("LDR light reading of ");    
  Serial.println(sensorValue); //prints the values coming from the sensor on the screen
  
  if(sensorValue < 300) //setting a threshold value
  digitalWrite(2,HIGH); //turn VNH5019 ON//
  
  else digitalWrite(2,LOW); //turn VNH5019 OFF//
  delay(100);
  
  //motor shutdown//
  Serial.println("M1 Speed 0%");
  md.setM1Speed(0);
  Serial.print("M1 current: ");
  Serial.println(md.getM1CurrentMilliamps());
  delay(120000);//MS delay to start = 2mins//
  delay(120000);//MS delay to start = 2mins//

}

So that,
The light values turn on the loop and then as light value drops turns off the loop

this is so that the sun light can control when the fan is on during the day only.

can you suggest code example.
cheers
jason


#16

I think you should focus on getting the one-hour-on one-hour-off code working how you want it to before adding your light sensor. You should be able to implement the customPause() example function I wrote out with the new code you are working on. The way the delay() function is used in my reply with the customPause() example should look very similar to the code you are currently working on. So, the instructions and progression in that post should help you write your own long delay function. Can you read through that post again and try modifying your code from this post?

-Jon


#17

HI Jon,

Got my motor working with some great code, I couldn’t get the customPause(60) to work and verify on the editor but got the following code to work very well and accurate for 1 hr on and 1hr off on the serial monitor.

const long oneSecond = 1000; // a second is a thousand milliseconds
const long oneMinute = oneSecond * 60;
const long oneHour = oneMinute * 60;
const long oneDay = oneHour * 24;

delay(oneHour);

Now that I have this working, Im keen to get the LDR working to only turn the VMH5019 on when there is more than 300 on the LDR,
So if below 300 then turn off as per the code below.

What pin do I need to control here to shut off signal to the VMH5019??

cheers
Jason

My code now looks like this:

#include "DualVNH5019MotorShield.h"

const long oneSecond = 1000;  // a second is a thousand milliseconds
const long oneMinute = oneSecond * 60;
const long oneHour   = oneMinute * 60;
const long oneDay    = oneHour * 24;

DualVNH5019MotorShield md;

int sensorPin = A0;   // select the input pin for ldr, JON Need to find pin to turn off M1 motor Vcc?? //
int sensorValue = 0;  // variable to store the value coming from the sensor


void setup()
{
  Serial.begin(115200);
  Serial.println("Dual VNH5019 Motor Shield");
  md.init();
  pinMode(2, OUTPUT); //pin connected to the VNH5019//
}

void loop()
{
  // read the value from the sensor:
  sensorValue = analogRead(sensorPin);
  Serial.print("LDR light reading of ");    
  Serial.println(sensorValue); //prints the values coming from the sensor on the screen
  
  if(sensorValue < 300) //setting a threshold value
  digitalWrite(2,HIGH); //turn VNH5019 ON//
  
  else digitalWrite(2,LOW); //turn VNH5019 OFF//
  delay(2);
  
  //motor startup//
  Serial.println("M1 Speed 50% Forward");// 400 is 100%//
  md.setM1Speed(200);
  Serial.print("M1 current: ");
  Serial.println(md.getM1CurrentMilliamps());
  Serial.print("Delay: ");
  Serial.println("delay for 1 hour");
  delay(oneHour);


  // read the value from the sensor:
  sensorValue = analogRead(sensorPin);
  Serial.print("LDR light reading of ");    
  Serial.println(sensorValue); //prints the values coming from the sensor on the screen
  
  if(sensorValue < 300) //setting a threshold value
  digitalWrite(2,HIGH); //turn VNH5019 ON//
  
  else digitalWrite(2,LOW); //turn VNH5019 OFF//
  delay(2);
  
  //motor shutdown//
  Serial.println("M1 Speed 0% stopped");
  md.setM1Speed(0);
  Serial.print("M1 current: ");
  Serial.println(md.getM1CurrentMilliamps());

  Serial.print("Delay: ");
  Serial.println("delay for 1 hour");
  delay(oneHour);
  

 }

#18

Hi.

To disable the motors you would use M1EN and M2EN. You can see what pins on the Arduino the shield connects those to by default in the “Shield Connections” section of the Dual VNH5019 Motor Driver Shield User’s Guide.

By the way, you mentioned you want to disable the drivers if the light value is below 300, but the comments in your code show that it is set up to disable the driver if the light value is not below 300.

-Claire


#19

Thanks Claire,

That’s what I needed to know as it’s not clear on the shield user guide as
to what pins disabled the motor shield, just the picture of all the digital
pins.

I’ll check my code and look at for function to turn off M1EN etc.

Best regards
Jason


#20

HI Claire,

Well, I got the system working how i need now with the current code. So all works, the LDR turns off as needed and the motor runs M1 as needed,
but for the motor speed.

I have it set at 200 but seems to not make any difference if its 100 or 400 full speed. Im needing it to run at 50% or 200 forward direction.

I cant see anything wrong with the code and I checked the motor now and it is brushed.

I also tested the motor with the DEMO code for the shield but it also doesnt work, just runs motor at full speed forward only. I did notice the small green LED flicker a little, but no Flicker when running my code as below.

Can you advise me where Im going wrong??
cheers
Jason

My current code is:

#include "DualVNH5019MotorShield.h"

const long oneSecond = 1000;  // a second is a thousand milliseconds
const long oneMinute = oneSecond * 60;
const long oneHour   = oneMinute * 60;
const long oneDay    = oneHour * 24;

DualVNH5019MotorShield md;

int sensorPin = A0;   // select the input pin for ldr//
int sensorValue = 0;  // variable to store the value coming from the sensor 

void setup()
{
   Serial.begin(115200);
   Serial.println("Dual VNH5019 Motor Shield");
   md.init();
   pinMode(6, OUTPUT); //pin connected to the VNH5019 M1EN//
}

void loop()
{
  // read the value from the sensor:
  sensorValue = analogRead(sensorPin);
  Serial.print("LDR light reading of ");    
  Serial.println(sensorValue); //prints the values coming from the sensor on the screen
  
  if(sensorValue < 400) //setting LDR threshold value//
  digitalWrite(6,LOW); //turn VNH5019 off//
  
  else digitalWrite(6,HIGH); //turn VNH5019 ON//
  delay(2);
  
  //motor startup//
  Serial.println("M1 Speed 50% Forward");// 400 is 100%//
  md.setM1Speed(200);
  Serial.print("M1 current: ");
  Serial.println(md.getM1CurrentMilliamps());
  Serial.print("Delay: ");
  Serial.println("delay for 1 Hour");
  delay(oneHour);


  // read the value from the sensor:
  sensorValue = analogRead(sensorPin);
  Serial.print("LDR light reading of ");    
  Serial.println(sensorValue); //prints the values coming from the sensor on the screen
   
  if(sensorValue < 400) //setting LDR threshold value
  digitalWrite(6,LOW); //turn VNH5019 OFF//
  
  else digitalWrite(6,HIGH); //turn VNH5019 ON//
  delay(2);
  
  //motor shutdown//
  Serial.println("M1 Speed 0% stopped");
  md.setM1Speed(0);
  Serial.print("M1 current: ");
  Serial.println(md.getM1CurrentMilliamps());
  Serial.print("Delay: ");
  Serial.println("delay for 1 Hour");
  delay(oneHour);
   

 }

#21

Can you remove your motor from your system and apply power to it directly to see if its speed changes with the voltage? If you have access to a benchtop power supply, try running your motor at a lower voltage (like 7V or 8V), then ramp up to a higher voltage (like 10V or 12V). How does the speed of the motor vary as the voltage changes?

If you do not have access to a benchtop power supply, you can try powering your motor with a couple different battery packs of differing voltages (e.g. start with a 2S LiPo or 7.2V NiMH battery pack, and then move up to a 3S LiPo or 8.4V NiMH battery pack) to perform a similar test.

-Jon