Arduino Due PWM Frequency Reduction

Hello everyone,,

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!

ESCs Datasheet (See last page): http://dl.djicdn.com/downloads/e310/en/E310_User_Manual_v1.0_en.pdf

You can generate PWM pulses thru the PWM peripheral or the Timer Counters.

For direct register programing, search in the DUE sub forum for one of the numerous example sketches, or use pwm library from antodom.

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.

Hi kimon1,

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.