- Why do we need this MBED_RP2040_PWM library
- Changelog
- Prerequisites
- Installation
- HOWTO Fix
Multiple Definitions
Linker Error - Usage
- Examples
- Example PWM_Multi
- Debug Terminal Output Samples
- Debug
- Troubleshooting
- Issues
- TO DO
- DONE
- Contributions and Thanks
- Contributing
- License
- Copyright
Why do we need this MBED_RP2040_PWM library
This library enables you to use Hardware-based PWM to create and output PWM to pins on MBED RP2040-based boards such as Nano_RP2040_Connect, RASPBERRY_PI_PICO, using Arduino-mbed mbed_rp2040 or mbed_nano core
This library is using the same or similar functions as other FastPWM libraries, as follows, to enable you to port your PWM code easily between platforms
- RP2040_PWM
- AVR_PWM
- megaAVR_PWM
- ESP32_FastPWM
- SAMD_PWM
- SAMDUE_PWM
- nRF52_PWM
- Teensy_PWM
- ATtiny_PWM
- Dx_PWM
- Portenta_H7_PWM
- MBED_RP2040_PWM
- nRF52_MBED_PWM
- STM32_PWM
The most important feature is they're purely hardware-based PWM
channels. Therefore, the frequency can be higher than hybrid or software-based PWM
, and their executions are not blocked by bad-behaving functions / tasks. This important feature is absolutely necessary for mission-critical tasks.
The PWM_Multi will demonstrate the usage of multichannel PWM using multiple Hardware Timers. The 4 independent Hardware Timers are used to control 4 different PWM outputs, with totally independent frequencies and dutycycles. You can start, stop, change and restore the settings of any PWM channel on-the-fly.
Being hardware-based PWM, their executions are not blocked by bad-behaving functions / tasks, such as connecting to WiFi, Internet or Blynk services.
This non-being-blocked important feature is absolutely necessary for mission-critical tasks.
- RP2040-based boards such as Nano_RP2040_Connect, RASPBERRY_PI_PICO, ADAFRUIT_FEATHER_RP2040 and GENERIC_RP2040, etc. using Arduino-mbed RP2040 core
Arduino IDE 1.8.19+
for Arduino.Arduino mbed_rp2040 core 3.5.4+
for Arduino (Use Arduino Board Manager) RP2040-based boards, such as Arduino Nano RP2040 Connect, RASPBERRY_PI_PICO, etc..
The best and easiest way is to use Arduino Library Manager
. Search for MBED_RP2040_PWM, then select / install the latest version.
You can also use this link for more detailed instructions.
Another way to install is to:
- Navigate to MBED_RP2040_PWM page.
- Download the latest release
MBED_RP2040_PWM-main.zip
. - Extract the zip file to
MBED_RP2040_PWM-main
directory - Copy whole
MBED_RP2040_PWM-main
folder to Arduino libraries' directory such as~/Arduino/libraries/
.
- Install VS Code
- Install PlatformIO
- Install MBED_RP2040_PWM library by using Library Manager. Search for MBED_RP2040_PWM in Platform.io Author's Libraries
- Use included platformio.ini file from examples to ensure that all dependent libraries will installed automatically. Please visit documentation for the other options and examples at Project Configuration File
The current library implementation, using xyz-Impl.h
instead of standard xyz.cpp
, possibly creates certain Multiple Definitions
Linker error in certain use cases.
You can include this .hpp
file
// Can be included as many times as necessary, without `Multiple Definitions` Linker Error
#include "MBED_RP2040_PWM.hpp" //https://github.com/khoih-prog/MBED_RP2040_PWM
in many files. But be sure to use the following .h
file in just 1 .h
, .cpp
or .ino
file, which must not be included in any other file, to avoid Multiple Definitions
Linker Error
// To be included only in main(), .ino with setup() to avoid `Multiple Definitions` Linker Error
#include "MBED_RP2040_PWM.h" //https://github.com/khoih-prog/MBED_RP2040_PWM
Check the new multiFileProject example for a HOWTO
demo.
Before using any Timer for a PWM channel, you have to make sure the Timer has not been used by any other purpose.
// Valid pins from 0-29 (GP0-GP29)
uint32_t myPin = 15; // GP15
float dutyCycle = 50.0f;
float freq = 5000.0f;
mbed::PwmOut* pwm = NULL;
void setup()
{
....
setPWM(pwm, myPin, freq, dutyCycle);
}
Use these functions
float getFreq(mbed::PwmOut* &pwm);
float getDutyCycle(mbed::PwmOut* &pwm);
float getPulseWidth_uS(mbed::PwmOut* &pwm);
float getPeriod_uS(mbed::PwmOut* &pwm);
For example
// Valid pins from 0-29 (GP0-GP29)
uint32_t myPin = 15; // GP15
float dutyCycle = 50.0f;
float freq = 5000.0f;
mbed::PwmOut* pwm = NULL;
setPWM(pwm, myPin, freq, dutyCycle);
if (pwm)
{
Serial.print(getPulseWidth_uS(pwm)); Serial.print(F("\t\t"));
Serial.print(getDutyCycle(pwm)); Serial.print(F("\t\t"));
Serial.print(getPeriod_uS(pwm));
}
Example PWM_Multi
MBED_RP2040_PWM/examples/PWM_Multi/PWM_Multi.ino
Lines 10 to 237 in 97018ae
The following is the sample terminal output when running example PWM_Single on RaspberryPi Pico to demonstrate how to start a single PWM channel, then stop, change, restore the PWM settings on-the-fly.
Starting PWM_Single on RaspberryPi Pico
MBED_RP2040_PWM v1.0.1
[PWM] Freq = 5000.00, DutyCycle % = 50.00, DutyCycle = 0.50, Pin = 15
============================================
PW (us) DutyCycle Period (uS)
============================================
100.00 50.00 200.00
Stop PWM
0.00 0.00 1000.00
0.00 0.00 1000.00
Change PWM
25.00 25.00 100.00
25.00 25.00 100.00
Restore PWM
100.00 50.00 200.00
100.00 50.00 200.00
Stop PWM
0.00 0.00 1000.00
0.00 0.00 1000.00
Change PWM
25.00 25.00 100.00
25.00 25.00 100.00
The following is the sample terminal output when running example PWM_Multi on RaspberryPi Pico to demonstrate how to start multiple PWM channels, then stop, change, restore the PWM settings on-the-fly.
Starting PWM_Multi on RaspberryPi Pico
MBED_RP2040_PWM v1.0.1
[PWM] Freq = 1000.00, DutyCycle % = 50.00, DutyCycle = 0.50, Pin = GP12
[PWM] Freq = 2500.00, DutyCycle % = 50.00, DutyCycle = 0.50, Pin = GP13
[PWM] Freq = 4000.00, DutyCycle % = 50.00, DutyCycle = 0.50, Pin = GP14
[PWM] Freq = 5000.00, DutyCycle % = 50.00, DutyCycle = 0.50, Pin = GP15
=========================================================
PW (us) 0 PW (us) 1 PW (us) 2 PW (us) 3
=========================================================
500.00 200.00 125.00 100.00
Stop all PWM
0.00 0.00 0.00 0.00
0.00 0.00 0.00 0.00
Change all PWM
125.00 50.00 31.25 25.00
125.00 50.00 31.25 25.00
Restore all PWM
500.00 200.00 125.00 100.00
500.00 200.00 125.00 100.00
Stop all PWM
0.00 0.00 0.00 0.00
0.00 0.00 0.00 0.00
Change all PWM
125.00 50.00 31.25 25.00
125.00 50.00 31.25 25.00
Restore all PWM
500.00 200.00 125.00 100.00
500.00 200.00 125.00 100.00
Debug is enabled by default on Serial.
You can also change the debugging level _PWM_LOGLEVEL_
from 0 to 4
// Don't define _PWM_LOGLEVEL_ > 0. Only for special ISR debugging only. Can hang the system.
#define _PWM_LOGLEVEL_ 0
If you get compilation errors, more often than not, you may need to install a newer version of the core for Arduino boards.
Sometimes, the library will only work if you update the board core to the latest version because I am using newly added functions.
Submit issues to: MBED_RP2040_PWM issues
- Search for bug and improvement.
- Similar features for remaining Arduino boards
- Basic hardware multi-channel PWM for Nano_RP2040_Connect and RASPBERRY_PI_PICO, etc. using Arduino-mbed core
- Add Table of Contents
- Permit to start, stop, modify, restore PWM settings on-the-fly
- Optimize library code by using
reference-passing
instead ofvalue-passing
- Use
h-only
style - Add functions to read PWM parameters
- Use
allman astyle
and addutils
- Add example PWM_StepperControl to demo how to control Stepper Motor using PWM
Many thanks for everyone for bug reporting, new feature suggesting, testing and contributing to the development of this library.
- Thanks to Paul van Dinther for proposing new way to use PWM to drive Stepper-Motor in Using PWM to step a stepper driver #16, leading to v1.0.1
![]() Paul van Dinther |
If you want to contribute to this project:
- Report bugs and errors
- Ask for enhancements
- Create issues and pull requests
- Tell other people about this library
- The library is licensed under MIT
Copyright (c) 2022- Khoi Hoang