From 26c98a1e257cd78b29ae59123439042894952b7d Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Fri, 6 Feb 2026 23:54:52 +0100 Subject: [PATCH] [ld2420] Batch UART reads to reduce loop overhead --- esphome/components/ld2420/ld2420.cpp | 30 +++++++++++++++++++++++----- esphome/components/ld2420/ld2420.h | 2 ++ 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/esphome/components/ld2420/ld2420.cpp b/esphome/components/ld2420/ld2420.cpp index 10c623bce0..2abeccc7ac 100644 --- a/esphome/components/ld2420/ld2420.cpp +++ b/esphome/components/ld2420/ld2420.cpp @@ -335,9 +335,10 @@ void LD2420Component::revert_config_action() { void LD2420Component::loop() { // If there is a active send command do not process it here, the send command call will handle it. - while (!this->cmd_active_ && this->available()) { - this->readline_(this->read(), this->buffer_data_, MAX_LINE_LENGTH); + if (this->cmd_active_) { + return; } + this->read_batch_(this->buffer_data_); } void LD2420Component::update_radar_data(uint16_t const *gate_energy, uint8_t sample_number) { @@ -539,6 +540,27 @@ void LD2420Component::handle_simple_mode_(const uint8_t *inbuf, int len) { } } +void LD2420Component::read_batch_(std::span buffer) { + int avail = this->available(); + if (avail == 0) { + return; + } + + // Read all available bytes in batches to reduce UART call overhead. + uint8_t buf[MAX_LINE_LENGTH]; + while (avail > 0) { + size_t to_read = std::min(static_cast(avail), sizeof(buf)); + if (!this->read_array(buf, to_read)) { + break; + } + avail -= to_read; + + for (size_t i = 0; i < to_read; i++) { + this->readline_(buf[i], buffer.data(), buffer.size()); + } + } +} + void LD2420Component::handle_ack_data_(uint8_t *buffer, int len) { this->cmd_reply_.command = buffer[CMD_FRAME_COMMAND]; this->cmd_reply_.length = buffer[CMD_FRAME_DATA_LENGTH]; @@ -645,9 +667,7 @@ int LD2420Component::send_cmd_from_array(CmdFrameT frame) { } while (!this->cmd_reply_.ack) { - while (this->available()) { - this->readline_(this->read(), ack_buffer, sizeof(ack_buffer)); - } + this->read_batch_(ack_buffer); delay_microseconds_safe(1450); // Wait on an Rx from the LD2420 for up to 3 1 second loops, otherwise it could trigger a WDT. if ((millis() - start_millis) > 1000) { diff --git a/esphome/components/ld2420/ld2420.h b/esphome/components/ld2420/ld2420.h index 50ddf45264..6d81f86497 100644 --- a/esphome/components/ld2420/ld2420.h +++ b/esphome/components/ld2420/ld2420.h @@ -4,6 +4,7 @@ #include "esphome/components/uart/uart.h" #include "esphome/core/automation.h" #include "esphome/core/helpers.h" +#include #ifdef USE_TEXT_SENSOR #include "esphome/components/text_sensor/text_sensor.h" #endif @@ -165,6 +166,7 @@ class LD2420Component : public Component, public uart::UARTDevice { void handle_energy_mode_(uint8_t *buffer, int len); void handle_ack_data_(uint8_t *buffer, int len); void readline_(int rx_data, uint8_t *buffer, int len); + void read_batch_(std::span buffer); void set_calibration_(bool state) { this->calibration_ = state; }; bool get_calibration_() { return this->calibration_; };