diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4712370..dd526c9 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -29,7 +29,7 @@ Please ensure to specify the following: Arduino IDE version: 1.8.19 Teensyduino Core Version 1.56 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 trying to use the Timer Interrupt. diff --git a/README.md b/README.md index e462edc..361da58 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/Teensy_Slow_PWM.svg)](http://github.com/khoih-prog/Teensy_Slow_PWM/issues) -Buy Me A Coffee +Donate to my libraries using BuyMeACoffee + --- @@ -196,7 +197,7 @@ Another way to install is to: 1. Install [VS Code](https://code.visualstudio.com/) 2. Install [PlatformIO](https://platformio.org/platformio-ide) -3. Install [**Teensy_Slow_PWM** library](https://platformio.org/lib/show/12888/Teensy_Slow_PWM) by using [Library Manager](https://platformio.org/lib/show/12888/Teensy_Slow_PWM/installation). Search for **Teensy_Slow_PWM** in [Platform.io Author's Libraries](https://platformio.org/lib/search?query=author:%22Khoi%20Hoang%22) +3. Install [**Teensy_Slow_PWM** library](https://registry.platformio.org/libraries/khoih-prog/Teensy_Slow_PWM) by using [Library Manager](https://registry.platformio.org/libraries/khoih-prog/Teensy_Slow_PWM/installation). Search for **Teensy_Slow_PWM** in [Platform.io Author's Libraries](https://platformio.org/lib/search?query=author:%22Khoi%20Hoang%22) 4. Use included [platformio.ini](platformio/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](https://docs.platformio.org/page/projectconf.html) @@ -314,459 +315,9 @@ void setup() ### Example [ISR_8_PWMs_Array_Complex](examples/ISR_8_PWMs_Array_Complex) -``` -#if !( defined(CORE_TEENSY) || defined(TEENSYDUINO) ) - #error This code is designed to run on Teensy platform! Please check your Tools->Board setting. -#endif - -// 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_ 3 - -#define USING_MICROS_RESOLUTION true //false - -// To be included only in main(), .ino with setup() to avoid `Multiple Definitions` Linker Error -#include "Teensy_Slow_PWM.h" - -#include // https://github.com/jfturcot/SimpleTimer - -#define LED_OFF HIGH -#define LED_ON LOW - -#ifndef LED_BUILTIN - #define LED_BUILTIN 13 -#endif - -#ifndef LED_BLUE - #define LED_BLUE 10 -#endif - -#ifndef LED_RED - #define LED_RED 11 -#endif - -#define USING_HW_TIMER_INTERVAL_MS false //true - -#if defined(__IMXRT1062__) - // For Teensy 4.0 and 4.1 - // Don't change these numbers to make higher Timer freq. System can hang - #define HW_TIMER_INTERVAL_MS 0.01f - #define HW_TIMER_INTERVAL_FREQ 100000L -#elif defined(__MK66FX1M0__) - // For Teensy 3.6 - // Don't change these numbers to make higher Timer freq. System can hang - #define HW_TIMER_INTERVAL_MS 0.05f - #define HW_TIMER_INTERVAL_FREQ 20000L -#else - // Don't change these numbers to make higher Timer freq. System can hang - #define HW_TIMER_INTERVAL_MS 0.1f - #define HW_TIMER_INTERVAL_FREQ 10000L -#endif - -volatile uint32_t startMicros = 0; - -// You can select Teensy Hardware Timer from TEENSY_TIMER_1 or TEENSY_TIMER_3 - -// Init Teensy timer TEENSY_TIMER_1 -TeensyTimer ITimer(TEENSY_TIMER_1); - -// Init Teensy_SLOW_PWM, each can service 16 different ISR-based PWM channels -Teensy_SLOW_PWM ISR_PWM; - -////////////////////////////////////////////////////// - -void TimerHandler() -{ - ISR_PWM.run(); -} - -///////////////////////////////////////////////// - -#define PIN_D0 0 -#define PIN_D1 1 -#define PIN_D2 2 -#define PIN_D3 3 -#define PIN_D4 4 -#define PIN_D5 5 -#define PIN_D6 6 - -// You can assign pins here. Be careful to select good pin to use or crash, e.g pin 6-11 -uint32_t PWM_Pin[] = -{ - LED_BUILTIN, PIN_D0, PIN_D1, PIN_D2, PIN_D3, PIN_D4, PIN_D5, PIN_D6 -}; - -#define NUMBER_ISR_PWMS ( sizeof(PWM_Pin) / sizeof(uint32_t) ) - -typedef void (*irqCallback) (); +https://github.com/khoih-prog/Teensy_Slow_PWM/blob/cdd23d2c5f0594d8453779c754877a98a35d2dcb/examples/ISR_8_PWMs_Array_Complex/ISR_8_PWMs_Array_Complex.ino#L16-L469 -////////////////////////////////////////////////////// -#define USE_COMPLEX_STRUCT true - -////////////////////////////////////////////////////// - -#if USE_COMPLEX_STRUCT - -typedef struct -{ - uint32_t PWM_Pin; - irqCallback irqCallbackStartFunc; - irqCallback irqCallbackStopFunc; - - float PWM_Freq; - - float PWM_DutyCycle; - - uint32_t deltaMicrosStart; - uint32_t previousMicrosStart; - - uint32_t deltaMicrosStop; - uint32_t previousMicrosStop; - -} ISR_PWM_Data; - -// In nRF52, avoid doing something fancy in ISR, for example Serial.print() -// The pure simple Serial.prints here are just for demonstration and testing. Must be eliminate in working environment -// Or you can get this run-time error / crash - -void doingSomethingStart(int index); - -void doingSomethingStop(int index); - -#else // #if USE_COMPLEX_STRUCT - -volatile unsigned long deltaMicrosStart [] = { 0, 0, 0, 0, 0, 0, 0, 0 }; -volatile unsigned long previousMicrosStart [] = { 0, 0, 0, 0, 0, 0, 0, 0 }; - -volatile unsigned long deltaMicrosStop [] = { 0, 0, 0, 0, 0, 0, 0, 0 }; -volatile unsigned long previousMicrosStop [] = { 0, 0, 0, 0, 0, 0, 0, 0 }; - - -// You can assign any interval for any timer here, in Microseconds -uint32_t PWM_Period[] = -{ - 1000L, 500L, 333L, 250L, 200L, 166L, 142L, 125L -}; - -// You can assign any interval for any timer here, in Hz -// 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, -}; - -// You can assign any interval for any timer here, in Microseconds -float PWM_DutyCycle[] = -{ - 5.0, 10.0, 20.0, 30.0, 40.0, 45.0, 50.0, 55.0 -}; - -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; -} - -#endif // #if USE_COMPLEX_STRUCT - -//////////////////////////////////// -// 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 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); -} - - -////////////////////////////////////////////////////// - -#if USE_COMPLEX_STRUCT - -ISR_PWM_Data curISR_PWM_Data[] = -{ - // pin, irqCallbackStartFunc, irqCallbackStopFunc, PWM_Freq, PWM_DutyCycle, deltaMicrosStart, previousMicrosStart, deltaMicrosStop, previousMicrosStop - { LED_BUILTIN, doingSomethingStart0, doingSomethingStop0, 1, 5, 0, 0, 0, 0 }, - { PIN_D0, doingSomethingStart1, doingSomethingStop1, 2, 10, 0, 0, 0, 0 }, - { PIN_D1, doingSomethingStart2, doingSomethingStop2, 3, 20, 0, 0, 0, 0 }, - { PIN_D2, doingSomethingStart3, doingSomethingStop3, 4, 30, 0, 0, 0, 0 }, - { PIN_D3, doingSomethingStart4, doingSomethingStop4, 5, 40, 0, 0, 0, 0 }, - { PIN_D4, doingSomethingStart5, doingSomethingStop5, 6, 45, 0, 0, 0, 0 }, - { PIN_D5, doingSomethingStart6, doingSomethingStop6, 7, 50, 0, 0, 0, 0 }, - { PIN_D6, doingSomethingStart7, doingSomethingStop7, 8, 55, 0, 0, 0, 0 }, -}; - - -void doingSomethingStart(int index) -{ - unsigned long currentMicros = micros(); - - curISR_PWM_Data[index].deltaMicrosStart = currentMicros - curISR_PWM_Data[index].previousMicrosStart; - curISR_PWM_Data[index].previousMicrosStart = currentMicros; -} - -void doingSomethingStop(int index) -{ - unsigned long currentMicros = micros(); - - //curISR_PWM_Data[index].deltaMicrosStop = currentMicros - curISR_PWM_Data[index].previousMicrosStop; - // Count from start to stop PWM pulse - curISR_PWM_Data[index].deltaMicrosStop = currentMicros - curISR_PWM_Data[index].previousMicrosStart; - curISR_PWM_Data[index].previousMicrosStop = currentMicros; -} - -#else // #if USE_COMPLEX_STRUCT - -irqCallback irqCallbackStartFunc[] = -{ - doingSomethingStart0, doingSomethingStart1, doingSomethingStart2, doingSomethingStart3, - doingSomethingStart4, doingSomethingStart5, doingSomethingStart6, doingSomethingStart7 -}; - -irqCallback irqCallbackStopFunc[] = -{ - doingSomethingStop0, doingSomethingStop1, doingSomethingStop2, doingSomethingStop3, - doingSomethingStop4, doingSomethingStop5, doingSomethingStop6, doingSomethingStop7 -}; - -#endif // #if USE_COMPLEX_STRUCT - -////////////////////////////////////////////////////// - -#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 (us): ")); 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++) - { -#if USE_COMPLEX_STRUCT - Serial.print(F("PWM Channel : ")); Serial.print(i); - Serial.print(F(", prog Period (ms): ")); - - Serial.print(1000.f / curISR_PWM_Data[i].PWM_Freq); - - Serial.print(F(", actual : ")); Serial.print((uint32_t) curISR_PWM_Data[i].deltaMicrosStart); - - Serial.print(F(", prog DutyCycle : ")); - - Serial.print(curISR_PWM_Data[i].PWM_DutyCycle); - - Serial.print(F(", actual : ")); Serial.println((float) curISR_PWM_Data[i].deltaMicrosStop * 100.0f / curISR_PWM_Data[i].deltaMicrosStart); - //Serial.print(F(", actual deltaMicrosStop : ")); Serial.println(curISR_PWM_Data[i].deltaMicrosStop); - //Serial.print(F(", actual deltaMicrosStart : ")); Serial.println(curISR_PWM_Data[i].deltaMicrosStart); - -#else - - Serial.print(F("PWM Channel : ")); Serial.print(i); - - Serial.print(1000 / PWM_Freq[i]); - - Serial.print(F(", prog. Period (us): ")); Serial.print(PWM_Period[i]); - Serial.print(F(", actual : ")); Serial.print(deltaMicrosStart[i]); - - Serial.print(F(", prog DutyCycle : ")); - - Serial.print(PWM_DutyCycle[i]); - - Serial.print(F(", actual : ")); Serial.println( (float) deltaMicrosStop[i] * 100.0f / deltaMicrosStart[i]); - //Serial.print(F(", actual deltaMicrosStop : ")); Serial.println(deltaMicrosStop[i]); - //Serial.print(F(", actual deltaMicrosStart : ")); Serial.println(deltaMicrosStart[i]); -#endif - } - - previousMicrosStart = currMicros; -} - -void setup() -{ - Serial.begin(115200); - while (!Serial); - - delay(2000); - - Serial.print(F("\nStarting ISR_8_PWMs_Array_Complex on ")); Serial.println(BOARD_NAME); - Serial.println(TEENSY_SLOW_PWM_VERSION); - Serial.print(F("CPU Frequency = ")); Serial.print(F_CPU / 1000000); Serial.println(F(" MHz")); - - // Timer0 is used for micros(), micros(), delay(), etc and can't be used - // Select Timer 1-2 for UNO, 1-5 for MEGA, 1,3,4 for 16u4/32u4 - // Timer 2 is 8-bit timer, only for higher frequency - // Timer 4 of 16u4 and 32u4 is 8/10-bit timer, only for higher frequency - -#if USING_HW_TIMER_INTERVAL_MS - - // Interval in microsecs - if (ITimer.attachInterruptInterval(HW_TIMER_INTERVAL_MS * 1000, TimerHandler)) - { - startMicros = micros(); - Serial.print(F("Starting ITimer OK, micros() = ")); Serial.println(startMicros); - } - else - Serial.println(F("Can't set ITimer correctly. Select another freq. or interval")); - -#else - - if (ITimer.attachInterrupt(HW_TIMER_INTERVAL_FREQ, TimerHandler)) - { - Serial.print(F("Starting ITimer OK, micros() = ")); Serial.println(micros()); - } - else - Serial.println(F("Can't set ITimer. Select another freq. or timer")); - -#endif - - 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++) - { -#if USE_COMPLEX_STRUCT - curISR_PWM_Data[i].previousMicrosStart = startMicros; - //ISR_PWM.setInterval(curISR_PWM_Data[i].PWM_Period, curISR_PWM_Data[i].irqCallbackStartFunc); - - //void setPWM(uint32_t pin, float frequency, float dutycycle - // , timer_callback_p StartCallback = nullptr, timer_callback_p StopCallback = nullptr) - - // You can use this with PWM_Freq in Hz - ISR_PWM.setPWM(curISR_PWM_Data[i].PWM_Pin, curISR_PWM_Data[i].PWM_Freq, curISR_PWM_Data[i].PWM_DutyCycle, - curISR_PWM_Data[i].irqCallbackStartFunc, curISR_PWM_Data[i].irqCallbackStopFunc); - -#else - previousMicrosStart[i] = micros(); - - // 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]); - -#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(); -} -``` --- --- @@ -779,7 +330,7 @@ The following is the sample terminal output when running example [ISR_8_PWMs_Arr ``` Starting ISR_8_PWMs_Array_Complex on Teensy 4.1 -Teensy_Slow_PWM v1.2.0 +Teensy_Slow_PWM v1.2.1 CPU Frequency = 600 MHz [PWM] TEENSY_TIMER_1: , F_BUS_ACTUAL (MHz) = 150 [PWM] Request interval = 10 , actual interval (us) = 10 @@ -839,7 +390,7 @@ The following is the sample terminal output when running example [**ISR_8_PWMs_A ``` Starting ISR_8_PWMs_Array on Teensy 4.1 -Teensy_Slow_PWM v1.2.0 +Teensy_Slow_PWM v1.2.1 CPU Frequency = 600 MHz [PWM] TEENSY_TIMER_1: , F_BUS_ACTUAL (MHz) = 150 [PWM] Request interval = 10 , actual interval (us) = 10 @@ -863,7 +414,7 @@ The following is the sample terminal output when running example [**ISR_8_PWMs_A ``` Starting ISR_8_PWMs_Array_Simple on Teensy 4.1 -Teensy_Slow_PWM v1.2.0 +Teensy_Slow_PWM v1.2.1 CPU Frequency = 600 MHz [PWM] TEENSY_TIMER_1: , F_BUS_ACTUAL (MHz) = 150 [PWM] Request interval = 10 , actual interval (us) = 10 @@ -887,16 +438,26 @@ The following is the sample terminal output when running example [ISR_Modify_PWM ``` Starting ISR_Modify_PWM on Teensy 4.1 -Teensy_Slow_PWM v1.2.0 +Teensy_Slow_PWM v1.2.1 CPU Frequency = 600 MHz [PWM] TEENSY_TIMER_1: , F_BUS_ACTUAL (MHz) = 150 [PWM] Request interval = 33 , actual interval (us) = 33 [PWM] Prescale = 0 , _timerCount = 2475 -Starting ITimer OK, micros() = 3196009 -Using PWM Freq = 1.00, PWM DutyCycle = 50.00 -Channel : 0 Period : 1000000 OnTime : 500000 Start_Time : 3196014 -Channel : 0 New Period : 500000 OnTime : 450000 Start_Time : 13196073 -Channel : 0 New Period : 1000000 OnTime : 500000 Start_Time : 23196400 +Starting ITimer OK, micros() = 2531009 +Using PWM Freq = 200.00, PWM DutyCycle = 1.00 +Channel : 0 Period : 5000 OnTime : 50 Start_Time : 2531014 +Channel : 0 New Period : 10000 OnTime : 555 Start_Time : 12529921 +Channel : 0 New Period : 5000 OnTime : 50 Start_Time : 22525957 +Channel : 0 New Period : 10000 OnTime : 555 Start_Time : 32529848 +Channel : 0 New Period : 5000 OnTime : 50 Start_Time : 42525884 +Channel : 0 New Period : 10000 OnTime : 555 Start_Time : 52534793 +Channel : 0 New Period : 5000 OnTime : 50 Start_Time : 62530829 +Channel : 0 New Period : 10000 OnTime : 555 Start_Time : 72534720 +Channel : 0 New Period : 5000 OnTime : 50 Start_Time : 82530756 +Channel : 0 New Period : 10000 OnTime : 555 Start_Time : 92539665 +Channel : 0 New Period : 5000 OnTime : 50 Start_Time : 102535701 +Channel : 0 New Period : 10000 OnTime : 555 Start_Time : 112539593 +Channel : 0 New Period : 5000 OnTime : 50 Start_Time : 122535629 ``` --- @@ -907,7 +468,7 @@ The following is the sample terminal output when running example [ISR_Changing_P ``` Starting ISR_Changing_PWM on Teensy 4.1 -Teensy_Slow_PWM v1.2.0 +Teensy_Slow_PWM v1.2.1 CPU Frequency = 600 MHz [PWM] TEENSY_TIMER_1: , F_BUS_ACTUAL (MHz) = 150 [PWM] Request interval = 33 , actual interval (us) = 33 @@ -980,7 +541,7 @@ Submit issues to: [Teensy_Slow_PWM issues](https://github.com/khoih-prog/Teensy_ 5. Optimize library code by using `reference-passing` instead of `value-passing` 6. Improve accuracy by using `float`, instead of `uint32_t` for `dutycycle` 7. DutyCycle to be optionally updated at the end current PWM period instead of immediately. - +8. Display informational warning only when `_PWM_LOGLEVEL_` > 3 --- --- diff --git a/changelog.md b/changelog.md index 16ea7c3..66d569d 100644 --- a/changelog.md +++ b/changelog.md @@ -12,6 +12,7 @@ ## Table of Contents * [Changelog](#changelog) + * [Releases v1.2.1](#releases-v121) * [Releases v1.2.0](#releases-v120) * [Releases v1.1.0](#releases-v110) * [Initial Releases v1.0.0](#Initial-Releases-v100) @@ -21,6 +22,12 @@ ## Changelog +### Releases v1.2.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.2.0 1. Fix `multiple-definitions` linker error. Drop `src_cpp` and `src_h` directories diff --git a/library.json b/library.json index 6c58cea..74637b6 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "Teensy_Slow_PWM", - "version": "1.2.0", + "version": "1.2.1", "keywords": "timing, device, control, timer, interrupt, hardware, isr, isr-based, hardware-timer, mission-critical, accuracy, precise, non-blocking, teensy-2x, teensy-3x, teensy-lc, teensy-4x, teensy-41, teensy-40, teensy-micromod", "description": "This library enables you to use ISR-based PWM channels on Teensy boards, such as Teensy 2.x, Teensy LC, Teensy 3.x, Teensy 4.x, Teensy MicroMod, etc., to create and output PWM any GPIO pin. It now supports 16 ISR-based PWM channels, while consuming only 1 Hardware Timer. PWM channel interval can be very long (ulong microsecs / millisecs). The most important feature is they're ISR-based PWM channels, supporting lower PWM frequencies with suitable accuracy. Their executions are not blocked by bad-behaving functions or tasks. This important feature is absolutely necessary for mission-critical tasks. These ISR-based PWMs, 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 PWM using millis() or micros(). That's necessary if you need to control devices requiring high precision. Now you can change the PWM settings on-the-fly", "authors": diff --git a/library.properties b/library.properties index fb16ce8..3f19cef 100644 --- a/library.properties +++ b/library.properties @@ -1,12 +1,12 @@ name=Teensy_Slow_PWM -version=1.2.0 +version=1.2.1 author=Khoi Hoang maintainer=Khoi Hoang sentence=This library enables you to use ISR-based PWM channels on Teensy boards, such as Teensy 2.x, Teensy LC, Teensy 3.x, Teensy 4.x, Teensy MicroMod, etc., to create and output PWM any GPIO pin. paragraph= It now supports 16 ISR-based PWM channels, while consuming only 1 Hardware Timer. PWM channel interval can be very long (ulong microsecs / millisecs). The most important feature is they're ISR-based PWM channels, supporting lower PWM frequencies with suitable accuracy. Their executions are not blocked by bad-behaving functions or tasks. This important feature is absolutely necessary for mission-critical tasks. These ISR-based PWMs, 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 PWM using millis() or micros(). That's necessary if you need to control devices requiring high precision. Now you can change the PWM settings on-the-fly category=Device Control url=https://github.com/khoih-prog/Teensy_Slow_PWM -architectures=teensy +architectures=* repository=https://github.com/khoih-prog/Teensy_Slow_PWM license=MIT includes=Teensy_Slow_PWM.h,Teensy_Slow_PWM.hpp diff --git a/src/PWM_Generic_Debug.h b/src/PWM_Generic_Debug.h index 0a2cfca..7538680 100644 --- a/src/PWM_Generic_Debug.h +++ b/src/PWM_Generic_Debug.h @@ -12,13 +12,14 @@ Therefore, their executions are not blocked by bad-behaving functions / tasks. This important feature is absolutely necessary for mission-critical tasks. - Version: 1.2.0 + Version: 1.2.1 Version Modified By Date Comments ------- ----------- ---------- ----------- 1.0.0 K.Hoang 28/09/2021 Initial coding for Teensy 2.x, Teensy LC, Teensy 3.x, Teensy 4.x, etc. 1.1.0 K Hoang 10/11/2021 Add functions to modify PWM settings on-the-fly 1.2.0 K.Hoang 07/02/2022 Fix `multiple-definitions` linker error. Improve accuracy. Optimize code. Fix bug + 1.2.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/Teensy_Slow_PWM.h b/src/Teensy_Slow_PWM.h index a959cb5..c07043a 100644 --- a/src/Teensy_Slow_PWM.h +++ b/src/Teensy_Slow_PWM.h @@ -12,13 +12,14 @@ Therefore, their executions are not blocked by bad-behaving functions / tasks. This important feature is absolutely necessary for mission-critical tasks. - Version: 1.2.0 + Version: 1.2.1 Version Modified By Date Comments ------- ----------- ---------- ----------- 1.0.0 K.Hoang 28/09/2021 Initial coding for Teensy 2.x, Teensy LC, Teensy 3.x, Teensy 4.x, etc. 1.1.0 K Hoang 10/11/2021 Add functions to modify PWM settings on-the-fly 1.2.0 K.Hoang 07/02/2022 Fix `multiple-definitions` linker error. Improve accuracy. Optimize code. Fix bug + 1.2.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/Teensy_Slow_PWM.hpp b/src/Teensy_Slow_PWM.hpp index d036626..f3ddc0d 100644 --- a/src/Teensy_Slow_PWM.hpp +++ b/src/Teensy_Slow_PWM.hpp @@ -12,13 +12,14 @@ Therefore, their executions are not blocked by bad-behaving functions / tasks. This important feature is absolutely necessary for mission-critical tasks. - Version: 1.2.0 + Version: 1.2.1 Version Modified By Date Comments ------- ----------- ---------- ----------- 1.0.0 K.Hoang 28/09/2021 Initial coding for Teensy 2.x, Teensy LC, Teensy 3.x, Teensy 4.x, etc. 1.1.0 K Hoang 10/11/2021 Add functions to modify PWM settings on-the-fly 1.2.0 K.Hoang 07/02/2022 Fix `multiple-definitions` linker error. Improve accuracy. Optimize code. Fix bug + 1.2.1 K Hoang 04/03/2022 Fix `DutyCycle` and `New Period` display bugs. Display warning only when debug level > 3 *****************************************************************************************************************************/ #pragma once @@ -31,13 +32,13 @@ #endif #ifndef TEENSY_SLOW_PWM_VERSION - #define TEENSY_SLOW_PWM_VERSION F("Teensy_Slow_PWM v1.2.0") + #define TEENSY_SLOW_PWM_VERSION F("Teensy_Slow_PWM v1.2.1") #define TEENSY_SLOW_PWM_VERSION_MAJOR 1 #define TEENSY_SLOW_PWM_VERSION_MINOR 2 - #define TEENSY_SLOW_PWM_VERSION_PATCH 0 + #define TEENSY_SLOW_PWM_VERSION_PATCH 1 - #define TEENSY_SLOW_PWM_VERSION_INT 1002000 + #define TEENSY_SLOW_PWM_VERSION_INT 1002001 #endif #ifndef _PWM_LOGLEVEL_ @@ -75,13 +76,25 @@ typedef void (*timerCallback) (); #ifndef BOARD_NAME #if defined(ARDUINO_TEENSY41) #define BOARD_NAME F("Teensy 4.1") - #warning Using Teensy 4.1 + + #if (_PWM_LOGLEVEL_ > 3) + #warning Using Teensy 4.1 + #endif + #elif defined(ARDUINO_TEENSY_MICROMOD) #define BOARD_NAME F("Teensy MicroMod") - #warning Using Teensy MicroMod + + #if (_PWM_LOGLEVEL_ > 3) + #warning Using Teensy MicroMod + #endif + #else #define BOARD_NAME F("Teensy 4.0") - #warning Using Teensy 4.0 + + #if (_PWM_LOGLEVEL_ > 3) + #warning Using Teensy 4.0 + #endif + #endif #endif diff --git a/src/Teensy_Slow_PWM_ISR.h b/src/Teensy_Slow_PWM_ISR.h index aa07dc2..dddaad9 100644 --- a/src/Teensy_Slow_PWM_ISR.h +++ b/src/Teensy_Slow_PWM_ISR.h @@ -12,13 +12,14 @@ Therefore, their executions are not blocked by bad-behaving functions / tasks. This important feature is absolutely necessary for mission-critical tasks. - Version: 1.2.0 + Version: 1.2.1 Version Modified By Date Comments ------- ----------- ---------- ----------- 1.0.0 K.Hoang 28/09/2021 Initial coding for Teensy 2.x, Teensy LC, Teensy 3.x, Teensy 4.x, etc. 1.1.0 K Hoang 10/11/2021 Add functions to modify PWM settings on-the-fly 1.2.0 K.Hoang 07/02/2022 Fix `multiple-definitions` linker error. Improve accuracy. Optimize code. Fix bug + 1.2.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/Teensy_Slow_PWM_ISR.hpp b/src/Teensy_Slow_PWM_ISR.hpp index ad5533f..5720ecd 100644 --- a/src/Teensy_Slow_PWM_ISR.hpp +++ b/src/Teensy_Slow_PWM_ISR.hpp @@ -12,13 +12,14 @@ Therefore, their executions are not blocked by bad-behaving functions / tasks. This important feature is absolutely necessary for mission-critical tasks. - Version: 1.2.0 + Version: 1.2.1 Version Modified By Date Comments ------- ----------- ---------- ----------- 1.0.0 K.Hoang 28/09/2021 Initial coding for Teensy 2.x, Teensy LC, Teensy 3.x, Teensy 4.x, etc. 1.1.0 K Hoang 10/11/2021 Add functions to modify PWM settings on-the-fly 1.2.0 K.Hoang 07/02/2022 Fix `multiple-definitions` linker error. Improve accuracy. Optimize code. Fix bug + 1.2.1 K Hoang 04/03/2022 Fix `DutyCycle` and `New Period` display bugs. Display warning only when debug level > 3 *****************************************************************************************************************************/ #pragma once @@ -31,13 +32,13 @@ #endif #ifndef TEENSY_SLOW_PWM_VERSION - #define TEENSY_SLOW_PWM_VERSION F("Teensy_Slow_PWM v1.2.0") + #define TEENSY_SLOW_PWM_VERSION F("Teensy_Slow_PWM v1.2.1") #define TEENSY_SLOW_PWM_VERSION_MAJOR 1 #define TEENSY_SLOW_PWM_VERSION_MINOR 2 - #define TEENSY_SLOW_PWM_VERSION_PATCH 0 + #define TEENSY_SLOW_PWM_VERSION_PATCH 1 - #define TEENSY_SLOW_PWM_VERSION_INT 1002000 + #define TEENSY_SLOW_PWM_VERSION_INT 1002001 #endif #ifndef _PWM_LOGLEVEL_ @@ -64,12 +65,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/Teensy_Slow_PWM_ISR_Impl.h b/src/Teensy_Slow_PWM_ISR_Impl.h index bb147bb..bf9b46c 100644 --- a/src/Teensy_Slow_PWM_ISR_Impl.h +++ b/src/Teensy_Slow_PWM_ISR_Impl.h @@ -12,13 +12,14 @@ Therefore, their executions are not blocked by bad-behaving functions / tasks. This important feature is absolutely necessary for mission-critical tasks. - Version: 1.2.0 + Version: 1.2.1 Version Modified By Date Comments ------- ----------- ---------- ----------- 1.0.0 K.Hoang 28/09/2021 Initial coding for Teensy 2.x, Teensy LC, Teensy 3.x, Teensy 4.x, etc. 1.1.0 K Hoang 10/11/2021 Add functions to modify PWM settings on-the-fly 1.2.0 K.Hoang 07/02/2022 Fix `multiple-definitions` linker error. Improve accuracy. Optimize code. Fix bug + 1.2.1 K Hoang 04/03/2022 Fix `DutyCycle` and `New Period` display bugs. Display warning only when debug level > 3 *****************************************************************************************************************************/ #pragma once @@ -234,7 +235,7 @@ bool TEENSY_SLOW_PWM_ISR::modifyPWMChannel_Period(const uint8_t& channelNum, con PWM[channelNum].newOnTime = ( period * dutycycle ) / 100; PWM_LOGINFO0("Channel : "); PWM_LOGINFO0(channelNum); - PWM_LOGINFO0("\tNew Period : "); PWM_LOGINFO0(PWM[channelNum].newPeriod); + 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); diff --git a/src/Teensy_Slow_PWM_Impl.h b/src/Teensy_Slow_PWM_Impl.h index 624dfb6..30a003b 100644 --- a/src/Teensy_Slow_PWM_Impl.h +++ b/src/Teensy_Slow_PWM_Impl.h @@ -12,13 +12,14 @@ Therefore, their executions are not blocked by bad-behaving functions / tasks. This important feature is absolutely necessary for mission-critical tasks. - Version: 1.2.0 + Version: 1.2.1 Version Modified By Date Comments ------- ----------- ---------- ----------- 1.0.0 K.Hoang 28/09/2021 Initial coding for Teensy 2.x, Teensy LC, Teensy 3.x, Teensy 4.x, etc. 1.1.0 K Hoang 10/11/2021 Add functions to modify PWM settings on-the-fly 1.2.0 K.Hoang 07/02/2022 Fix `multiple-definitions` linker error. Improve accuracy. Optimize code. Fix bug + 1.2.1 K Hoang 04/03/2022 Fix `DutyCycle` and `New Period` display bugs. Display warning only when debug level > 3 *****************************************************************************************************************************/ #pragma once