Go Down

Topic: PWM frequency library (Read 317887 times) previous topic - next topic

Uup115

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:

Code: [Select]

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.

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.

  • Added support for ATmega16U4/32U4 (Leonardo) by "Pierre" Oct 23, 2013. Copied from https://code.google.com/archive/p/arduino-pwm-frequency-library/issues/2
  • Modified to avoid changing prescaler when changing frequency by Paul Abbott - 2017


You can find the updated code here: https://github.com/phatpaul/arduino-pwm-frequency-library

Hope it helps,
Paul

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.

sthudium

#183
Dec 18, 2017, 07:18 pm Last Edit: Dec 18, 2017, 07:52 pm by sthudium
Does this library work with the Arduino Zero, which has a SAMD processor?

If not, can someone make the necessary changes?
I study the use of cognitive dissonance and confirmation bias to manipulate gullible people.

usertogo

#184
Dec 26, 2017, 02:13 pm Last Edit: Dec 26, 2017, 03:23 pm by usertogo
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: https://code.google.com/archive/p/arduino-pwm-frequency-library/downloads
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...

usertogo

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?

Trimjohan

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...

Trimjohan

#187
Jan 09, 2018, 11:15 am Last Edit: Jan 09, 2018, 11:25 am by Trimjohan
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.


Uup115

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.

  • Added support for ATmega16U4/32U4 (Leonardo) by "Pierre" Oct 23, 2013. Copied from https://code.google.com/archive/p/arduino-pwm-frequency-library/issues/2
  • Modified to avoid changing prescaler when changing frequency by Paul Abbott - 2017


You can find the updated code here: https://github.com/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


rholk

#189
Jan 16, 2018, 05:29 pm Last Edit: Jan 17, 2018, 10:07 am by rholk
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:
Code: [Select]

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:
Code: [Select]

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
Code: [Select]

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:
Code: [Select]

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.

Jelmer_

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?

asgeiro

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: [Select]
//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);
}

rholk

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?

JacksonAudio

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.

seggi

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.

Go Up