STM32_PWM Library for multichannel hardware-based PWMs

STM32_PWM library GitHub release
How To Install Using Arduino Library Manager


Features

This wrapper library enables you to use Hardware-based PWM on STM32F/L/H/G/WB/MP1 boards to create and output PWM to pins.

The most important feature is they're purely hardware-based PWM channels. Therefore, their executions are very precise and not blocked by bad-behaving functions or tasks. This important feature is absolutely necessary for mission-critical tasks.

These hardware PWM channels still work even if other functions are blocking. Moreover, they are much more precise (certainly depending on clock frequency accuracy) than other ISR-based or software-based PWM using millis() or micros(). That's necessary if you need to measure some data requiring very high frequency and much better accuracy.

The PWMs_Array_Complex example will demonstrate the nearly perfect accuracy, compared to software timers, by printing the actual period / duty-cycle in microsecs of each of PWM-channels.

The PWM_Multi_Args 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.


Currently Supported Boards

This STM32_PWM library currently supports the following boards:

  1. STM32F/L/H/G/WB/MP1 boards such as NUCLEO_H743ZI2, NUCLEO_L552ZE_Q, NUCLEO_F767ZI, BLUEPILL_F103CB, etc., using Arduino Core for STM32


Changelog

Initial Releases v1.0.0

  1. Initial coding to support STM32F/L/H/G/WB/MP1 boards such as NUCLEO_H743ZI2, NUCLEO_L552ZE_Q, NUCLEO_F767ZI, BLUEPILL_F103CB, etc., using Arduino Core for STM32

Examples

Examples:

  1. PWM_Multi
  2. PWM_Multi_Args
  3. PWMs_Array_Complex

Debug Terminal Output Samples

1. PWMs_Array_Complex on NUCLEO_F767ZI

The following is the sample terminal output when running example PWMs_Array_Complex on NUCLEO_F767ZI to demonstrate the accuracy of Hardware-based PWM, especially when system is very busy.

Starting PWMs_Array_Complex on NUCLEO_F767ZI
STM32_PWM v1.0.0
Index = 0, Instance = 0x40000000, channel = 1, TimerIndex = 1, PinName = 0
Index = 1, Instance = 0x40010000, channel = 3, TimerIndex = 0, PinName = 77
Index = 2, Instance = 0x40000800, channel = 4, TimerIndex = 3, PinName = 63
SimpleTimer (ms): 2000, us : 12025001, Dus : 10019423
PWM Channel : 0100000, programmed Period (us): 100000, actual : 100000, programmed DutyCycle : 20, actual : 20.00
PWM Channel : 150000, programmed Period (us): 50000, actual : 50000, programmed DutyCycle : 30, actual : 30.00
PWM Channel : 22000, programmed Period (us): 2000, actual : 2000, programmed DutyCycle : 50, actual : 50.00
SimpleTimer (ms): 2000, us : 22058001, Dus : 10033000
PWM Channel : 0100000, programmed Period (us): 100000, actual : 99999, programmed DutyCycle : 20, actual : 20.00
PWM Channel : 150000, programmed Period (us): 50000, actual : 49999, programmed DutyCycle : 30, actual : 30.00
PWM Channel : 22000, programmed Period (us): 2000, actual : 2000, programmed DutyCycle : 50, actual : 50.00
SimpleTimer (ms): 2000, us : 32091001, Dus : 10033000

2. PWMs_Array_Complex on NUCLEO_H743ZI2

The following is the sample terminal output when running example PWMs_Array_Complex on NUCLEO_H743ZI2 to demonstrate the accuracy of Hardware-based PWM, especially when system is very busy.

