跳转到内容

UART 总线

UART 是许多设备的常见串行协议。例如,当您将二进制文件上传到 ESP 时, 您可能已经使用 UART 访问了芯片。UART(或在 Arduino 中通常也称为 Serial)通常 由 2 个引脚组成:

  • TX: 此线用于向另一端的设备发送数据。
  • RX: 此线用于从另一端的设备接收数据。

请注意,这两个引脚的命名取决于所选的视角,可能会有歧义。例如, 虽然 ESP 可能在引脚 A 上发送(TX)并在引脚 B 上接收(RX)数据,但从另一设备的角度来看,这两个引脚是交换的(即在引脚 B 上发送并在引脚 A 上接收)。所以如果立即不起作用,您可能需要尝试交换这两个引脚。

此外,每个 UART 总线可以以不同的速度(波特率)运行,所以 ESPHome 需要知道使用 baud_rate 选项以什么速度接收/发送数据。两个常见的波特率是 9600 和 115200。

在某些情况下,只有 TXRX 存在,因为另一端的设备只接受数据或只发送数据。

UART 组件可以用作 数据包传输组件 的平台,使传感器数据能够直接从一个 ESPHome 节点通过 UART 总线发送到另一个节点。使用 RS485 时,这可以在多点配置下运行。

NOTE

在 ESP32 上,此组件使用硬件 UART 单元,因此非常准确。但在 ESP8266 上, ESPHome 必须使用软件实现,因为除了用于日志记录的硬件 UART 单元外没有其他可用的硬件 UART 单元。因此,ESP8266 上的 UART 数据可能会有偶尔的数据故障,特别是在较高波特率下。

NOTE

从 ESPHome 2021.8 开始,ESP8266SoftwareSerial UART write_byte 函数的奇偶校验位已修复为对发送的数据正确。如果您使用软件 UART 且有明确检查奇偶校验的设备,这可能会导致意外问题。您很可能需要在 YAML 中翻转 parity 标志。

NOTE

主机平台的 UART 实现不使用 TX 和 RX 引脚,而是使用端口名称。

# 示例配置项
uart:
tx_pin: GPIOXX
rx_pin: GPIOXX
baud_rate: 9600
  • baud_rate (Required, int): UART 总线的波特率。

  • tx_pin (Optional, Pin): 从 ESP 角度发送数据的引脚。使用完整引脚 模式并设置 inverted: true 以反转逻辑电平。主机平台不支持。

  • rx_pin (Optional, Pin): 从 ESP 角度接收数据的引脚。使用完整引脚 模式并设置 inverted: true 以反转逻辑电平。主机平台不支持。

  • flow_control_pin (Optional, Pin): 仅限 ESP32。用于硬件 RS485 流控制的引脚。 使用此设置可启用半双工模式。使用完整引脚模式并设置 inverted: true 以反转逻辑电平。

  • port (Optional, string): 仅限主机平台。要使用的端口的 Unix 风格名称。

  • rx_buffer_size (Optional, int): 用于接收 UART 消息的缓冲区大小。如果您使用的 集成需要从 UART 读取大负载,请增加此值。默认为 256

  • rx_full_threshold (Optional, int): 仅限 ESP32。接收到此字节数后,数据变得可供处理。 默认值在编译时计算,大约为十毫秒(9600 波特下约 8 字节,115200 波特下约 114 字节)。

  • rx_timeout (Optional, int): 仅限 ESP32。此值指定用于确定超时持续时间的字节数。超时持续时间基于接收此字节数所需的时间量。换句话说,对于给定的值和波特率,波特率加倍将使超时持续时间减半。超时过后,数据变得可供处理。默认为 2

  • data_bits (Optional, int): UART 总线上使用的数据位数。选项:5 到 8。默认为 8。

  • parity (Optional): UART 总线上使用的奇偶校验。选项:NONEEVENODD。默认为 NONE

  • stop_bits (Optional, int): 要发送的停止位数。选项:1、2。默认为 1。

  • id (Optional, ID): 如果需要多个 UART 集线器,手动为此 UART 集线器指定 ID。

  • debug (Optional, mapping): 用于调试 UART 集线器上通信的选项,请参阅 调试

