DUE PWM Frequency

Maple's pwmWrite appears to be only a 16 bit version of analogWrite

How does it let you also control the frequency?

It seems that you must use HardwareTimer methods:

this API is not final, since they put a disclaimer that says:

"Warning:
The timer interface is still taking shape, and is expected to change significantly between releases. Because of that, the functionality described in this page shouldn’t be considered stable."

I am finalizing my code for the maple, wow the documentation on maple is wonderful.

In the maple world they have a library timer.h which allows the easy modification of the timer properties. I am not sure how it all works as I am not the sharpest guy in the world, but I assure you it works quite well.

This is the first code I was playing with the pwm freq with on maple

#include <timer.h>

//HardwareTimerb timer(1);
int d = 100;
int b = 177;
int pin2 = 5;
int pin3 = 6;
HardwareTimer timer1(1);
HardwareTimer timer4(4);


void setup() {
    // Set up the built-in LED pin as an output:
    timer1.pause();
    timer4.pause();
    timer1.setPrescaleFactor(3);
    timer4.setPrescaleFactor(3);
    timer1.setOverflow(4000);
    timer4.setOverflow(4000);
    timer1.refresh();
    timer4.refresh();
    timer1.resume();
    timer4.resume();
    pinMode(24, OUTPUT);
    digitalWrite(24, HIGH);

   // pinMode(23, OUTPUT);
    //digitalWrite(23, HIGH);
    pinMode(20, INPUT);
    pinMode(19, INPUT);
    pinMode(pin2, PWM);
    pinMode(pin3, PWM);

}

void loop() {
d = (analogRead(20) + 1);//  pot on20
b = (analogRead(19)); //read other  pot on19
if(b > 4000) { b = 4000; }
//SerialUSB.println(b);
analogWrite (pin2, 0);
analogWrite (pin3, b);
    delay(100);          // Wait for d milis
    analogWrite (pin3, 0);
    analogWrite(pin2, b);
    delay (100);
}

It alternately blinks two leds back to back in parallel across pins 5 and 6.
Renders 6000 Hz pwm exactly the way I want it to.

It would be really nice to do this the same way with due

There was actually a recent discussion on the Arduino developers mail list about this feature. I believe the final consensus was on analogWriteFrequency(pin, frequency), though there's some lingering controversy over using the pin number vs some way of specifying which timer resource is being programmed. It's not easy to agree on an API that is easy to understand and flexible and general enough to work across different boards with different chips, yet can be implemented efficiently and doesn't abstract the hardware so much that the user is completely unaware of possible compatibility issues.

Maple's API gives you low-level access to the timers, but it's very hardware specific. You can't reasonably expect that code, using raw overflow and prescaler constants for ST's chip, to work the same way across different boards. It might not even work when/if Leaflabs makes another board based on a newer ST chip. That API also produces very unreable code. How can anyone reading the code know the output is 6 kHz? Somehow a prescale factor of 3 and an overflow of 4000 make 6 kHz? Will that be true on every Maple board to come in the future? Certainly AVR and SAM3X and Freescale MK20 need different parameters, because they have dramatically different timer hardware. Maple's API just isn't practical for non-ST chips, and long term I suspect it won't even work well for whatever boards appear in the future with new ST parts.

I've implemented analogWriteFrequency() on Teensy 3.0, so far only as a code drop in a forum topic, but soon to be released as a beta test.

I don't know when or if Christian is planning to implement it on Arduino Due.

Paul,

Yes all those things are true. The scetch is only going to work on the maple with that exact chip.

My original code would only run on the 2560, However it was reasonably well documented how to do it. I would expect that the same would be true of due. That in calling a timer one would have to know the pin map in relation to the timer and how the modification will affect the timer. I am also reasonably sure that it is possible to time up the due in a similar way. Basically the original code I used on the 2560 did the same thing prescaling the timer. Just did not have the ability to set the number of counts. That is provably also possible I just have not discovered it.

All is well, the maple is doing my bidding The due is communicating with the maple i2c or serial, much testing to do. Getting the due to run the interface the lcd touchscreen monitoring the battery, running the 12 v charging system many things for due to do. I am sure that as due matures pwm modification will mainstream in one form or an other. My pcb is ready for maple my first beta code for maple is meeting my expectation. My project is moving forward and soon I will drive down the road under ~duino control hopefully before Christmas.

