Hi all,
I have ESP32-S3 and I am trying to generate some slow PWM's around 500Hz to 1Khz for a LED driver project. I am reading mixed things about number of PWM's possible, some say only 8 channels are possible but this github repo says 16 are possible https://github.com/khoih-prog/ESP32_PWM ... SP32S3_DEV
But datasheet says 8 PWM's + 2 MCPWMs. Which one is correct? I need atleast 9 PWM"S to be generated and I want to know is it really possible to generate 9 pwms on esp32-s3 WROOM specifically or not?
Any examples or references would be highly appreciated.
Thanks
Slow PWM's with ESP32-S3
-
- Posts: 1955
- Joined: Mon Oct 17, 2022 7:38 pm
- Location: Europe, Germany
Re: Slow PWM's with ESP32-S3
The library you found uses timer interrupts to generate PWM signals in software.
The S3's LEDC hardware indeed has only 8 channels, the MCPWM has additional 3 channels (x2 outputs). So yes, generating 8+3=11 PWM signals via hardware is possible. (Even more if you're willing to (ab)use the RMT.)
The S3 also provides 8 "Sigma Delta Modulated Output" channels which enable you to generate up to 8 PDM outputs at a resolution of 8 bits (effectively approximating an 8-bit DAC output).
The S3's LEDC hardware indeed has only 8 channels, the MCPWM has additional 3 channels (x2 outputs). So yes, generating 8+3=11 PWM signals via hardware is possible. (Even more if you're willing to (ab)use the RMT.)
The S3 also provides 8 "Sigma Delta Modulated Output" channels which enable you to generate up to 8 PDM outputs at a resolution of 8 bits (effectively approximating an 8-bit DAC output).
Re: Slow PWM's with ESP32-S3
Thanks alot for the response, so I'll use the all 8 native PWMs and then I'll use one PDM channel using this code https://github.com/espressif/esp-idf/bl ... ple_main.c
Can you also point me to an example if MCPWM can be used as a normal PWM signal?
would that be fine? Also I have another feature I need to implement, by adjusting the PWM's to my LED drivers I will arrive at a brightness or color right. Now I want to generate a 200mS flash of this color. What's the best way to switch off and on the PWM channels this quickly?
I tried with an arduino code, but looks like only if the delay is above 500mS I am able to see the PWM switching on and off, below this delay PWM is off. I'll have to test again but wanted to hear your recommendation.
Can you also point me to an example if MCPWM can be used as a normal PWM signal?
would that be fine? Also I have another feature I need to implement, by adjusting the PWM's to my LED drivers I will arrive at a brightness or color right. Now I want to generate a 200mS flash of this color. What's the best way to switch off and on the PWM channels this quickly?
I tried with an arduino code, but looks like only if the delay is above 500mS I am able to see the PWM switching on and off, below this delay PWM is off. I'll have to test again but wanted to hear your recommendation.
Re: Slow PWM's with ESP32-S3
Ran your question
Yes, you can use the MCPWM module to control a LED via PWM on the ESP32, even though MCPWM is typically used for motor control. When controlling a LED, you typically only care about generating a standard PWM signal to adjust the brightness of the LED.
Here’s how you can do this in the ESP-IDF framework:
Steps to control an LED using MCPWM
Initialize MCPWM and set it up for PWM control.
Configure a frequency for PWM (e.g., 1 kHz).
Set the duty cycle to control the brightness of the LED.
Connect the MCPWM output to the GPIO pin where your LED is connected (make sure the pin supports PWM functionality).
Adjust the duty cycle to control the brightness of the LED. A duty cycle of 0% means the LED is off, and 100% means the LED is fully on.
Example Code to control an LED using MCPWM
Here’s a simplified example of controlling an LED with PWM using the MCPWM module in ESP-IDF:
through AI, and this is what It shot back.an example if MCPWM can be used as a normal PWM signal?
Yes, you can use the MCPWM module to control a LED via PWM on the ESP32, even though MCPWM is typically used for motor control. When controlling a LED, you typically only care about generating a standard PWM signal to adjust the brightness of the LED.
Here’s how you can do this in the ESP-IDF framework:
Steps to control an LED using MCPWM
Initialize MCPWM and set it up for PWM control.
Configure a frequency for PWM (e.g., 1 kHz).
Set the duty cycle to control the brightness of the LED.
Connect the MCPWM output to the GPIO pin where your LED is connected (make sure the pin supports PWM functionality).
Adjust the duty cycle to control the brightness of the LED. A duty cycle of 0% means the LED is off, and 100% means the LED is fully on.
Example Code to control an LED using MCPWM
Here’s a simplified example of controlling an LED with PWM using the MCPWM module in ESP-IDF:
Code: Select all
#include "driver/mcpwm.h"
#include "esp_system.h"
#include "driver/gpio.h"
#define LED_GPIO_PIN 18 // The GPIO pin where the LED is connected
void app_main() {
// Initialize MCPWM for PWM output
mcpwm_gpio_init(MCPWM_UNIT_0, MCPWM0A, LED_GPIO_PIN); // Set GPIO18 as MCPWM0A
// Configure the MCPWM parameters (frequency and duty cycle)
mcpwm_config_t pwm_config;
pwm_config.frequency = 1000; // 1kHz PWM frequency
pwm_config.duty_cycle_a = 50; // 50% duty cycle for MCPWM0A (this will control brightness)
pwm_config.duty_cycle_b = 0; // No signal on MCPWM0B (not used)
pwm_config.motor_direction = MCPWM_DIR_CW; // Not necessary for LED, just a placeholder
mcpwm_init(MCPWM_UNIT_0, MCPWM_TIMER_0, &pwm_config); // Initialize MCPWM
// Now the LED should be blinking with 50% brightness at 1kHz frequency
// If you want to dynamically change the brightness:
while (1) {
// Gradually increase and decrease the LED brightness
for (int duty = 0; duty <= 100; duty++) {
mcpwm_set_duty(MCPWM_UNIT_0, MCPWM_TIMER_0, MCPWM_OPR_A, duty); // Change duty cycle
vTaskDelay(10 / portTICK_PERIOD_MS);
}
for (int duty = 100; duty >= 0; duty--) {
mcpwm_set_duty(MCPWM_UNIT_0, MCPWM_TIMER_0, MCPWM_OPR_A, duty); // Change duty cycle
vTaskDelay(10 / portTICK_PERIOD_MS);
}
}
}
Re: Slow PWM's with ESP32-S3
Hahaha I already tried, looks like I could do it, but the code is not correct. According to the esp-idf API guide there's no API called mcpwm_set_duty. Thisexample tells to use mcpwm_set_comparator_value but I don't understand how to use it for my application. I'm kind of a noob to esp-idf sorry for basic questions.mikemoy wrote: ↑Sun Jan 12, 2025 6:47 amRan your questionthrough AI, and this is what It shot back.an example if MCPWM can be used as a normal PWM signal?
Code: Select all
#include "driver/mcpwm.h" // Now the LED should be blinking with 50% brightness at 1kHz frequency // If you want to dynamically change the brightness: while (1) { // Gradually increase and decrease the LED brightness for (int duty = 0; duty <= 100; duty++) { [b]mcpwm_set_duty[/b](MCPWM_UNIT_0, MCPWM_TIMER_0, MCPWM_OPR_A, duty); // Change duty cycle vTaskDelay(10 / portTICK_PERIOD_MS); } for (int duty = 100; duty >= 0; duty--) { [b] mcpwm_set_duty[/b](MCPWM_UNIT_0, MCPWM_TIMER_0, MCPWM_OPR_A, duty); // Change duty cycle vTaskDelay(10 / portTICK_PERIOD_MS); } } }
-
- Posts: 1955
- Joined: Mon Oct 17, 2022 7:38 pm
- Location: Europe, Germany
Re: Slow PWM's with ESP32-S3
A basic PWM generator uses a timer/counter and one (or two) comparators.
The timer/counter counts up to a certain max value, then resets to 0 and goes on counting up. The time it takes for the timer/counter to complete one of these cycles defines the PWM frequency.
The most simple way to create a PWM signal based on the timer/counter is by doing two things: 1. when the counter resets to 0, set an output to HIGH; 2. when the counter value matches the comparator's value, set the output to LOW.
Done in this way, the duty cycle of the PWM signal is defined by the comparator's set value between 0 (=0%) and the counter's max value (=100%).
With the MCPWM, you can 'build' your own PWM generator from building blocks: a timer/counter, a comparator, and two 'actions': One action is to set the output HIGH when the counter goes to 0 (it's "empty"), the other action is to set the output LOW when the counter matches the comparator.
The timer/counter counts up to a certain max value, then resets to 0 and goes on counting up. The time it takes for the timer/counter to complete one of these cycles defines the PWM frequency.
The most simple way to create a PWM signal based on the timer/counter is by doing two things: 1. when the counter resets to 0, set an output to HIGH; 2. when the counter value matches the comparator's value, set the output to LOW.
Done in this way, the duty cycle of the PWM signal is defined by the comparator's set value between 0 (=0%) and the counter's max value (=100%).
With the MCPWM, you can 'build' your own PWM generator from building blocks: a timer/counter, a comparator, and two 'actions': One action is to set the output HIGH when the counter goes to 0 (it's "empty"), the other action is to set the output LOW when the counter matches the comparator.
Re: Slow PWM's with ESP32-S3
Thanks for your guidance, for anyone who's coming here later here's the code that worked perfectly fine for me. Just load the code and press 'o' to start the pwm and press 'f' to stop the pwm. The duty cycle is 50%, you can change it when needed.
Code: Select all
#include "driver/mcpwm.h"
#define GPIO_PWM0A_OUT 22
const uint8_t doPress = GPIO_PWM0A_OUT; // PWM
void setup() {
Serial.begin(115200);
mcpwm_gpio_init(MCPWM_UNIT_0, MCPWM0A, doPress);
mcpwm_config_t pwm_config = {};
pwm_config.frequency = 1000;
pwm_config.cmpr_a = 0;
pwm_config.cmpr_b = 0;
pwm_config.counter_mode = MCPWM_UP_COUNTER;
pwm_config.duty_mode = MCPWM_DUTY_MODE_0;
mcpwm_init(MCPWM_UNIT_0, MCPWM_TIMER_0, &pwm_config);
}
static void pwm_set_duty(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num, float duty_cycle) {
mcpwm_set_signal_low(mcpwm_num, timer_num, MCPWM_OPR_B);
mcpwm_set_duty(mcpwm_num, timer_num, MCPWM_OPR_A, duty_cycle);
mcpwm_set_duty_type(mcpwm_num, timer_num, MCPWM_OPR_A, MCPWM_DUTY_MODE_0);
}
void loop() {
if(Serial.available()>0)
{
char in = Serial.read();
if(in == 'o')
{
pwm_set_duty(MCPWM_UNIT_0, MCPWM_TIMER_0, 50);
}
if(in == 'f')
{
pwm_set_duty(MCPWM_UNIT_0, MCPWM_TIMER_0, 0);
}
}
}
Who is online
Users browsing this forum: No registered users and 102 guests