- Why do we need this nRF52_MBED_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 nRF52_MBED_PWM library
This library enables you to use Hardware-based PWM to create and output PWM to pins on an nRF52840-based Nano_33_BLE board.
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, their executions are not blocked by bad-behaving functions / tasks. This important feature is absolutely necessary for mission-critical tasks.
This important feature is absolutely necessary for mission-critical tasks. These hardware timers, using interrupt, still work even if other functions are blocking. Moreover, they are much more precise (certainly depending on clock frequency accuracy) than other software timers using millis() or micros(). That's necessary if you need to measure some data requiring better accuracy.
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.
- MBED nRF52840-based boards such as Nano_33_BLE, Nano_33_BLE_Sense, etc. using Arduino-mbed mbed_nano core
- Seeeduino nRF52840-based boards such as SEEED_XIAO_NRF52840 and SEEED_XIAO_NRF52840_SENSE, etc. using Seeeduino
mbed
core
Arduino IDE 1.8.19+
for Arduino.Arduino mbed_nano core 3.4.1+
for Arduino (Use Arduino Board Manager) MBED nRF52840-based boards such as Nano_33_BLE, Nano_33_BLE_Sense.Seeeduino mbed core 2.9.0+
for Seeed nRF52840-based boards such as SEEED_XIAO_NRF52840 and SEEED_XIAO_NRF52840_SENSE.
The best and easiest way is to use Arduino Library Manager
. Search for nRF52_MBED_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 nRF52_MBED_PWM page.
- Download the latest release
nRF52_MBED_PWM-main.zip
. - Extract the zip file to
nRF52_MBED_PWM-main
directory - Copy whole
nRF52_MBED_PWM-main
folder to Arduino libraries' directory such as~/Arduino/libraries/
.
- Install VS Code
- Install PlatformIO
- Install nRF52_MBED_PWM library by using Library Manager. Search for nRF52_MBED_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 "nRF52_MBED_PWM.hpp" //https://github.com/khoih-prog/nRF52_MBED_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 "nRF52_MBED_PWM.h" //https://github.com/khoih-prog/nRF52_MBED_PWM
Check the new multiFileProject example for a HOWTO
demo.
All the digital pins on Arduino Nano 33 BLE sense are PWM-enabled pins which are numbered from D0 to D13
Check Nano_33_BLE Specs
Before using any Timer for a PWM channel, you have to make sure the Timer has not been used by any other purpose.
// All the digital pins on Arduino Nano 33 BLE sense are PWM-enabled pins which are numbered from D0 to D13
uint32_t myPin = D2;
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
// All the digital pins on Arduino Nano 33 BLE sense are PWM-enabled pins which are numbered from D0 to D13
uint32_t myPin = D2;
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
The following is the sample terminal output when running example PWM_Single on Nano_33_BLE to demonstrate how to start a single PWM channel, then stop, change, restore the PWM settings on-the-fly.
Starting PWM_Single on Nano_33_BLE
nRF52_MBED_PWM v1.0.3
[PWM] Freq = 5000.00, DutyCycle % = 50.00, DutyCycle = 0.50, Pin = 2
============================================
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 Nano_33_BLE to demonstrate how to start multiple PWM channels, then stop, change, restore the PWM settings on-the-fly.
Starting PWM_Multi on Nano_33_BLE
nRF52_MBED_PWM v1.0.3
[PWM] Freq = 1000.00, DutyCycle % = 50.00, DutyCycle = 0.50, Pin = 2
[PWM] Freq = 2500.00, DutyCycle % = 50.00, DutyCycle = 0.50, Pin = 3
[PWM] Freq = 4000.00, DutyCycle % = 50.00, DutyCycle = 0.50, Pin = 4
[PWM] Freq = 5000.00, DutyCycle % = 50.00, DutyCycle = 0.50, Pin = 5
=========================================================
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: nRF52_MBED_PWM issues
- Search for bug and improvement.
- Similar features for remaining Arduino boards
- Basic hardware multi-channel PWM for Nano_33_BLE.
- 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.
- Add support to Seeeduino nRF52840-based boards such as SEEED_XIAO_NRF52840 and SEEED_XIAO_NRF52840_SENSE, etc. using Seeeduino
mbed
core - Add astyle using
allman
style. Restyle the library - 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 v2.0.3
![]() 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