在可能的情况下,ESPHome 将使用 ESP8266 上的硬件 UART 单元进行快速准确的通信。 当所有硬件 UART 都被占用时,ESPHome 将回退到软件实现,该实现在较高波特率下可能不准确。

UART0(默认)被日志组件使用,使用 tx_pin: GPIO1rx_pin: GPIO3。如果您配置的 UART 与这些引脚重叠,您可以与 日志记录器共享硬件,并将其他硬件留给其他用途。如果您已将日志记录器配置为使用不同的硬件 UART,用于硬件共享的引脚会相应更改。

原始 ESP32 有三个 UART。ESP32 变体(ESP32-C3、ESP32-S2 等)可能有不同数量的 UART (通常在两到六个之间)。任何 GPIO 引脚对都可以使用,只要它们支持正确的输出/输入模式。

ESP8266 有两个 UART;其中第二个仅支持 TX。只有有限的引脚集可以使用。UART0 可以使用 tx_pin: GPIO1rx_pin: GPIO3,或 tx_pin: GPIO15rx_pin: GPIO13UART1 必须使用 tx_pin: GPIO2。任何其他引脚组合将导致使用软件 UART。

NOTE

软件 UART 仅在 ESP8266 上可用。在 ESP32 及其变体上不可用。

动作 向给定的 UART 总线发送定义的 UART 信号。

on_...:
- uart.write: 'Hello World'
# 对于转义字符,必须使用双引号!
- uart.write: "Hello World\r\n"
# 原始数据
- uart.write: [0x00, 0x20, 0x42]
# 使用模板,返回类型是 std::vector<uint8_t>
- uart.write: !lambda
return {0x00, 0x20, 0x42};
# 如果您需要指定 uart id
- uart.write:
id: my_second_uart
data: 'other data'

如果您需要了解通过 UART 总线发送和/或接收的通信,可以使用调试功能。

# 示例配置项
uart:
baud_rate: 115200
debug:
direction: BOTH
dummy_receiver: false
after:
delimiter: "\n"
sequence:
- lambda: UARTDebug::log_string(direction, bytes);
# 最小配置示例,默认记录十六进制字符串
uart:
baud_rate: 9600
debug:
  • direction (Optional, enum): 要调试的通信方向,可选值之一:“RX”(接收,传入)、 “TX”(发送,传出)或 “BOTH”。默认为 “BOTH”。

  • dummy_receiver (Optional, boolean): 是否启用虚拟接收器功能。调试器 只会累积实际被 UART 设备组件读取或发送的字节。当您想调试所有传入通信, 而尚未为 UART 总线配置 UART 设备组件时,此功能很有用。这对开发者特别有用。通常您会希望保持此选项禁用。默认为 false。

  • after (Optional, mapping): 调试器累积通信字节。此选项定义何时 触发发布累积的字节。可能的选项有:

    • bytes (Optional, int): 累积指定数量的字节后触发。默认为 150。

    • timeout (Optional, Time): 在指定的超时时间内没有看到通信, 而已累积一个或多个字节时触发。默认为 100ms。

    • delimiter (Optional, string 或字节列表): 在通信中检测到指定的字节序列后 触发。

  • sequence (Optional, Action): 用于发布调试数据的动作。 默认为以十六进制格式记录字节的动作。动作可以使用以下变量:

    • direction: uart::UART_DIRECTION_RXuart::UART_DIRECTION_TX
    • bytes: 包含累积字节的 std::vector<uint8_t>

    日志记录辅助函数

    提供了辅助函数,使以各种格式记录调试数据变得容易:

    • UARTDebug::log_hex(direction, bytes, char separator) 将字节记录为十六进制值,用提供的分隔符字符分隔。

    • UARTDebug::log_string(direction, bytes) 将字节记录为字符串值,转义不可打印字符。

    • UARTDebug::log_int(direction, bytes, char separator) 将字节记录为整数值,用提供的分隔符字符分隔。

    • UARTDebug::log_binary(direction, bytes, char separator) 将字节记录为 <binary> (<hex>) 值, 用提供的分隔符字符分隔。

    日志缓冲区大小

    请注意,logger 组件默认使用 512 字节的有限缓冲区大小。如果 UART 调试器日志行变得太长,您会注意到它们在日志输出中被截断。

    在这种情况下,要么确保调试器每行日志输出较少的数据(例如,通过将 after.bytes 选项设置为较低的值),要么使用日志记录器的 tx_buffer_size 选项增加日志缓冲区大小。

