diff --git a/esphome/components/rp2040_pwm/rp2040_pwm.cpp b/esphome/components/rp2040_pwm/rp2040_pwm.cpp index 664a3734f7..3c5591885e 100644 --- a/esphome/components/rp2040_pwm/rp2040_pwm.cpp +++ b/esphome/components/rp2040_pwm/rp2040_pwm.cpp @@ -9,6 +9,7 @@ #include #include #include +#include namespace esphome { namespace rp2040_pwm { @@ -23,8 +24,14 @@ void RP2040PWM::setup() { void RP2040PWM::setup_pwm_() { pwm_config config = pwm_get_default_config(); - pwm_config_set_clkdiv(&config, clock_get_hz(clk_sys) / (255.0f * this->frequency_)); - pwm_config_set_wrap(&config, 254); + + uint32_t clock = clock_get_hz(clk_sys); + float divider = ceil(clock / (4096 * this->frequency_)) / 16.0f; + uint16_t wrap = clock / divider / this->frequency_ - 1; + this->wrap_ = wrap; + + pwm_config_set_clkdiv(&config, divider); + pwm_config_set_wrap(&config, wrap); pwm_init(pwm_gpio_to_slice_num(this->pin_->get_pin()), &config, true); } @@ -48,7 +55,7 @@ void HOT RP2040PWM::write_state(float state) { } gpio_set_function(this->pin_->get_pin(), GPIO_FUNC_PWM); - pwm_set_gpio_level(this->pin_->get_pin(), state * 255.0f); + pwm_set_gpio_level(this->pin_->get_pin(), state * this->wrap_); } } // namespace rp2040_pwm diff --git a/esphome/components/rp2040_pwm/rp2040_pwm.h b/esphome/components/rp2040_pwm/rp2040_pwm.h index 9c88826ae9..e499e72b06 100644 --- a/esphome/components/rp2040_pwm/rp2040_pwm.h +++ b/esphome/components/rp2040_pwm/rp2040_pwm.h @@ -34,6 +34,7 @@ class RP2040PWM : public output::FloatOutput, public Component { InternalGPIOPin *pin_; float frequency_{1000.0}; + uint16_t wrap_{65535}; /// Cache last output level for dynamic frequency updating float last_output_{0.0}; bool frequency_changed_{false};