0

I'm using Arduino Due and I set the analog read and write resolution to 12-bit for better resolution. Basically all I do is to vary PWM duty cycle by controlling analog DC input voltage from 0 to 3.3V. The simple code as it is now works fine as follows:

int pwmPin9 = 9;      
int analogPin0 = 0;   
int val = 0;         


void setup() {

  Serial.begin(9600);

  pinMode(pwmPin9, OUTPUT);  // sets the pin as output    
  analogWriteResolution(12);
  analogReadResolution(12);

}

void loop() {

  val = analogRead(analogPin0);  // read the input pin    
  Serial.println(val);
  analogWrite(pwmPin9, val); 

}

My problem is I need to set the frequency of the PWM output to 25kHz or at least something nearest above 25kHz.

I have been searching forums hours and couldn't find any solution. Here I came across a way but there is no library called variant.h in my folders. And that code if I include in my script doesn't change anything. What could be a workaround for this?

(I used to achieve this via this site by using Arduino Uno but for Due couldn't find any working solution)

Edit: I found the file and made the following change in variant.h:

 * PWM
 */
#define PWM_INTERFACE       PWM
#define PWM_INTERFACE_ID    ID_PWM
#define PWM_FREQUENCY       20000
#define PWM_MAX_DUTY_CYCLE  4095
#define PWM_MIN_DUTY_CYCLE  0
#define PWM_RESOLUTION      12

/*
 * TC
 */
#define TC_INTERFACE        TC0
#define TC_INTERFACE_ID     ID_TC0
#define TC_FREQUENCY        20000
#define TC_MAX_DUTY_CYCLE   255
#define TC_MIN_DUTY_CYCLE   0
#define TC_RESOLUTION       8

But it only works for 20kHz. If I set to 25kHz or 30kHz I don't get any error but also don't get any output :((

1 Answer 1

1

There are a few things to do. I've used this successfully in the past with older projects.

As a side note one can very easily change PWM settings on pins with the esp32, a single line of code being ledcSetup(PWM_Channel_Number, Frequency, resolution) without ever having to actually dive into modifying variant.h

To Quote Kerry D. Wong:

If you take a look at the function PWMC_ConfigureClocks in pwmc.c, you will see that the highest PWM frequency can be accommodated as the function input is 42 MHz, this is because inside the function it calls FindClockConfiguration which in turn ensures that the frequency parameter passed in is less than the MCK frequency. Thus for integer dividers, the highest frequency we can pass in is 42 MHz (with divider 2).

To achieve the highest output frequency, we can use a one bit PWM which essentially just outputs a square wave with a duty cycle of one. We can then set the prescaler to 2 to obtain an 84 MHz waveform.

#include <Arduino.h>

uint32_t pwmPin = 8;
uint32_t maxDutyCount = 2;
uint32_t clkAFreq = 42000000ul;
uint32_t pwmFreq = 42000000ul; 

void setup() {
  pmc_enable_periph_clk(PWM_INTERFACE_ID);
  PWMC_ConfigureClocks(clkAFreq, 0, VARIANT_MCK);

  PIO_Configure(
    g_APinDescription[pwmPin].pPort,
    g_APinDescription[pwmPin].ulPinType,
    g_APinDescription[pwmPin].ulPin,
    g_APinDescription[pwmPin].ulPinConfiguration);

  uint32_t channel = g_APinDescription[pwmPin].ulPWMChannel;
  PWMC_ConfigureChannel(PWM_INTERFACE, channel , pwmFreq, 0, 0);
  PWMC_SetPeriod(PWM_INTERFACE, channel, maxDutyCount);
  PWMC_EnableChannel(PWM_INTERFACE, channel);
  PWMC_SetDutyCycle(PWM_INTERFACE, channel, 1);

  pmc_mck_set_prescaler(2);
}

void loop() 
{

Note that VARIANT_MCK is defined in /arduino-1.5.7/hardware/arduino/sam/variants/arduino_due_x/variant.h as 84000000. PWM_INTERFACE_ID and PWM_INTERFACE are defined in variant.h as ID_PWM and PWM which in turn are defined in /arduino-1.5.7/hardware/arduino/sam/system/CMSIS/Device/ATMEL/sam3xa/include/sam3x8e.h.

So as the conclusion, the highest stable frequency we can generate using an Arduino Due is 84 MHz. The pictures below show the captured waveforms under different frequencies. For the 21 MHz waveform, pwmFreq is set to 21000000, no prescaler is used. For the 42 Mhz waveform, pwmFreq is set to 420000 with no prescaler. The 84 MHz waveform is generated with set to 42000000 and the prescaler set to 2.

Hope this helps.

5
  • Did you read what I was asking? My question is "But it only works for 20kHz. If I set to 25kHz or 30kHz I don't get any error but also don't get any output :(( " This does not set to PWM freq, to 25kHz.
    – user16307
    Commented Jul 18, 2019 at 16:22
  • Yes, but following the methods i said, should allow you to achieve the pwm setting you want...does it not do so? Can you set to any other freq above the khz range? Or does it just fall apart at anything above 25khz? Commented Jul 18, 2019 at 19:41
  • No that doesnt work. And your answer is not an answer at all. Im looking for a solution not advice. This is bounty question. Please delete your answer otherwise I will have to delete this question. You are not even using Due but attempting to answer such a technical specific question about it.
    – user16307
    Commented Jul 19, 2019 at 17:47
  • If you want a solution to ‘why doesnt the technical solution work with my hardware that i have no errors except it doesnt work to help with trouble shooting’ then you should delete this question, and re ask with useful information than ‘it doesnt work!!!!!’ :) Commented Jul 19, 2019 at 17:54
  • @user16307, you can wait for another answer. if you delete the question, you loose the bounty points. this answer will not get bounty points without at least two upvotes.
    – Juraj
    Commented Jul 19, 2019 at 17:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.