diff --git a/esphome/components/modbus/modbus.cpp b/esphome/components/modbus/modbus.cpp index 28e26e307e3..da5bfa5ef85 100644 --- a/esphome/components/modbus/modbus.cpp +++ b/esphome/components/modbus/modbus.cpp @@ -21,8 +21,14 @@ void Modbus::setup() { // 3.5 characters * 11 bits per character * 1000ms/sec / (bits/sec) (Standard modbus frame delay) (uint16_t) (3.5 * 11 * 1000 / this->parent_->get_baud_rate()) + 1); - this->long_rx_buffer_delay_ms_ = - (this->parent_->get_rx_full_threshold() * 11 * 1000 / this->parent_->get_baud_rate()) + 1; + // When rx_full_threshold is configured (non-zero), the UART has a hardware FIFO with a + // meaningful threshold (e.g., ESP32 native UART), so we can calculate a precise delay. + // Otherwise (e.g., USB UART), use 50ms to handle data arriving in chunks. + static constexpr uint16_t DEFAULT_LONG_RX_BUFFER_DELAY_MS = 50; + size_t rx_threshold = this->parent_->get_rx_full_threshold(); + this->long_rx_buffer_delay_ms_ = rx_threshold != uart::UARTComponent::RX_FULL_THRESHOLD_UNSET + ? (rx_threshold * 11 * 1000 / this->parent_->get_baud_rate()) + 1 + : DEFAULT_LONG_RX_BUFFER_DELAY_MS; } void Modbus::loop() { diff --git a/esphome/components/uart/uart_component.h b/esphome/components/uart/uart_component.h index 078ce64b30f..3d2a848462e 100644 --- a/esphome/components/uart/uart_component.h +++ b/esphome/components/uart/uart_component.h @@ -187,7 +187,10 @@ class UARTComponent { InternalGPIOPin *rx_pin_{}; InternalGPIOPin *flow_control_pin_{}; size_t rx_buffer_size_{}; - size_t rx_full_threshold_{1}; + static constexpr size_t RX_FULL_THRESHOLD_UNSET = 0; + // ESP-IDF always sets this at codegen time via set_rx_full_threshold(). + // Other platforms (USB UART, Arduino, etc.) leave it unset. + size_t rx_full_threshold_{RX_FULL_THRESHOLD_UNSET}; size_t rx_timeout_{0}; uint32_t baud_rate_{0}; uint8_t stop_bits_{0};