Any idea when the "analogWriteFrequency(pin, frequency)" function to be released for the Due?

In the meantime, I verified that the default PWM frequency (1000hz) can be changed in the variant.h file (see PWM_FREQUENCY variable).

Is there an easy way of setting frequency in the sketch directly? I tried the following code, but no success. Any verified suggestions for the community? Thank you.

\\ This approach not working:
void setup()  { 
  pinMode(6, OUTPUT);
  analogWrite(6, 64);
  PWMC_ConfigureClocks(4000 * PWM_MAX_DUTY_CYCLE , 0, VARIANT_MCK);
}

Has anyone found a solid way (preferably in sketch) to modify the output PWM frequency? Also changing variant.h from 1k to what ever you want isnt working for me. Changing it and saving doesn't change the output frequency.

Daniel

dgelman:
Has anyone found a solid way (preferably in sketch) to modify the output PWM frequency? Also changing variant.h from 1k to what ever you want isnt working for me. Changing it and saving doesn't change the output frequency.

Daniel

You have to restart the IDE if you make changes to the underlying libraries as they are compiled only once for the sketch "to save time".

you might look at PWMC_ConfigureClocks()

You have to restart the IDE if you make changes to the underlying libraries as they are compiled only once for the sketch "to save time".

you might look at PWMC_ConfigureClocks()

Hello,

I restarted my IDE to let it recompile, but I am still getting 1KHz PWM frequency, also I put the following line into setup but that did not do anything.

PWMC_ConfigureClocks(3922 * PWM_MAX_DUTY_CYCLE , 0, VARIANT_MCK);.

I wouldn't prefer either way since this micro is designated for motor control, if anything I would like to strictly change the variable in variant.h - if you know any reason why it is still not change, I would much appreciate it.

Daniel

Hello,

I have fixed the problem, somewhat.

Looking into variant.cpp

  { PIOB, PIO_PB25B_TIOA0,   ID_PIOB, PIO_PERIPH_B, PIO_DEFAULT, (PIN_ATTR_DIGITAL|PIN_ATTR_TIMER), NO_ADC, NO_ADC, NOT_ON_PWM,  TC0_CHA0     }, // TIOA0
  { PIOC, PIO_PC28B_TIOA7,   ID_PIOC, PIO_PERIPH_B, PIO_DEFAULT, (PIN_ATTR_DIGITAL|PIN_ATTR_TIMER), NO_ADC, NO_ADC, NOT_ON_PWM,  TC2_CHA7     }, // TIOA7
  { PIOC, PIO_PC26B_TIOB6,   ID_PIOC, PIO_PERIPH_B, PIO_DEFAULT, (PIN_ATTR_DIGITAL|PIN_ATTR_TIMER), NO_ADC, NO_ADC, NOT_ON_PWM,  TC2_CHB6     }, // TIOB6

  // 5
  { PIOC, PIO_PC25B_TIOA6,   ID_PIOC, PIO_PERIPH_B, PIO_DEFAULT, (PIN_ATTR_DIGITAL|PIN_ATTR_TIMER), NO_ADC, NO_ADC, NOT_ON_PWM,  TC2_CHA6     }, // TIOA6
  { PIOC, PIO_PC24B_PWML7,   ID_PIOC, PIO_PERIPH_B, PIO_DEFAULT, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM),   NO_ADC, NO_ADC, PWM_CH7,     NOT_ON_TIMER }, // PWML7
  { PIOC, PIO_PC23B_PWML6,   ID_PIOC, PIO_PERIPH_B, PIO_DEFAULT, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM),   NO_ADC, NO_ADC, PWM_CH6,     NOT_ON_TIMER }, // PWML6
  { PIOC, PIO_PC22B_PWML5,   ID_PIOC, PIO_PERIPH_B, PIO_DEFAULT, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM),   NO_ADC, NO_ADC, PWM_CH5,     NOT_ON_TIMER }, // PWML5
  { PIOC, PIO_PC21B_PWML4,   ID_PIOC, PIO_PERIPH_B, PIO_DEFAULT, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM),   NO_ADC, NO_ADC, PWM_CH4,

