Go Down

Topic: Due PWM frequency (Read 3560 times) previous topic - next topic

buckboostbill

This may help you understand where I am coming from..

I don't get why you would have to start from the ground up like enabling pwm. Isn't that done when you select an output with analogWrite?

MartinL

Quote
I don't get why you would have to start from the ground up like enabling pwm. Isn't that done when you select an output with analogWrite?
The issue with analogWrite() is that it only gives you a fixed PWM frequency and an 8-bit resolution. It  doesn't really harness the full potential of the SAM3X8E's PWM controller.

buckboostbill

Understood. I will need to change my approach. I will code with the atmel language.

After your last few posts I now fully understand this. Works great.
Code: [Select]
// Output a 40kHz PWM waveform at a resolution of 11-bits on pin DAC1 (PWML0)
void setup() {
  // PWM Set-up on pin: DAC1
  REG_PMC_PCER1 |= PMC_PCER1_PID36;                     // Enable PWM
  REG_PIOB_ABSR |= PIO_ABSR_P16;                        // Set PWM pin perhipheral type A or B, in this case B
  REG_PIOB_PDR |= PIO_PDR_P16;                          // Set PWM pin to an output
  REG_PWM_CLK = PWM_CLK_PREA(0) | PWM_CLK_DIVA(1);      // Set the PWM clock rate to 84MHz (84MHz/1)
  REG_PWM_CMR0 = PWM_CMR_CPRE_CLKA;                     // Enable single slope PWM and set the clock source as CLKA
  REG_PWM_CPRD0 = 2100;                                  // Set the PWM frequency 84MHz/40kHz = 2100
  REG_PWM_CDTY0 = 1050;                                  // Set the PWM duty cycle 50% (2100/2=1050)
  REG_PWM_ENA = PWM_ENA_CHID0;                          // Enable the PWM channel     
}

void loop() {}


0-2100 resolution is much better suited to my project.

I now need to figure out how to make REG_PWM_CDTY0 = the value from an ADC input with 0-2100 resolution instead of a fixed 1050..

buckboostbill

I at least have 10bit ADC input now

Code: [Select]
int Feedback = A0;   // feedback connected to pin 0
int val = 0;         // variable to store the read value

void setup() {
  // PWM Set-up on pin: DAC1
   
  REG_PMC_PCER1 |= PMC_PCER1_PID36;                     // Enable PWM
  REG_PIOB_ABSR |= PIO_ABSR_P16;                        // Set PWM pin perhipheral type A or B, in this case B
  REG_PIOB_PDR |= PIO_PDR_P16;                          // Set PWM pin to an output
  REG_PWM_CLK = PWM_CLK_PREA(0) | PWM_CLK_DIVA(1);      // Set the PWM clock rate to 84MHz (84MHz/1)
  REG_PWM_CMR0 = PWM_CMR_CPRE_CLKA;                     // Enable single slope PWM and set the clock source as CLKA
  REG_PWM_CPRD0 = 2100;                                  // Set the PWM frequency 84MHz/40kHz = 2100                                   // Set the PWM duty cycle 50% (2100/2=1050)
  REG_PWM_ENA = PWM_ENA_CHID0;                          // Enable the PWM channel     
}

void loop()
{
val = analogRead(Feedback);
REG_PWM_CDTY0 = val * 2;
}

dlloyd

Try this for 11-bit. Note that the duty cycle range is about 0-97.5%
Code: [Select]
int Feedback = A0;   // feedback connected to pin 0
int val = 0;         // variable to store the read value

void setup() {
  // PWM Set-up on pin: DAC1

  REG_PMC_PCER1 |= PMC_PCER1_PID36;                     // Enable PWM
  REG_PIOB_ABSR |= PIO_ABSR_P16;                        // Set PWM pin perhipheral type A or B, in this case B
  REG_PIOB_PDR |= PIO_PDR_P16;                          // Set PWM pin to an output
  REG_PWM_CLK = PWM_CLK_PREA(0) | PWM_CLK_DIVA(1);      // Set the PWM clock rate to 84MHz (84MHz/1)
  REG_PWM_CMR0 = PWM_CMR_CPRE_CLKA;                     // Enable single slope PWM and set the clock source as CLKA
  REG_PWM_CPRD0 = 2100;                                 // Set the PWM frequency 84MHz/40kHz = 2100                                   // Set the PWM duty cycle 50% (2100/2=1050)
  REG_PWM_ENA = PWM_ENA_CHID0;                          // Enable the PWM channel

  analogReadResolution(11);                             // 11-bit, 0-2048
}

void loop()
{
  val = analogRead(Feedback);
  REG_PWM_CDTY0 = val;
}

antodom

Hi there @buckboostbill,

Maybe you will find interesting to have a look to pwm_lib: https://github.com/antodom/pwm_lib

This library abstract the use of the eight hardware PWM channels available on Arduino DUE's Atmel ATSAM3X8E microcontroller. I think you can generate easily the 40 kHz PWM signals that you need using pwm_lib.

Have a look to the exampes that come with the library, and if in doubt just ask me.

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

tcorkum

Try this for 11-bit. Note that the duty cycle range is about 0-97.5%
Code: [Select]
int Feedback = A0;   // feedback connected to pin 0
int val = 0;         // variable to store the read value

void setup() {
  // PWM Set-up on pin: DAC1

  REG_PMC_PCER1 |= PMC_PCER1_PID36;                     // Enable PWM
  REG_PIOB_ABSR |= PIO_ABSR_P16;                        // Set PWM pin perhipheral type A or B, in this case B
  REG_PIOB_PDR |= PIO_PDR_P16;                          // Set PWM pin to an output
  REG_PWM_CLK = PWM_CLK_PREA(0) | PWM_CLK_DIVA(1);      // Set the PWM clock rate to 84MHz (84MHz/1)
  REG_PWM_CMR0 = PWM_CMR_CPRE_CLKA;                     // Enable single slope PWM and set the clock source as CLKA
  REG_PWM_CPRD0 = 2100;                                 // Set the PWM frequency 84MHz/40kHz = 2100                                   // Set the PWM duty cycle 50% (2100/2=1050)
  REG_PWM_ENA = PWM_ENA_CHID0;                          // Enable the PWM channel

  analogReadResolution(11);                             // 11-bit, 0-2048
}

void loop()
{
  val = analogRead(Feedback);
  REG_PWM_CDTY0 = val;
}

Can I use this approach to get a frequency of 200KHz?

dlloyd

#22
Feb 22, 2017, 12:12 am Last Edit: Feb 22, 2017, 05:57 am by dlloyd
Sure. At 200kHz PWM, you'll get 420 steps for duty cycle.
Code: [Select]
REG_PWM_CPRD0 = 420;  //Set PWM frequency to 200kHz (84000000/200000 = 420)

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