Go Down

Topic: Multiple PWM Outputs with Unique Frequencies (Read 32618 times) previous topic - next topic


Sorry for my super-late reply..
No I didn't solve it, but it's not a problem; for my purpose I set a value uint32_t pwm_freq1=84000 and the PMW frequency is about 20KHz.
Thanks ;)


Oct 27, 2013, 07:34 am Last Edit: Oct 30, 2013, 07:05 am by randomvibe Reason: 1

Dear randomvibe, I'm grateful for this library. I'm testing it on my Arduino Due, it works great but I'm facing an issue about frequency; for example, if I set:
uint32_t pwm_freq1=1000;
then on pin 6 my (old) oscilloscope measures more or less 200Hz. So: either my oscilloscope is too old, or I'm missing something...

I tested your 1000 value on my "pwm01.h" library on a clean Arduino Due board compiled using arduino-1.5.4r2 , and my frequency counter reads 1,005 Hz.  Perhaps your circuit is disrupting the PWM frequency - try a bare board.

As I mentioned before, "pwm01.h" is best suited low frequency applications (2hz to 40,000hz) such as PWM motor drivers, 38khz infrared transmitters, etc.  This limitation is borne from setting the "pwm_max_duty_Ncount" variable equal to 255, which is the same approach taken by Arduino in the "variant.h" file.  My intent was to stay consistent with Arduino.

I programmed several frequencies and checked the actual frequency with my frequency counter - results listed below.  Note that beyond 40khz, the error increases in steps.
Code: [Select]

Program  Delta   Actual   Delta
-------  -----   ------   ----------
2        n/a     2        n/a
10       8       10       8
100      90      100      90
1000     900     1005     905
2000     1000    2020     1015
3000     1000    3030     1010
4000     1000    4020     990
5000     1000    5070     1050
10000    5000    10300    5230
15000    5000    15690    5390
20000    5000    20600    4910
25000    5000    25400    4800
30000    5000    33000    7600
35000    5000    36700    3700
40000    5000    41200    4500
45000    5000    47100    5900
50000    5000    54900    7800
55000    5000    66000    11100
60000    5000    66000    0
65000    5000    66000    0
70000    5000    82400    16400
75000    5000    82400    0
80000    5000    82400    0
85000    5000    109800   27400
90000    5000    109800   0
95000    5000    109800   0
100000   5000    109900   100
105000   5000    109900   0
110000   5000    164700   54800
115000   5000    164700   0
120000   5000     164700  0

Also plotted the table above (login to see image).  Notice that the error grows and oscillates at high frequencies.  Results may differ on your Arduino Due.  I think the lesson here is to measure your actual frequency and adjust the programmed value accordingly.


Michael Myers

Jun 05, 2014, 09:39 pm Last Edit: Jun 05, 2014, 09:59 pm by Michael Myers Reason: 1
Just downloaded the library DuePWM.zip, ran it on my Due, and got some rather odd results. The pin 6 output frequency shows up on my logic analyzer as about 2Hz.  Nice square wave and all, but something must be wrong somewhere.  Could be on my end. I'm using IDE 1.5.6-r2. Screen capture attached.

Seems I confused DuePWM.cpp with pwm01.h. I changed PWM_FREQ1 in the DuePWM example to 2000, and indeed got about 2kHz. It was in fact set at 2Hz. So, um . . . never mind.


Code: [Select]
#include "C:\Programs\arduino-1.5.1r2\hardware\arduino\sam\libraries\Pwm01\pwm01.h"

void setup()
   uint32_t  pwm_duty = 32767;
   uint32_t  pwm_freq1 = 2;  
   uint32_t  pwm_freq2 = 5000;

   // Set PWM Resolution

   // Setup PWM Once (Up to two unique frequencies allowed
   pwm_setup( 6, pwm_freq1, 1);  // Pin 6 freq set to "pwm_freq1" on clock A
   pwm_setup( 7, pwm_freq2, 2);  // Pin 7 freq set to "pwm_freq2" on clock B
   pwm_setup( 8, pwm_freq2, 2);  // Pin 8 freq set to "pwm_freq2" on clock B
   pwm_setup( 9, pwm_freq2, 2);  // Pin 9 freq set to "pwm_freq2" on clock B
   // Write PWM Duty Cycle Anytime After PWM Setup
   pwm_write_duty( 6, pwm_duty );  // 50% duty cycle on Pin 6
   pwm_write_duty( 7, pwm_duty );  // 50% duty cycle on Pin 7
   pwm_write_duty( 8, pwm_duty );  // 50% duty cycle on Pin 8
   pwm_write_duty( 9, pwm_duty );  // 50% duty cycle on Pin 9

   delay(30000);  // 30sec Delay; PWM signal will still stream
   // Force PWM Stop On All Pins
   pwm_stop( 6 );
   pwm_stop( 7 );
   pwm_stop( 8 );
   pwm_stop( 9 );

void loop()

The pwm01.h library and example code were tested in IDE 1.5.1r2.  Additional notes on this library:
- Applies to Arduino-Due board, PWM pins 6, 7, 8 & 9.
- Libary Does not operate on the TIO pins.
- Unique frequencies set via PWM Clock-A ("CLKA") and Clock-B ("CLKB")
 Therefore, up to two unique frequencies allowed.