Notice that only pins 7, 6, 5 and 4 respond to the #define in the variant.h file. I am not sure how to configure the rest of the pins to act accordingly. I havent tried changing NOT_ON_PWM (highlighted in the other pin configurations) to PWM_CH#, if this is possible. I am assuming the architecture allocates pins 2-13 as PWM pins but on 5-7 as reconfigurable PWM pins.

If anyone would like to contribute why/how to reconfigure other pins - that would be helpful.

Daniel

Hi, after I read through the thread, I wanted to ask two things about PWM frequency on DUE:

  1. It seems the function for customizing PWM frequency (e.g. 100Hz on Pin 9, and 10kHz on pin 7) in the sketch isn't officially released yet, is it?? if not, do we have an expecting time on that?

  2. I'm wondering if we could just use the Servo library to adjust the PWM frequency to whatever we want? I did find the 20000 us time intervel being set for the servo to have a 50 Hz PWM output. It seems to me we don't have to get anything like analogWriteFrequency(). We could just generalize the Servo library to do that?

When this was discussed on the Arduino developers mail list, there was some agreement on analogWriteFrequency(pin, frequency).

About a week later, I implemented analogWriteFrequency() on Teensy 3.0, but I didn't create any documentation until only days ago. Here's the new page. Scroll down to "PWM Frequency".

http://www.pjrc.com/teensy/td_pulse.html

One of the concerns with analogWriteFrequency() was possibly implying each pin can have a unique frequency. Now that both the function and documentation exist, I'd be really curious to hear any feedback?

Hopefully this will someday become implemented on Arduino Due?

Hello, I came up with a library for the Due specifically to setup PWM with unique frequencies (up to 2 for now) on different PWM pins. If you'd like, have a go and let me know how it goes.

The link below has an example Due program and the PWM library.

Your library works quite well!!!

Thanks a lot!!

randomvibe:
Hello, I came up with a library for the Due specifically to setup PWM with unique frequencies (up to 2 for now) on different PWM pins. If you'd like, have a go and let me know how it goes.

The link below has an example Due program and the PWM library.

Multiple PWM Outputs with Unique Frequencies - #7 by randomvibe - Arduino Due - Arduino Forum

Has anything progressed on this? I've not seen anything like analogWriteFrequency() for the Due and on another thread (Multiple PWM Outputs with Unique Frequencies - #14 by sandrograssia - Arduino Due - Arduino Forum) someone has said that he is having problem's with randomvibe's pwm01 implementation.

My understanding is we agreed, at least in principle, on the analogWriteFrequency() function after much discussion on the Arduino Developers mail list.

So far, it looks like the Arduino team hasn't worked on this, and nobody appears to have tried to contribute it. Perhaps this library could be used as a basis for making such a contribution? Odds seem good Cristian might merge it into Arduino 1.5.5 or some future version, since we all basically agreed on the API many months ago.

I implemented analogWriteFrequency() on Teensy 3.0, but that code is specific to the timer peripherals on the Freescale Kinetis chip. It won't work on Due's SAM3X chip.

I'd be very thankful if somebody finally accomplished this. :slight_smile:

Rigth now I am using the fix of changing variant.h file to change PWM frequency, but on my due board it only affects PWM frequency of pins 6,7,8 and 9. Others keep working at 1KHz.

It would be great to be able to change all pins' PWM frequency and more important, changing it from IDE (not asking to have different frequencies in every pin, maybe 2 frequencies would be enough).

Thank you very much!

Luis

It's unfortunate these new API ideas, which have been agreed upon in principle (usually after much conversation on the developer mail list) don't get implemented or even documented in the official Arduino software.

If this had been a documented part of the API, even as "coming in a future version", odds are good Intel would have incorporated variable frequency into their I/O scheme on the new Galileo board. Looking through their code, it seems they did special support for the pulse generation for Servo.

Then again, I could do far better at documenting stuff for Teensy. Maybe next year I ought to slow down on the tech side and focus on that?

Hi there

can you please post your software with the 3 sinwaves as an output

thanks in advance

to change the PWM frequency of all pins.. that means also the ones not in range 6,7,8,9.. you should change also TC_FREQUENCY in variant.h.

this works perfectly. i get a nice 330 kHz period for all pins now.