PWM frequency library

Thanks a lot. This library is AWESOME.

I was able to get 100kHz PWM with 16 bit resolution!

I'm experiencing an issue between a UNO and MEGA - my problem is described in a new post (did not notice this thread was still active, assumed it was too old)

Hi all,
this is really a great library - very helpful :slight_smile:

There's just one thing, that's bugging me. Each time, i include the lib in any of my programs, i get some warnings during the compiling.

/Users/philipp/Documents/Arduino/libraries/PWM/utility/BTimerDefs.cpp:26:0: warning: "UINT16_MAX" redefined
 #define UINT16_MAX 65535

 ^
In file included from /Applications/Arduino.app/Contents/Java/hardware/tools/avr/lib/gcc/avr/4.9.2/include/stdint.h:9:0,
                 from /Applications/Arduino.app/Contents/Java/hardware/tools/avr/avr/include/inttypes.h:37,
                 from /Applications/Arduino.app/Contents/Java/hardware/tools/avr/avr/include/avr/sfr_defs.h:126,
                 from /Applications/Arduino.app/Contents/Java/hardware/tools/avr/avr/include/avr/io.h:99,
                 from /Applications/Arduino.app/Contents/Java/hardware/arduino/avr/cores/arduino/wiring_private.h:26,
                 from /Users/philipp/Documents/Arduino/libraries/PWM/utility/BTimerDefs.cpp:23:
/Applications/Arduino.app/Contents/Java/hardware/tools/avr/avr/include/stdint.h:346:0: note: this is the location of the previous definition
 #define UINT16_MAX (__CONCAT(INT16_MAX, U) * 2U + 1U)
 ^
/Users/philipp/Documents/Arduino/libraries/PWM/utility/BTimerDefs.cpp:27:0: warning: "UINT8_MAX" redefined
 #define UINT8_MAX 255

 ^
In file included from /Applications/Arduino.app/Contents/Java/hardware/tools/avr/lib/gcc/avr/4.9.2/include/stdint.h:9:0,
                 from /Applications/Arduino.app/Contents/Java/hardware/tools/avr/avr/include/inttypes.h:37,
                 from /Applications/Arduino.app/Contents/Java/hardware/tools/avr/avr/include/avr/sfr_defs.h:126,
                 from /Applications/Arduino.app/Contents/Java/hardware/tools/avr/avr/include/avr/io.h:99,
                 from /Applications/Arduino.app/Contents/Java/hardware/arduino/avr/cores/arduino/wiring_private.h:26,
                 from /Users/philipp/Documents/Arduino/libraries/PWM/utility/BTimerDefs.cpp:23:
/Applications/Arduino.app/Contents/Java/hardware/tools/avr/avr/include/stdint.h:331:0: note: this is the location of the previous definition
 #define UINT8_MAX (INT8_MAX * 2 + 1)
 ^
Sketch uses 6508 bytes (20%) of program storage space. Maximum is 32256 bytes.
Global variables use 258 bytes (12%) of dynamic memory, leaving 1790 bytes for local variables. Maximum is 2048 bytes.

Nevertheless the code compiles and works fine.

Is someone else having the same problems and how can i solve this?

Thank you all!

Philipp

looks like two developers got the same name idea for a #define... the second one reinventing the wheel from [url=https://github.com/f32c/arduino/blob/master/hardware/fpga/f32c/system/include/stdint.h]stdint.h[/url] which has been here for more than 18 years and is better written....(it's a header file in the C standard library introduced in the C99 standard library section 7.18 to allow programmers to write more portable code)

you could go modify the library and put a test to see if it's already defined, something like

#ifndef UINT8_MAX
#define UINT8_MAX 255
#endif

