mirror of
https://github.com/esphome/esphome.git
synced 2025-02-18 01:03:12 +01:00
Allow setting htop for ledc (#6340)
This commit is contained in:
parent
b95a7f6438
commit
b0db7319f9
5 changed files with 26 additions and 2 deletions
|
@ -96,6 +96,12 @@ esp_err_t configure_timer_frequency(ledc_mode_t speed_mode, ledc_timer_t timer_n
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_ESP_IDF
|
||||||
|
constexpr int ledc_angle_to_htop(float angle, uint8_t bit_depth) {
|
||||||
|
return static_cast<int>(angle * ((1U << bit_depth) - 1) / 360.);
|
||||||
|
}
|
||||||
|
#endif // USE_ESP_IDF
|
||||||
|
|
||||||
void LEDCOutput::write_state(float state) {
|
void LEDCOutput::write_state(float state) {
|
||||||
if (!initialized_) {
|
if (!initialized_) {
|
||||||
ESP_LOGW(TAG, "LEDC output hasn't been initialized yet!");
|
ESP_LOGW(TAG, "LEDC output hasn't been initialized yet!");
|
||||||
|
@ -117,7 +123,8 @@ void LEDCOutput::write_state(float state) {
|
||||||
#ifdef USE_ESP_IDF
|
#ifdef USE_ESP_IDF
|
||||||
auto speed_mode = get_speed_mode(channel_);
|
auto speed_mode = get_speed_mode(channel_);
|
||||||
auto chan_num = static_cast<ledc_channel_t>(channel_ % 8);
|
auto chan_num = static_cast<ledc_channel_t>(channel_ % 8);
|
||||||
ledc_set_duty(speed_mode, chan_num, duty);
|
int hpoint = ledc_angle_to_htop(this->phase_angle_, this->bit_depth_);
|
||||||
|
ledc_set_duty_with_hpoint(speed_mode, chan_num, duty, hpoint);
|
||||||
ledc_update_duty(speed_mode, chan_num);
|
ledc_update_duty(speed_mode, chan_num);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -143,8 +150,10 @@ void LEDCOutput::setup() {
|
||||||
this->status_set_error();
|
this->status_set_error();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
int hpoint = ledc_angle_to_htop(this->phase_angle_, this->bit_depth_);
|
||||||
|
|
||||||
ESP_LOGV(TAG, "Configured frequency %f with a bit depth of %u bits", this->frequency_, this->bit_depth_);
|
ESP_LOGV(TAG, "Configured frequency %f with a bit depth of %u bits", this->frequency_, this->bit_depth_);
|
||||||
|
ESP_LOGV(TAG, "Angle of %.1f° results in hpoint %u", this->phase_angle_, hpoint);
|
||||||
|
|
||||||
ledc_channel_config_t chan_conf{};
|
ledc_channel_config_t chan_conf{};
|
||||||
chan_conf.gpio_num = pin_->get_pin();
|
chan_conf.gpio_num = pin_->get_pin();
|
||||||
|
@ -153,7 +162,7 @@ void LEDCOutput::setup() {
|
||||||
chan_conf.intr_type = LEDC_INTR_DISABLE;
|
chan_conf.intr_type = LEDC_INTR_DISABLE;
|
||||||
chan_conf.timer_sel = timer_num;
|
chan_conf.timer_sel = timer_num;
|
||||||
chan_conf.duty = inverted_ == pin_->is_inverted() ? 0 : (1U << bit_depth_);
|
chan_conf.duty = inverted_ == pin_->is_inverted() ? 0 : (1U << bit_depth_);
|
||||||
chan_conf.hpoint = 0;
|
chan_conf.hpoint = hpoint;
|
||||||
ledc_channel_config(&chan_conf);
|
ledc_channel_config(&chan_conf);
|
||||||
initialized_ = true;
|
initialized_ = true;
|
||||||
this->status_clear_error();
|
this->status_clear_error();
|
||||||
|
@ -165,6 +174,7 @@ void LEDCOutput::dump_config() {
|
||||||
LOG_PIN(" Pin ", this->pin_);
|
LOG_PIN(" Pin ", this->pin_);
|
||||||
ESP_LOGCONFIG(TAG, " LEDC Channel: %u", this->channel_);
|
ESP_LOGCONFIG(TAG, " LEDC Channel: %u", this->channel_);
|
||||||
ESP_LOGCONFIG(TAG, " PWM Frequency: %.1f Hz", this->frequency_);
|
ESP_LOGCONFIG(TAG, " PWM Frequency: %.1f Hz", this->frequency_);
|
||||||
|
ESP_LOGCONFIG(TAG, " Phase angle: %.1f°", this->phase_angle_);
|
||||||
ESP_LOGCONFIG(TAG, " Bit depth: %u", this->bit_depth_);
|
ESP_LOGCONFIG(TAG, " Bit depth: %u", this->bit_depth_);
|
||||||
ESP_LOGV(TAG, " Max frequency for bit depth: %f", ledc_max_frequency_for_bit_depth(this->bit_depth_));
|
ESP_LOGV(TAG, " Max frequency for bit depth: %f", ledc_max_frequency_for_bit_depth(this->bit_depth_));
|
||||||
ESP_LOGV(TAG, " Min frequency for bit depth: %f",
|
ESP_LOGV(TAG, " Min frequency for bit depth: %f",
|
||||||
|
|
|
@ -19,6 +19,7 @@ class LEDCOutput : public output::FloatOutput, public Component {
|
||||||
|
|
||||||
void set_channel(uint8_t channel) { this->channel_ = channel; }
|
void set_channel(uint8_t channel) { this->channel_ = channel; }
|
||||||
void set_frequency(float frequency) { this->frequency_ = frequency; }
|
void set_frequency(float frequency) { this->frequency_ = frequency; }
|
||||||
|
void set_phase_angle(float angle) { this->phase_angle_ = angle; }
|
||||||
/// Dynamically change frequency at runtime
|
/// Dynamically change frequency at runtime
|
||||||
void update_frequency(float frequency) override;
|
void update_frequency(float frequency) override;
|
||||||
|
|
||||||
|
@ -35,6 +36,7 @@ class LEDCOutput : public output::FloatOutput, public Component {
|
||||||
InternalGPIOPin *pin_;
|
InternalGPIOPin *pin_;
|
||||||
uint8_t channel_{};
|
uint8_t channel_{};
|
||||||
uint8_t bit_depth_{};
|
uint8_t bit_depth_{};
|
||||||
|
float phase_angle_{0.0f};
|
||||||
float frequency_{};
|
float frequency_{};
|
||||||
float duty_{0.0f};
|
float duty_{0.0f};
|
||||||
bool initialized_ = false;
|
bool initialized_ = false;
|
||||||
|
|
|
@ -3,6 +3,7 @@ from esphome.components import output
|
||||||
import esphome.config_validation as cv
|
import esphome.config_validation as cv
|
||||||
import esphome.codegen as cg
|
import esphome.codegen as cg
|
||||||
from esphome.const import (
|
from esphome.const import (
|
||||||
|
CONF_PHASE_ANGLE,
|
||||||
CONF_CHANNEL,
|
CONF_CHANNEL,
|
||||||
CONF_FREQUENCY,
|
CONF_FREQUENCY,
|
||||||
CONF_ID,
|
CONF_ID,
|
||||||
|
@ -46,6 +47,9 @@ CONFIG_SCHEMA = output.FLOAT_OUTPUT_SCHEMA.extend(
|
||||||
cv.Required(CONF_PIN): pins.internal_gpio_output_pin_schema,
|
cv.Required(CONF_PIN): pins.internal_gpio_output_pin_schema,
|
||||||
cv.Optional(CONF_FREQUENCY, default="1kHz"): cv.frequency,
|
cv.Optional(CONF_FREQUENCY, default="1kHz"): cv.frequency,
|
||||||
cv.Optional(CONF_CHANNEL): cv.int_range(min=0, max=15),
|
cv.Optional(CONF_CHANNEL): cv.int_range(min=0, max=15),
|
||||||
|
cv.Optional(CONF_PHASE_ANGLE): cv.All(
|
||||||
|
cv.only_with_esp_idf, cv.angle, cv.float_range(min=0.0, max=360.0)
|
||||||
|
),
|
||||||
}
|
}
|
||||||
).extend(cv.COMPONENT_SCHEMA)
|
).extend(cv.COMPONENT_SCHEMA)
|
||||||
|
|
||||||
|
@ -58,6 +62,8 @@ async def to_code(config):
|
||||||
if CONF_CHANNEL in config:
|
if CONF_CHANNEL in config:
|
||||||
cg.add(var.set_channel(config[CONF_CHANNEL]))
|
cg.add(var.set_channel(config[CONF_CHANNEL]))
|
||||||
cg.add(var.set_frequency(config[CONF_FREQUENCY]))
|
cg.add(var.set_frequency(config[CONF_FREQUENCY]))
|
||||||
|
if CONF_PHASE_ANGLE in config:
|
||||||
|
cg.add(var.set_phase_angle(config[CONF_PHASE_ANGLE]))
|
||||||
|
|
||||||
|
|
||||||
@automation.register_action(
|
@automation.register_action(
|
||||||
|
|
|
@ -2,9 +2,12 @@ output:
|
||||||
- platform: ledc
|
- platform: ledc
|
||||||
id: light_output_1
|
id: light_output_1
|
||||||
pin: 1
|
pin: 1
|
||||||
|
channel: 0
|
||||||
- platform: ledc
|
- platform: ledc
|
||||||
id: light_output_2
|
id: light_output_2
|
||||||
pin: 2
|
pin: 2
|
||||||
|
channel: 1
|
||||||
|
phase_angle: 180°
|
||||||
|
|
||||||
light:
|
light:
|
||||||
- platform: cwww
|
- platform: cwww
|
||||||
|
|
|
@ -2,9 +2,12 @@ output:
|
||||||
- platform: ledc
|
- platform: ledc
|
||||||
id: light_output_1
|
id: light_output_1
|
||||||
pin: 12
|
pin: 12
|
||||||
|
channel: 0
|
||||||
- platform: ledc
|
- platform: ledc
|
||||||
id: light_output_2
|
id: light_output_2
|
||||||
pin: 13
|
pin: 13
|
||||||
|
channel: 1
|
||||||
|
phase_angle: 180°
|
||||||
|
|
||||||
light:
|
light:
|
||||||
- platform: cwww
|
- platform: cwww
|
||||||
|
|
Loading…
Add table
Reference in a new issue