Hi,
when using PWM with mbed on raspberry pico, the period only works fine from 10us to 2ms. If i use the SDK it works fine from 800ns to 133.7ms with 1% precision.
Here is the code
#include <mbed.h>
using namespace mbed;
PwmOut led(p27); // Sortie GPIO 27
void setup() {
led.period_ms(1000); // Doesn't work, period is not good
for(int i=0;i<3;i++) { // Blink 3 times
led = 1;
delay(200);
led = 0;
delay(200);
}
}
// Duty cycle from 0 to 100% during 1s
void loop() {
static int rapport=0;
led=0.001*rapport;
rapport = (rapport + 1)%1001;
delay(1);
}
I use platformIO on VSCode for my project.
Sincerely
Olivier
Targets in MbedOS are usually ported and maintained by (ST, NXP, ArduinoâŠ) their makers/creators or people/companies who want to have it in MbedOS officially and not Mbed team. So if there is a hardware specific issue it is up to that targetâs maintainer.
With Raspberry Pi Pico it is little bit different. It is not Mbed enabled board and was never officially supported in ARM Mbed only in MbedCE. Here you can see a Pull request what was never finished. It was done only in a fork of Mbed OS in Arduino github repo - arduino/mbed-os: Arm Mbed OS is a platform operating system designed for the internet of things (github.com)
So how you can see you are on wrong forum.
Btw you can try to check the PWM implementation and make a PR for fix (if you tried it witk SDK maybe you will find something wrong).
I also somewhere read about much more better is a solution by Earle Philhower. So maybe try to check if is possible to use it in PlatformIO.
First of all, the code doesnât properly handle periods smaller than about 10us, because doing that would require using a smaller count_top constant (the value at which the PWM counter resets), which it isnât smart enough to do. Additionally, with count_top fixed to 1000, and a max clock divider of 256, the longest possible duty cycle is 1/(133MHz / 256 / 1000) = ~2ms.
It also has resolution problems â it doesnât use the fractional part of the clock divider pwm_config_set_clkdiv_int_frac(), so the frequency resolution is lower than it could be. Additionally, with count_top locked to 1000, the duty cycle resolution is locked to 1/1000, when it could be 1/65536 (using the full 16 bit counter).
I think this code should be updated so that it dynamically determines count_top based on the frequency. It should use count_top = 65536 in most cases, but if the calculated clock divider would be less than 1, it should decrease count_top as needed so that the lower period can be accommodated. That should restore the full frequency range.
#include <Arduino.h>
void setup() {
gpio_set_function(0, GPIO_FUNC_PWM); // GPIO 0 used
int slice=pwm_gpio_to_slice_num(0);
pwm_set_clkdiv(slice,125); // Divide by 125 (float from 1 to 256 max)
// TOP Value between 0 and 65535 so here frequency is 1Mhz period of 10ns
pwm_set_wrap(slice,19999); // TOP value 19999 so 20000 countsx10ns=20ms
pwm_set_chan_level(slice,PWM_CHAN_A,9999); // 19999/2=50% duty cycle
pwm_set_enabled(slice,true); // Enable PWM
}
The fix from above was done in Mbed fork called MbedCE . This fork was created because original Mbed stopped their work. Unfortunately this fork is not used by Arduino or PlatformIO.
PlatformIO uses original Mbed, but this one does not contain RP Pico support
PlatformIO probably uses also Arduino-Mbed-Core which contains RP Pico and was done by Arduino for Arduino
How you can see there is no way how you can get this fix into PlatformIO for now. You have to ask a PlatformIO support probably.
Yes thanks. To be honest, it is not for my own purpose, but for a courses i give, and it is a bit a pity to say that it is buggy and to use the pico_sdk to do it.
If i knew where the code is, i would have done it by myself to have this old code updated.