I've been using the following code for years, to get 20Mhz PWM on D9 & D10 (Atmega328P-AU), to drive 2 small motors. My motor driver is no longer available so I've had to switch to a different one, which requires 2 PWM pins, one for each direction, rather than just 1. So now, I need 2 PWM pins each, 4 total. I need the 20mhz as the project is used very close to pro-audio equipment. Is it possible to do this same thing with digital PWM pins 5 & 6, as well as 9 & 10. The Atmega328P-AU isn't doing much else, other than monitoring 2 analog joystick inputs, and a couple switches & LEDS. This changing registry things on the arduino is way out of my league, and I greatly appreciated coding_badly for helping me with this over 10 years ago. If someone could help with doing this for 4 PWM outputs, it would be greatly appreciated.
//From this thread:
//http://forum.arduino.cc/index.php?topic=135847.15
void analogWriteSAHA( uint16_t value )
{
if ( (value >= 0) && (value < 800) )
{
OCR1A = value;
}
}
void analogWriteSAHB( uint16_t value )
{
if ( (value >= 0) && (value < 800) )
{
OCR1B = value;
}
}
void analogWriteSAH_Init( void )
{
// Stop the timer while we muck with it
TCCR1B = (0 << ICNC1) | (0 << ICES1) | (0 << WGM13) | (0 << WGM12) | (0 << CS12) | (0 << CS11) | (0 << CS10);
// Set the timer to mode 14...
//
// Mode WGM13 WGM12 WGM11 WGM10 Timer/Counter Mode of Operation TOP Update of OCR1x at TOV1 Flag Set on
// CTC1 PWM11 PWM10
// ---- ----- ----- ----- ----- ------------------------------- ---- ----------------------- -----------
// 14 1 1 1 0 Fast PWM ICR1 BOTTOM TOP
// Set output on Channel A and B to...
//
// COM1z1 COM1z0 Description
// ------ ------ -----------------------------------------------------------
// 1 0 Clear OC1A/OC1B on Compare Match (Set output to low level).
TCCR1A =
(1 << COM1A1) | (0 << COM1A0) | // COM1A1, COM1A0 = 1, 0
(1 << COM1B1) | (0 << COM1B0) |
(1 << WGM11) | (0 << WGM10); // WGM11, WGM10 = 1, 0
// Set TOP to...
//
// fclk_I/O = 16000000
// N = 1
// TOP = 799
//
// fOCnxPWM = fclk_I/O / (N * (1 + TOP))
// fOCnxPWM = 16000000 / (1 * (1 + 799))
// fOCnxPWM = 16000000 / 800
// fOCnxPWM = 20000
ICR1 = 799;
// Ensure the first slope is complete
TCNT1 = 0;
// Ensure Channel A and B start at zero / off
OCR1A = 0;
OCR1B = 0;
// We don't need no stinkin interrupts
TIMSK1 = (0 << ICIE1) | (0 << OCIE1B) | (0 << OCIE1A) | (0 << TOIE1);
// Ensure the Channel A and B pins are configured for output
DDRB |= (1 << DDB1);
DDRB |= (1 << DDB2);
// Start the timer...
//
// CS12 CS11 CS10 Description
// ---- ---- ---- ------------------------
// 0 0 1 clkI/O/1 (No prescaling)
TCCR1B =
(0 << ICNC1) | (0 << ICES1) |
(1 << WGM13) | (1 << WGM12) | // WGM13, WGM12 = 1, 1
(0 << CS12) | (0 << CS11) | (1 << CS10);
}
I think you mean 20kHz. I don't know any motor or motor driver that can work on 20Mhz.
Post a link to the driver.
You only need one PWM pin per motor. Direction is just a logic level.
Leo..
The DRV8256PPWPR needs 2 PWM pins.
I was hoping to use the DRV8256PPWPR , as I've already used it, and made some custom PCBS with it, but only fro 1 motor. So I already have circuitry for it, but I don't have to use it.
I'm looking now for some alternate motor drivers in case it's not possible to get 4 PWM pins @ 20Khz on the Atmega328P
Thanks for the datasheet. Several pins need to be hardwired in various ways.
That's the key question. The PWM uses timers/internal resources and the might no have the same range. What's available, more deep hardware knowing guys must tell.
If you require a PWM signals out of audible range then it's possible to generate 31.25kHz PWM on pins 3, 9, 10 and 11. Just add the following lines to your sketch then use the analogWrite() function as normal:
TCCR1B &= ~_BV(CS11); // Increase the timer1 PWM frequency to 31.25kHz
TCCR2B &= ~_BV(CS22); // Increase the timer2 PWM frequency to 31.25kHz
TCCR2B |= _BV(CS20);
I see this from the PWM link mentioned in post 10. So to get it out of audible hearing range, these lines should do the trick it seems. And the data sheet for my motor drivers says it works with PWM up to 100khz, so this should work great for me. Thanks.
//---------------------------------------------- Set PWM frequency for D9 & D10 ------------------------------
//TCCR1B = TCCR1B & B11111000 | B00000001; // set timer 1 divisor to 1 for PWM frequency of 31372.55 Hz
//---------------------------------------------- Set PWM frequency for D3 & D11 ------------------------------
//TCCR2B = TCCR2B & B11111000 | B00000001; // set timer 2 divisor to 1 for PWM frequency of 31372.55 Hz