Starting PWMs_Array_Complex on NUCLEO_H743ZI2
STM32_PWM v1.0.0
Index = 0, Instance = 0x40000000, channel = 1, TimerIndex = 1, PinName = 0
Index = 1, Instance = 0x40010000, channel = 3, TimerIndex = 0, PinName = 77
Index = 2, Instance = 0x40000800, channel = 4, TimerIndex = 3, PinName = 63
SimpleTimer (ms): 2000, us : 12025000, Dus : 10019435
PWM Channel : 0100000, programmed Period (us): 100000, actual : 100000, programmed DutyCycle : 20, actual : 20.00
PWM Channel : 150000, programmed Period (us): 50000, actual : 50000, programmed DutyCycle : 30, actual : 30.00
PWM Channel : 22000, programmed Period (us): 2000, actual : 2000, programmed DutyCycle : 50, actual : 50.00
SimpleTimer (ms): 2000, us : 22058000, Dus : 10033000
PWM Channel : 0100000, programmed Period (us): 100000, actual : 99999, programmed DutyCycle : 20, actual : 20.00
PWM Channel : 150000, programmed Period (us): 50000, actual : 49999, programmed DutyCycle : 30, actual : 30.00
PWM Channel : 22000, programmed Period (us): 2000, actual : 2000, programmed DutyCycle : 50, actual : 50.00
SimpleTimer (ms): 2000, us : 32091000, Dus : 10033000
PWM Channel : 0100000, programmed Period (us): 100000, actual : 100000, programmed DutyCycle : 20, actual : 20.00
PWM Channel : 150000, programmed Period (us): 50000, actual : 49999, programmed DutyCycle : 30, actual : 30.00
PWM Channel : 22000, programmed Period (us): 2000, actual : 2000, programmed DutyCycle : 50, actual : 50.00

3. PWMs_Array_Complex on BLUEPILL_F103CB

The following is the sample terminal output when running example PWMs_Array_Complex on BLUEPILL_F103CB to demonstrate the accuracy of Hardware-based PWM, especially when system is very busy.

Starting PWMs_Array_Complex on BLUEPILL_F103CB
STM32_PWM v1.0.0
Using pin = 0, 1, etc => Index = 0, Instance = 0x40000000, channel = 1, TimerIndex = 1, PinName = 0
Using pin = 0, 1, etc => Index = 1, Instance = 0x40000400, channel = 2, TimerIndex = 2, PinName = 21
Using pin = 0, 1, etc => Index = 2, Instance = 0x40012C00, channel = 3, TimerIndex = 0, PinName = 10
SimpleTimer (ms): 2000, us : 12970007, Dus : 9999926
PWM Channel : 0, programmed Period (us): 50000, actual : 50000, programmed DutyCycle : 20, actual : 20.00
PWM Channel : 1, programmed Period (us): 20000, actual : 20000, programmed DutyCycle : 30, actual : 30.00
PWM Channel : 2, programmed Period (us): 2000, actual : 2000, programmed DutyCycle : 50, actual : 50.00
SimpleTimer (ms): 2000, us : 22971007, Dus : 10001000
PWM Channel : 0, programmed Period (us): 50000, actual : 49999, programmed DutyCycle : 20, actual : 20.00
PWM Channel : 1, programmed Period (us): 20000, actual : 20000, programmed DutyCycle : 30, actual : 30.00
PWM Channel : 2, programmed Period (us): 2000, actual : 2000, programmed DutyCycle : 50, actual : 50.00
SimpleTimer (ms): 2000, us : 32972007, Dus : 10001000
PWM Channel : 0, programmed Period (us): 50000, actual : 49999, programmed DutyCycle : 20, actual : 20.00
PWM Channel : 1, programmed Period (us): 20000, actual : 20000, programmed DutyCycle : 30, actual : 30.00
PWM Channel : 2, programmed Period (us): 2000, actual : 2000, programmed DutyCycle : 50, actual : 50.00
SimpleTimer (ms): 2000, us : 42973007, Dus : 10001000
PWM Channel : 0, programmed Period (us): 50000, actual : 49999, programmed DutyCycle : 20, actual : 20.00
PWM Channel : 1, programmed Period (us): 20000, actual : 19999, programmed DutyCycle : 30, actual : 30.00
PWM Channel : 2, programmed Period (us): 2000, actual : 2000, programmed DutyCycle : 50, actual : 50.00
SimpleTimer (ms): 2000, us : 52974007, Dus : 10001000
PWM Channel : 0, programmed Period (us): 50000, actual : 49999, programmed DutyCycle : 20, actual : 20.00
PWM Channel : 1, programmed Period (us): 20000, actual : 20000, programmed DutyCycle : 30, actual : 30.00
PWM Channel : 2, programmed Period (us): 2000, actual : 2000, programmed DutyCycle : 50, actual : 50.00