Dual VNH5019 Motor Shield (Arduino Mega problem)

Dear members from the Pololu forum,

I just received this week my Dual VNH5019 Motor Shield. The shield works perfectly with my Arduino Uno, but i have problems with my Arduino mega (2560). I get the error M1 fault. I read what the error means, shortcut etc.

I just wonder if more people has the same problem… (i already did some research [google] but not much hits).

I just the next libarary file from the shield: https://github.com/pololu/Dual-VNH5019-Motor-Shield

Now i hope somebody can help me out.

Kind Regards,

Dave


The code:

Demo.pde

[code]#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++)
{
md.setM1Speed(i);
stopIfFault();
if (i%200 == 100)
{
Serial.print("M1 current: ");
Serial.println(md.getM1CurrentMilliamps());
}
delay(2);
}

for (int i = 400; i >= -400; i–)
{
md.setM1Speed(i);
stopIfFault();
if (i%200 == 100)
{
Serial.print("M1 current: ");
Serial.println(md.getM1CurrentMilliamps());
}
delay(2);
}

for (int i = -400; i <= 0; i++)
{
md.setM1Speed(i);
stopIfFault();
if (i%200 == 100)
{
Serial.print("M1 current: ");
Serial.println(md.getM1CurrentMilliamps());
}
delay(2);
}

for (int i = 0; i <= 400; i++)
{
md.setM2Speed(i);
stopIfFault();
if (i%200 == 100)
{
Serial.print("M2 current: ");
Serial.println(md.getM2CurrentMilliamps());
}
delay(2);
}

for (int i = 400; i >= -400; i–)
{
md.setM2Speed(i);
stopIfFault();
if (i%200 == 100)
{
Serial.print("M2 current: ");
Serial.println(md.getM2CurrentMilliamps());
}
delay(2);
}

for (int i = -400; i <= 0; i++)
{
md.setM2Speed(i);
stopIfFault();
if (i%200 == 100)
{
Serial.print("M2 current: ");
Serial.println(md.getM2CurrentMilliamps());
}
delay(2);
}
}[/code]

DualVNH5019MotorShield.cpp

#include "DualVNH5019MotorShield.h"

// Constructors ////////////////////////////////////////////////////////////////

DualVNH5019MotorShield::DualVNH5019MotorShield()
{
  //Pin map
  _INA1 = 2;
  _INB1 = 4;
  _EN1DIAG1 = 6;
  _CS1 = A0; 
  _INA2 = 7;
  _INB2 = 8;
  _EN2DIAG2 = 12;
  _CS2 = A1;
}

DualVNH5019MotorShield::DualVNH5019MotorShield(unsigned char INA1, unsigned char INB1, unsigned char EN1DIAG1, unsigned char CS1, 
                                               unsigned char INA2, unsigned char INB2, unsigned char EN2DIAG2, unsigned char CS2)
{
  //Pin map
  //PWM1 and PWM2 cannot be remapped because the library assumes PWM is on timer1
  _INA1 = INA1;
  _INB1 = INB1;
  _EN1DIAG1 = EN1DIAG1;
  _CS1 = CS1;
  _INA2 = INA2;
  _INB2 = INB2;
  _EN2DIAG2 = EN2DIAG2;
  _CS2 = CS2;
}

// Public Methods //////////////////////////////////////////////////////////////
void DualVNH5019MotorShield::init()
{
// Define pinMode for the pins and set the frequency for timer1.

  pinMode(_INA1,OUTPUT);
  pinMode(_INB1,OUTPUT);
  pinMode(_PWM1,OUTPUT);
  pinMode(_EN1DIAG1,INPUT);
  pinMode(_CS1,INPUT);
  pinMode(_INA2,OUTPUT);
  pinMode(_INB2,OUTPUT);
  pinMode(_PWM2,OUTPUT);
  pinMode(_EN2DIAG2,INPUT);
  pinMode(_CS2,INPUT);
  #if defined(__AVR_ATmega168__)|| defined(__AVR_ATmega328P__)
  // Timer 1 configuration
  // prescaler: clockI/O / 1
  // outputs enabled
  // phase-correct PWM
  // top of 400
  //
  // PWM frequency calculation
  // 16MHz / 1 (prescaler) / 2 (phase-correct) / 400 (top) = 20kHz
  TCCR1A = 0b10100000;
  TCCR1B = 0b00010001;
  ICR1 = 400;
  #endif
}
// Set speed for motor 1, speed is a number betwenn -400 and 400
void DualVNH5019MotorShield::setM1Speed(int speed)
{
  unsigned char reverse = 0;
  
  if (speed < 0)
  {
    speed = -speed;  // Make speed a positive quantity
    reverse = 1;  // Preserve the direction
  }
  if (speed > 400)  // Max PWM dutycycle
    speed = 400;
  #if defined(__AVR_ATmega168__)|| defined(__AVR_ATmega328P__)
  OCR1A = speed;
  #else
  analogWrite(_PWM1,speed * 51 / 80); // default to using analogWrite, mapping 400 to 255
  #endif
  if (speed == 0)
  {
    digitalWrite(_INA1,LOW);   // Make the motor coast no
    digitalWrite(_INB1,LOW);   // matter which direction it is spinning.
  }
  else if (reverse)
  {
    digitalWrite(_INA1,LOW);
    digitalWrite(_INB1,HIGH);
  }
  else
  {
    digitalWrite(_INA1,HIGH);
    digitalWrite(_INB1,LOW);
  }
}

