From aa8675522cb6a2c94cce3558230a74d66d800063 Mon Sep 17 00:00:00 2001 From: Khoi Hoang <57012152+khoih-prog@users.noreply.github.com> Date: Fri, 4 Mar 2022 21:58:40 -0500 Subject: [PATCH] v1.3.1 to fix `DutyCycle` bug, etc. ### Releases v1.3.1 1. Fix `DutyCycle` bug. Check [float precisison of DutyCycle only sometimes working #3](https://github.com/khoih-prog/SAMD_Slow_PWM/issues/3) 2. Fix `New Period` display bug. Check [random dropouts #4](https://github.com/khoih-prog/SAMD_Slow_PWM/issues/4) 3. Update examples --- CONTRIBUTING.md | 2 +- README.md | 548 +++++---------------------------------- changelog.md | 7 + library.json | 2 +- library.properties | 2 +- src/ESP32_PWM.h | 3 +- src/ESP32_PWM.hpp | 9 +- src/ESP32_PWM_ISR.h | 3 +- src/ESP32_PWM_ISR.hpp | 20 +- src/ESP32_PWM_ISR_Impl.h | 27 +- src/PWM_Generic_Debug.h | 3 +- 11 files changed, 120 insertions(+), 506 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c66df40..d05c1c0 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -34,7 +34,7 @@ Arduino IDE version: 1.8.19 ESP32 core v2.0.2 ESP32S3_DEV Module OS: Ubuntu 20.04 LTS -Linux xy-Inspiron-3593 5.4.0-99-generic #112-Ubuntu SMP Thu Feb 3 13:50:55 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux +Linux xy-Inspiron-3593 5.4.0-100-generic #113-Ubuntu SMP Thu Feb 3 18:43:29 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux Context: I encountered a crash while using TimerInterrupt. diff --git a/README.md b/README.md index bd7ab0d..2a19cd4 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,8 @@ [![contributions welcome](https://img.shields.io/badge/contributions-welcome-brightgreen.svg?style=flat)](#Contributing) [![GitHub issues](https://img.shields.io/github/issues/khoih-prog/ESP32_PWM.svg)](http://github.com/khoih-prog/ESP32_PWM/issues) -Buy Me A Coffee +Donate to my libraries using BuyMeACoffee + --- --- @@ -293,454 +294,9 @@ Before using any Timer, you have to make sure the Timer has not been used by any ### Example [ISR_16_PWMs_Array_Complex](examples/ISR_16_PWMs_Array_Complex) -``` -#if !defined( ESP32 ) - #error This code is designed to run on ESP32 platform, not Arduino nor ESP8266! Please check your Tools->Board setting. -#endif +https://github.com/khoih-prog/ESP32_PWM/blob/8ec2d60c4f49727e911b6722c46c455c1cbcf457/examples/ISR_16_PWMs_Array_Complex/ISR_16_PWMs_Array_Complex.ino#L25-L470 -// These define's must be placed at the beginning before #include "ESP32_PWM.h" -// _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_ 4 - -#define USING_MICROS_RESOLUTION true //false - -// Default is true, uncomment to false -//#define CHANGING_PWM_END_OF_CYCLE false - -// To be included only in main(), .ino with setup() to avoid `Multiple Definitions` Linker Error -#include "ESP32_PWM.h" -#include // https://github.com/jfturcot/SimpleTimer - -#ifndef LED_BUILTIN - #define LED_BUILTIN 2 -#endif - -#ifndef LED_BLUE - #define LED_BLUE 25 -#endif - -#ifndef LED_RED - #define LED_RED 27 -#endif - -#define HW_TIMER_INTERVAL_US 20L - -volatile uint32_t startMicros = 0; - -// Init ESP32 timer 1 -ESP32Timer ITimer(1); - -// Init ESP32_ISR_PWM -ESP32_PWM ISR_PWM; - -bool IRAM_ATTR TimerHandler(void * timerNo) -{ - ISR_PWM.run(); - - return true; -} - -///////////////////////////////////////////////// - -#if ( ARDUINO_ESP32C3_DEV ) - #define NUMBER_ISR_PWMS 4 -#elif ( ARDUINO_ESP32S3_DEV ) - #define NUMBER_ISR_PWMS 16 -#else - #define NUMBER_ISR_PWMS 16 -#endif - -#define PIN_D0 0 // Pin D0 mapped to pin GPIO0/BOOT/ADC11/TOUCH1 of ESP32 -#define PIN_D1 1 // Pin D1 mapped to pin GPIO1/TX0 of ESP32 -#define PIN_D2 2 // Pin D2 mapped to pin GPIO2/ADC12/TOUCH2 of ESP32 -#define PIN_D3 3 // Pin D3 mapped to pin GPIO3/RX0 of ESP32 -#define PIN_D4 4 // Pin D4 mapped to pin GPIO4/ADC10/TOUCH0 of ESP32 -#define PIN_D5 5 // Pin D5 mapped to pin GPIO5/SPISS/VSPI_SS of ESP32 -#define PIN_D6 6 // Pin D6 mapped to pin GPIO6 of ESP32 -#define PIN_D7 7 // Pin D7 mapped to pin GPIO7 of ESP32 -#define PIN_D8 8 // Pin D8 mapped to pin GPIO8 of ESP32 -#define PIN_D9 9 // Pin D9 mapped to pin GPIO9 of ESP32 -#define PIN_D10 10 // Pin D10 mapped to pin GPIO10 of ESP32 -#define PIN_D11 11 // Pin D11 mapped to pin GPIO11 of ESP32 -#define PIN_D12 12 // Pin D12 mapped to pin GPIO12/HSPI_MISO/ADC15/TOUCH5/TDI of ESP32 -#define PIN_D13 13 // Pin D13 mapped to pin GPIO13/HSPI_MOSI/ADC14/TOUCH4/TCK of ESP32 -#define PIN_D14 14 // Pin D14 mapped to pin GPIO14/HSPI_SCK/ADC16/TOUCH6/TMS of ESP32 -#define PIN_D15 15 // Pin D15 mapped to pin GPIO15/HSPI_SS/ADC13/TOUCH3/TDO of ESP32 -#define PIN_D16 16 // Pin D16 mapped to pin GPIO16/TX2 of ESP32 -#define PIN_D17 17 // Pin D17 mapped to pin GPIO17/RX2 of ESP32 -#define PIN_D18 18 // Pin D18 mapped to pin GPIO18/VSPI_SCK of ESP32 -#define PIN_D19 19 // Pin D19 mapped to pin GPIO19/VSPI_MISO of ESP32 - -#define PIN_D21 21 // Pin D21 mapped to pin GPIO21/SDA of ESP32 -#define PIN_D22 22 // Pin D22 mapped to pin GPIO22/SCL of ESP32 -#define PIN_D23 23 // Pin D23 mapped to pin GPIO23/VSPI_MOSI of ESP32 -#define PIN_D24 24 // Pin D24 mapped to pin GPIO24 of ESP32 -#define PIN_D25 25 // Pin D25 mapped to pin GPIO25/ADC18/DAC1 of ESP32 -#define PIN_D26 26 // Pin D26 mapped to pin GPIO26/ADC19/DAC2 of ESP32 -#define PIN_D27 27 // Pin D27 mapped to pin GPIO27/ADC17/TOUCH7 of ESP32 - -typedef void (*irqCallback) (); - -////////////////////////////////////////////////////// - -#define USING_PWM_FREQUENCY false //true - -////////////////////////////////////////////////////// - -volatile unsigned long deltaMicrosStart [] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; -volatile unsigned long previousMicrosStart [] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - -volatile unsigned long deltaMicrosStop [] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; -volatile unsigned long previousMicrosStop [] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - -// You can assign pins here. Be carefull to select good pin to use or crash, e.g pin 6-11 -// Can't use PIN_D1 for core v2.0.1+ - -#if ( ARDUINO_ESP32C3_DEV ) -uint32_t PWM_Pin[] = -// Bad pins to use: PIN_D12-PIN_D24 -{ - LED_BUILTIN, PIN_D3, PIN_D4, PIN_D5 -}; -#elif ( ARDUINO_ESP32S3_DEV ) -uint32_t PWM_Pin[] = -// Bad pins to use: PIN_D24 -{ - PIN_D1, PIN_D2, PIN_D3, PIN_D4, PIN_D5, PIN_D6, PIN_D7, PIN_D8, - PIN_D9, PIN_D10, PIN_D11, PIN_D12, PIN_D13, PIN_D14, PIN_D15, PIN_D16, -}; -#else -uint32_t PWM_Pin[] = -{ - PIN_D24, LED_BUILTIN, PIN_D3, PIN_D4, PIN_D5, PIN_D12, PIN_D13, PIN_D14, - PIN_D15, PIN_D16, PIN_D17, PIN_D18, PIN_D19, PIN_D21, PIN_D22, PIN_D23 -}; -#endif - -// You can assign any interval for any timer here, in microseconds -uint32_t PWM_Period[] = -{ - 1000000, 500000, 333333, 250000, 200000, 166667, 142857, 125000, - 111111, 100000, 66667, 50000, 40000, 33333, 25000, 20000 -}; - -// You can assign any interval for any timer here, in Hz -float PWM_Freq[] = -{ - 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, - 9.0f, 10.0f, 15.0f, 20.0f, 25.0f, 30.0f, 40.0f, 50.0f -}; - -// You can assign any interval for any timer here, in milliseconds -float PWM_DutyCycle[] = -{ - 5.00, 10.00, 20.00, 30.00, 40.00, 45.00, 50.00, 55.00, - 60.00, 65.00, 70.00, 75.00, 80.00, 85.00, 90.00, 95.00 -}; - -void doingSomethingStart(int index) -{ - unsigned long currentMicros = micros(); - - deltaMicrosStart[index] = currentMicros - previousMicrosStart[index]; - previousMicrosStart[index] = currentMicros; -} - -void doingSomethingStop(int index) -{ - unsigned long currentMicros = micros(); - - // Count from start to stop PWM pulse - deltaMicrosStop[index] = currentMicros - previousMicrosStart[index]; - previousMicrosStop[index] = currentMicros; -} - -//////////////////////////////////// -// Shared -//////////////////////////////////// - -void doingSomethingStart0() -{ - doingSomethingStart(0); -} - -void doingSomethingStart1() -{ - doingSomethingStart(1); -} - -void doingSomethingStart2() -{ - doingSomethingStart(2); -} - -void doingSomethingStart3() -{ - doingSomethingStart(3); -} - -void doingSomethingStart4() -{ - doingSomethingStart(4); -} - -void doingSomethingStart5() -{ - doingSomethingStart(5); -} - -void doingSomethingStart6() -{ - doingSomethingStart(6); -} - -void doingSomethingStart7() -{ - doingSomethingStart(7); -} - -void doingSomethingStart8() -{ - doingSomethingStart(8); -} - -void doingSomethingStart9() -{ - doingSomethingStart(9); -} - -void doingSomethingStart10() -{ - doingSomethingStart(10); -} - -void doingSomethingStart11() -{ - doingSomethingStart(11); -} - -void doingSomethingStart12() -{ - doingSomethingStart(12); -} - -void doingSomethingStart13() -{ - doingSomethingStart(13); -} - -void doingSomethingStart14() -{ - doingSomethingStart(14); -} - -void doingSomethingStart15() -{ - doingSomethingStart(15); -} - -////////////////////////////////////////////////////// - -void doingSomethingStop0() -{ - doingSomethingStop(0); -} - -void doingSomethingStop1() -{ - doingSomethingStop(1); -} - -void doingSomethingStop2() -{ - doingSomethingStop(2); -} - -void doingSomethingStop3() -{ - doingSomethingStop(3); -} - -void doingSomethingStop4() -{ - doingSomethingStop(4); -} - -void doingSomethingStop5() -{ - doingSomethingStop(5); -} - -void doingSomethingStop6() -{ - doingSomethingStop(6); -} - -void doingSomethingStop7() -{ - doingSomethingStop(7); -} - -void doingSomethingStop8() -{ - doingSomethingStop(8); -} - -void doingSomethingStop9() -{ - doingSomethingStop(9); -} - -void doingSomethingStop10() -{ - doingSomethingStop(10); -} - -void doingSomethingStop11() -{ - doingSomethingStop(11); -} - -void doingSomethingStop12() -{ - doingSomethingStop(12); -} - -void doingSomethingStop13() -{ - doingSomethingStop(13); -} - -void doingSomethingStop14() -{ - doingSomethingStop(14); -} - -void doingSomethingStop15() -{ - doingSomethingStop(15); -} - -////////////////////////////////////////////////////// - -irqCallback irqCallbackStartFunc[] = -{ - doingSomethingStart0, doingSomethingStart1, doingSomethingStart2, doingSomethingStart3, - doingSomethingStart4, doingSomethingStart5, doingSomethingStart6, doingSomethingStart7, - doingSomethingStart8, doingSomethingStart9, doingSomethingStart10, doingSomethingStart11, - doingSomethingStart12, doingSomethingStart13, doingSomethingStart14, doingSomethingStart15 -}; - -irqCallback irqCallbackStopFunc[] = -{ - doingSomethingStop0, doingSomethingStop1, doingSomethingStop2, doingSomethingStop3, - doingSomethingStop4, doingSomethingStop5, doingSomethingStop6, doingSomethingStop7, - doingSomethingStop8, doingSomethingStop9, doingSomethingStop10, doingSomethingStop11, - doingSomethingStop12, doingSomethingStop13, doingSomethingStop14, doingSomethingStop15 -}; - -////////////////////////////////////////////////////// - -#define SIMPLE_TIMER_MS 2000L - -// Init SimpleTimer -SimpleTimer simpleTimer; - -// Here is software Timer, you can do somewhat fancy stuffs without many issues. -// But always avoid -// 1. Long delay() it just doing nothing and pain-without-gain wasting CPU power.Plan and design your code / strategy ahead -// 2. Very long "do", "while", "for" loops without predetermined exit time. -void simpleTimerDoingSomething2s() -{ - static unsigned long previousMicrosStart = startMicros; - - unsigned long currMicros = micros(); - - Serial.print(F("SimpleTimer (ms): ")); Serial.print(SIMPLE_TIMER_MS); - Serial.print(F(", us : ")); Serial.print(currMicros); - Serial.print(F(", Dus : ")); Serial.println(currMicros - previousMicrosStart); - - for (uint16_t i = 0; i < NUMBER_ISR_PWMS; i++) - { - Serial.print(F("PWM Channel : ")); Serial.print(i); - - #if USING_PWM_FREQUENCY - Serial.print(1000000 / PWM_Freq[i]); - #else - Serial.print(PWM_Period[i]); - #endif - - Serial.print(F(", programmed Period (us): ")); Serial.print(PWM_Period[i]); - Serial.print(F(", actual : ")); Serial.print(deltaMicrosStart[i]); - - Serial.print(F(", programmed DutyCycle : ")); - - Serial.print(PWM_DutyCycle[i]); - - Serial.print(F(", actual : ")); Serial.println( (float) deltaMicrosStop[i] * 100.0f / deltaMicrosStart[i]); - } - - previousMicrosStart = currMicros; -} - -void setup() -{ - Serial.begin(115200); - while (!Serial); - - delay(2000); - - Serial.print(F("\nStarting ISR_16_PWMs_Array_Complex on ")); Serial.println(ARDUINO_BOARD); - Serial.println(ESP32_PWM_VERSION); - Serial.print(F("CPU Frequency = ")); Serial.print(F_CPU / 1000000); Serial.println(F(" MHz")); - - // Interval in microsecs - if (ITimer.attachInterruptInterval(HW_TIMER_INTERVAL_US, TimerHandler)) - { - startMicros = micros(); - Serial.print(F("Starting ITimer OK, micros() = ")); Serial.println(startMicros); - } - else - Serial.println(F("Can't set ITimer. Select another freq. or timer")); - - startMicros = micros(); - - // Just to demonstrate, don't use too many ISR Timers if not absolutely necessary - // You can use up to 16 timer for each ISR_PWM - for (uint16_t i = 0; i < NUMBER_ISR_PWMS; i++) - { - previousMicrosStart[i] = micros(); - - #if USING_PWM_FREQUENCY - // You can use this with PWM_Freq in Hz - ISR_PWM.setPWM(PWM_Pin[i], PWM_Freq[i], PWM_DutyCycle[i], irqCallbackStartFunc[i], irqCallbackStopFunc[i]); - #else - // Or You can use this with PWM_Period in us - ISR_PWM.setPWM_Period(PWM_Pin[i], PWM_Period[i], PWM_DutyCycle[i], irqCallbackStartFunc[i], irqCallbackStopFunc[i]); - #endif - } - - // You need this timer for non-critical tasks. Avoid abusing ISR if not absolutely necessary. - simpleTimer.setInterval(SIMPLE_TIMER_MS, simpleTimerDoingSomething2s); -} - -#define BLOCKING_TIME_MS 10000L - -void loop() -{ - // This unadvised blocking task is used to demonstrate the blocking effects onto the execution and accuracy to Software timer - // You see the time elapse of ISR_PWM still accurate, whereas very unaccurate for Software Timer - // The time elapse for 2000ms software timer now becomes 3000ms (BLOCKING_TIME_MS) - // While that of ISR_PWM is still prefect. - delay(BLOCKING_TIME_MS); - - // You need this Software timer for non-critical tasks. Avoid abusing ISR if not absolutely necessary - // You don't need to and never call ISR_PWM.run() here in the loop(). It's already handled by ISR timer. - simpleTimer.run(); -} -``` --- --- @@ -753,7 +309,7 @@ The following is the sample terminal output when running example [ISR_16_PWMs_Ar ``` Starting ISR_16_PWMs_Array_Complex on ESP32_DEV -ESP32_PWM v1.3.0 +ESP32_PWM v1.3.1 CPU Frequency = 240 MHz [PWM] ESP32_TimerInterrupt: _timerNo = 1 , _fre = 1000000 [PWM] TIMER_BASE_CLK = 80000000 , TIMER_DIVIDER = 80 @@ -821,7 +377,7 @@ The following is the sample terminal output when running example [ISR_16_PWMs_Ar ``` Starting ISR_16_PWMs_Array on ESP32_DEV -ESP32_PWM v1.3.0 +ESP32_PWM v1.3.1 CPU Frequency = 240 MHz [PWM] ESP32_TimerInterrupt: _timerNo = 1 , _fre = 1000000 [PWM] TIMER_BASE_CLK = 80000000 , TIMER_DIVIDER = 80 @@ -856,7 +412,7 @@ The following is the sample terminal output when running example [ISR_16_PWMs_Ar ``` Starting ISR_16_PWMs_Array_Simple on ESP32_DEV -ESP32_PWM v1.3.0 +ESP32_PWM v1.3.1 CPU Frequency = 240 MHz [PWM] ESP32_TimerInterrupt: _timerNo = 1 , _fre = 1000000 [PWM] TIMER_BASE_CLK = 80000000 , TIMER_DIVIDER = 80 @@ -890,19 +446,32 @@ The following is the sample terminal output when running example [ISR_Modify_PWM ``` Starting ISR_Modify_PWM on ESP32_DEV -ESP32_PWM v1.3.0 +ESP32_PWM v1.3.1 CPU Frequency = 240 MHz [PWM] ESP32_TimerInterrupt: _timerNo = 1 , _fre = 1000000 [PWM] TIMER_BASE_CLK = 80000000 , TIMER_DIVIDER = 80 [PWM] _timerIndex = 1 , _timerGroup = 0 [PWM] _count = 0 - 20 [PWM] timer_set_alarm_value = 20.00 -Starting ITimer OK, micros() = 2058747 -Using PWM Freq = 1.00, PWM DutyCycle = 10.00 -Channel : 0 Period : 1000000 OnTime : 100000 Start_Time : 2059403 -Channel : 0 New Period : 500000 OnTime : 450000 Start_Time : 12059493 -Channel : 0 New Period : 1000000 OnTime : 100000 Start_Time : 22059493 -Channel : 0 New Period : 500000 OnTime : 450000 Start_Time : 31559494 +Starting ITimer OK, micros() = 2059642 +Using PWM Freq = 200.00, PWM DutyCycle = 1.00 +Channel : 0 Period : 5000 OnTime : 50 Start_Time : 2060337 +Channel : 0 Period : 10000 OnTime : 555 Start_Time : 12071208 +Channel : 0 Period : 5000 OnTime : 50 Start_Time : 22066228 +Channel : 0 Period : 10000 OnTime : 555 Start_Time : 32071347 +Channel : 0 Period : 5000 OnTime : 50 Start_Time : 42066348 +Channel : 0 Period : 10000 OnTime : 555 Start_Time : 52072208 +Channel : 0 Period : 5000 OnTime : 50 Start_Time : 62077247 +Channel : 0 Period : 10000 OnTime : 555 Start_Time : 72078208 +Channel : 0 Period : 5000 OnTime : 50 Start_Time : 82078228 +Channel : 0 Period : 10000 OnTime : 555 Start_Time : 92078347 +Channel : 0 Period : 5000 OnTime : 50 Start_Time : 102073347 +Channel : 0 Period : 10000 OnTime : 555 Start_Time : 112079208 +Channel : 0 Period : 5000 OnTime : 50 Start_Time : 122074208 +Channel : 0 Period : 10000 OnTime : 555 Start_Time : 132079347 +Channel : 0 Period : 5000 OnTime : 50 Start_Time : 142084368 +Channel : 0 Period : 10000 OnTime : 555 Start_Time : 152085208 +Channel : 0 Period : 5000 OnTime : 50 Start_Time : 162080208 ``` --- @@ -913,7 +482,7 @@ The following is the sample terminal output when running example [ISR_Changing_P ``` Starting ISR_Changing_PWM on ESP32_DEV -ESP32_PWM v1.3.0 +ESP32_PWM v1.3.1 CPU Frequency = 240 MHz [PWM] ESP32_TimerInterrupt: _timerNo = 1 , _fre = 1000000 [PWM] TIMER_BASE_CLK = 80000000 , TIMER_DIVIDER = 80 @@ -947,19 +516,32 @@ The following is the sample terminal output when running example [ISR_Modify_PWM ``` Starting ISR_Modify_PWM on ESP32S2_DEV -ESP32_PWM v1.3.0 +ESP32_PWM v1.3.1 CPU Frequency = 240 MHz [PWM] ESP32_S2_TimerInterrupt: _timerNo = 1 , _fre = 1000000 [PWM] TIMER_BASE_CLK = 80000000 , TIMER_DIVIDER = 80 [PWM] _timerIndex = 1 , _timerGroup = 0 [PWM] _count = 0 - 20 [PWM] timer_set_alarm_value = 20.00 -Starting ITimer OK, micros() = 2554070 -Using PWM Freq = 1.00, PWM DutyCycle = 10.00 -Channel : 0 Period : 1000000 OnTime : 100000 Start_Time : 2564709 -Channel : 0 New Period : 500000 OnTime : 450000 Start_Time : 12564759 -Channel : 0 New Period : 1000000 OnTime : 100000 Start_Time : 22564859 -Channel : 0 New Period : 500000 OnTime : 450000 Start_Time : 32064879 +Starting ITimer OK, micros() = 2059642 +Using PWM Freq = 200.00, PWM DutyCycle = 1.00 +Channel : 0 Period : 5000 OnTime : 50 Start_Time : 2060337 +Channel : 0 Period : 10000 OnTime : 555 Start_Time : 12071208 +Channel : 0 Period : 5000 OnTime : 50 Start_Time : 22066228 +Channel : 0 Period : 10000 OnTime : 555 Start_Time : 32071347 +Channel : 0 Period : 5000 OnTime : 50 Start_Time : 42066348 +Channel : 0 Period : 10000 OnTime : 555 Start_Time : 52072208 +Channel : 0 Period : 5000 OnTime : 50 Start_Time : 62077247 +Channel : 0 Period : 10000 OnTime : 555 Start_Time : 72078208 +Channel : 0 Period : 5000 OnTime : 50 Start_Time : 82078228 +Channel : 0 Period : 10000 OnTime : 555 Start_Time : 92078347 +Channel : 0 Period : 5000 OnTime : 50 Start_Time : 102073347 +Channel : 0 Period : 10000 OnTime : 555 Start_Time : 112079208 +Channel : 0 Period : 5000 OnTime : 50 Start_Time : 122074208 +Channel : 0 Period : 10000 OnTime : 555 Start_Time : 132079347 +Channel : 0 Period : 5000 OnTime : 50 Start_Time : 142084368 +Channel : 0 Period : 10000 OnTime : 555 Start_Time : 152085208 +Channel : 0 Period : 5000 OnTime : 50 Start_Time : 162080208 ``` --- @@ -970,7 +552,7 @@ The following is the sample terminal output when running example [ISR_Changing_P ``` Starting ISR_Changing_PWM on ESP32S2_DEV -ESP32_PWM v1.3.0 +ESP32_PWM v1.3.1 CPU Frequency = 240 MHz [PWM] ESP32_S2_TimerInterrupt: _timerNo = 1 , _fre = 1000000 [PWM] TIMER_BASE_CLK = 80000000 , TIMER_DIVIDER = 80 @@ -996,20 +578,32 @@ The following is the sample terminal output when running example [ISR_Modify_PWM ``` Starting ISR_Modify_PWM on ESP32C3_DEV -ESP32_PWM v1.3.0 +ESP32_PWM v1.3.1 CPU Frequency = 160 MHz [PWM] ESP32_TimerInterrupt: _timerNo = 1 , _fre = 1000000 [PWM] TIMER_BASE_CLK = 80000000 , TIMER_DIVIDER = 80 [PWM] _timerIndex = 0 , _timerGroup = 1 [PWM] _count = 0 - 20 [PWM] timer_set_alarm_value = 20.00 -Starting ITimer OK, micros() = 2100385 -Using PWM Freq = 1.00, PWM DutyCycle = 10.00 -Channel : 0 Period : 1000000 OnTime : 100000 Start_Time : 2113126 -Channel : 0 Period : 500000 OnTime : 450000 Start_Time : 12118037 -Channel : 0 Period : 1000000 OnTime : 100000 Start_Time : 22119020 -Channel : 0 Period : 500000 OnTime : 450000 Start_Time : 32120019 -Channel : 0 Period : 1000000 OnTime : 100000 Start_Time : 42121019 +Starting ITimer OK, micros() = 2059642 +Using PWM Freq = 200.00, PWM DutyCycle = 1.00 +Channel : 0 Period : 5000 OnTime : 50 Start_Time : 2060337 +Channel : 0 Period : 10000 OnTime : 555 Start_Time : 12071208 +Channel : 0 Period : 5000 OnTime : 50 Start_Time : 22066228 +Channel : 0 Period : 10000 OnTime : 555 Start_Time : 32071347 +Channel : 0 Period : 5000 OnTime : 50 Start_Time : 42066348 +Channel : 0 Period : 10000 OnTime : 555 Start_Time : 52072208 +Channel : 0 Period : 5000 OnTime : 50 Start_Time : 62077247 +Channel : 0 Period : 10000 OnTime : 555 Start_Time : 72078208 +Channel : 0 Period : 5000 OnTime : 50 Start_Time : 82078228 +Channel : 0 Period : 10000 OnTime : 555 Start_Time : 92078347 +Channel : 0 Period : 5000 OnTime : 50 Start_Time : 102073347 +Channel : 0 Period : 10000 OnTime : 555 Start_Time : 112079208 +Channel : 0 Period : 5000 OnTime : 50 Start_Time : 122074208 +Channel : 0 Period : 10000 OnTime : 555 Start_Time : 132079347 +Channel : 0 Period : 5000 OnTime : 50 Start_Time : 142084368 +Channel : 0 Period : 10000 OnTime : 555 Start_Time : 152085208 +Channel : 0 Period : 5000 OnTime : 50 Start_Time : 162080208 ``` --- @@ -1020,7 +614,7 @@ The following is the sample terminal output when running example [ISR_Changing_P ``` Starting ISR_Changing_PWM on ESP32C3_DEV -ESP32_PWM v1.3.0 +ESP32_PWM v1.3.1 CPU Frequency = 160 MHz [PWM] ESP32_TimerInterrupt: _timerNo = 1 , _fre = 1000000 [PWM] TIMER_BASE_CLK = 80000000 , TIMER_DIVIDER = 80 @@ -1049,7 +643,7 @@ The following is the sample terminal output when running example [ISR_16_PWMs_Ar ``` Starting ISR_16_PWMs_Array_Complex on ESP32S3_DEV -ESP32_PWM v1.3.0 +ESP32_PWM v1.3.1 CPU Frequency = 240 MHz [PWM] ESP32_S3_TimerInterrupt: _timerNo = 1 , _fre = 1000000 [PWM] TIMER_BASE_CLK = 80000000 , TIMER_DIVIDER = 80 @@ -1179,7 +773,7 @@ Submit issues to: [ESP32_PWM issues](https://github.com/khoih-prog/ESP32_PWM/iss 8. Improve accuracy by using `float`, instead of `uint32_t` for `dutycycle` 9. DutyCycle to be optionally updated at the end current PWM period instead of immediately. 10. Add support to `ESP32-S3` - +11. Display informational warning only when `_PWM_LOGLEVEL_` > 3 --- --- diff --git a/changelog.md b/changelog.md index a4c8427..dceb6e5 100644 --- a/changelog.md +++ b/changelog.md @@ -12,6 +12,7 @@ ## Table of Contents * [Changelog](#changelog) + * [Releases v1.3.1](#releases-v131) * [Releases v1.3.0](#releases-v130) * [Releases v1.2.2](#releases-v122) * [Releases v1.2.1](#releases-v121) @@ -26,6 +27,12 @@ ## Changelog +### Releases v1.3.1 + +1. Fix `DutyCycle` bug. Check [float precisison of DutyCycle only sometimes working #3](https://github.com/khoih-prog/SAMD_Slow_PWM/issues/3) +2. Fix `New Period` display bug. Check [random dropouts #4](https://github.com/khoih-prog/SAMD_Slow_PWM/issues/4) +3. Update examples + ### Releases v1.3.0 1. Add support to new `ESP32-S3` (ESP32S3_DEV, ESP32_S3_BOX, UM TINYS3, UM PROS3, UM FEATHERS3, etc.) diff --git a/library.json b/library.json index 216d0f9..ddd9888 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "ESP32_PWM", - "version": "1.3.0", + "version": "1.3.1", "keywords": "timing, device, control, pwm, timer, interrupt, hardware, isr, isr-based, hardware-timer, isr-timer, isr-based-timer, mission-critical, accuracy, precise, non-blocking, esp32, esp32-s2, esp32-c3, esp32-s3, synchronized-PWM, on-the-fly", "description": "This library enables you to use Interrupt from Hardware Timers on an ESP32, ESP32_S2, ESP32_S3 or ESP32_C3-based board to create and output PWM to pins. It now supports 16 ISR-based synchronized PWM channels, while consuming only 1 Hardware Timer. PWM interval can be very long (uint32_t millisecs). The most important feature is they're ISR-based PWM channels. Therefore, their executions are not blocked by bad-behaving functions or tasks. This important feature is absolutely necessary for mission-critical tasks. These hardware PWM channels, 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. Now you can change the PWM settings on-the-fly", "authors": diff --git a/library.properties b/library.properties index 476120a..af2e0bf 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=ESP32_PWM -version=1.3.0 +version=1.3.1 author=Khoi Hoang maintainer=Khoi Hoang sentence=This library enables you to use Interrupt from Hardware Timers on an ESP32, ESP32_S2, ESP32_S3 or ESP32_C3-based board to create and output PWM to pins. diff --git a/src/ESP32_PWM.h b/src/ESP32_PWM.h index e3cb967..ea7a469 100644 --- a/src/ESP32_PWM.h +++ b/src/ESP32_PWM.h @@ -22,7 +22,7 @@ Therefore, their executions are not blocked by bad-behaving functions / tasks. This important feature is absolutely necessary for mission-critical tasks. - Version: 1.3.0 + Version: 1.3.1 Version Modified By Date Comments ------- ----------- ---------- ----------- @@ -34,6 +34,7 @@ 1.2.1 K Hoang 30/01/2022 DutyCycle to be updated at the end current PWM period 1.2.2 K Hoang 01/02/2022 Use float for DutyCycle and Freq, uint32_t for period. Optimize code 1.3.0 K Hoang 12/02/2022 Add support to new ESP32-S3 + 1.3.1 K Hoang 04/03/2022 Fix `DutyCycle` and `New Period` display bugs. Display warning only when debug level > 3 *****************************************************************************************************************************/ #pragma once diff --git a/src/ESP32_PWM.hpp b/src/ESP32_PWM.hpp index cccc72e..9bebaf6 100644 --- a/src/ESP32_PWM.hpp +++ b/src/ESP32_PWM.hpp @@ -22,7 +22,7 @@ Therefore, their executions are not blocked by bad-behaving functions / tasks. This important feature is absolutely necessary for mission-critical tasks. - Version: 1.3.0 + Version: 1.3.1 Version Modified By Date Comments ------- ----------- ---------- ----------- @@ -34,6 +34,7 @@ 1.2.1 K Hoang 30/01/2022 DutyCycle to be updated at the end current PWM period 1.2.2 K Hoang 01/02/2022 Use float for DutyCycle and Freq, uint32_t for period. Optimize code 1.3.0 K Hoang 12/02/2022 Add support to new ESP32-S3 + 1.3.1 K Hoang 04/03/2022 Fix `DutyCycle` and `New Period` display bugs. Display warning only when debug level > 3 *****************************************************************************************************************************/ #pragma once @@ -69,13 +70,13 @@ #endif #ifndef ESP32_PWM_VERSION - #define ESP32_PWM_VERSION "ESP32_PWM v1.3.0" + #define ESP32_PWM_VERSION "ESP32_PWM v1.3.1" #define ESP32_PWM_VERSION_MAJOR 1 #define ESP32_PWM_VERSION_MINOR 3 - #define ESP32_PWM_VERSION_PATCH 0 + #define ESP32_PWM_VERSION_PATCH 1 - #define ESP32_PWM_VERSION_INT 1003000 + #define ESP32_PWM_VERSION_INT 1003001 #endif #ifndef TIMER_INTERRUPT_DEBUG diff --git a/src/ESP32_PWM_ISR.h b/src/ESP32_PWM_ISR.h index edaa797..886680c 100644 --- a/src/ESP32_PWM_ISR.h +++ b/src/ESP32_PWM_ISR.h @@ -21,7 +21,7 @@ Therefore, their executions are not blocked by bad-behaving functions / tasks. This important feature is absolutely necessary for mission-critical tasks. - Version: 1.3.0 + Version: 1.3.1 Version Modified By Date Comments ------- ----------- ---------- ----------- @@ -33,6 +33,7 @@ 1.2.1 K Hoang 30/01/2022 DutyCycle to be updated at the end current PWM period 1.2.2 K Hoang 01/02/2022 Use float for DutyCycle and Freq, uint32_t for period. Optimize code 1.3.0 K Hoang 12/02/2022 Add support to new ESP32-S3 + 1.3.1 K Hoang 04/03/2022 Fix `DutyCycle` and `New Period` display bugs. Display warning only when debug level > 3 *****************************************************************************************************************************/ #pragma once diff --git a/src/ESP32_PWM_ISR.hpp b/src/ESP32_PWM_ISR.hpp index 0220dce..138c237 100644 --- a/src/ESP32_PWM_ISR.hpp +++ b/src/ESP32_PWM_ISR.hpp @@ -21,7 +21,7 @@ Therefore, their executions are not blocked by bad-behaving functions / tasks. This important feature is absolutely necessary for mission-critical tasks. - Version: 1.3.0 + Version: 1.3.1 Version Modified By Date Comments ------- ----------- ---------- ----------- @@ -33,6 +33,7 @@ 1.2.1 K Hoang 30/01/2022 DutyCycle to be updated at the end current PWM period 1.2.2 K Hoang 01/02/2022 Use float for DutyCycle and Freq, uint32_t for period. Optimize code 1.3.0 K Hoang 12/02/2022 Add support to new ESP32-S3 + 1.3.1 K Hoang 04/03/2022 Fix `DutyCycle` and `New Period` display bugs. Display warning only when debug level > 3 *****************************************************************************************************************************/ #pragma once @@ -53,13 +54,13 @@ #endif #ifndef ESP32_PWM_VERSION - #define ESP32_PWM_VERSION "ESP32_PWM v1.3.0" + #define ESP32_PWM_VERSION "ESP32_PWM v1.3.1" #define ESP32_PWM_VERSION_MAJOR 1 #define ESP32_PWM_VERSION_MINOR 3 - #define ESP32_PWM_VERSION_PATCH 0 + #define ESP32_PWM_VERSION_PATCH 1 - #define ESP32_PWM_VERSION_INT 1003000 + #define ESP32_PWM_VERSION_INT 1003001 #endif #ifndef _PWM_LOGLEVEL_ @@ -89,12 +90,19 @@ typedef void (*timer_callback)(); typedef void (*timer_callback_p)(void *); #if !defined(USING_MICROS_RESOLUTION) - #warning Not USING_MICROS_RESOLUTION, using millis resolution + + #if (_PWM_LOGLEVEL_ > 3) + #warning Not USING_MICROS_RESOLUTION, using millis resolution + #endif + #define USING_MICROS_RESOLUTION false #endif #if !defined(CHANGING_PWM_END_OF_CYCLE) - #warning Using default CHANGING_PWM_END_OF_CYCLE == true + #if (_PWM_LOGLEVEL_ > 3) + #warning Using default CHANGING_PWM_END_OF_CYCLE == true + #endif + #define CHANGING_PWM_END_OF_CYCLE true #endif diff --git a/src/ESP32_PWM_ISR_Impl.h b/src/ESP32_PWM_ISR_Impl.h index c6d6aa0..1f186d0 100644 --- a/src/ESP32_PWM_ISR_Impl.h +++ b/src/ESP32_PWM_ISR_Impl.h @@ -21,7 +21,7 @@ Therefore, their executions are not blocked by bad-behaving functions / tasks. This important feature is absolutely necessary for mission-critical tasks. - Version: 1.3.0 + Version: 1.3.1 Version Modified By Date Comments ------- ----------- ---------- ----------- @@ -33,6 +33,7 @@ 1.2.1 K Hoang 30/01/2022 DutyCycle to be updated at the end current PWM period 1.2.2 K Hoang 01/02/2022 Use float for DutyCycle and Freq, uint32_t for period. Optimize code 1.3.0 K Hoang 12/02/2022 Add support to new ESP32-S3 + 1.3.1 K Hoang 04/03/2022 Fix `DutyCycle` and `New Period` display bugs. Display warning only when debug level > 3 *****************************************************************************************************************************/ #pragma once @@ -221,10 +222,10 @@ int ESP32_PWM_ISR::setupPWMChannel(const uint32_t& pin, const uint32_t& period, // ESP32 is a multi core / multi processing chip. It is mandatory to disable task switches during modifying shared vars portEXIT_CRITICAL(&PWM_Mux); - PWM_LOGDEBUG0("Channel : "); PWM_LOGDEBUG0(channelNum); - PWM_LOGDEBUG0("\t Period : "); PWM_LOGDEBUG0(PWM[channelNum].period); - PWM_LOGDEBUG0("\t\tOnTime : "); PWM_LOGDEBUG0(PWM[channelNum].onTime); - PWM_LOGDEBUG0("\tStart_Time : "); PWM_LOGDEBUGLN0(PWM[channelNum].prevTime); + PWM_LOGINFO0("Channel : "); PWM_LOGINFO0(channelNum); + PWM_LOGINFO0("\t Period : "); PWM_LOGINFO0(PWM[channelNum].period); + PWM_LOGINFO0("\t\tOnTime : "); PWM_LOGINFO0(PWM[channelNum].onTime); + PWM_LOGINFO0("\tStart_Time : "); PWM_LOGINFOLN0(PWM[channelNum].prevTime); numChannels++; @@ -268,10 +269,10 @@ bool ESP32_PWM_ISR::modifyPWMChannel_Period(const uint8_t& channelNum, const uin // ESP32 is a multi core / multi processing chip. It is mandatory to disable task switches during modifying shared vars portEXIT_CRITICAL(&PWM_Mux); - PWM_LOGDEBUG0("Channel : "); PWM_LOGDEBUG0(channelNum); - PWM_LOGDEBUG0("\tNew Period : "); PWM_LOGDEBUG0(PWM[channelNum].newPeriod); - PWM_LOGDEBUG0("\t\tOnTime : "); PWM_LOGDEBUG0(PWM[channelNum].newOnTime); - PWM_LOGDEBUG0("\tStart_Time : "); PWM_LOGDEBUGLN0(PWM[channelNum].prevTime); + PWM_LOGINFO0("Channel : "); PWM_LOGINFO0(channelNum); + PWM_LOGINFO0("\t Period : "); PWM_LOGINFO0(period); + PWM_LOGINFO0("\t\tOnTime : "); PWM_LOGINFO0(PWM[channelNum].newOnTime); + PWM_LOGINFO0("\tStart_Time : "); PWM_LOGINFOLN0(PWM[channelNum].prevTime); #else @@ -286,10 +287,10 @@ bool ESP32_PWM_ISR::modifyPWMChannel_Period(const uint8_t& channelNum, const uin // ESP32 is a multi core / multi processing chip. It is mandatory to disable task switches during modifying shared vars portEXIT_CRITICAL(&PWM_Mux); - PWM_LOGDEBUG0("Channel : "); PWM_LOGDEBUG0(channelNum); - PWM_LOGDEBUG0("\t Period : "); PWM_LOGDEBUG0(PWM[channelNum].period); - PWM_LOGDEBUG0("\t\tOnTime : "); PWM_LOGDEBUG0(PWM[channelNum].onTime); - PWM_LOGDEBUG0("\tStart_Time : "); PWM_LOGDEBUGLN0(PWM[channelNum].prevTime); + PWM_LOGINFO0("Channel : "); PWM_LOGINFO0(channelNum); + PWM_LOGINFO0("\t Period : "); PWM_LOGINFO0(PWM[channelNum].period); + PWM_LOGINFO0("\t\tOnTime : "); PWM_LOGINFO0(PWM[channelNum].onTime); + PWM_LOGINFO0("\tStart_Time : "); PWM_LOGINFOLN0(PWM[channelNum].prevTime); #endif diff --git a/src/PWM_Generic_Debug.h b/src/PWM_Generic_Debug.h index df1828f..b43be49 100644 --- a/src/PWM_Generic_Debug.h +++ b/src/PWM_Generic_Debug.h @@ -21,7 +21,7 @@ Therefore, their executions are not blocked by bad-behaving functions / tasks. This important feature is absolutely necessary for mission-critical tasks. - Version: 1.3.0 + Version: 1.3.1 Version Modified By Date Comments ------- ----------- ---------- ----------- @@ -33,6 +33,7 @@ 1.2.1 K Hoang 30/01/2022 DutyCycle to be updated at the end current PWM period 1.2.2 K Hoang 01/02/2022 Use float for DutyCycle and Freq, uint32_t for period. Optimize code 1.3.0 K Hoang 12/02/2022 Add support to new ESP32-S3 + 1.3.1 K Hoang 04/03/2022 Fix `DutyCycle` and `New Period` display bugs. Display warning only when debug level > 3 *****************************************************************************************************************************/ #pragma once