在某些情况下,您可能需要在运行时调整 UART 参数以提高通信效率 并适应不同的操作条件。ESPHome 通过 lambda 调用实现了这一点。 以下是读取当前设置和动态修改它们的方法:

  • 读取当前设置: 使用这些只读属性访问 UART 的当前配置:
// RX 缓冲区大小
id(my_uart).get_rx_buffer_size();
// RX FIFO 满阈值
id(my_uart).get_rx_full_threshold();
// RX 超时
id(my_uart).get_rx_timeout();
// 停止位
id(my_uart).get_stop_bits();
// 数据位
id(my_uart).get_data_bits();
// 奇偶校验
id(my_uart).get_parity();
// 波特率
id(my_uart).get_baud_rate();
  • 在运行时修改设置: 您可以在运行时更改某些 UART 参数。 设置新值后,调用 load_settings()(仅限 ESP)以应用这些更改:
select:
- id: change_baud_rate
name: 波特率
platform: template
options:
- "2400"
- "9600"
- "38400"
- "57600"
- "115200"
- "256000"
- "512000"
- "921600"
initial_option: "115200"
optimistic: true
restore_value: True
internal: false
entity_category: config
icon: mdi:swap-horizontal
set_action:
- lambda: |-
id(my_uart).flush();
uint32_t new_baud_rate = stoi(x);
ESP_LOGD("change_baud_rate", "将波特率从 %i 更改为 %i",id(my_uart).get_baud_rate(),
new_baud_rate);
if (id(my_uart).get_baud_rate() != new_baud_rate) {
id(my_uart).set_baud_rate(new_baud_rate);
id(my_uart).load_settings();
}

可用于运行时更改的方法:

// 设置 TX/RX/流控制引脚
id(my_uart).set_tx_pin(InternalGPIOPin *tx_pin);
id(my_uart).set_rx_pin(InternalGPIOPin *rx_pin);
id(my_uart).set_flow_control_pin(InternalGPIOPin *flow_control_pin);
// RX 缓冲区大小
id(my_uart).set_rx_buffer_size(size_t rx_buffer_size);
// RX FIFO 满阈值(以字节为单位)
id(my_uart).set_rx_full_threshold(size_t rx_full_threshold);
// RX FIFO 满阈值(以时间单位)
id(my_uart).set_rx_full_threshold_ms(uint8_t time);
// RX 超时
id(my_uart).set_rx_timeout(size_t rx_timeout);
// 停止位
id(my_uart).set_stop_bits(uint8_t stop_bits);
// 数据位
id(my_uart).set_data_bits(uint8_t data_bits);
// 奇偶校验
id(my_uart).set_parity(UARTParityOptions parity);
// 波特率
id(my_uart).set_baud_rate(uint32_t baud_rate);

这种灵活性允许动态适应不同的通信要求,增强您的 ESPHome 设置的多功能性。

由于主机平台没有物理 UART 引脚,UART 组件使用 Unix 风格的端口实现。 您可以使用端口名称来指定要使用的端口,而不是使用引脚。此实现还支持具有 require_txrequire_rx 选项的组件,如 smt100 等。

# 主机平台的示例配置项
uart:
baud_rate: 9600
port: "/dev/ttyUSB0"