// Set speed for motor 2, speed is a number betwenn -400 and 400
void DualVNH5019MotorShield::setM2Speed(int speed)
{
  unsigned char reverse = 0;
  
  if (speed < 0)
  {
    speed = -speed;  // make speed a positive quantity
    reverse = 1;  // preserve the direction
  }
  if (speed > 400)  // Max 
    speed = 400;
  #if defined(__AVR_ATmega168__)|| defined(__AVR_ATmega328P__)
  OCR1B = speed;
  #else
  analogWrite(_PWM2,speed * 51 / 80); // default to using analogWrite, mapping 400 to 255
  #endif 
  if (speed == 0)
  {
    digitalWrite(_INA2,LOW);   // Make the motor coast no
    digitalWrite(_INB2,LOW);   // matter which direction it is spinning.
  }
  else if (reverse)
  {
    digitalWrite(_INA2,LOW);
    digitalWrite(_INB2,HIGH);
  }
  else
  {
    digitalWrite(_INA2,HIGH);
    digitalWrite(_INB2,LOW);
  }
}

// Set speed for motor 1 and 2
void DualVNH5019MotorShield::setSpeeds(int m1Speed, int m2Speed)
{
  setM1Speed(m1Speed);
  setM2Speed(m2Speed);
}

// Brake motor 1, brake is a number between 0 and 400
void DualVNH5019MotorShield::setM1Brake(int brake)
{
  // normalize brake
  if (brake < 0)
  {
    brake = -brake;
  }
  if (brake > 400)  // Max brake
    brake = 400;
  digitalWrite(_INA1, LOW);
  digitalWrite(_INB1, LOW);
  #if defined(__AVR_ATmega168__)|| defined(__AVR_ATmega328P__)
  OCR1A = brake;
  #else
  analogWrite(_PWM1,brake * 51 / 80); // default to using analogWrite, mapping 400 to 255
  #endif
}

// Brake motor 2, brake is a number between 0 and 400
void DualVNH5019MotorShield::setM2Brake(int brake)
{
  // normalize brake
  if (brake < 0)
  {
    brake = -brake;
  }
  if (brake > 400)  // Max brake
    brake = 400;
  digitalWrite(_INA2, LOW);
  digitalWrite(_INB2, LOW);
  #if defined(__AVR_ATmega168__)|| defined(__AVR_ATmega328P__)
  OCR1B = brake;
  #else
  analogWrite(_PWM2,brake * 51 / 80); // default to using analogWrite, mapping 400 to 255
  #endif
}

// Brake motor 1 and 2, brake is a number between 0 and 400
void DualVNH5019MotorShield::setBrakes(int m1Brake, int m2Brake)
{
  setM1Brake(m1Brake);
  setM2Brake(m2Brake);
}

// Return motor 1 current value in milliamps.
unsigned int DualVNH5019MotorShield::getM1CurrentMilliamps()
{
  // 5V / 1024 ADC counts / 144 mV per A = 34 mA per count
  return analogRead(_CS1) * 34;
}

// Return motor 2 current value in milliamps.
unsigned int DualVNH5019MotorShield::getM2CurrentMilliamps()
{
  // 5V / 1024 ADC counts / 144 mV per A = 34 mA per count
  return analogRead(_CS2) * 34;
}

