Calculate PWM wrap dynamically whenever the frequency is changed (#4294)

fixes https://github.com/esphome/issues/issues/3841
This commit is contained in:
tradeJmark 2023-01-15 21:17:57 -04:00 committed by GitHub
parent 27185265f6
commit a45646af1b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 11 additions and 3 deletions

View file

@ -9,6 +9,7 @@
#include <hardware/clocks.h> #include <hardware/clocks.h>
#include <hardware/gpio.h> #include <hardware/gpio.h>
#include <hardware/pwm.h> #include <hardware/pwm.h>
#include <cmath>
namespace esphome { namespace esphome {
namespace rp2040_pwm { namespace rp2040_pwm {
@ -23,8 +24,14 @@ void RP2040PWM::setup() {
void RP2040PWM::setup_pwm_() { void RP2040PWM::setup_pwm_() {
pwm_config config = pwm_get_default_config(); 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); 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); 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 } // namespace rp2040_pwm

View file

@ -34,6 +34,7 @@ class RP2040PWM : public output::FloatOutput, public Component {
InternalGPIOPin *pin_; InternalGPIOPin *pin_;
float frequency_{1000.0}; float frequency_{1000.0};
uint16_t wrap_{65535};
/// Cache last output level for dynamic frequency updating /// Cache last output level for dynamic frequency updating
float last_output_{0.0}; float last_output_{0.0};
bool frequency_changed_{false}; bool frequency_changed_{false};