1
0
mirror of https://github.com/esphome/esphome.git synced 2025-04-16 07:40:29 +01:00

[uart] Add hardware flow control

This commit is contained in:
brambo123 2025-01-17 15:36:20 +01:00
parent 9e40d4cf45
commit f96069196f
4 changed files with 33 additions and 1 deletions

View File

@ -11,6 +11,7 @@ from esphome.const import (
CONF_NUMBER, CONF_NUMBER,
CONF_RX_PIN, CONF_RX_PIN,
CONF_TX_PIN, CONF_TX_PIN,
CONF_FLOW_CONTROL_PIN,
CONF_PORT, CONF_PORT,
CONF_UART_ID, CONF_UART_ID,
CONF_DATA, CONF_DATA,
@ -116,6 +117,11 @@ def validate_rx_pin(value):
raise cv.Invalid("Pins GPIO16 and GPIO17 cannot be used as RX pins on ESP8266.") raise cv.Invalid("Pins GPIO16 and GPIO17 cannot be used as RX pins on ESP8266.")
return value return value
def validate_flow_control_support(config):
if CONF_FLOW_CONTROL_PIN in config and not CORE.is_esp32:
raise cv.Invalid("Hardware does not support flow control.")
return config
def validate_invert_esp32(config): def validate_invert_esp32(config):
if ( if (
@ -239,6 +245,7 @@ CONFIG_SCHEMA = cv.All(
cv.Required(CONF_BAUD_RATE): cv.int_range(min=1), cv.Required(CONF_BAUD_RATE): cv.int_range(min=1),
cv.Optional(CONF_TX_PIN): pins.internal_gpio_output_pin_schema, cv.Optional(CONF_TX_PIN): pins.internal_gpio_output_pin_schema,
cv.Optional(CONF_RX_PIN): validate_rx_pin, cv.Optional(CONF_RX_PIN): validate_rx_pin,
cv.Optional(CONF_FLOW_CONTROL_PIN): pins.internal_gpio_output_pin_schema,
cv.Optional(CONF_PORT): cv.All(validate_port, cv.only_on(PLATFORM_HOST)), cv.Optional(CONF_PORT): cv.All(validate_port, cv.only_on(PLATFORM_HOST)),
cv.Optional(CONF_RX_BUFFER_SIZE, default=256): cv.validate_bytes, cv.Optional(CONF_RX_BUFFER_SIZE, default=256): cv.validate_bytes,
cv.Optional(CONF_STOP_BITS, default=1): cv.one_of(1, 2, int=True), cv.Optional(CONF_STOP_BITS, default=1): cv.one_of(1, 2, int=True),
@ -254,6 +261,7 @@ CONFIG_SCHEMA = cv.All(
).extend(cv.COMPONENT_SCHEMA), ).extend(cv.COMPONENT_SCHEMA),
cv.has_at_least_one_key(CONF_TX_PIN, CONF_RX_PIN, CONF_PORT), cv.has_at_least_one_key(CONF_TX_PIN, CONF_RX_PIN, CONF_PORT),
validate_invert_esp32, validate_invert_esp32,
validate_flow_control_support,
validate_host_config, validate_host_config,
) )
@ -296,6 +304,9 @@ async def to_code(config):
if CONF_RX_PIN in config: if CONF_RX_PIN in config:
rx_pin = await cg.gpio_pin_expression(config[CONF_RX_PIN]) rx_pin = await cg.gpio_pin_expression(config[CONF_RX_PIN])
cg.add(var.set_rx_pin(rx_pin)) cg.add(var.set_rx_pin(rx_pin))
if CONF_FLOW_CONTROL_PIN in config:
flow_control_pin = await cg.gpio_pin_expression(config[CONF_FLOW_CONTROL_PIN])
cg.add(var.set_flow_control_pin(flow_control_pin))
if CONF_PORT in config: if CONF_PORT in config:
cg.add(var.set_name(config[CONF_PORT])) cg.add(var.set_name(config[CONF_PORT]))
cg.add(var.set_rx_buffer_size(config[CONF_RX_BUFFER_SIZE])) cg.add(var.set_rx_buffer_size(config[CONF_RX_BUFFER_SIZE]))

View File

@ -82,6 +82,10 @@ class UARTComponent {
// @param rx_pin Pointer to the internal GPIO pin used for reception. // @param rx_pin Pointer to the internal GPIO pin used for reception.
void set_rx_pin(InternalGPIOPin *rx_pin) { this->rx_pin_ = rx_pin; } void set_rx_pin(InternalGPIOPin *rx_pin) { this->rx_pin_ = rx_pin; }
// Sets the flow control pin for the UART bus.
// @param rx_pin Pointer to the internal GPIO pin used for reception.
void set_flow_control_pin(InternalGPIOPin *flow_control_pin) { this->flow_control_pin_ = flow_control_pin; }
// Sets the size of the RX buffer. // Sets the size of the RX buffer.
// @param rx_buffer_size Size of the RX buffer in bytes. // @param rx_buffer_size Size of the RX buffer in bytes.
void set_rx_buffer_size(size_t rx_buffer_size) { this->rx_buffer_size_ = rx_buffer_size; } void set_rx_buffer_size(size_t rx_buffer_size) { this->rx_buffer_size_ = rx_buffer_size; }
@ -161,6 +165,7 @@ class UARTComponent {
InternalGPIOPin *tx_pin_; InternalGPIOPin *tx_pin_;
InternalGPIOPin *rx_pin_; InternalGPIOPin *rx_pin_;
InternalGPIOPin *flow_control_pin_;
size_t rx_buffer_size_; size_t rx_buffer_size_;
uint32_t baud_rate_; uint32_t baud_rate_;
uint8_t stop_bits_; uint8_t stop_bits_;

View File

@ -141,6 +141,10 @@ void ESP32ArduinoUARTComponent::load_settings(bool dump_config) {
invert = true; invert = true;
this->hw_serial_->setRxBufferSize(this->rx_buffer_size_); this->hw_serial_->setRxBufferSize(this->rx_buffer_size_);
this->hw_serial_->begin(this->baud_rate_, get_config(), rx, tx, invert); this->hw_serial_->begin(this->baud_rate_, get_config(), rx, tx, invert);
if (this->flow_control_pin_ != nullptr) {
this->hw_serial_->setPins(-1, -1, -1, this->flow_control_pin_->get_pin());
this->hw_serial_->setMode(UART_MODE_RS485_HALF_DUPLEX);
}
if (dump_config) { if (dump_config) {
ESP_LOGCONFIG(TAG, "UART %u was reloaded.", this->number_); ESP_LOGCONFIG(TAG, "UART %u was reloaded.", this->number_);
this->dump_config(); this->dump_config();
@ -151,6 +155,7 @@ void ESP32ArduinoUARTComponent::dump_config() {
ESP_LOGCONFIG(TAG, "UART Bus %d:", this->number_); ESP_LOGCONFIG(TAG, "UART Bus %d:", this->number_);
LOG_PIN(" TX Pin: ", tx_pin_); LOG_PIN(" TX Pin: ", tx_pin_);
LOG_PIN(" RX Pin: ", rx_pin_); LOG_PIN(" RX Pin: ", rx_pin_);
LOG_PIN(" Flow Control Pin: ", flow_control_pin_);
if (this->rx_pin_ != nullptr) { if (this->rx_pin_ != nullptr) {
ESP_LOGCONFIG(TAG, " RX Buffer Size: %u", this->rx_buffer_size_); ESP_LOGCONFIG(TAG, " RX Buffer Size: %u", this->rx_buffer_size_);
} }

View File

@ -106,6 +106,7 @@ void IDFUARTComponent::setup() {
int8_t tx = this->tx_pin_ != nullptr ? this->tx_pin_->get_pin() : -1; int8_t tx = this->tx_pin_ != nullptr ? this->tx_pin_->get_pin() : -1;
int8_t rx = this->rx_pin_ != nullptr ? this->rx_pin_->get_pin() : -1; int8_t rx = this->rx_pin_ != nullptr ? this->rx_pin_->get_pin() : -1;
int8_t flow_control = this->flow_control_pin_ != nullptr ? this->flow_control_pin_->get_pin() : -1;
uint32_t invert = 0; uint32_t invert = 0;
if (this->tx_pin_ != nullptr && this->tx_pin_->is_inverted()) if (this->tx_pin_ != nullptr && this->tx_pin_->is_inverted())
@ -120,7 +121,7 @@ void IDFUARTComponent::setup() {
return; return;
} }
err = uart_set_pin(this->uart_num_, tx, rx, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE); err = uart_set_pin(this->uart_num_, tx, rx, flow_control, UART_PIN_NO_CHANGE);
if (err != ESP_OK) { if (err != ESP_OK) {
ESP_LOGW(TAG, "uart_set_pin failed: %s", esp_err_to_name(err)); ESP_LOGW(TAG, "uart_set_pin failed: %s", esp_err_to_name(err));
this->mark_failed(); this->mark_failed();
@ -139,6 +140,15 @@ void IDFUARTComponent::setup() {
return; return;
} }
if (this->flow_control_pin_ != nullptr) {
err = uart_set_mode(this->uart_num_, UART_MODE_RS485_HALF_DUPLEX);
if (err != ESP_OK) {
ESP_LOGW(TAG, "uart_set_mode failed: %s", esp_err_to_name(err));
this->mark_failed();
return;
}
}
xSemaphoreGive(this->lock_); xSemaphoreGive(this->lock_);
} }
@ -159,6 +169,7 @@ void IDFUARTComponent::dump_config() {
ESP_LOGCONFIG(TAG, "UART Bus %u:", this->uart_num_); ESP_LOGCONFIG(TAG, "UART Bus %u:", this->uart_num_);
LOG_PIN(" TX Pin: ", tx_pin_); LOG_PIN(" TX Pin: ", tx_pin_);
LOG_PIN(" RX Pin: ", rx_pin_); LOG_PIN(" RX Pin: ", rx_pin_);
LOG_PIN(" Flow Control Pin: ", flow_control_pin_);
if (this->rx_pin_ != nullptr) { if (this->rx_pin_ != nullptr) {
ESP_LOGCONFIG(TAG, " RX Buffer Size: %u", this->rx_buffer_size_); ESP_LOGCONFIG(TAG, " RX Buffer Size: %u", this->rx_buffer_size_);
} }