// Return error status for motor 1 
unsigned char DualVNH5019MotorShield::getM1Fault()
{
  return !digitalRead(_EN1DIAG1);
}

// Return error status for motor 2 
unsigned char DualVNH5019MotorShield::getM2Fault()
{
  return !digitalRead(_EN2DIAG2);
}

DualVNH5019MotorShield.h

[code]#ifndef DualVNH5019MotorShield_h
#define DualVNH5019MotorShield_h

#include <Arduino.h>

class DualVNH5019MotorShield
{
public:
// CONSTRUCTORS
DualVNH5019MotorShield(); // Default pin selection.
DualVNH5019MotorShield(unsigned char INA1, unsigned char INB1, unsigned char EN1DIAG1, unsigned char CS1,
unsigned char INA2, unsigned char INB2, unsigned char EN2DIAG2, unsigned char CS2); // User-defined pin selection.

// PUBLIC METHODS
void init(); // Initialize TIMER 1, set the PWM to 20kHZ. 
void setM1Speed(int speed); // Set speed for M1.
void setM2Speed(int speed); // Set speed for M2.
void setSpeeds(int m1Speed, int m2Speed); // Set speed for both M1 and M2.
void setM1Brake(int brake); // Brake M1. 
void setM2Brake(int brake); // Brake M2.
void setBrakes(int m1Brake, int m2Brake); // Brake both M1 and M2.
unsigned int getM1CurrentMilliamps(); // Get current reading for M1. 
unsigned int getM2CurrentMilliamps(); // Get current reading for M2.
unsigned char getM1Fault(); // Get fault reading from M1.
unsigned char getM2Fault(); // Get fault reading from M2.

private:
unsigned char _INA1;
unsigned char _INB1;
static const unsigned char _PWM1 = 9;
unsigned char _EN1DIAG1;
unsigned char _CS1;
unsigned char _INA2;
unsigned char _INB2;
static const unsigned char _PWM2 = 10;
unsigned char _EN2DIAG2;
unsigned char _CS2;

};

#endif[/code]

Hi, Dave.

Is the Arduino the only thing changing between your working Uno setup and your non-working Mega 2560 setup? If you disconnect the motor, does the Mega 2560 still report a fault on M1? Can you post some pictures of your setup?

-Derrill

[quote=“Derrill”]Hi, Dave.

Is the Arduino the only thing changing between your working Uno setup and your non-working Mega 2560 setup? If you disconnect the motor, does the Mega 2560 still report a fault on M1? Can you post some pictures of your setup?

-Derrill[/quote]

First at all, thank you for replying and helping me.

Yes the only think i did is changing the board so from Uno to Mega and reverse. When i disconnect the motor i still have the same problem.

The ICSP pin is a bit crooked but it didn’t make short shortcut or anything.

And i need the Mega because i need to count also three encoders as positioning.

Hello, Dave.

It looks like you linked to pictures hosted on a password-protected ftp server, which was bringing up a login prompt for anyone who viewed this thread. I removed the images. Can you either upload them to our forum directly or host them on a public server/image-hosting site?

If the problem happens without the motors connected, then I suspect the problem is with your Arduino Mega. Can you confirm that the fault happens with the most basic setup possible: just the Arduino Mega, the motor shield, and power? If you have any other hardware connected to the Arduino, such as encoders, please disconnect them.

If you are still getting a fault after simplifying, please try running the following program:

[code]
void setup()
{
pinMode(6, INPUT_PULLUP);
pinMode(12, INPUT_PULLUP);
Serial.begin(115200);
delay(1000);

if (!digitalRead(6))
Serial.println(“M1 fault”);
if (!digitalRead(12))
Serial.println(“M2 fault”);
Serial.println(“done”);
}

void loop()
{}[/code]

What does that program print if you run it with just the motor shield connected to the Arduino and nothing else? What does it print if you run it on your bare Arduino Mega (no shield connected)? If you comment out the stopIfFault() calls from loop() in the original example program you were running and use the motor indicator LEDs as feedback, what does the shield do?

- Ben

Thank you for replying.
I will post a update tomorrow evening with the output from your script.

I updated the links (forgot to chmod them)

Hi sorry for the very late responds,

I got some personal issues at home and finnaly got time again!!
Ok i used your code and tested it, as output i get the next responds:

M1 fault done

With motor disconnected same results.
With shield unplugged same results, this is really weird i think? This means he cannot read my input 6 but there is nothing on it?

