Hi,
I can find lots of "hits" for MAX PWM Frequency, but I want Sub-Hz values (0.1 - 0.5Hz).
Using this commonly found technique:
int PWM_FREQUENCY = 1; // this variable is used to define the time period
int PWM_CHANNEL = 0; // this variable is used to select the channel number
int PWM_RESOUTION = 8; // this will define the resolution of the signal which is 8 in this case
int GPIOPIN =2 ; // GPIO to which we want to attach this channel signal
int dutyCycle = 8; // it will define the width of signal or also the one time
void setup()
{
ledcSetup(PWM_CHANNEL, PWM_FREQUENCY, PWM_RESOUTION);
ledcAttachPin(GPIOPIN, PWM_CHANNEL);
ledcWrite(PWM_CHANNEL, dutyCycle);
}
void loop()
{
//Do Stuff....
}
... gets me near what I want. But I can not provide a value less than 1 for the PWM_FREQUENCY.
Can anyone offer an alternative hardware solution?
Here's an example using the ESP32's MCPWM peripheral to generate a 0.1Hz PWM signal, 50% duty-cycle on GPIO pin 27 with timer 0:
// ESP32: Output PWM 0.1Hz (10 second period), 50% duty-cycle on GPIO pin 27
#include "soc/mcpwm_reg.h"
#include "soc/mcpwm_struct.h"
#include "driver/mcpwm.h"
#define GPIO_PWM0A_OUT 27
void setup() {
mcpwm_gpio_init(MCPWM_UNIT_0, MCPWM0A, GPIO_PWM0A_OUT); // Initialise channel MCPWM0A on GPIO pin 27
MCPWM0.clk_cfg.prescale = 199; // Set the 160MHz clock prescaler to 199 (160MHz/(199+1)=800kHz)
MCPWM0.timer[0].period.prescale = 199; // Set timer 0 prescaler to 199 (800kHz/(199+1))=4kHz)
MCPWM0.timer[0].period.period = 39999; // Set the PWM period to 0.1Hz (4kHz/(39999+1)=0.1Hz)
MCPWM0.channel[0].cmpr_value[0].val = 20000; // Set the counter compare for 50% duty-cycle
MCPWM0.channel[0].generator[0].utez = 2; // Set the PWM0A ouput to go high at the start of the timer period
MCPWM0.channel[0].generator[0].utea = 1; // Clear on compare match
MCPWM0.timer[0].mode.mode = 1; // Set timer 0 to increment
MCPWM0.timer[0].mode.start = 2; // Set timer 0 to free-run
}
void loop() {}
Note that "clk_cfg" and "period" prescaler register bifields are 8-bit (0 to 255 + 1), while "period" is 16-bit (0 to 65535 + 1).
There is a lower limit to how low the hardware can divide the clock. You can find more information in the ESP documentation. The ESP-IDF API is different to the ESP Arduino API but the hardware information is valid.