Closed RockingYProductions closed 2 years ago
Hi @RockingYProductions
Thanks for the issue report. I'll certainly spend some time soon to investigate and try to fix, depending on the necessity and popularity.
This can be much harder to solve as the library is using fully hardware-based PWM, designed for very high Frequencies.
These purely hardware-based PWM channels can generate from very low (lowest is 7.5Hz) to very high PWM frequencies (in the MHz range, up to 62.5MHz).
Can you post more info about your use-case, such as
analogWrite()
still shows same issue (I guess so, but haven't tested / measured)so that we can all learn from the experience.
BTW, if your use-case requires only low frequency ( < 1000Hz ) as you're using 100Hz now, try the ISR-based RP2040_Slow_PWM library, which already fixed the same issue
3. DutyCycle to be optionally updated at the end current PWM period instead of immediately
// Default is true, uncomment to false
//#define CHANGING_PWM_END_OF_CYCLE false
Hi @RockingYProductions
The new RP2040_PWM v1.4.0 has just been published. Your contribution, by requesting good enhancement, is noted in Contributions and Thanks
Please test and report if there is any more issue.
Be sure to modify your code as follows by not using phase_correct == true
#define _PWM_LOGLEVEL_ 1
#include "RP2040_PWM.h"
//creates pwm instance
RP2040_PWM* PWM_Instance;
const float PWMFREQ = 100; // PWM frequency on GPIO pin
const byte GPIO_PIN = 19;
float dutyCycle;
void setup()
{
Serial.begin(115200);
while (!Serial);
delay(100);
Serial.print(F("\nStarting PWM_Glitch on ")); Serial.println(BOARD_NAME);
Serial.println(RP2040_PWM_VERSION);
PWM_Instance = new RP2040_PWM(GPIO_PIN, PWMFREQ, 0);
PWM_Instance->setPWM(GPIO_PIN, PWMFREQ, 0);
}
void loop()
{
dutyCycle = 50;
PWM_Instance->setPWM(GPIO_PIN, PWMFREQ, dutyCycle);
delay(100);
dutyCycle = 20;
PWM_Instance->setPWM(GPIO_PIN, PWMFREQ, dutyCycle);
delay(100);
}
MIN_PWM_FREQUENCY
and MAX_PWM_FREQUENCY
dynamically according to actual F_CPU
Confirmed that Release v1.4.0 removes the observed glitch when changing duty cycles and verified by scope. Excellent!
In our use case, a system was wired such that it had one GPIO pin between the RPI PICO (buffered to 5v) and an Arduino UNO input pin. This generated a simple logic signal that triggered the Arduino to start a mechanical assembly. Later, it was required to have four (possibly more) trigger signals. We cannot add/move additional signals in the design.
By using the PWM output of the PICO, 10 PWM frequencies (duty cycle 0%, 10%, etc,) where chosen to represent 10 trigger outputs. The Arduino UNO used pin-change IRQ's to measure the pulse width (or lack of at 0% and 100%). 100Hz was chosen to minimize the IRQ service overhead on the UNO. The PICO can now transmit 10 (or more) 'trigger' outputs and it was acceptable that only one trigger output at a time was required.
We observed that when the PWM runt/glitch was received, the UNO would measure the pulse and create an incorrect trigger output, then create the correct trigger after the next cycle. A work around was to 'debounce' the received PWM for two consecutive PWM values, but this was adding IRQ overhead. Now we can successfully transmit may triggers without any PCB changes or IRQ overhead. Thank you very much!
Great to know it's working for you now. We can all learn from your use-case and experience.
The library is better and better thanks to contributing users like you.
Best Regards,
Contextual information
There was observed to be a runt or glitch generated when switching the duty cycle, that lasted only the cycle the update occurred at. This runt/glitch is detectable by our receiver, and although it only lasts one cycle, it causes jitter issues.
Is there a way to switch Duty Cycle precisely between the last complete cycle of the current PWM cycle and the next complete cycle of the new PWM duty cycle value.
Simplest possible steps to reproduce (see attached scope shot). You can pick different duty cycles and get the same effect.
Attached Scope Screen Shot where the duty cycle changed.