but you could also simply remove them (possibly #include <stdint.h> but I think is added automatically hence the compiler barking at the redefinition - to be tested)

Thank you!
I just altered ATimerDefs.cpp and BTimerDefs.cpp.

Changed

#define UINT16_MAX 65535
#define UINT8_MAX 255

to

#ifndef UINT16_MAX
#define UINT16_MAX 65535
#endif
#ifndef UINT8_MAX
#define UINT8_MAX 255
#endif

in both files.

Works and the compiler is not barking anymore :slight_smile:

Very nice library indeed!

Regarding the frequency sweep, hugoabreu mentioned... I'm actually doing that for a project, using the Arduino Pro Mini (sweeping from 1 Hz to 500 Hz, with a 1 Hz step size, transitioning steps every 1000 - 2000 msec). Simply set the frequency and duty cycle for each frequency step:

if (SetPinFrequencySafe(led, frequency)) 
{
       pwmWrite(led, brightness);
}

Only one problem... The frequency steps sometimes do not transition smoothly. Meaning, the output will glitch and stick in the high or low state, for up to a second, before stabilizing at the new frequency/duty cycle. In my use case, the duty cycle remains constant throughout the sweep.

Unfortunately, for me, this is not good. Sweeping with these glitches is causing problems with connected device(s). Has anyone else encountered this problem? Is there a fix for it? Any assistance is appreciated.

I noticed the same issue that Uup115 reported. The frequency does not transition smoothly. Also the frequency is not exact (off by ~0.5%). This is due to the ceramic osc. used on the Uno and Mega. The Leonardo has a crystal osc. with much higher accuracy, but was not supported by this library.

So I forked the library and improved it with the following.

You can find the updated code here: GitHub - phatpaul/arduino-pwm-frequency-library

Hope it helps,
Paul

It would seem that you changed things so that InitTimers() and InitTimersSafe() now require a minimum frequency argument, breaking everyone's existing code. Could you explain that? I'm just getting started reading through the timer section of the ATmega data sheet.

Does this library work with the Arduino Zero, which has a SAMD processor?

If not, can someone make the necessary changes?

Aloha very happy to see that people are still using the library successfully! I once tested it out and all worked great, but now years later different IDE version (latest on Linux arduino-1.8.5-linux64.tar ) I have a problem getting the library to install, I am using V_05 from: Google Code Archive - Long-term storage for Google Code Project Hosting.
Regardless of how I put it the IDE complains about the package 'does not contain a valid library'...
It seems nobody has worked on the code since the end of 2012, what could cause this error in my IDE? Any suggestions or workarounds are highly appreciated!

PS: I think I just found the solution in post #126 of this thread (tab 9) a user posted a fixed PWM.zip library, which installed fine and I am onto troubleshooting the rest of my adventure...

meninas92:
Hi i have tried to contact the supporter of the library "runnerup". i have some minor fixes to the library i have created a zip compatible with newer versions of arduino. does anyone knows how to contact runnerup?

Would be great if you could upload it at a Git site or so, if the license permits?
And we are all very curious what it was that caused the library to fail to install in those newer IDEs?

Briney_Eye:
It would seem that you changed things so that InitTimers() and InitTimersSafe() now require a minimum frequency argument, breaking everyone's existing code. Could you explain that? I'm just getting started reading through the timer section of the ATmega data sheet.

+1
Yes that is wierd...

meninas92:
Hi i have tried to contact the supporter of the library "runnerup". i have some minor fixes to the library i have created a zip compatible with newer versions of arduino. does anyone knows how to contact runnerup?

Great Job with the library! Meninas's version above works flawless for me.

Here is a neat example how to use PWM frequency library by Riham.

https://codebender.cc/sketch:211750#PWM%20Frequency%20Library%20Example.ino

This library really is perfect if you need a lower PWM frequency for solenoids.
As we we all know they need PWM frequencies around 8-40 hz to function properly.

phatpaul:
I noticed the same issue that Uup115 reported. The frequency does not transition smoothly. Also the frequency is not exact (off by ~0.5%). This is due to the ceramic osc. used on the Uno and Mega. The Leonardo has a crystal osc. with much higher accuracy, but was not supported by this library.

So I forked the library and improved it with the following.

You can find the updated code here: GitHub - phatpaul/arduino-pwm-frequency-library

Hope it helps,
Paul

Paul, nice work! I've been reluctantly accepting these glitches, until I could find another solution. Unfortunately, I'm not savvy enough to do what you did.

Many thanks!

Best Regards,
Uup115

Hi,

I have some problem with this library using an arduino mega:

I want to pilot 4 fans (classic pc pwm).

On my setup() i have:

InitTimersSafe();

tryF(2, frequency); // Front fan 1 t3B
tryF(3, frequency); // Front fan 2 t3C
tryF(5, frequency); // Front fan 3 t3A
tryF(6, frequency); // Front fan 4 t4A
  Serial.print("t3:");
  Serial.print(Timer3_GetFrequency());
  Serial.print("\nt4:");
  Serial.print(Timer4_GetFrequency());

tryF function:

void tryF(int8_t pin, int32_t freq)
{ 
  //sets the frequency for the specified pin
  bool success = SetPinFrequencySafe(pin, freq);

  if (success) {
    set(pin, 0);
    Serial.print(pin);
    Serial.print("=>");
    Serial.print(freq);
    Serial.print(": SUCCESS\n");
  } else {
    Serial.print(pin);
    Serial.print("=>");
    Serial.print(freq);
    Serial.print(": FAIL\n");
  }
}

And then, i have a set function callable by serial

void set(uint8_t pin, uint16_t val)
{
  Serial.print("Applicating ");
  Serial.print(pin);
  Serial.print("/");
  Serial.print(val);
  Serial.print("\n");
  pwmWriteHR(pin, val);
}

At the begin of my soft i have:

mega: init...
mega: Applicating 2/0
mega: 2=>25000: SUCCESS
mega: Applicating 3/0
mega: 3=>25000: SUCCESS
mega: Applicating 5/0
mega: 5=>25000: SUCCESS
mega: Applicating 6/0
mega: 6=>25000: SUCCESS
mega: init done (pwm)
mega: t3:25000
mega: t4:25000

So everything is fine and i see my fan throttle down to 500 rpm (hall detection on pins 21 20 19 18).
If i call set(2, 65535), my fan 1 goes to max speed (~1600 rpm) and not the others.
RPM:1695,540,570,525
If i call set(5, 65535), my fan 3 goes to max speed (~1600 rpm).
RPM:1650,540,1605,510

My problem is when i use for example:
set(5, 32767), my rpm report is strange:
RPM:1050,555,1620,525 => fan 1 on pin 2 have it's speed reduced!

I don't know where is the bad behavior of my soft. can someone help me?

Electricaly, pins of the arduino are directly connected to the pwm of the fan. Ground / 12v is supplied by an ATX power supply.
Same supply powers the PC piloting the arduino, threw usb.
Possibly ground issue?

Complete code linked.

antec_arduino.ino (2.74 KB)

Hi,
Is there also a way to get a more precise frequency. Because i need a frequency of about 80.4 hz. Can i send a float in the function or is there some other method?

Hi,
I am working on a light control project, and i need 16 PWM pins with exactly 100Hz, and individually alter the dutycycle. I need to Control 16 dimmers this way, so I can co it either with 3 UNO´s or 2 Mega´s.
On Uno, 4 pins work, and 2 gives me error.
On Mega I experience weird behaviour on most of the pins, and 2 gives me error. They do not give the correct DutyCycle. Here follows the code examples for both boards. I have measured the dutycycle with picoscope, and written the results commented into the code below. Do you have Any Idea how I can achieve my goal using this Library?

//CODE FOR MEGA

#include <PWM.h>


void setup() {

 Serial.begin(9600);
 InitTimers();
 if (!SetPinFrequency(2, 100))Serial.println("PWM pin 2 failed.");
 if (!SetPinFrequency(3, 100))Serial.println("PWM pin 3 failed.");
 if (!SetPinFrequency(4, 100))Serial.println("PWM pin 4 failed.");
 if (!SetPinFrequency(5, 100))Serial.println("PWM pin 5 failed.");
 if (!SetPinFrequency(6, 100))Serial.println("PWM pin 6 failed.");
 if (!SetPinFrequency(8, 100))Serial.println("PWM pin 7 failed.");
 if (!SetPinFrequency(9, 100))Serial.println("PWM pin 8 failed.");
 if (!SetPinFrequency(10, 100))Serial.println("PWM pin 9 failed.");
 if (!SetPinFrequency(11, 100))Serial.println("PWM pin 10 failed.");
 if (!SetPinFrequency(12, 100))Serial.println("PWM pin 11 failed.");
 if (!SetPinFrequency(13, 100))Serial.println("PWM pin 12 failed.");
 Serial.println("Running..");
}
void loop() {

 pwmWrite(2, 25);    //Should have been ca 10%, actual is 40% not changed by changing 25 
 pwmWrite(3, 51);    //Should have been ca 20%, actual is 10% seemes to be changing with pin 2
 pwmWrite(4, 76);    //Should have been ca 30%, actual is 30%
 pwmWrite(5, 102);   //Should have been ca 40%, actual is 80%
 pwmWrite(6, 127);   //Should have been ca 50%, actual is 20%
 pwmWrite(7, 153);   //Should have been ca 60%, actual is50%
 pwmWrite(8, 177);   //Should have been ca 70%, actual is60%
 pwmWrite(9, 204);   //Should have been ca 80%, actual is90%
 pwmWrite(10, 230);  //No duty cycle
 pwmWrite(11, 204);  //Should have been ca 80%, actual is80%
 pwmWrite(12, 177);  //Should have been ca 70%, actual is70%
 pwmWrite(13, 153);  //No duty cycle

 delay(30);
}

//CODE FOR UNO

#include <PWM.h>


void setup() {

 Serial.begin(9600);
 InitTimers();
 if (!SetPinFrequency(3, 100))Serial.println("PWM pin 3 failed.");
 if (!SetPinFrequency(5, 100))Serial.println("PWM pin 5 failed.");
 if (!SetPinFrequency(6, 100))Serial.println("PWM pin 6 failed.");
 if (!SetPinFrequency(9, 100))Serial.println("PWM pin 9 failed.");
 if (!SetPinFrequency(10, 100))Serial.println("PWM pin 10 failed.");
 if (!SetPinFrequency(11, 100))Serial.println("PWM pin 11 failed.");
 Serial.println("Running..");
}
void loop() {

 pwmWrite(3, 26);    //DutyCycle 10% OK
 pwmWrite(5, 51);    //DutyCycle 20% OK
 pwmWrite(6, 76);    //No duty cycle
 pwmWrite(9, 102);   //DutyCycle 40% OK
 pwmWrite(10, 127);  //DutyCycle 50% OK
 pwmWrite(11, 153);  //No duty cycle
 delay(30);
}

I don't know why, but i feel this library is deprecated somehow. The github repository do no allow to send messages / issue to the owner.

Possibly the library work with an older arduino IDE?

Has anyone been able to compile this for the Atmega1284? I'm using the MightyCore bootloader and I get the following message every time I try and compile:

Arduino: 1.8.4 (Mac OS X), Board: "ATmega1284, Standard, 1284, 2.7v, Disabled (default), 20 MHz external"

Build options changed, rebuilding all
sketch/PWM_lib_example.ino.cpp.o: In function setup': /Users/BradJackson/Google Drive/Jackson Ampworks/Arduino/PWM_lib_example/PWM_lib_example.ino:24: undefined reference to InitTimersSafe()'
/Users/BradJackson/Google Drive/Jackson Ampworks/Arduino/PWM_lib_example/PWM_lib_example.ino:27: undefined reference to SetPinFrequencySafe(signed char, unsigned long)' sketch/PWM_lib_example.ino.cpp.o: In function loop':
/Users/BradJackson/Google Drive/Jackson Ampworks/Arduino/PWM_lib_example/PWM_lib_example.ino:39: undefined reference to `pwmWrite(unsigned char, unsigned char)'
collect2: error: ld returned 1 exit status
exit status 1
Error compiling for board ATmega1284.

Hello

I am using arduino nano can i generate 7 mhz pwm signal with 50%duty cycle ?
if yes then guide me How Can i generate ?

Best Regards
seggi.