-
Notifications
You must be signed in to change notification settings - Fork 7.6k
PWM (LEDc driver) doesn't work during light sleep #3534
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
[STALE_SET] This issue has been automatically marked as stale because it has not had recent activity. It will be closed in 14 days if no further activity occurs. Thank you for your contributions. |
[STALE_DEL] This stale issue has been automatically closed. Thank you for your contributions. |
I would be happy to know if you have found a solution @shraiwi? |
In the current state, it looks like the LEDC won't work during light sleep. If you read the the ESP32 forums, it looks like there is a workaround but you'd likely have to implement that yourself, as it is not supported in the ESP32 Arduino Core. |
I did found the workaround, hoping for an easier way. I got it working though. Anyway, this works: #include <stdio.h>
#include <Arduino.h>
#include "freertos/task.h"
#include "driver/ledc.h"
#include "esp_err.h"
#include "esp_pm.h"
#include "esp_sleep.h"
#include "driver/uart.h"
#include "esp32/rom/uart.h"
#include "ulp_common.h"
#include "esp32/ulp.h"
#define LEDC_LS_TIMER LEDC_TIMER_0
#define LEDC_LS_MODE LEDC_LOW_SPEED_MODE
#define LEDC_LS_CH2_GPIO (4)
#define LEDC_LS_CH2_CHANNEL LEDC_CHANNEL_2
ledc_channel_config_t ledc_channel[1] = {
{
.gpio_num = LEDC_LS_CH2_GPIO,
.speed_mode = LEDC_LS_MODE,
.channel = LEDC_LS_CH2_CHANNEL,
.timer_sel = LEDC_LS_TIMER,
.duty = 0,
.hpoint = 0,
},
};
void setup()
{
Serial.begin(115200);
ledc_timer_config_t ledc_timer = {
.speed_mode = LEDC_LS_MODE, // timer mode
.duty_resolution = LEDC_TIMER_8_BIT, // resolution of PWM duty
.timer_num = LEDC_LS_TIMER, // timer index
.freq_hz = 100, // frequency of PWM signal
.clk_cfg = LEDC_USE_RTC8M_CLK, // Force source clock to RTC8M
};
ledc_timer_config(&ledc_timer);
ledc_channel_config(&ledc_channel[0]);
printf("Frequency %u Hz\n", ledc_get_freq(LEDC_LS_MODE, LEDC_LS_TIMER));
}
void loop()
{
// Fade up from 0 to 255
for (int i = 0; i < 255; i++)
{
ledc_set_duty(ledc_channel[0].speed_mode, ledc_channel[0].channel, i);
ledc_update_duty(ledc_channel[0].speed_mode, ledc_channel[0].channel);
delay(10);
}
// stay at 100% for 5s
delay(5000);
// Set duty to 55/255 (21%)
ledc_set_duty(ledc_channel[0].speed_mode, ledc_channel[0].channel, 55);
ledc_update_duty(ledc_channel[0].speed_mode, ledc_channel[0].channel);
printf("Sleep for 10s\n");
esp_sleep_enable_timer_wakeup(10000000L);
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_AUTO);
fflush(stdout);
uart_tx_wait_idle(CONFIG_CONSOLE_UART_NUM);
esp_light_sleep_start();
} |
I tried to compile this in platform = espressif32@=6..2.0 and it doesn't compile |
What is your error? For me it compiles fine with |
Hm... Funny. I just tried it again and it works fine. So operator error. These files are missing though: // #include "ulp_common.h"
// #include "esp32/ulp.h" |
I got it to work. The esp32 documentation is missing the following key requirements:
The following code is confirmed working on the v5.1 and v4.4 toolchain. I've named this thing psuedo i2s because reasons: #include <math.h>
#include <Arduino.h>
#include <stdio.h>
#include "driver/ledc.h"
#include "esp_err.h"
#include "driver/ledc.h"
#include "defs.h"
#include "pseudo_i2s.h"
#include "esp32-hal-ledc.h"
#define LEDC_TIMER LEDC_TIMER_0
#define LEDC_MODE LEDC_LOW_SPEED_MODE
#define LEDC_CHANNEL LEDC_CHANNEL_0
#define LEDC_DUTY_RES LEDC_TIMER_1_BIT // Set duty resolution to 13 bits
#define LEDC_FREQUENCY (1024 * 1024) // 1 mhz clock.
#define PIN_PSUEDO_I2S GPIO_NUM_6
// #define LEDC_CLOCK LEDC_USE_RC_FAST_CLK // still clocks during light sleep.
#define LEDC_CLOCK LEDC_USE_RTC8M_CLK // still clocks during light sleep.
namespace
{
enum {
// use bith manipuation against the LEDC_TIMER_8_BIT to come to a max duty.
// For example, if LEDC_TIMER_8_BIT is 8, then the max duty is 255.
kMaxDuty = (1 << LEDC_DUTY_RES) - 1,
};
ledc_timer_config_t ledc_timer = {
//.duty_resolution = LEDC_TIMER_13_BIT, // resolution of PWM duty
.speed_mode = LEDC_MODE,
.duty_resolution = LEDC_DUTY_RES,
.timer_num = LEDC_TIMER,
.freq_hz = LEDC_FREQUENCY, // Set output frequency
.clk_cfg = LEDC_CLOCK
};
// Prepare and then apply the LEDC PWM channel configuration
ledc_channel_config_t ledc_channel = {
.gpio_num = PIN_PSUEDO_I2S,
.speed_mode = LEDC_MODE,
.channel = LEDC_CHANNEL,
.intr_type = LEDC_INTR_DISABLE,
.timer_sel = LEDC_TIMER,
.duty = 0,
.hpoint = 0,
.flags = {
.output_invert = 1,
}
};
} // namespace
void pseudo_i2s_start()
{
//rtc_clk_slow_freq_set(RTC_SLOW_FREQ_8MD256);
std::cout << "pseudo_i2s_start\n";
std::flush(std::cout);
ESP_ERROR_CHECK(esp_sleep_pd_config(ESP_PD_DOMAIN_RTC8M, ESP_PD_OPTION_ON));
ESP_ERROR_CHECK(gpio_sleep_sel_dis(PIN_PSUEDO_I2S)); // Needed for light sleep.
// Prepare and then apply the LEDC PWM timer configuration
ESP_ERROR_CHECK(ledc_timer_config(&ledc_timer));
ESP_ERROR_CHECK(ledc_channel_config(&ledc_channel));
ESP_ERROR_CHECK(ledc_set_duty(LEDC_MODE, LEDC_CHANNEL, 1));
std::cout << "pseudo_i2s_start done\n";
std::flush(std::cout);
ESP_ERROR_CHECK(ledc_update_duty(LEDC_MODE, LEDC_CHANNEL));
std::cout << "pseudo_i2s_start done\n";
std::flush(std::cout);
}
void pseudo_i2s_stop()
{
ESP_ERROR_CHECK(ledc_stop(LEDC_MODE, LEDC_CHANNEL, 0));
pinMode(PIN_PSUEDO_I2S, INPUT);
} |
Hello!
I've been messing around with the ESP32 but I've run into an issue. I want to keep the PWM peripherals running when the ESP32 sleeps, but it seems that the LEDc module is paused during light and deep sleep. Is it possible to find a workaround where the LEDc module can run during light sleep?
I've found this on the ESP32 forums outlining a possible workaround
Thank you!
The text was updated successfully, but these errors were encountered: