Arduino Leonardo Frequency Changing

Hi All,

I am using Arduino Leonardo for LED Brightness controlling.
I give 0-5 Input to Leonardo to "A0" Channel and i have connected an LED to "Pin 3".
I made a program so that if i vary 0-5 V Input, PWM from pin 3 will vary 0-100%.
By default the PIN 3 frequency will be 980 HZ.

I need a help to change PWM frequency in Leonardo.
I will give analog voltage 0-5V to "A1" pin so that PWM frequency will change from 50-300 HZ.
This frequency i will keep constant.(Say Freqency is fixed to 150 HZ)
Now if i vary input in A0 pin PWM in Pin 3 should vary from 0-100% at 150 HZ.

Is it possible to do .

Please share code if possible.

It is certainly possible on an Uno and Mega so I presume it is possible on a Leonardo.

The PWM frequency is controlled by the registers for the appropriate HardwareTimer and all the details will be in the Atmega 32U4 datasheet. Don't change the frequency of the Timer (presumably Timer0) that is used for millis() and micros()

There may be a library that makes it easy to change the PWM frequency.

...R

Here is an example sketch for variable frequency and duty-cycle on Timer1 of the Arduino UNO. It should be fairly easy to adapt for a 16-bit timer on the Leorando.

// Generating Variable-Frequency PWM on Timer1 of an Arduino UNO (Pins 9 and 10)
// Good for integer frequencies from 1 Hz to 65535 Hz.
// Written June 19th, 2020 by John Wasser


uint16_t TimerTOP = 0xFFFF;
byte PercentPWM_A = 50;  // Default to 50% duty cycle
byte PercentPWM_B = 50;  // Default to 50% duty cycle


void FPWMBegin()
{
  digitalWrite(9, LOW);
  pinMode(9, OUTPUT);
  digitalWrite(10, LOW);
  pinMode(10, OUTPUT);


  // Stop Timer/Counter1
  TCCR1A = 0;  // Timer/Counter1 Control Register A
  TCCR1B = 0;  // Timer/Counter1 Control Register B
  TIMSK1 = 0;   // Timer/Counter1 Interrupt Mask Register


  // Set Timer/Counter1 to Waveform Generation Mode 8: Phase and Frequency correct PWM with TOP set by ICR1
  TCCR1B |= (1 << WGM13);  // WGM=8
  TCCR1A |= (1 << COM1A1);  // Normal PWM on Pin 9
  TCCR1A |= (1 << COM1B1);  // Norml PWM on Pin 10


  FPWMSetFrequency(1000);  // Default to 1 kHz
}


bool FPWMSetFrequency(uint16_t frequency)
{
  byte prescaleBits; // 1, 2, 3, 4, 5
  uint16_t prescaleFactor;  // 1, 8, 64, 256, 1024
  uint32_t top32;


  // Clear the three clock select bits to stop the timer
  TCCR1B &= ~((1 << CS12) | (1 << CS11) | (1 << CS10));


  // Find the smallest prescale factor that will fit the TOP value within 16 bits.
  // frequency = F_CPU / (2 * prescale *  TOP)
  // TOP = F_CPU / (2UL * prescale * frequency);


  prescaleBits = 1;
  prescaleFactor = 1;  // Used for 123-65535 Hz
  top32 = F_CPU / (2UL * prescaleFactor * frequency);
  if (top32 > 65535UL) // Too many clocks to count in 16 bits?
  {
    prescaleBits = 2;
    prescaleFactor = 8;  // Used for 16-122 Hz
    top32 = F_CPU / (2UL * prescaleFactor * frequency);
    if (top32 > 65535UL) // Too many clocks to count in 16 bits?
    {
      prescaleBits = 3;
      prescaleFactor = 64;  // Used for 2-15 Hz
      top32 = F_CPU / (2UL * prescaleFactor * frequency);
      if (top32 > 65535UL) // Too many clocks to count in 16 bits?
      {
        prescaleBits = 4;
        prescaleFactor = 256; // Only used for 1 Hz
        top32 = F_CPU / (2UL * prescaleFactor * frequency);
        if (top32 > 65535UL) // Too many clocks to count in 16 bits?
        {
          prescaleBits = 5;
          prescaleFactor = 1024;
          top32 = F_CPU / (2UL * prescaleFactor * frequency);
          if (top32 > 65535UL) // Too many clocks to count in 16 bits?
          {
            return false;
          }
        }
      }
    }
  }


  //  Serial.print("Freq: ");
  //  Serial.print(frequency);
  //  Serial.print(" prescale: ");
  //  Serial.print(prescaleFactor);
  //  Serial.print(" TOP: ");
  //  Serial.println(top32);


  if (top32 < 16)
    return false; // Require at least 16 levels of PWM


  TimerTOP = top32;


  OCR1A = (PercentPWM_A * (uint32_t)TimerTOP) / 100;
  OCR1B = (PercentPWM_A * (uint32_t)TimerTOP) / 100;


  ICR1 = TimerTOP;


  TCCR1B |= prescaleBits; // Set clock prescale bits to start the timer
  return true;
}


void FPWMSetDutyCyclePercentageA(byte percent)
{
  PercentPWM_A = min(percent, 100);
  OCR1A = (PercentPWM_A * (uint32_t)TimerTOP) / 100;
}


void FPWMSetDutyCyclePercentageB(byte percent)
{
  PercentPWM_B = min(percent, 100);
  OCR1A = (PercentPWM_B * (uint32_t)TimerTOP) / 100;
}


void setup()
{
  Serial.begin(115200);


  FPWMBegin();  // Start output at 1000 Hz, 505 duty cycle
}


void loop()
{
  // Call FPWMSetFrequency(uint16_t frequency) any time to change the output frequency
  // Call FPWMSetDutyCyclePercentageA(byte percent) at any time to change duty cycle
  // Call FPWMSetDutyCyclePercentageB(byte percent) at any time to change duty cycle
}