Go Down

Topic: VNH5019 Motor Driver - Arduino Mega 2560 - Help needed (Read 1 time) previous topic - next topic

MAAhelp

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: [Select]
#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: [Select]

#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: [Select]
TCCR3A = 0b10100000;
TCCR3C = 0b00010001;
ICR3 = 400;


to

Code: [Select]
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




PaulS

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?

MAAhelp

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


Go Up
 


Please enter a valid email to subscribe

Confirm your email address

We need to confirm your email address.
To complete the subscription, please click the link in the email we just sent you.

Thank you for subscribing!

Arduino
via Egeo 16
Torino, 10131
Italy