- Important Note for Arduino IDE
- Why do we need this Dx_PWM library
- Changelog
- Prerequisites
- Installation
- More useful Information
- Usage
- Examples
- Example PWM_Multi
- Debug Terminal Output Samples
- Debug
- Troubleshooting
- Issues
- TO DO
- DONE
- Contributions and Thanks
- Contributing
- License
- Copyright
With some Arduino IDE versions, such as v1.8.19, upload directly via USB to some boards, such as AVR_CuriosityNano3217
can't be done without unknown-to-me
fix. We'll get the following error when uploading
avrdude: Version 6.3-20201216
Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/
Copyright (c) 2007-2014 Joerg Wunsch
System wide configuration file is "/home/kh/.arduino15/packages/megaTinyCore/hardware/megaavr/2.5.11/avrdude.conf"
User configuration file is "/home/kh/.avrduderc"
User configuration file does not exist or is not a regular file, skipping
Using Port : usb
Using Programmer : curiosity_updi
avrdude: usbdev_open(): Found nEDBG CMSIS-DAP, serno: MCHP3333021800000998
avrdude: usbdev_open(): WARNING: failed to set configuration 1: Device or resource busy
avrdude: Found CMSIS-DAP compliant device, using EDBG protocol
avrdude: usbdev_send(): wrote -5 out of 912 bytes, err = Input/output error
avrdude: jtag3_edbg_prepare(): failed to send command to serial port
avrdude done. Thank you.
the selected serial port
does not exist or your board is not connected
We can use drag-and-drop method to drag-and-drop
the compiled hex file to CURIOSITY
virtual drive.
If success
, The LED blinks slowly for 2 sec, or rapidly for 2 sec if failure
For example, to run Change_Interval example, use Arduino IDE to compile, and get the Change_Interval.ino.hex
file. For Ubuntu Linux, the file is stored in directory /tmp/arduino_build_xxxxxx
After drag-and-drop the Change_Interval.ino.hex
into CURIOSITY
virtual drive, the code will run immediately if successfully loaded (LED blinks slowly)
Why do we need this Dx_PWM library
This hardware-based PWM library, a wrapper and enhancement around DxCore analogWrite()
code, enables you to use Hardware-PWM on AVRDx-based boards (AVR128Dx, AVR64Dx, AVR32Dx, etc.) using DxCore, to create and output PWM. These purely hardware-based PWM channels can generate very high PWM frequencies, depending on CPU clock and acceptable accuracy, due to 8 or 16-bit PWM / Timer registers.
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 operations are not blocked by bad-behaving software functions / tasks.
This important feature is absolutely necessary for mission-critical tasks. These hardware PWM-channels, still work even if other software 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 control external systems (Servo, etc.) requiring better accuracy.
New efficient setPWM_manual()
function enables waveform creation using PWM.
The PWM_Multi example will demonstrate the usage of multichannel PWM using multiple Hardware-PWM blocks (slices). The 4 independent Hardware-PWM channels are used to control 4 different PWM outputs, with totally independent frequencies and dutycycles on Arduino Mega
.
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.
Imagine you have a system with a mission-critical function, controlling a robot or doing something much more important. You normally use a software timer to poll, or even place the function in loop(). But what if another function is blocking the loop() or setup().
So your function might not be executed, and the result would be disastrous.
You'd prefer to have your function called, no matter what happening with other functions (busy loop, bug, etc.).
The correct choice is to use hardware-based PWM
.
These hardware-based PWM channels still work even if other software functions are blocking. Moreover, they are much more precise (certainly depending on clock frequency accuracy) than other software-based PWMs, using millis() or micros().
Functions using normal software-based PWMs, relying on loop() and calling millis(), won't work if the loop() or setup() is blocked by certain operation. For example, certain function is blocking while it's connecting to WiFi or some services.
- AVRDA-based boards (AVR128DA, AVR64DA, AVR32DA, etc.) using DxCore
- AVRDB-based boards (AVR128DB, AVR64DB, AVR32DB, etc.) using DxCore
- AVRDD-based boards (AVR64DD, AVR32DD, AVR16DD, etc.) using DxCore v1.5.1+
Arduino IDE 1.8.19+
for Arduino.SpenceKonde DxCore core 1.5.3+
for Arduino AVRDx boards. . Follow DxCore Installation.
The best and easiest way is to use Arduino Library Manager
. Search for Dx_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 Dx_PWM page.
- Download the latest release
Dx_PWM-main.zip
. - Extract the zip file to
Dx_PWM-main
directory - Copy whole
Dx_PWM-main
folder to Arduino libraries' directory such as~/Arduino/libraries/
.
- Install VS Code
- Install PlatformIO
- Install Dx_PWM library by using Library Manager. Search for Dx_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
- Arduino 101: Timers and Interrupts
- Getting Started with Timer/Counter Type B (TCB)
- DXCore README.md
- AVR128DA48-Curiosity-Nano-Hardware-User Guide
- AVR128DB48-Curiosity-Nano-Hardware-User Guide
TCB0-TCB4 are 16-bit timers
The AVRDx boards with 14, 20, 28 or 32 pins, such as AVRDx28
, will have only 3 TCB timers, (TCB0-TCB2)
The AVRDx with 48 pins, such as Curiosity Nano AVRDA48
, Curiosity Nano AVRDB48
, will have 4 TCB timers, (TCB0-TCB3)
The AVRDx with 64 pins, such as AVRDA64
, AVRDB64
, will have 5 TCB timers, (TCB0-TCB4)
The number of TCB timers will be automatically configured by the library.
Before using any PWM Timer
and channel
, you have to make sure the Timer
and channel
has not been used by any other purpose.
Dx_PWM* PWM_Instance;
PWM_Instance = new Dx_PWM(PWM_Pins, freq, dutyCycle);
if (PWM_Instance)
{
PWM_Instance->setPWM();
}
To use float new_dutyCycle
PWM_Instance->setPWM(PWM_Pins, new_frequency, new_dutyCycle);
such as
dutyCycle = 10.0f;
Serial.print(F("Change PWM DutyCycle to ")); Serial.println(dutyCycle);
PWM_Instance->setPWM(pinToUse, frequency, dutyCycle);
To use uint32_t new_dutyCycle
= (real_dutyCycle * 65536) / 100
PWM_Instance->setPWM_Int(PWM_Pins, new_frequency, new_dutyCycle);
such as for real_dutyCycle = 50%
// 50% dutyCycle = (real_dutyCycle * 65535) / 100
dutyCycle = 32767;
Serial.print(F("Change PWM DutyCycle to (%) "));
Serial.println((float) dutyCycle * 100 / 65536);
PWM_Instance->setPWM_Int(pinToUse, frequency, dutyCycle);
for real_dutyCycle = 50%
// 20% dutyCycle = (real_dutyCycle * 65535) / 100
dutyCycle = 13107;
Serial.print(F("Change PWM DutyCycle to (%) "));
Serial.println((float) dutyCycle * 100 / 65536);
PWM_Instance->setPWM_Int(pinToUse, frequency, dutyCycle);
Function prototype
bool setPWM_manual(const uint8_t& pin, const uint16_t& DCValue);
Need to call only once for each pin
PWM_Instance->setPWM(PWM_Pins, frequency, dutyCycle);
after that, if just changing dutyCycle
/ level
, use
PWM_Instance->setPWM_manual(PWM_Pins, new_level);
- PWM_Basic
- PWM_DynamicDutyCycle
- PWM_DynamicDutyCycle_Int
- PWM_DynamicFreq
- PWM_Multi
- PWM_MultiChannel
- PWM_Waveform
- PWM_StepperControl New
Example PWM_Multi
Dx_PWM/examples/PWM_Multi/PWM_Multi.ino
Lines 11 to 140 in 3090d0e
The following is the sample terminal output when running example PWM_DynamicDutyCycle on AVR128DB using DxCore
, to demonstrate the ability to provide high PWM frequencies and ability to change DutyCycle on-the-fly
.
Starting PWM_DynamicDutyCycle on AVR128DB
Dx_PWM v1.1.1
[PWM] Dx_PWM: freq = 5000.00
[PWM] Dx_PWM: _dutycycle = 0
=====================================================================================
Change PWM DutyCycle to 90.00
[PWM] setPWM: _dutycycle = 58981
[PWM] setPWM_Int: pin = 39 , _dutycycle = 58981 , old frequency = 5000.00
[PWM] setPWM_Int: TimerB, _dutycycle = 58981
[PWM] setPeriod_TimerB: F_CPU = 24000000 , cycles = 4800
[PWM] setPeriod_TimerB: cycles < TIMERB_RESOLUTION * 64, using divider = 64
[PWM] setPeriod_TimerB: pwmPeriod = 75 , _actualFrequency = 5000.00
[PWM] setPWM_Int: TIMERB, dutycycle = 67 , DC % = 90.67
=====================================================================================
Actual data: pin = 39, PWM DC = 78642.67, PWMPeriod = 75.00, PWM Freq (Hz) = 5000.0000
=====================================================================================
Change PWM DutyCycle to 20.00
[PWM] setPWM: _dutycycle = 13107
[PWM] setPWM_Int: pin = 39 , _dutycycle = 13107 , old frequency = 5000.00
[PWM] setPWM_Int: TimerB, _dutycycle = 13107
[PWM] setPWM_Int: TIMERB, dutycycle = 15 , DC % = 21.33
=====================================================================================
Actual data: pin = 39, PWM DC = 17477.33, PWMPeriod = 75.00, PWM Freq (Hz) = 5000.0000
=====================================================================================
Change PWM DutyCycle to 90.00
[PWM] setPWM: _dutycycle = 58981
[PWM] setPWM_Int: pin = 39 , _dutycycle = 58981 , old frequency = 5000.00
[PWM] setPWM_Int: TimerB, _dutycycle = 58981
[PWM] setPWM_Int: TIMERB, dutycycle = 67 , DC % = 90.67
=====================================================================================
Actual data: pin = 39, PWM DC = 78642.67, PWMPeriod = 75.00, PWM Freq (Hz) = 5000.0000
=====================================================================================
Change PWM DutyCycle to 20.00
[PWM] setPWM: _dutycycle = 13107
[PWM] setPWM_Int: pin = 39 , _dutycycle = 13107 , old frequency = 5000.00
[PWM] setPWM_Int: TimerB, _dutycycle = 13107
[PWM] setPWM_Int: TIMERB, dutycycle = 15 , DC % = 21.33
=====================================================================================
Actual data: pin = 39, PWM DC = 17477.33, PWMPeriod = 75.00, PWM Freq (Hz) = 5000.0000
=====================================================================================
Change PWM DutyCycle to 90.00
[PWM] setPWM: _dutycycle = 58981
[PWM] setPWM_Int: pin = 39 , _dutycycle = 58981 , old frequency = 5000.00
[PWM] setPWM_Int: TimerB, _dutycycle = 58981
[PWM] setPWM_Int: TIMERB, dutycycle = 67 , DC % = 90.67
=====================================================================================
Actual data: pin = 39, PWM DC = 78642.67, PWMPeriod = 75.00, PWM Freq (Hz) = 5000.0000
=====================================================================================
The following is the sample terminal output when running example PWM_Multi on AVR128DB, to demonstrate the ability to provide high PWM frequencies on multiple PWM-capable
pins.
Starting PWM_Multi on AVR128DB
Dx_PWM v1.1.1
[PWM] Dx_PWM: freq = 2000.00
[PWM] Dx_PWM: _dutycycle = 13107
[PWM] setPWM_Int: pin = 10 , _dutycycle = 13107 , old frequency = 2000.00
[PWM] setPeriod_TimerA1: F_CPU = 24000000 , microseconds = 500 , TCA_Freq_mult = 1.00 , beginning pwmPeriod = 1500
[PWM] setPeriod_TimerA1: CLKSEL_DIV64
[PWM] setPeriod_TimerA1: pwmPeriod = 188 , _actualFrequency = 1994.00
[PWM] setPWM_Int: TIMER_TCA1, _dutycycle = 38
[PWM] Dx_PWM: freq = 3000.00
[PWM] Dx_PWM: _dutycycle = 19660
[PWM] setPWM_Int: pin = 14 , _dutycycle = 19660 , old frequency = 3000.00
[PWM] setPeriod_TimerA0: F_CPU = 24000000 , microseconds = 333 , TCA_Freq_mult = 1.00
[PWM] setPeriod_TimerA0: CLKSEL_DIV64
[PWM] setPeriod_TimerA0: pwmPeriod = 125 , _actualFrequency = 3000.00
[PWM] setPWM_Int 4: _dutycycle = 38
[PWM] Dx_PWM: freq = 4000.00
[PWM] Dx_PWM: _dutycycle = 26214
[PWM] setPWM_Int: pin = 38 , _dutycycle = 26214 , old frequency = 4000.00
[PWM] setPWM_Int: TimerB, _dutycycle = 26214
[PWM] setPeriod_TimerB: F_CPU = 24000000 , cycles = 6000
[PWM] setPeriod_TimerB: cycles < TIMERB_RESOLUTION * 64, using divider = 64
[PWM] setPeriod_TimerB: pwmPeriod = 93 , _actualFrequency = 4000.00
[PWM] setPWM_Int: TIMERB, dutycycle = 37 , DC % = 40.86
[PWM] Dx_PWM: freq = 8000.00
[PWM] Dx_PWM: _dutycycle = 52428
[PWM] setPWM_Int: pin = 39 , _dutycycle = 52428 , old frequency = 8000.00
[PWM] setPWM_Int: TimerB, _dutycycle = 52428
[PWM] setPeriod_TimerB: F_CPU = 24000000 , cycles = 3000
[PWM] setPeriod_TimerB: cycles < TIMERB_RESOLUTION * 64, using divider = 64
[PWM] setPeriod_TimerB: pwmPeriod = 46 , _actualFrequency = 8000.00
[PWM] setPWM_Int: TIMERB, dutycycle = 36 , DC % = 80.43
=====================================================================================
Index Pin PWM_freq DutyCycle Actual Freq
=====================================================================================
0 10 2000.00 20.00 1994.0000
1 14 3000.00 30.00 3000.0000
2 38 4000.00 40.00 4000.0000
3 39 8000.00 80.00 8000.0000
=====================================================================================
Actual data: pin = 10, PWM DC = 20.74, PWMPeriod = 188.00, PWM Freq (Hz) = 1994.0000
=====================================================================================
=====================================================================================
Actual data: pin = 14, PWM DC = 31.20, PWMPeriod = 125.00, PWM Freq (Hz) = 3000.0000
=====================================================================================
=====================================================================================
Actual data: pin = 38, PWM DC = 28188.17, PWMPeriod = 93.00, PWM Freq (Hz) = 4000.0000
=====================================================================================
=====================================================================================
Actual data: pin = 39, PWM DC = 113976.09, PWMPeriod = 46.00, PWM Freq (Hz) = 8000.0000
=====================================================================================
The following is the sample terminal output when running example PWM_DynamicFreq on AVR128DB, to demonstrate the ability to change dynamically PWM frequencies.
Starting PWM_DynamicFreq on AVR128DB
Dx_PWM v1.1.1
[PWM] Dx_PWM: freq = 10000.00
[PWM] Dx_PWM: _dutycycle = 32767
Stop here forever
Starting PWM_DynamicFreq on AVR128DB
Dx_PWM v1.1.1
[PWM] Dx_PWM: freq = 10000.00
[PWM] Dx_PWM: _dutycycle = 32767
=====================================================================================
Change PWM Freq to 20000.00
[PWM] setPWM: _dutycycle = 32767
[PWM] setPWM_Int: pin = 39 , _dutycycle = 32767 , new frequency = 20000.00
[PWM] setPWM_Int: TimerB, _dutycycle = 32767
[PWM] setPeriod_TimerB: F_CPU = 24000000 , cycles = 1200
[PWM] setPeriod_TimerB: cycles < TIMERB_RESOLUTION * 64, using divider = 64
[PWM] setPeriod_TimerB: pwmPeriod = 18 , _actualFrequency = 20000.00
[PWM] setPWM_Int: TIMERB, dutycycle = 8 , DC % = 50.00
=====================================================================================
Actual data: pin = 39, PWM DC = 182044.43, PWMPeriod = 18.00, PWM Freq (Hz) = 20000.0000
=====================================================================================
Change PWM Freq to 10000.00
[PWM] setPWM: _dutycycle = 32767
[PWM] setPWM_Int: pin = 39 , _dutycycle = 32767 , new frequency = 10000.00
[PWM] setPWM_Int: TimerB, _dutycycle = 32767
[PWM] setPeriod_TimerB: F_CPU = 24000000 , cycles = 2400
[PWM] setPeriod_TimerB: cycles < TIMERB_RESOLUTION * 64, using divider = 64
[PWM] setPeriod_TimerB: pwmPeriod = 37 , _actualFrequency = 10000.00
[PWM] setPWM_Int: TIMERB, dutycycle = 18 , DC % = 51.35
=====================================================================================
Actual data: pin = 39, PWM DC = 88562.17, PWMPeriod = 37.00, PWM Freq (Hz) = 10000.0000
=====================================================================================
Change PWM Freq to 20000.00
[PWM] setPWM: _dutycycle = 32767
[PWM] setPWM_Int: pin = 39 , _dutycycle = 32767 , new frequency = 20000.00
[PWM] setPWM_Int: TimerB, _dutycycle = 32767
[PWM] setPeriod_TimerB: F_CPU = 24000000 , cycles = 1200
[PWM] setPeriod_TimerB: cycles < TIMERB_RESOLUTION * 64, using divider = 64
[PWM] setPeriod_TimerB: pwmPeriod = 18 , _actualFrequency = 20000.00
[PWM] setPWM_Int: TIMERB, dutycycle = 8 , DC % = 50.00
=====================================================================================
Actual data: pin = 39, PWM DC = 182044.43, PWMPeriod = 18.00, PWM Freq (Hz) = 20000.0000
=====================================================================================
The following is the sample terminal output when running example PWM_Waveform on AVR128DB, to demonstrate how to use the setPWM_manual()
function in wafeform creation
Starting PWM_Waveform on AVR128DB
Dx_PWM v1.1.1
[PWM] Dx_PWM: freq = 2000.00
[PWM] Dx_PWM: _dutycycle = 0
[PWM] setPWM: _dutycycle = 0
[PWM] setPeriod_TimerB: F_CPU = 24000000 , cycles = 12000
[PWM] setPeriod_TimerB: cycles < TIMERB_RESOLUTION * 64, using divider = 64
[PWM] setPeriod_TimerB: pwmPeriod = 187 , _actualFrequency = 2000.00
[PWM] setPWM_Int: TIMERB, dutycycle = 0 , DC % = 0.00
============================================================================================
Actual data: pin = 39, PWM DutyCycle = 0.53, PWMPeriod = 187.00, PWM Freq (Hz) = 2000.0000
============================================================================================
[PWM] setPWM_Int: TIMERB, dutycycle = 0 , DC % = 0.00
[PWM] setPWM_Int: TIMERB, dutycycle = 9 , DC % = 4.81
[PWM] setPWM_Int: TIMERB, dutycycle = 18 , DC % = 9.63
[PWM] setPWM_Int: TIMERB, dutycycle = 28 , DC % = 14.97
[PWM] setPWM_Int: TIMERB, dutycycle = 37 , DC % = 19.79
[PWM] setPWM_Int: TIMERB, dutycycle = 46 , DC % = 24.60
[PWM] setPWM_Int: TIMERB, dutycycle = 56 , DC % = 29.95
[PWM] setPWM_Int: TIMERB, dutycycle = 65 , DC % = 34.76
[PWM] setPWM_Int: TIMERB, dutycycle = 74 , DC % = 39.57
[PWM] setPWM_Int: TIMERB, dutycycle = 84 , DC % = 44.92
[PWM] setPWM_Int: TIMERB, dutycycle = 93 , DC % = 49.73
[PWM] setPWM_Int: TIMERB, dutycycle = 102 , DC % = 54.55
[PWM] setPWM_Int: TIMERB, dutycycle = 112 , DC % = 59.89
[PWM] setPWM_Int: TIMERB, dutycycle = 121 , DC % = 64.71
[PWM] setPWM_Int: TIMERB, dutycycle = 130 , DC % = 69.52
[PWM] setPWM_Int: TIMERB, dutycycle = 140 , DC % = 74.87
[PWM] setPWM_Int: TIMERB, dutycycle = 149 , DC % = 79.68
[PWM] setPWM_Int: TIMERB, dutycycle = 158 , DC % = 84.49
[PWM] setPWM_Int: TIMERB, dutycycle = 168 , DC % = 89.84
[PWM] setPWM_Int: TIMERB, dutycycle = 177 , DC % = 94.65
[PWM] setPWM_Int: TIMERB, dutycycle = 187 , DC % = 100.00
[PWM] setPWM_Int: TIMERB, dutycycle = 177 , DC % = 94.65
[PWM] setPWM_Int: TIMERB, dutycycle = 168 , DC % = 89.84
[PWM] setPWM_Int: TIMERB, dutycycle = 158 , DC % = 84.49
[PWM] setPWM_Int: TIMERB, dutycycle = 149 , DC % = 79.68
[PWM] setPWM_Int: TIMERB, dutycycle = 140 , DC % = 74.87
[PWM] setPWM_Int: TIMERB, dutycycle = 130 , DC % = 69.52
[PWM] setPWM_Int: TIMERB, dutycycle = 121 , DC % = 64.71
[PWM] setPWM_Int: TIMERB, dutycycle = 112 , DC % = 59.89
[PWM] setPWM_Int: TIMERB, dutycycle = 102 , DC % = 54.55
[PWM] setPWM_Int: TIMERB, dutycycle = 93 , DC % = 49.73
[PWM] setPWM_Int: TIMERB, dutycycle = 84 , DC % = 44.92
[PWM] setPWM_Int: TIMERB, dutycycle = 74 , DC % = 39.57
[PWM] setPWM_Int: TIMERB, dutycycle = 65 , DC % = 34.76
[PWM] setPWM_Int: TIMERB, dutycycle = 56 , DC % = 29.95
[PWM] setPWM_Int: TIMERB, dutycycle = 46 , DC % = 24.60
[PWM] setPWM_Int: TIMERB, dutycycle = 37 , DC % = 19.79
[PWM] setPWM_Int: TIMERB, dutycycle = 28 , DC % = 14.97
[PWM] setPWM_Int: TIMERB, dutycycle = 18 , DC % = 9.63
[PWM] setPWM_Int: TIMERB, dutycycle = 9 , DC % = 4.81
[PWM] setPWM_Int: TIMERB, dutycycle = 0 , DC % = 0.00
The following is the sample terminal output when running example PWM_Waveform on AVR128DA, to demonstrate how to use the setPWM_manual()
function in wafeform creation
Starting PWM_Waveform on AVR128DA
Dx_PWM v1.1.1
[PWM] Dx_PWM: freq = 2000.00
[PWM] Dx_PWM: _dutycycle = 0
[PWM] setPWM: _dutycycle = 0
[PWM] setPeriod_TimerB: F_CPU = 24000000 , cycles = 12000
[PWM] setPeriod_TimerB: cycles < TIMERB_RESOLUTION * 64, using divider = 64
[PWM] setPeriod_TimerB: pwmPeriod = 187 , _actualFrequency = 2000.00
[PWM] setPWM_Int: TIMERB, dutycycle = 0 , DC % = 0.00
============================================================================================
Actual data: pin = 39, PWM DutyCycle = 0.53, PWMPeriod = 187.00, PWM Freq (Hz) = 2000.0000
============================================================================================
[PWM] setPWM_Int: TIMERB, dutycycle = 0 , DC % = 0.00
[PWM] setPWM_Int: TIMERB, dutycycle = 9 , DC % = 4.81
[PWM] setPWM_Int: TIMERB, dutycycle = 18 , DC % = 9.63
[PWM] setPWM_Int: TIMERB, dutycycle = 28 , DC % = 14.97
[PWM] setPWM_Int: TIMERB, dutycycle = 37 , DC % = 19.79
[PWM] setPWM_Int: TIMERB, dutycycle = 46 , DC % = 24.60
[PWM] setPWM_Int: TIMERB, dutycycle = 56 , DC % = 29.95
[PWM] setPWM_Int: TIMERB, dutycycle = 65 , DC % = 34.76
[PWM] setPWM_Int: TIMERB, dutycycle = 74 , DC % = 39.57
[PWM] setPWM_Int: TIMERB, dutycycle = 84 , DC % = 44.92
[PWM] setPWM_Int: TIMERB, dutycycle = 93 , DC % = 49.73
[PWM] setPWM_Int: TIMERB, dutycycle = 102 , DC % = 54.55
[PWM] setPWM_Int: TIMERB, dutycycle = 112 , DC % = 59.89
[PWM] setPWM_Int: TIMERB, dutycycle = 121 , DC % = 64.71
[PWM] setPWM_Int: TIMERB, dutycycle = 130 , DC % = 69.52
[PWM] setPWM_Int: TIMERB, dutycycle = 140 , DC % = 74.87
[PWM] setPWM_Int: TIMERB, dutycycle = 149 , DC % = 79.68
[PWM] setPWM_Int: TIMERB, dutycycle = 158 , DC % = 84.49
[PWM] setPWM_Int: TIMERB, dutycycle = 168 , DC % = 89.84
[PWM] setPWM_Int: TIMERB, dutycycle = 177 , DC % = 94.65
[PWM] setPWM_Int: TIMERB, dutycycle = 187 , DC % = 100.00
[PWM] setPWM_Int: TIMERB, dutycycle = 177 , DC % = 94.65
[PWM] setPWM_Int: TIMERB, dutycycle = 168 , DC % = 89.84
[PWM] setPWM_Int: TIMERB, dutycycle = 158 , DC % = 84.49
[PWM] setPWM_Int: TIMERB, dutycycle = 149 , DC % = 79.68
[PWM] setPWM_Int: TIMERB, dutycycle = 140 , DC % = 74.87
[PWM] setPWM_Int: TIMERB, dutycycle = 130 , DC % = 69.52
[PWM] setPWM_Int: TIMERB, dutycycle = 121 , DC % = 64.71
[PWM] setPWM_Int: TIMERB, dutycycle = 112 , DC % = 59.89
[PWM] setPWM_Int: TIMERB, dutycycle = 102 , DC % = 54.55
[PWM] setPWM_Int: TIMERB, dutycycle = 93 , DC % = 49.73
[PWM] setPWM_Int: TIMERB, dutycycle = 84 , DC % = 44.92
[PWM] setPWM_Int: TIMERB, dutycycle = 74 , DC % = 39.57
[PWM] setPWM_Int: TIMERB, dutycycle = 65 , DC % = 34.76
[PWM] setPWM_Int: TIMERB, dutycycle = 56 , DC % = 29.95
[PWM] setPWM_Int: TIMERB, dutycycle = 46 , DC % = 24.60
[PWM] setPWM_Int: TIMERB, dutycycle = 37 , DC % = 19.79
[PWM] setPWM_Int: TIMERB, dutycycle = 28 , DC % = 14.97
[PWM] setPWM_Int: TIMERB, dutycycle = 18 , DC % = 9.63
[PWM] setPWM_Int: TIMERB, dutycycle = 9 , DC % = 4.81
[PWM] setPWM_Int: TIMERB, dutycycle = 0 , DC % = 0.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: Dx_PWM issues
- Search for bug and improvement.
- Support to TCD0 to change frequency
- Basic hardware-based multi-channel PWMs for AVRDx-based boards (AVR128Dx, AVR64Dx, AVR32Dx, etc.) using DxCore
- Add support to
AVRDD
(AVR64DD, AVR32DDx, AVR16DD, etc.) - Modify to use either breaking DxCore
v1.5.1+
orv1.4.10-
- 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