VNH5019 pin remapping speed issue

I am using the VNH5019 with an Arduino Uno. I needed the default Arduino pins for other uses so I modified the VNH5019 board as follows:
M2ED --> pin 0
M1PS --> pin 5
M2PS --> pin 6
M1ED --> pin 9
M2IA --> pin 3

I then modified DualVNH5019MotorShield.h and DualVNH5019MotorShield.cpp (code snippets below). Direction works fine but I have no control over speed. The motors always run at what appears to be max no matter what speed values I use, including zero (I don’t have a scope).

Any ideas?


DualVNH5019MotorShield.h
....
  private:
    unsigned char _INA1;
    unsigned char _INB1;
    //static const unsigned char _PWM1 = 9;
    static const unsigned char _PWM1 = 5;
    unsigned char _EN1DIAG1;
    unsigned char _CS1;
    unsigned char _INA2;
    unsigned char _INB2;
    //static const unsigned char _PWM2 = 10;
    static const unsigned char _PWM2 = 6;
    unsigned char _EN2DIAG2;
    unsigned char _CS2;
....

DualVNH5019MotorShield.cpp

DualVNH5019MotorShield::DualVNH5019MotorShield()
{
  //Pin map
  _INA1 = 2;
  _INB1 = 4;
  //_EN1DIAG1 = 6;
  _EN1DIAG1 = 9;
  _CS1 = A0; 
  //_INA2 = 7;
  _INA2 = 3;
  _INB2 = 8;
  //_EN2DIAG2 = 12;
  _EN2DIAG2 = 0;
  _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;


// Use Timer 0
  TCCR0A = 0b11111000;
  //TCCR0B = 0b00001001;
  //OCR0A = 20;
  
  byte mode;
  //mode = 0x01;    62500
  //mode = 0x02;    7812.5
  mode = 0x03;    // 976.5625
  //mode = 0x04;    244.140625
  //mode = 0x05;     61.03515625
  
  TCCR0B = TCCR0B & 0b11111000 | mode;

  #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;
  OCR0A = speed;
  #else
  analogWrite(_PWM1,speed * 51 / 80); // default to using analogWrite, mapping 400 to 255
  #endif
  */
  analogWrite(_PWM1,speed * 51 / 80);
  
  if (reverse)
  {
    digitalWrite(_INA1,LOW);
    digitalWrite(_INB1,HIGH);
  }
  else
  {
    digitalWrite(_INA1,HIGH);
    digitalWrite(_INB1,LOW);
  }
}

...

Hello.

You appear to be using pin names that don’t appear anywhere in the product documentation, which makes it unclear what pins you’re talking about remapping (the “M1PS” and “M2PS” are especially confusing).

I can guess what pins you’re talking about from how you changed the library code, though. Your problem is that the library code is written specifically for generating PWMs using Timer1, and you can’t just swap in Timer0 (Timer0 is an 8-bit timer, so it behaves differently, and the Arduino uses it for the system clock, so you have almost no flexibility about how to use it). If you want different PWM outputs for controlling the motor speed, I suggest you just rewrite the library to use Arduino’s built-in analogWrite() (max speed would then be 255, not 400). If you need help making these changes, please let me know.

- Ben

Thanks, Ben.

Sorry about not catching the homegrown pin labels. Yes M1PS is M1PWM and M2PS is M2PWM.

“If you want different PWM outputs for controlling the motor speed, I suggest you just rewrite the library to use Arduino’s built-in analogWrite() (max speed would then be 255, not 400). If you need help making these changes, please let me know.”

Do you mean implement the motor waveform in code without using a timer? I understand this could be a problem if the code has to manage a lot of other functionality. Can you provide a code hint as to what you have in mind?

If I switch to the Mega, does it have a timer (other than 0,1,2) that would make the coding change straight froward?

- John

Hello, John.

The code change is straight forward without changing controllers. If you just delete all the code branches in DualVNH5019MotorShield.cpp that begin with

#if defined(__AVR_ATmega168__)|| defined(__AVR_ATmega328P__)

, you will be using analogWrite(). You would still use speeds from 0 to 400, which get mapped to 0-255 by the library.

- Ryan

Thanks, Ryan. The revised code works on my remapped motor controller and the Uno.

So what was the reason for using Timer1 in the original pin map and code?

-John

Timer1 allows us to get 20kHz PWM, which eliminates audible noise attributed to the switching frequency.

- Ryan