Go Down

Topic: Programmable PWM Frequency (Read 227 times) previous topic - next topic

julianbostick

Hello,

I am currently working on a project and have run into a wall. I need to be able to generate a PWM wave with an adjustable frequency (0 - 10kHZ) with a resolution of ~ 10Hz. This also has to have a Duty cycle of 0-100, with resolution ~1. Is this possible with the Due? I know that pin 9 acts as a true PWM output, but after searching for awhile I couldn't find any straightforward answers. If this isn't possible, are there any hardware solutions, I have looked into programmable oscillators with no luck, as well as PLL's, the last thing I can think of is silly, but an FPGA could do it!

antodom

Hi there Julian,

Have a look to pwm_lib, you can use example basic_test.ino as an starting point. The library is available at:

   https://github.com/antodom/pwm_lib

If in any doubt, just let me know.

I hope it helps.
------------
antodom

ard_newbie

@julianbostick . Hello Julian

As a simple example of PWM implementation, you could try this :
Code: [Select]
void setup() {
  // PWM Set-up on pin PC7 (Arduino Pin 39): see Datasheet chap. 38.5.1
  // Select Instance=PWM; Signal=PWMH2 (channel 2); I/O Line=PC7 (P7, Arduino pine 39, see pinout diagram) ; Peripheral=B

  PMC->PMC_PCER1 |= PMC_PCER1_PID36;                   // Enable PWM
 
  REG_PIOC_ABSR |= PIO_ABSR_P7;                        // Set PWM pin perhipheral type B
  REG_PIOC_PDR |= PIO_PDR_P7;                          // Set PWM pin to an output

  REG_PWM_ENA = PWM_ENA_CHID2;                         // Enable the PWM channel 2 (see datasheet page 973)
 
  REG_PWM_CLK = PWM_CLK_PREA(0) | PWM_CLK_DIVA(42);    // Set the PWM clock rate to 2MHz (84MHz/42) ; Adjust DIVA for the resolution you are looking for
                                                       // I suspect that the smaller the DIVA factor, the higher the resolution will be
  REG_PWM_CMR2 = PWM_CMR_CALG |PWM_CMR_CPRE_CLKA;      // The period is left aligned, clock source as CLKA on channel 2
  REG_PWM_CPRD2 = 1000000;                             // Channel 2 : Set the PWM frequency 2MHz/(2 * CPRD) = F ; 1< CPRD < 2exp24  -1 ; here CPRD = 10 exp 6
  REG_PWM_CDTY2 = 200000;                              // Channel 2: Set the PWM duty cycle to x%= (CDTY/ CPRD)  * 100 % ; here CDTY = 2 * 10 exp 5
 // Alternatively, you can use this format :  PWM->PWM_CH_NUM[2].PWM_CPRD = 1000000 ; 

                   
 // In this example, Frequency is 1 HZ with a DT of 20% so you can see it with an LED attached to pin 39 with a resistor 
 
  Serial.begin(250000); // for debugging purpose
}

void loop() {
 
// If you want to modify the PWM frequency during operation :
REG_PWM_CPRDUPD2 = 800000;
REG_PWM_SCM = PWM_SCM_UPDM_MODE0 ;
REG_PWM_SCUC = PWM_SCUC_UPDULOCK;

//delay(1000);


 // if you want to modify duty cycle during operation:
REG_PWM_CDTYUPD2 = 50000;
REG_PWM_SCM = PWM_SCM_UPDM_MODE0 ;
REG_PWM_SCUC = PWM_SCUC_UPDULOCK;
 
//delay(1000);

  }



Go Up
 


Please enter a valid email to subscribe

Confirm your email address

We need to confirm your email address.
To complete the subscription, please click the link in the email we just sent you.

Thank you for subscribing!

Arduino
via Egeo 16
Torino, 10131
Italy