Hello
Beginner here. Noted that the VNH5019 dual_vnh5019_motor_driver_shield.pdf (911.9 KB) motor shield can be configured to drive-brake operation. Currently the equipment I’m using is a 6v,3.3aH lead acid battery from unicell, an Arduino Uno(328P) and the 2 motors are from Pololu - 47:1 Metal Gearmotor 25Dx64L mm LP 6V with 48 CPR Encoder (No End Cap). I have connected the jumper ON from page 10 of the PDF attached. Searching past forums got me useful info but raises slightly more questions for a beginner like myself.
According to the user guide of the VNH5019 motor shield, it states clearly that I will have to connect physically a jumper wire of both MxPWM pins to Vcc and simply provide PWM to MxINA/B pins. Below is the edits I’ve made to the library for my needs.
The edits are assuming:
- I will not be moving in reverse direction.
- No need for current sense pins.
- Drive-Brake
My main question is whether I have done the changes to enable drive-brake operation properly. Is it even possible? Would like to seek clarification on this. Thanks in advance.
DualVNH5019MotorShield.cpp
#include "DualVNH5019MotorShield.h"
// Constructors ////////////////////////////////////////////////////////////////
DualVNH5019MotorShield::DualVNH5019MotorShield()
{
//Pin map
_INA1 = 2; // pin operates at ~490Hz
_INB1 = 4; // pin operates at ~490Hz
_EN1DIAG1 = 6;
//_CS1 = A0;
_INA2 = 7; // pin operates at ~490Hz
_INB2 = 8; // pin operates at ~490Hz
_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,INPUT);
pinMode(_EN1DIAG1,INPUT);
//pinMode(_CS1,INPUT);
pinMode(_INA2,OUTPUT);
pinMode(_INB2,OUTPUT);
pinMode(_PWM2,INPUT);
pinMode(_EN2DIAG2,INPUT);
//pinMode(_CS2,INPUT);
#if defined(__AVR_ATmega168__)|| defined(__AVR_ATmega328P__) || defined(__AVR_ATmega32U4__)
// 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(unsigned int speed)
{
// if (speed < 0)
// {
// speed = -speed; // Make speed a positive quantity
// reverse = true; // Preserve the direction
// }
if (speed > 400) // Max PWM dutycycle
speed = 400;
// #if defined(__AVR_ATmega168__)|| defined(__AVR_ATmega328P__) || defined(__AVR_ATmega32U4__)
// OCR1A = speed;
// #else
// analogWrite(_PWM1,temp); // default to using analogWrite, mapping 400 to 255
// #endif
if (speed == 0)
{
analogWrite(_INA1,0); // Make the motor brake immediately no
analogWrite(_INB1,0); // matter which direction it is spinning.
}
// else if (reverse)
// {
// analogWrite(_INA1,0);
// analogWrite(_INB1,speed * 51 / 80);
// }
else
{
analogWrite(_INA1,speed*51/80);
analogWrite(_INB1,0);
}
}
// Set speed for motor 2, speed is a number betwenn -400 and 400
void DualVNH5019MotorShield::setM2Speed(unsigned int speed)
{
// if (speed < 0)
// {
// speed = -speed; // make speed a positive quantity
// reverse = true; // preserve the direction
// }
if (speed > 400) // Max
speed = 400;
// #if defined(__AVR_ATmega168__)|| defined(__AVR_ATmega328P__) || defined(__AVR_ATmega32U4__)
// OCR1B = speed;
// #else
// analogWrite(_PWM2,temp); // default to using analogWrite, mapping 400 to 255
// #endif
if (speed == 0)
{
analogWrite(_INA2,0); // Make the motor brake immediately no
analogWrite(_INB2,0); // matter which direction it is spinning.
}
// else if (reverse)
// {
// analogWrite(_INA2,0);
// analogWrite(_INB2,speed * 51 / 80);
// }
else
{
analogWrite(_INA2,speed*51/80);
analogWrite(_INB2,0);
}
}
// Set speed for motor 1 and 2
void DualVNH5019MotorShield::setSpeeds(unsigned int m1Speed, unsigned int m2Speed)
{
setM1Speed(m1Speed);
setM2Speed(m2Speed);
}
// Brake motor 1, brake is a number between 0 and 400
void DualVNH5019MotorShield::setM1Brake(unsigned int brake)
{
if (brake > 400) // Max brake
brake = 400;
// #if defined(__AVR_ATmega168__)|| defined(__AVR_ATmega328P__) || defined(__AVR_ATmega32U4__)
// OCR1A = brake;
// #else
// analogWrite(_PWM1,temp); // default to using analogWrite, mapping 400 to 255
// #endif
analogWrite(_INA1, 400);
analogWrite(_INB1, 400);
}
// Brake motor 2, brake is a number between 0 and 400
void DualVNH5019MotorShield::setM2Brake(unsigned int brake)
{
if (brake > 400) // Max brake
brake = 400;
// #if defined(__AVR_ATmega168__)|| defined(__AVR_ATmega328P__) || defined(__AVR_ATmega32U4__)
// OCR1B = brake;
// #else
// analogWrite(_PWM2,temp); // default to using analogWrite, mapping 400 to 255
// #endif
analogWrite(_INA2, 400);
analogWrite(_INB2, 400);
}
// Brake motor 1 and 2, brake is a number between 0 and 400
void DualVNH5019MotorShield::setBrakes(unsigned int m1Brake, unsigned 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);
}
EDIT 1:
Strangely enough, I have stumbled upon other similar posts. According to this post PWM based speed controlling is not possible of VNH5019 with Arduino MEGA, seems that I’ll only be able to in some hybrid mode(which is fine by me) @nathanb. According to the same post @Claire, mentioned compensation by software, if it’s possible may I enquire further on this?