Pages: [1]   Go Down
Author Topic: VNH5019 Motor Driver - Arduino Mega 2560 - Help needed  (Read 1407 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 10
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,

I am having problems regarding the connection between the Arduino Mega 2560 and the Motor Driver VNH5019. I am trying to connect the Motor Driver to Timer 3 (that is pins 3&5 on the Arduino Mega),in order to use the 16-bit timer instead of the 8-bit timer which is connected to pins 9&10 which is the default connection used. I used these threads http://arduino.cc/forum/index.php?topic=77168.0 & http://forum.pololu.com/viewtopic.php?f=15&t=5806&p=27874&hilit=vnh5019#p27874 but have not been able to get both motors working.
I was previously using an Uno with the Motor Driver and did not have any problems since the 16-bit timer is connected to pins 9&10 on the Uno thus able to get the required PWM frequency (20kHz).
The motors I am using are: http://www.pololu.com/catalog/product/1103.
My set up is:
2 motors connected to the Mega via the Motor Driver powered by a 12V laptop charger which does not seem to have any problems.The connections I have are:

Digital 13      M1INA            Motor 1 direction input A
Digital 4       M1INB             Motor 1 direction input B
Digital 6       M1EN/DIAG      Motor 1 enable input/fault output
Digital 7       M2INA             Motor 2 direction input A
Digital 8       M2INB             Motor 2 direction input B
Digital 3       M1PWM           Motor 1 speed input
Digital 5       M2PWM           Motor 2 speed input
Digital 12     M2EN/DIAG      Motor 2 enable input/fault output
Analog 0       M1CS              Motor 1 current sense output
Analog 1       M2CS              Motor 2 current sense output


The header file is:

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 (or timer 3 for mega) set the PWM to 20kHZ
    void setM1Speed(int speed); // Set speed
    void setM2Speed(int speed); // Set speed
    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
    unsigned int getM2CurrentMilliamps(); // Get current reading
    unsigned char getM1Fault(); // Get fault reading
    unsigned char getM2Fault(); // Get fault reading
  
  private:
    unsigned char _INA1;
    unsigned char _INB1;
  /*#if defined(__AVR_ATmega168__)|| defined(__AVR_ATmega328P__)
    static const unsigned char _PWM1 = 9;
    static const unsigned char _PWM2 = 10;
  #endif*/
  #if defined(__AVR_ATmega128__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
    static const unsigned char _PWM1 = 3;
    static const unsigned char _PWM2 = 5;
  #endif
    unsigned char _EN1DIAG1;
    unsigned char _CS1;
    unsigned char _INA2;
    unsigned char _INB2;
    unsigned char _EN2DIAG2;
    unsigned char _CS2;  
};
#endif

while the .cpp file is:
Code:
#include "DualVNH5019MotorShield.h"

// Constructors

DualVNH5019MotorShield::DualVNH5019MotorShield()
{
  //Pin map
  _INA1 = 13;
  _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
  #if defined(__AVR_ATmega128__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
  // Mega board specific stuff here - assumes assigning timer3, using pins 3 &5
  TCCR3A = 0b10100000; // Mega pin 5
  TCCR3C = 0b00010001; // Mega pin 3
  ICR3 = 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;
#if defined(__AVR_ATmega128__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
  // Mega board specific stuff here - assumes assigning timer3, using pins 3 &5
  OCR3A = speed;
//  #else
//  analogWrite(_PWM1,speed * 51 / 80);
  #endif
  if (reverse)
  {
    digitalWrite(_INA1,LOW);
    digitalWrite(_INB1,HIGH);
  }
  else
  {
    digitalWrite(_INA1,HIGH);
    digitalWrite(_INB1,LOW);
  }
}

// Same as motor 1
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;
  #if defined(__AVR_ATmega128__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
  // Mega board specific stuff here - assumes assigning timer3, using pins 3 &5
  OCR3C = speed;
 // #else
 // analogWrite(_PWM2,speed * 51 / 80);
  #endif
  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;
  #if defined(__AVR_ATmega128__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
  // Mega board specific stuff here - assumes assigning timer3, using pins 3 &5
  OCR3A = brake;
 // #else
 // analogWrite(_PWM1,brake * 51 / 80);
  #endif
}

// Same as motor 1
void DualVNH5019MotorShield::setM2Brake(int brake)
{
  // normalize brake
  if (brake < 0)
  {
    brake = -brake;
  }
  if (brake > 400)  
    brake = 400;
  digitalWrite(_INA2, LOW);
  digitalWrite(_INB2, LOW);
//  #if defined(__AVR_ATmega168__)|| defined(__AVR_ATmega328P__)
 // OCR1B = brake;
  #if defined(__AVR_ATmega128__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
  // Mega board specific stuff here - assumes assigning timer3, using pins 3 &5
  OCR3C = brake;
 // #else
 // analogWrite(_PWM2,brake * 51 / 80);
  #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);
}

Strangely enough in the .cpp file changing:
 
Code:
TCCR3A = 0b10100000;
 TCCR3C = 0b00010001;
 ICR3 = 400;

to

Code:
TCCR3A = 0b10100000;
TCCR3B = 0b00010001;
ICR3 = 400;

gets one motor working but from the research I did TCCR3B should be connected to pin 2 which is not being used.

Many thanks,
MAAhelp



Logged

Seattle, WA USA
Online Online
Brattain Member
*****
Karma: 634
Posts: 50226
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
I am trying to connect the Motor Driver to Timer 3 (that is pins 3&5 on the Arduino Mega),in order to use the 16-bit timer instead of the 8-bit timer which is connected to pins 9&10 which is the default connection used.
Why?
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 10
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

To get a PWM frequency of 20kHz as opposed to the maximum of an 8-bit timer. Pololu have developed a library specific to the Arduino Mega for all those interested.

http://forum.pololu.com/viewtopic.php?f=15&t=6139

Logged

Pages: [1]   Go Up
Jump to: