Well, it generally sounds like you know what you’re doing, though I’m still worried that your shoot-through problems might be a show-stopper, even at lower PWM frequencies. You really should have some dead-time between when you turn off one MOSFET and turn on another, and you aren’t going to get that from the SVP’s motor driver outputs. As an alternative, you could decrease the shoot-through if you can get your MOSFETs to turn on more slowly.
The SVP motor control code is located in the file:
libpololu-avr/src/OrangutanMotors/OrangutanMotors.cpp
and the relevant code is in the initialization method init2():
#ifdef _ORANGUTAN_SVP
// Configure for non-inverted fast PWM output on motor PWM pins:
// Normal port operation, OC2x disconnected (changes later when a non-zero speed is set)
// Timer2 counts up from 0 to 255 and then overflows directly to 0.
TCCR2A = 0x03;
// use the system clock/8 (=2.5 MHz) as the timer clock,
// which will produce a PWM frequency of 10 kHz
TCCR2B = 0x02;
If you want to understand these register settings better, you should look at the ATmega1284P datasheet.
The easiest way to change the PWM frequency is to change the prescaler of the timer that generates the PWM, which can be accomplished by changing the three lowest bits of the TCCR2B register. For example, if you set TCCR2B to 0x03, the prescaler changes from 8 to 32, and the PWM frequency is divided by 4 (2.5 kHz). The following list shows the approximate frequencies you can get for different TCCR2B values:
- 0x01: 80 kHz
- 0x02: 10 kHz
- 0x03: 2.5 kHz
- 0x04: 1.25 kHz
- 0x05: 625 Hz
- 0x06: 300 Hz
- 0x07: 75 Hz
There are other ways to change the frequency, and you can achieve different frequencies from those listed above using those alternate methods, but I figure this is the simplest way to see if your problems go away, or at least become more manageable, at lower PWM frequencies.
While you could edit the library code directly and recompile it, I think the easiest way to try this out is to just overwrite the TCCR2B register after you get the OrangutanMotor code to initialize itself. You could do something like the following:
set_motors(0, 0); // automatically initializes motor driver routines
TCCR2B = 0x06; // change PWM frequency from 10 kHz to 300 Hz
// the rest of your code goes here
Does this make sense? Please let me know how this works for you.
- Ben