mirror of
https://github.com/esphome/esphome.git
synced 2026-10-01 08:50:22 +00:00
[modbus] Speed up the bus with microsecond-accurate timing (#12421)
This commit is contained in:
@@ -11,7 +11,14 @@ namespace esphome::modbus::testing {
|
||||
// A UART that discards all writes, for tests that never inspect the wire.
|
||||
class NullUART : public uart::UARTComponent {
|
||||
public:
|
||||
NullUART() { this->set_baud_rate(115200); }
|
||||
// 8N1, matching what the uart schema emits for a real hub; the framing drives the modbus
|
||||
// interframe timing, so leaving data/stop bits at their zero defaults would not be representative.
|
||||
NullUART() {
|
||||
this->set_baud_rate(115200);
|
||||
this->set_data_bits(8);
|
||||
this->set_stop_bits(1);
|
||||
this->set_parity(uart::UART_CONFIG_PARITY_NONE);
|
||||
}
|
||||
void write_array(const uint8_t *data, size_t len) override {}
|
||||
bool peek_byte(uint8_t *data) override { return false; }
|
||||
bool read_array(uint8_t *data, size_t len) override { return false; }
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "common.h"
|
||||
#include "esphome/components/modbus/modbus.h"
|
||||
|
||||
namespace esphome::modbus::testing {
|
||||
|
||||
namespace {
|
||||
|
||||
// Exposes the timing values setup() derives from the UART framing.
|
||||
class FramingProbeHub : public ModbusClientHub {
|
||||
public:
|
||||
uint32_t bits_per_char() const { return this->bits_per_char_; }
|
||||
uint32_t frame_delay_us() const { return this->frame_delay_us_; }
|
||||
};
|
||||
|
||||
class FramedUART : public NullUART {
|
||||
public:
|
||||
FramedUART(uint32_t baud_rate, uint8_t data_bits, uint8_t stop_bits, uart::UARTParityOptions parity) {
|
||||
this->set_baud_rate(baud_rate);
|
||||
this->set_data_bits(data_bits);
|
||||
this->set_stop_bits(stop_bits);
|
||||
this->set_parity(parity);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
// 8N1 is 10 bits on the wire, so t3.5 at 9600 baud is 3.5 * 10 / 9600 = 3645.8us.
|
||||
TEST(ModbusFraming, EightNoneOneDerivesTenBits) {
|
||||
FramedUART uart(9600, 8, 1, uart::UART_CONFIG_PARITY_NONE);
|
||||
FramingProbeHub hub;
|
||||
hub.set_uart_parent(&uart);
|
||||
hub.setup();
|
||||
|
||||
EXPECT_EQ(hub.bits_per_char(), 10u);
|
||||
EXPECT_EQ(hub.frame_delay_us(), 3646u);
|
||||
}
|
||||
|
||||
// Spec-conformant RTU framing is 11 bits, which lengthens the interframe gap to
|
||||
// 3.5 * 11 / 9600 = 4010.4us, rounded up.
|
||||
TEST(ModbusFraming, EightEvenOneDerivesElevenBits) {
|
||||
FramedUART uart(9600, 8, 1, uart::UART_CONFIG_PARITY_EVEN);
|
||||
FramingProbeHub hub;
|
||||
hub.set_uart_parent(&uart);
|
||||
hub.setup();
|
||||
|
||||
EXPECT_EQ(hub.bits_per_char(), 11u);
|
||||
EXPECT_EQ(hub.frame_delay_us(), 4011u);
|
||||
}
|
||||
|
||||
// Above 19200 baud the spec's fixed 1750us floor governs instead of 3.5 characters.
|
||||
TEST(ModbusFraming, FastBaudUsesSpecFloor) {
|
||||
FramedUART uart(115200, 8, 1, uart::UART_CONFIG_PARITY_NONE);
|
||||
FramingProbeHub hub;
|
||||
hub.set_uart_parent(&uart);
|
||||
hub.setup();
|
||||
|
||||
EXPECT_EQ(hub.frame_delay_us(), 1750u);
|
||||
}
|
||||
|
||||
} // namespace esphome::modbus::testing
|
||||
Reference in New Issue
Block a user