diff --git a/esphome/components/sensor/__init__.py b/esphome/components/sensor/__init__.py index 2acdaed589..650f5ed826 100644 --- a/esphome/components/sensor/__init__.py +++ b/esphome/components/sensor/__init__.py @@ -810,7 +810,7 @@ async def calibrate_polynomial_filter_to_code(config, filter_id): # Column vector b = [[v] for v in y] res = [v[0] for v in _lstsq(a, b)] - return cg.new_Pvariable(filter_id, res) + return cg.new_Pvariable(filter_id, cg.TemplateArguments(len(res)), res) def validate_clamp(config): diff --git a/esphome/components/sensor/filter.cpp b/esphome/components/sensor/filter.cpp index 90e1b82793..a226ed5af1 100644 --- a/esphome/components/sensor/filter.cpp +++ b/esphome/components/sensor/filter.cpp @@ -383,14 +383,11 @@ optional calibrate_linear_compute(const std::array *functions, return NAN; } -CalibratePolynomialFilter::CalibratePolynomialFilter(std::initializer_list coefficients) - : coefficients_(coefficients) {} - -optional CalibratePolynomialFilter::new_value(float value) { +optional calibrate_polynomial_compute(const float *coefficients, size_t count, float value) { float res = 0.0f; float x = 1.0f; - for (const auto &coefficient : this->coefficients_) { - res += x * coefficient; + for (size_t i = 0; i < count; i++) { + res += x * coefficients[i]; x *= value; } return res; diff --git a/esphome/components/sensor/filter.h b/esphome/components/sensor/filter.h index 7560c28986..8bb495edd2 100644 --- a/esphome/components/sensor/filter.h +++ b/esphome/components/sensor/filter.h @@ -566,13 +566,26 @@ template class CalibrateLinearFilter : public Filter { std::array, N> linear_functions_{}; }; -class CalibratePolynomialFilter : public Filter { +/// Non-template helper for polynomial calibration (implementation in filter.cpp) +optional calibrate_polynomial_compute(const float *coefficients, size_t count, float value); + +/// N is set by code generation to match the exact number of polynomial coefficients. +template class CalibratePolynomialFilter : public Filter { public: - explicit CalibratePolynomialFilter(std::initializer_list coefficients); - optional new_value(float value) override; + explicit CalibratePolynomialFilter(std::initializer_list coefficients) { + size_t i = 0; + for (float c : coefficients) { + if (i >= N) + break; + this->coefficients_[i++] = c; + } + } + optional new_value(float value) override { + return calibrate_polynomial_compute(this->coefficients_.data(), N, value); + } protected: - FixedVector coefficients_; + std::array coefficients_{}; }; class ClampFilter : public Filter {