- Set max duty cycle counts (pwm_max_duty_Ncount) equal to 255 per Arduino approach.  
 This value is best SUITED for low frequency applications (2hz to 40,000hz) such as
 PWM motor drivers, 38khz infrared transmitters, etc.
- Future library versions will address high frequency applications.
- Arduino's "wiring_analog.c" function was very helpful in this effort.

Thanks a lot for your library! This was very useful to me! I am driving a LED with a 2hz Frequency and it was not easy to find a sample or library that works on such a low Rrequency.

Unfortunately I am now having a little bit of trouble. It seems that the PWM is not working on Pin 8. I have measured all Outputs of Pin 6 to 9 and I do not receive any Data on my Oszilloscope on Pin 8. I have already measured it on a second Arduino Due Board, but I still get the same Result.

My Board is driving four LEDs (Pin 6-9) with the same frequency and same clock. Now I have experienced that the Signals on Pin 6 and 7 are not exactly the same. The Signal on Pin 6 makes all 30 seconds a short dropout for only one cycle, while the other Pins are still sending.
Does anyone else has experienced something similar? Where can I start to find the cause of both of my problems?


I noticed the same thing.  I'm not getting any PWM signal on pin 8.  I'm going to try reconfiguring my board to use pin7 which is kind of a bummer because the that means more manual labor on my motor controller to get the right pins where they are supposed to be :(


Hmm, the source code to DuePMW library doesn't seem to do anything special with pin 8,
which is PWML5 (peripheral B on pin PC22).  Have you checked normal PWM works on
pin 8?

Pin 8 works for me normally and with DuePWM library.
[ I will NOT respond to personal messages, I WILL delete them, use the forum please ]


I did try that later and it worked fine in its own sketch.  It must be a conflict with another feature of the SAM3X I'm using.  I have this thing very busy.  I'm using 32 digital inputs, 6 analog inputs (via ADC), the hardware quadrature decoder, a dual channel pwm motor controller, the SPI header, the CAN bus interface, and the two DAC pins to produce an analog signal from a digital value.  I'm also using both USB ports for different communication packets and protocols.  It's a very busy chip :)


I added the DuePWM library to Github pointing to original author message, for easier further development.



randomvibe.  Thanks for the useful library.  Sometimes I would like to have the exact PWM signal from two different pins.  That is, the two pins should go high and low at the same time.  Can this be done with  this library?  Would it be possible to do by other methods?  Thank.


Yes, you can set the same frequency for two pins with the pwm01.h library.   Just be advised that the libary can only produce frequencies in the range of 2hz to 40,000hz.


In fact, I tried this. At 10,000hz the two signals are slightly out of phase although they are exactly the same frequency.  Oh well...



I need to generate a two 65kHZ PWM, for my bi directional buck boost converter, i have gone through the forum and learnt that there are 2 method for changing the default PWM freq. to desired value...i.e. using timers and using PWM controller.......in my project the freq. required is 65khz, while the duty ratio must be varied based on the input to the converter...using a controller like a PID maybe.....i would like to know , which method (i.e. using timers and using PWM controller) of changing the frequency is better for my application?? any help is appreciated...

Any one have a library for the 65khz pwm?



Hi all,

I have just announced a library which abstract ATSAM3X8E PWM channels in this post: http://forum.arduino.cc/index.php?topic=144446.msg2589358#msg2589358.

The name of the library is pwm_lib and is available at: https://github.com/antodom/pwm_lib.

The library provides two kind of objects associated with each PWM channel: pwm and servo objects. As those objects abstract the PWM channels available on the micro controller, using pwm_lib you can use, at most, eight independent pwm_lib objects in your application, each one with its own PWM characteristics (PWM signal period and pulse duration). In its current version, the maximum period for PWM signals you can get using pwm_lib is a period of 0.798915048 seconds (minimum frequency of 1.251697539 Hz). The maximum frequency you can get is the one provided by the hardware. I see no problems even to get to 1 Mhz but in this case the resolution of the duty will be limited to 84 clock ticks, at 2 Mhz 42 ticks, etc.

Two examples comes with pwm_lib to illustrate its use: basic_test.ino and servo_test.ino, who illustrate respectively the use of pwm and servo objects. Example basic_test.ino uses two PWM objects for generating two independent PWM outputs with different PWM characteristics (period and duty). Example servo_test.ino uses a servo object to generated a PWM output for a typical servo.

If any questions just tell me.
I hope it helps.


I have problem with compiling example using antodom's library

#include <tc_defs.h>
#include <tc_lib.h>

void setup() {
  // put your setup code here, to run once:


void loop() {
  // put your main code here, to run repeatedly:



In file included from sketch_apr11a.ino:2:0:
C:\Users\webapps\Documents\Arduino\libraries\tc_lib-master/tc_lib.h:39:19: fatal error: cstdint: No such file or directory
 #include <cstdint>
compilation terminated.
Error compiling.

In arduino IDE, i have changed flag in platform file to use -std=gnu++11
any ideas?

Go Up