i also used the newest program (even the one special for the mega (20khz option))

Same results

Looks like my pin-mapping isnt right?

I’ve had a similar issue a few times. Frmo memory its been due to bad connections, since I tend to plugs a terminal board in between the mega and VNH5019 shield.

I can’t see your images - do you have any other shields attached ?

Hi thank you for your reply,

The link is to my dropbox with a picture in it:

https://www.dropbox.com/s/moict8sljzuvh7b/2013-11-03%2011.33.52.jpg

And i try all option with the arduino UNO and all works fine!

Since the program that Ben gave you is returning a fault when nothing is connected to the Arduino Mega (it reads pin 6 as low even though it is pulled high in the code), it seems that something is wrong with the Mega. It is possible that only pin 6 is damaged, so you might try verifying that some other pin on your Mega is functioning properly and remapping the shield connection to use that other pin instead. More information on remapping the connections can be found in the “Remapping the Arduino Connections” section of the shield’s user’s guide.

-Derrill

So stupid from me to not think about that… the change of a broken pin is big ofcrouse. I will first make a loop with a wire to look if this is the problem.

Thanks so far!

I try it out tonight

[quote=“Derrill”]Since the program that Ben gave you is returning a fault when nothing is connected to the Arduino Mega (it reads pin 6 as low even though it is pulled high in the code), it seems that something is wrong with the Mega. It is possible that only pin 6 is damaged, so you might try verifying that some other pin on your Mega is functioning properly and remapping the shield connection to use that other pin instead. More information on remapping the connections can be found in the “Remapping the Arduino Connections” section of the shield’s user’s guide.

-Derrill[/quote]

Derril,

Can i just hook up pin 6 from the shield to digital pin 22?

if i do that and i change the code:

[code]#include “DualVNH5019MotorShieldMega.h”

// Constructors ////////////////////////////////////////////////////////////////

DualVNH5019MotorShield::DualVNH5019MotorShield()
{
//Pin map
_INA1 = 2;
_INB1 = 4;
_EN1DIAG1 = 22; <------- FROM 6
_CS1 = A0;
_INA2 = 7;
_INB2 = 8;
_EN2DIAG2 = 5;
_CS2 = A1;
}
[/code]

I readed the link of you to change the pin mapping but i wanne first try it by this way. If its possible ofcourse :slight_smile: but i dont now where to find elswhere in the code (this doesnt work what i did here above).

When i changed the pin 6 to 22 in the program from Ben it worked fine btw!

If you cut the trace to pin 6, reconnect it to pin 22, and change the code, then you will have effectively remapped that pin.

-Derrill

Ok i did that but still same error… i try to measure everything tonight for check

Really weird,

I changed in the code _EN1DIAG1 = 6; to 22 or other pins. Without shield i get the same error! Just with a clean arduino mega 2560.

I hope one of you guys know the problem.

With the code of ben i get the message done when i change the pin 6 to 22 or other pins.

My files:

DualVNH5019MotorShieldMega.cpp (5.98 KB) <— All the changes is in this file pin 6 to 22
DualVNH5019MotorShieldMega.h (1.78 KB)
Demo.ino (1.64 KB)

Can you add the line:

pinMode(22, INPUT_PULLUP);

to your the end of your setup() (after md.init()) and see if you still get a fault (both with and without the motor driver shield on the Arduino)?

-Derrill

Derill,

I did a total I/O check by letting pull up every pin, now it seems every digital pin is broken… i really dont know why because i bought it new. Now i used one from my work and YES everythings works. I got some garanty on the arduino so no problem i send it back and i will get a new one (Just rip it of his package!).

Thanks for the support so far!

I really like your guys stuff!

Kind Regards,

Vleud101

Hello!
I’m having a similar problem. I have got a vnh5019 shield, arduino mega 2560 and Dagu Wild Thumper 4WD All-Terrain Chassis.
Everything was working fine (except backward movement on m2, which is still a mystery for me :slight_smile: ) but suddenly, when i connected the controller to my laptop and uploaded the working sketch, in the serial monitor I saw “M1 fault”. Now m2 doesn’t work also. I have already tried your test code, but i got “done” with no faults.

I’m frustrated. What can it be?

Hello.

Can you post some pictures of your setup and of your solder connections on the VNH5019 shield? Also, can you post the code you are using?

-Derrill