7 #include <esp32-hal-ledc.h> 9 #include <driver/ledc.h> 11 #define CLOCK_FREQUENCY 80e6f 14 #ifdef SOC_LEDC_SUPPORT_XTAL_CLOCK 15 #undef CLOCK_FREQUENCY 17 #define CLOCK_FREQUENCY 40e6f 20 #ifdef SOC_LEDC_SUPPORT_APB_CLOCK 21 #define DEFAULT_CLK LEDC_USE_APB_CLK 23 #define DEFAULT_CLK LEDC_AUTO_CLK 27 static const uint8_t SETUP_ATTEMPT_COUNT_MAX = 5;
32 static const char *
const TAG =
"ledc.output";
34 static const int MAX_RES_BITS = LEDC_TIMER_BIT_MAX - 1;
36 #if SOC_LEDC_SUPPORT_HS_MODE 38 inline ledc_mode_t
get_speed_mode(uint8_t channel) {
return channel < 8 ? LEDC_HIGH_SPEED_MODE : LEDC_LOW_SPEED_MODE; }
43 inline ledc_mode_t
get_speed_mode(uint8_t) {
return LEDC_LOW_SPEED_MODE; }
50 const float max_div_num = ((1 << MAX_RES_BITS) - 1) / (low_frequency ? 32.0f : 256.0f);
51 return CLOCK_FREQUENCY / (max_div_num * float(1 << bit_depth));
55 ESP_LOGD(TAG,
"Calculating resolution bit-depth for frequency %f", frequency);
56 for (
int i = MAX_RES_BITS; i >= 1; i--) {
59 if (min_frequency <= frequency && frequency <= max_frequency) {
60 ESP_LOGD(TAG,
"Resolution calculated as %d", i);
69 uint8_t channel, uint8_t &bit_depth,
float frequency) {
72 ESP_LOGE(TAG,
"Frequency %f can't be achieved with any bit depth", frequency);
75 ledc_timer_config_t timer_conf{};
76 timer_conf.speed_mode = speed_mode;
77 timer_conf.duty_resolution =
static_cast<ledc_timer_bit_t
>(bit_depth);
78 timer_conf.timer_num = timer_num;
79 timer_conf.freq_hz = (uint32_t) frequency;
80 timer_conf.clk_cfg = DEFAULT_CLK;
83 int attempt_count_max = SETUP_ATTEMPT_COUNT_MAX;
84 esp_err_t init_result = ESP_FAIL;
85 while (attempt_count_max > 0 && init_result != ESP_OK) {
86 init_result = ledc_timer_config(&timer_conf);
87 if (init_result != ESP_OK) {
88 ESP_LOGW(TAG,
"Unable to initialize timer with frequency %.1f and bit depth of %u", frequency, bit_depth);
90 timer_conf.duty_resolution =
static_cast<ledc_timer_bit_t
>(--bit_depth);
101 return static_cast<int>(angle * ((1U << bit_depth) - 1) / 360.);
103 #endif // USE_ESP_IDF 107 ESP_LOGW(TAG,
"LEDC output hasn't been initialized yet!");
112 state = 1.0f - state;
115 const uint32_t max_duty = (uint32_t(1) << this->
bit_depth_) - 1;
116 const float duty_rounded = roundf(state * max_duty);
117 auto duty =
static_cast<uint32_t
>(duty_rounded);
120 ESP_LOGV(TAG,
"Setting duty: %u on channel %u", duty, this->
channel_);
125 auto chan_num =
static_cast<ledc_channel_t
>(
channel_ % 8);
127 ledc_set_duty_with_hpoint(speed_mode, chan_num, duty, hpoint);
128 ledc_update_duty(speed_mode, chan_num);
133 ESP_LOGV(TAG,
"Entering setup...");
142 auto timer_num =
static_cast<ledc_timer_t
>((
channel_ % 8) / 2);
143 auto chan_num =
static_cast<ledc_channel_t
>(
channel_ % 8);
145 esp_err_t timer_init_result =
148 if (timer_init_result != ESP_OK) {
149 ESP_LOGE(TAG,
"Frequency %f can't be achieved with computed bit depth %u", this->
frequency_, this->
bit_depth_);
155 ESP_LOGV(TAG,
"Configured frequency %f with a bit depth of %u bits", this->
frequency_, this->
bit_depth_);
156 ESP_LOGV(TAG,
"Angle of %.1f° results in hpoint %u", this->
phase_angle_, hpoint);
158 ledc_channel_config_t chan_conf{};
160 chan_conf.speed_mode = speed_mode;
161 chan_conf.channel = chan_num;
162 chan_conf.intr_type = LEDC_INTR_DISABLE;
163 chan_conf.timer_sel = timer_num;
165 chan_conf.hpoint = hpoint;
166 ledc_channel_config(&chan_conf);
173 ESP_LOGCONFIG(TAG,
"LEDC Output:");
174 LOG_PIN(
" Pin ", this->
pin_);
175 ESP_LOGCONFIG(TAG,
" LEDC Channel: %u", this->
channel_);
176 ESP_LOGCONFIG(TAG,
" PWM Frequency: %.1f Hz", this->
frequency_);
177 ESP_LOGCONFIG(TAG,
" Phase angle: %.1f°", this->
phase_angle_);
178 ESP_LOGCONFIG(TAG,
" Bit depth: %u", this->
bit_depth_);
180 ESP_LOGV(TAG,
" Min frequency for bit depth: %f",
183 ESP_LOGV(TAG,
" Min frequency for bit depth-1: %f",
186 ESP_LOGV(TAG,
" Min frequency for bit depth+1: %f",
188 ESP_LOGV(TAG,
" Max res bits: %d", MAX_RES_BITS);
189 ESP_LOGV(TAG,
" Clock frequency: %f", CLOCK_FREQUENCY);
194 if (!bit_depth_opt.has_value()) {
195 ESP_LOGE(TAG,
"Frequency %f can't be achieved with any bit depth", this->
frequency_);
201 ESP_LOGV(TAG,
"Using Arduino API - Trying to define channel, frequency and bit depth...");
202 u_int32_t configured_frequency = 0;
205 int attempt_count_max = SETUP_ATTEMPT_COUNT_MAX;
206 while (attempt_count_max > 0 && configured_frequency == 0) {
207 ESP_LOGV(TAG,
"Trying initialize channel %u with frequency %.1f and bit depth of %u...", this->
channel_,
210 if (configured_frequency != 0) {
213 ESP_LOGV(TAG,
"Configured frequency: %u with bit depth: %u", configured_frequency, this->
bit_depth_);
215 ESP_LOGW(TAG,
"Unable to initialize channel %u with frequency %.1f and bit depth of %u", this->
channel_,
223 if (configured_frequency == 0) {
224 ESP_LOGE(TAG,
"Permanently failed to initialize channel %u with frequency %.1f and bit depth of %u", this->
channel_,
230 #endif // USE_ARDUINO 233 ESP_LOGW(TAG,
"LEDC output hasn't been initialized yet!");
238 auto timer_num =
static_cast<ledc_timer_t
>((
channel_ % 8) / 2);
239 auto chan_num =
static_cast<ledc_channel_t
>(
channel_ % 8);
241 esp_err_t timer_init_result =
244 if (timer_init_result != ESP_OK) {
245 ESP_LOGE(TAG,
"Frequency %f can't be achieved with computed bit depth %u", this->
frequency_, this->
bit_depth_);
virtual void turn_off()
Disable this binary output.
uint8_t next_ledc_channel
void update_frequency(float frequency) override
Dynamically change frequency at runtime.
virtual uint8_t get_pin() const =0
void status_set_error(const char *message="unspecified")
ledc_mode_t get_speed_mode(uint8_t channel)
void write_state(float state) override
Override FloatOutput's write_state.
void status_clear_error()
constexpr int ledc_angle_to_htop(float angle, uint8_t bit_depth)
void setup() override
Setup LEDC.
void dump_config() override
float ledc_min_frequency_for_bit_depth(uint8_t bit_depth, bool low_frequency)
optional< uint8_t > ledc_bit_depth_for_frequency(float frequency)
This is a workaround until we can figure out a way to get the tflite-micro idf component code availab...
esp_err_t configure_timer_frequency(ledc_mode_t speed_mode, ledc_timer_t timer_num, ledc_channel_t chan_num, uint8_t channel, uint8_t &bit_depth, float frequency)
float ledc_max_frequency_for_bit_depth(uint8_t bit_depth)
virtual bool is_inverted() const =0