Problem with setting the variable PWM frequency

Hello, i have the problem with using this library: GitHub - khoih-prog/AVR_PWM: This library enables you to use Hardware-based PWM channels on AVR-based boards, such as Nano, UNO, Mega, Leonardo, 32u4, etc., to create and output PWM. Using the same functions as other FastPWM libraries to enable you to port PWM code easily between platforms.

I need to generate a variable frequency in steps (in this example, the PWM frequency is variable from 100 kHz to 128 kHz)


#define _PWM_LOGLEVEL_       4

#include "AVR_PWM.h"

#define pinToUse     10            // Timer1B on UNO, Nano, etc

#endif

AVR_PWM* PWM_Instance;

float frequency;

char dashLine[] = "=====================================================================================";

void printPWMInfo(AVR_PWM* PWM_Instance)
{
  Serial.println(dashLine);
  Serial.print("Actual data: pin = ");
  Serial.print(PWM_Instance->getPin());
  Serial.print(", PWM DC = ");
  Serial.print(PWM_Instance->getActualDutyCycle());
  Serial.print(", PWMPeriod = ");
  Serial.print(PWM_Instance->getPWMPeriod());
  Serial.print(", PWM Freq (Hz) = ");
  Serial.println(PWM_Instance->getActualFreq(), 4);
  Serial.println(dashLine);
}

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

  while (!Serial);

  delay(100);

  Serial.print(F("\nStarting PWM_DynamicFreq on "));
  Serial.println(BOARD_NAME);
  Serial.println(AVR_PWM_VERSION);

  frequency = 100000.0f;
  PWM_Instance = new AVR_PWM(pinToUse, frequency, 50.0f);

  if (PWM_Instance)
  {
    PWM_Instance->setPWM();
  }

  Serial.println(dashLine);
}

void loop()
{
  delay(5000);

  frequency = 100000.0f;

  Serial.print(F("Change PWM Freq to "));
  Serial.println(frequency);
  PWM_Instance->setPWM(pinToUse, frequency, 50.0f);
  printPWMInfo(PWM_Instance);

  delay(5000);

  frequency = 128000.0f;

  Serial.print(F("Change PWM Freq to "));
  Serial.println(frequency);
  PWM_Instance->setPWM(pinToUse, frequency, 50.0f);
  printPWMInfo(PWM_Instance);
}

And the problem is I get frequencies equal 100 and approximately 142 kHz on my oscilloscope. What could be the cause?

I believe that you have found a bug in the library related to

setPWM(pinToUse, frequency, 50.0f);

which calls

setPWM_Int(const uint8_t& pin, const float& frequency, const uint16_t& dutycycle)

which in the case of the Timer used for the Uno calls

setPeriod_Timer1(1000000UL / new_frequency);

This function takes an input parameter in microseconds, and any value of the frequency such that 1000000/frequency is not an integer will be truncated.
In your case with frequency 128000 the division is 7.8125 which is truncated to 7 which gives the 143KHz. (142.875)

void setPeriod_Timer1(unsigned long microseconds) __attribute__((always_inline))

Unfortunately, the library is now read only, and you can not report the bug. I think that Khoi Hoang, who is the author of the library, has moved on to new things.

Although it is usually best to push fixes and improvements to the original library when possible, as you explained it is not possible since the library is no longer maintained and the repository is archived. In this case, the best way forward is for a community member to create a fork of the library to allow the development to continue.

The library fork could be given a unique name and submitted for inclusion in the Arduino Library Manager in order to make it easy for Arduino users to install and update.