I'll be direct... I have to command an ESC (Electronic Speed Controller) through PWM, but it wants a PWM frequency between 30-450Hz and, as far as I know, Due's default PWM frequency is much higher than that.
I just wanted to set that frequency for 6 of the 12 PWM capable pins (I have 6 ESCs) to use analogWrite() to command them, without messing up the board timing.
PD: I have never tried Direct Port Manipulation before, but I would be happy to learn (if necessary), thank you!
You can program the timers to do it for you or you can do it in software, the PWM you are trying to achieve is not that fast.
You might want to get the Arduino cookbook and read it. Also on line there are many videos etc showing the Arduino and how to do what you want. This additional information will go a long way in getting your problem solved. At that point you start on the hardware design and write your software.
Here's some example code that set-up 8 dual-slope PWM channels, at 400Hz PWM on the Arduino Due:
// Enable dual slope, 11-bit resolution PWM at 400Hz on 8 channels
void setup() {
// PWM set-up on pins DAC1, A8, A9, A10, D9, D8, D7 and D6 for channels 0 through to 7 respectively
PMC->PMC_PCER1 |= PMC_PCER1_PID36; // Enable PWM controller
PIOB->PIO_ABSR |= PIO_ABSR_P19 | PIO_ABSR_P18 | PIO_ABSR_P17 | PIO_ABSR_P16; // Set the port B PWM pins to peripheral type B
PIOC->PIO_ABSR |= PIO_ABSR_P24 | PIO_ABSR_P23 | PIO_ABSR_P22 | PIO_ABSR_P21; // Set the port C PWM pins to peripheral type B
PIOB->PIO_PDR |= PIO_PDR_P19 | PIO_PDR_P18 | PIO_PDR_P17 | PIO_PDR_P16; // Set the port B PWM pins to outputs
PIOC->PIO_PDR |= PIO_PDR_P24 | PIO_PDR_P23 | PIO_PDR_P22 | PIO_PDR_P21; // Set the port C PWM pins to outputs
PWM->PWM_CLK = PWM_CLK_PREA(0) | PWM_CLK_DIVA(42); // Set the PWM clock A rate to 2MHz (84MHz/42)
for (uint8_t i = 0; i < PWMCH_NUM_NUMBER; i++) // Loop for each PWM channel (8 in total)
{
PWM->PWM_CH_NUM[i].PWM_CMR = PWM_CMR_CALG | PWM_CMR_CPRE_CLKA; // Enable dual slope PWM and set the clock source as CLKA
PWM->PWM_CH_NUM[i].PWM_CPRD = 2500; // Set the PWM frequency 2MHz/(2 * 2500) = 400Hz;
}
PWM->PWM_ENA = PWM_ENA_CHID7 | PWM_ENA_CHID6 | PWM_ENA_CHID5 | PWM_ENA_CHID4 | // Enable all PWM channels
PWM_ENA_CHID3 | PWM_ENA_CHID2 | PWM_ENA_CHID1 | PWM_ENA_CHID0;
for (uint8_t i = 0; i < PWMCH_NUM_NUMBER; i++) // Loop for each PWM channel (8 in total)
{
PWM->PWM_CH_NUM[i].PWM_CDTY = 1000; // Set the PWM duty cycle to 1000 min throttle, 2000 max throttle
}
}
void loop()
{
PWM->PWM_CH_NUM[0].PWM_CDTYUPD = 1200; // Set the PWM duty cycle to low throttle on channel 0
delay(1000); // Wait for 1 second
PWM->PWM_CH_NUM[0].PWM_CDTYUPD = 1000; // Set the PWM duty cycle to throttle off on channel 0
delay(1000); // Wait for 1 second
}
The code allows the ESCs to be controlled by loading the corresponding channel's duty-cycle update register with the pulse with in microseconds: 1000 ESC standby, 1500 mid throttle, 2000 full throttle.
Warning: If you're using propellers, please test the motors with the propellers removed.