Fast PWM on Nucleo-F030R8 with Arduino IDE

STM32F103 Nucleo boards e.g. STM Nucleo F103RB
Ollie
Posts: 188
Joined: Thu Feb 25, 2016 7:27 pm

Re: Fast PWM on Nucleo-F030R8 with Arduino IDE

Post by Ollie » Fri Aug 04, 2017 2:48 pm

For the developers who are using both Teensy and STM32duino boards, it would be nice if the two libraries would be compatible. In this case, the PWM frequency is already managed by Teensy library, and it would be nice if the support is added using the same syntax and functionality.

User avatar
Rick Kimball
Posts: 1012
Joined: Tue Apr 28, 2015 1:26 am
Location: Eastern NC, US
Contact:

Re: Fast PWM on Nucleo-F030R8 with Arduino IDE

Post by Rick Kimball » Fri Aug 04, 2017 3:20 pm

Good idea @Ollie

analogWriteFrequency (pin, frequency)
...
void setup() {
analogWriteFrequency(4, 375000); // Teensy 3.0 pin 3 also changes to 375 kHz
}
-rick

fpiSTM
Posts: 192
Joined: Fri Sep 16, 2016 12:33 pm
Location: Le Mans, France

Re: Fast PWM on Nucleo-F030R8 with Arduino IDE

Post by fpiSTM » Fri Aug 04, 2017 7:47 pm

If you have any API reference already available no problem ;)
I will check Teensy api.

User avatar
RogerClark
Posts: 6907
Joined: Mon Apr 27, 2015 10:36 am
Location: Melbourne, Australia
Contact:

Re: Fast PWM on Nucleo-F030R8 with Arduino IDE

Post by RogerClark » Fri Aug 04, 2017 9:27 pm

Sometimes another good place to look is the EPS8266 implementation.

User avatar
Rick Kimball
Posts: 1012
Joined: Tue Apr 28, 2015 1:26 am
Location: Eastern NC, US
Contact:

Re: Fast PWM on Nucleo-F030R8 with Arduino IDE

Post by Rick Kimball » Fri Aug 04, 2017 9:54 pm

Seems that the esp8266 takes a global approach setting the frequency that affects all pwm output. That might be a hardware limitation

http://esp8266.github.io/Arduino/versio ... log-output
-rick

User avatar
RogerClark
Posts: 6907
Joined: Mon Apr 27, 2015 10:36 am
Location: Melbourne, Australia
Contact:

Re: Fast PWM on Nucleo-F030R8 with Arduino IDE

Post by RogerClark » Fri Aug 04, 2017 10:37 pm

Rick Kimball wrote:
Fri Aug 04, 2017 9:54 pm
Seems that the esp8266 takes a global approach setting the frequency that affects all pwm output. That might be a hardware limitation

http://esp8266.github.io/Arduino/versio ... log-output
I think we probably have a similar limitation,because I think the pins probably share timers.

Edit

Well, we have multiple timers but probably going for a global approach would lead to less confusion

timer2 /* PA0 */
timer2 /* PA1 */
timer2 /* PA2 */
timer2 /* PA3 */
timer3 /* PA6 */
timer3 /* PA7 */
timer1 /* PA8 */
timer1 /* PA9 */
timer1 /* PA10 */
timer1 /* PA11 */
timer3 /* PB0 */
timer3 /* PB1 */
timer4 /* PB6 */
timer4 /* PB7 */
timer4 /* PB8 */
timer4 /* PB9 */

Should not be too difficult to code as we already have

https://github.com/rogerclarkmelbourne/ ... #L103-L118

BTW.

I wonder whether the teensy really can run all its PWM pins at different rates?

User avatar
RogerClark
Posts: 6907
Joined: Mon Apr 27, 2015 10:36 am
Location: Melbourne, Australia
Contact:

Re: Fast PWM on Nucleo-F030R8 with Arduino IDE

Post by RogerClark » Sat Aug 05, 2017 4:22 am

I've investigated how we can add this in LibMaple

This example allows the period

Code: Select all

#include <libmaple/rcc.h>

void setup() {
  pinMode(PA0,PWM);

  #define MAX_RELOAD ((1 << 16) - 1)
  uint32_t pwmFreqHz = 100000;    
  uint32_t period_cyc = F_CPU / pwmFreqHz;
  uint16_t prescaler = (uint16)(period_cyc / MAX_RELOAD + 1);
  uint16_t overflow = (uint16)((period_cyc + (prescaler / 2)) / prescaler);
  timer_set_prescaler(&timer2, (uint16)(prescaler - 1));
  timer_set_reload(&timer2, overflow);

 // analogWriteResolution(8);

  int duty=128;// 0 - 255
  
  pwmWrite(PA0,(timer_get_reload(&timer2) * duty)/255);
  
  //analogWrite(PA0,1);
  while (1)
  {
    Serial.print("prescaler: ");
    Serial.print(prescaler);
    Serial.print(" overflow: ");
    Serial.println(overflow);
    delay(1000);          
  }
}
One problem I can see is if anyone changes the frequency, the value that needs to be passed to pwmWrite would change, as the overflow value may no longer be 65535 (max unsigned 16 bit number)

So for maximum conpatibility I would need to change pwmWrite as well as analogWrite

However I'm tempted to leave pwmWrite alone and just modify analogWrite so that it reads the current overflow value using timer_get_reload()


And... I've also realised we don't currently support

analogWriteResolution()

This would not be that hard to implement, except we'd need a global to store this setting, so that analogWrite can determine the divisor value that is required.


Also...

In terms of whether we follow the teensy or ESP8266 API.

The ESP8266 API causes the least confusion, as we could initialise all the timers with the same prescaler and overflow at in the same function.

We could also implement the Teensy style API, e.g. its a different function signature, but if people tried to set 2 pins which use the same timer with different frequencies, they may not get what they expect

Post Reply