mirror of
https://github.com/esphome/esphome-docs.git
synced 2024-12-24 17:08:15 +01:00
Modbus controller docs (#1388)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
This commit is contained in:
parent
32ae4bf8e2
commit
33ba298b13
69
components/binary_sensor/modbus_controller.rst
Normal file
69
components/binary_sensor/modbus_controller.rst
Normal file
@ -0,0 +1,69 @@
|
||||
Modbus Binary Sensor
|
||||
====================
|
||||
|
||||
.. seo::
|
||||
:description: Instructions for setting up a modbus_controller device binary sensor.
|
||||
:image: modbus.png
|
||||
|
||||
The ``modbus_controller`` binary sensor platform creates a binary sensor from a modbus_controller component
|
||||
and requires :doc:`/components/modbus_controller` to be configured.
|
||||
|
||||
|
||||
Configuration variables:
|
||||
------------------------
|
||||
|
||||
- **id** (*Optional*, :ref:`config-id`): Manually specify the ID used for code generation.
|
||||
- **name** (**Required**, string): The name of the sensor.
|
||||
- **modbus_functioncode** (**Required**): type of the modbus register.
|
||||
- "read_coils": Function 01 (01hex) Read Coils - Reads the ON/OFF status of discrete coils in the device.
|
||||
- "read_discrete_inputs": Function 02(02hex) - Reads the ON/OFF status of discrete inputs in the device.
|
||||
- "read_holding_registers": Function 03 (03hex) Read Holding Registers - Read the binary contents of holding registers in the device.
|
||||
- "read_input_registers": Function 04 (04hex) Read Input Registers - Read the binary contents of input registers in the device.
|
||||
|
||||
- **address**: (**Required**, integer): start address of the first register in a range
|
||||
- **bitmask** : some values are packed in a response. The bitmask is used to determined if the result is true or false
|
||||
- **skip_updates**: (*Optional*, integer): By default all sensors of of a modbus_controller are updated together. For data points that don't change very frequently updates can be skipped. A value of 5 would only update this sensor range in every 5th update cycle
|
||||
- **force_new_range**: (*Optional*, boolean): If possible sensors with sequential addresses are grouped together and requested in one range. Setting `foce_new_range: true` enforces the start of a new range at that address.
|
||||
- **lambda** (*Optional*, :ref:`lambda <config-lambda>`):
|
||||
Lambda to be evaluated every update interval to get the new value of the sensor
|
||||
- **offset**: (*Optional*, integer): not required for most cases
|
||||
offset from start address in bytes. If more than one register is read a modbus read registers command this value is used to find the start of this datapoint relative to start address. The component calculates the size of the range based on offset and size of the value type
|
||||
The value for offset depends on the register type. If a binary_sensor is created from an input register the offset is in bytes. For coil and discrete input resisters the LSB of the first data byte contains the coil addressed in the request. The other coils follow toward the high-order end of this byte and from low order to high order in subsequent bytes. For the registers offset is the position of the relevant bit.
|
||||
To get the value of the coil register 2 can be retrived using address: 2 / offset: 0 or address: 0 / offset 2
|
||||
|
||||
|
||||
Example
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
binary_sensor:
|
||||
- platform: modbus_controller
|
||||
modbus_controller_id: epever
|
||||
id: battery_internal_resistance_abnormal
|
||||
name: "Battery internal resistance abnormal"
|
||||
register_type: read
|
||||
address: 0x3200
|
||||
bitmask: 0x80 #(bit 8)
|
||||
|
||||
|
||||
Parameters passed into the lambda
|
||||
|
||||
- **x** (bool): The parsed float value of the modbus data
|
||||
- **data** (std::vector<uint8_t): vector containing the complete raw modbus response bytes for this sensor
|
||||
- **item** (const pointer to a ModbusBinarySensor object): The sensor object itself.
|
||||
|
||||
Possible return values for the lambda:
|
||||
|
||||
- ``return true/false;`` the new value for the sensor.
|
||||
|
||||
|
||||
See Also
|
||||
--------
|
||||
- :apiclass:`:modbus_controller::ModbusBinarySensor`
|
||||
- :doc:`/components/modbus_controller`
|
||||
- :doc:`/components/switch/modbus_controller`
|
||||
- :doc:`/components/output/modbus_controller`
|
||||
- :doc:`/components/sensor/modbus_controller`
|
||||
- :doc:`/components/text_sensor/modbus_controller`
|
||||
- https://www.modbustools.com/modbus.html
|
||||
- :ghedit:`Edit`
|
@ -39,9 +39,9 @@ Configuration variables:
|
||||
:ref:`float output <output>` connected to Pin A (alternatively IN1, etc.) of the h-bridge.
|
||||
- **pin_b** (**Required**, :ref:`config-id`): The id of the
|
||||
:ref:`float output <output>` connected to Pin B (alternatively IN2, etc.) of the h-bridge.
|
||||
- **enable_pin** (**Optional**, :ref:`config-id`): The id of the
|
||||
- **enable_pin** (*Optional*, :ref:`config-id`): The id of the
|
||||
:ref:`float output <output>` connected to the Enable pin of the h-bridge (if h-bridge uses enable).
|
||||
- **decay_mode** (**Optional**, string): The decay mode you want to use with
|
||||
- **decay_mode** (*Optional*, string): The decay mode you want to use with
|
||||
the h-bridge. Either ``slow`` (braking) or ``fast`` (coasting). Defaults to ``slow``.
|
||||
- **name** (**Required**, string): The name for this fan.
|
||||
- **oscillation_output** (*Optional*, :ref:`config-id`): The id of the
|
||||
|
@ -24,8 +24,14 @@ Configuration variables:
|
||||
------------------------
|
||||
|
||||
- **flow_control_pin** (*Optional*, :ref:`config-pin`): The pin used to switch flow control.
|
||||
This is useful for RS485 transeivers that do not have automatic flow control switching,
|
||||
like the common MAX485.
|
||||
This is useful for RS485 transeivers that do not have automatic flow control switching,
|
||||
like the common MAX485.
|
||||
|
||||
- **send_wait_time** (*Optional*, :ref:`time`): Time in milliseconds before a new modbus command is sent if an answer from a previous command is pending. Defaults to 250 ms.
|
||||
If multiple modbus devices are attached increasing this value can help avoiding to to overlapping reads.
|
||||
When 2 devices are sending a command at the same the the response read from uart can't be assigend to the proper design.
|
||||
This value defines the maximumm queuing time for a command before it is send anyways.
|
||||
|
||||
|
||||
See Also
|
||||
--------
|
||||
|
464
components/modbus_controller.rst
Normal file
464
components/modbus_controller.rst
Normal file
@ -0,0 +1,464 @@
|
||||
Modbus Controller
|
||||
=================
|
||||
|
||||
.. seo::
|
||||
:description: Instructions for setting up the Modbus Controller component.
|
||||
:image: modbus.png
|
||||
|
||||
The ``modbus_controller`` component creates a RS485 connection to control a modbus device
|
||||
|
||||
.. warning::
|
||||
|
||||
If you are using the :doc:`logger` uart logging might interfere especially on esp8266. You can disable the uart logging with the ``baud_rate: 0`` option.
|
||||
|
||||
.. figure:: /images/modbus.png
|
||||
:align: center
|
||||
:width: 25%
|
||||
|
||||
The ``modbus_controller`` component uses the modbus component
|
||||
|
||||
|
||||
|
||||
Hardware setup
|
||||
--------------
|
||||
I'm using a RS 485 module connected to an ESP32
|
||||
|
||||
.. figure:: /images/rs485.jpg
|
||||
|
||||
See [How is this RS485 Module Working?](https://electronics.stackexchange.com/questions/244425/how-is-this-rs485-module-working) on stackexchange for more details
|
||||
|
||||
The controller connects to the UART of the MCU. For ESP32 GPIO PIN 16 to TXD PIN 17 to RXD are the default ports but any other pins can be used as well . 3.3V to VCC and GND to GND.
|
||||
|
||||
|
||||
Configuration variables:
|
||||
------------------------
|
||||
|
||||
- **modbus_id** (*Optional*, :ref:`config-id`): Manually specify the ID of the modbus hub.
|
||||
|
||||
- **address** (*Required*, :ref:`config-id`): The modbus address of the device
|
||||
Specify the modbus device address of the.
|
||||
|
||||
- **command_throttle** (*Optional*, int): minimum time in milliseconds between 2 requests to the device. Default is 0ms
|
||||
Because some modbus devices limit the rate of requests the interval between sending requests to the device can be modified.
|
||||
|
||||
|
||||
Getting started with Home Assistant
|
||||
-----------------------------------
|
||||
The following code create a modbus_controller hub talking to a modbus device at address 1 with 115200 bps
|
||||
|
||||
|
||||
Modbus sensors can be directly defined (inline) under the modbus_controller hub or as standalone components
|
||||
Technically there is no difference between the "inline" and the standard definitions approach.
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
esphome:
|
||||
name: solarstation
|
||||
platform: ESP32
|
||||
board: esp32dev
|
||||
|
||||
substitutions:
|
||||
updates: 30s
|
||||
|
||||
wifi:
|
||||
ssid: !secret wifi_sid
|
||||
password: !secret wifi_password
|
||||
reboot_timeout: 2min
|
||||
|
||||
logger:
|
||||
level: INFO
|
||||
baud_rate: 0
|
||||
|
||||
api:
|
||||
password: !secret api_password
|
||||
|
||||
uart:
|
||||
id: mod_bus
|
||||
tx_pin: 17
|
||||
rx_pin: 16
|
||||
baud_rate: 115200
|
||||
stop_bits: 1
|
||||
|
||||
modbus:
|
||||
flow_control_pin: 5
|
||||
id: modbus1
|
||||
|
||||
modbus_controller:
|
||||
- id: epever
|
||||
## the Modbus device addr
|
||||
address: 0x1
|
||||
modbus_id: modbus1
|
||||
setup_priority: -10
|
||||
|
||||
text_sensor:
|
||||
- name: "rtc_clock"
|
||||
platform: modbus_controller
|
||||
modbus_controller_id: epever
|
||||
id: rtc_clock
|
||||
internal: true
|
||||
register_type: holding
|
||||
address: 0x9013
|
||||
register_count: 3
|
||||
raw_encode: HEXBYTES
|
||||
response_size: 6
|
||||
|
||||
switch:
|
||||
- platform: modbus_controller
|
||||
modbus_controller_id: epever
|
||||
id: reset_to_fabric_default
|
||||
name: "Reset to Factory Default"
|
||||
register_type: coil
|
||||
address: 0x15
|
||||
bitmask: 1
|
||||
|
||||
sensor:
|
||||
- platform: modbus_controller
|
||||
modbus_controller_id: epever
|
||||
name: "Battery Capacity"
|
||||
id: battery_capacity
|
||||
register_type: holding
|
||||
address: 0x9001
|
||||
unit_of_measurement: "AH"
|
||||
value_type: U_WORD
|
||||
|
||||
|
||||
Protocol decoding example
|
||||
-------------------------
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
sensors:
|
||||
- platform: modbus_controller
|
||||
modbus_controller_id: epever
|
||||
id: array_rated_voltage
|
||||
name: "array_rated_voltage"
|
||||
address: 0x3000
|
||||
unit_of_measurement: "V"
|
||||
register_type: read
|
||||
value_type: U_WORD
|
||||
accuracy_decimals: 1
|
||||
skip_updates: 60
|
||||
filters:
|
||||
- multiply: 0.01
|
||||
|
||||
- platform: modbus_controller
|
||||
modbus_controller_id: epever
|
||||
id: array_rated_current
|
||||
name: "array_rated_current"
|
||||
address: 0x3001
|
||||
unit_of_measurement: "V"
|
||||
register_type: read
|
||||
value_type: U_WORD
|
||||
accuracy_decimals: 2
|
||||
filters:
|
||||
- multiply: 0.01
|
||||
|
||||
- platform: modbus_controller
|
||||
modbus_controller_id: epever
|
||||
id: array_rated_power
|
||||
name: "array_rated_power"
|
||||
address: 0x3002
|
||||
unit_of_measurement: "W"
|
||||
register_type: read
|
||||
value_type: U_DWORD_R
|
||||
accuracy_decimals: 1
|
||||
filters:
|
||||
- multiply: 0.01
|
||||
|
||||
-platform: modbus_controller
|
||||
modbus_controller_id: epever
|
||||
id: battery_rated_voltage
|
||||
name: "battery_rated_voltage"
|
||||
address: 0x3004
|
||||
unit_of_measurement: "V"
|
||||
register_type: read
|
||||
value_type: U_WORD
|
||||
accuracy_decimals: 1
|
||||
filters:
|
||||
- multiply: 0.01
|
||||
|
||||
- platform: modbus_controller
|
||||
modbus_controller_id: epever
|
||||
id: battery_rated_current
|
||||
name: "battery_rated_current"
|
||||
address: 0x3005
|
||||
unit_of_measurement: "A"
|
||||
register_type: read
|
||||
value_type: U_WORD
|
||||
accuracy_decimals: 1
|
||||
filters:
|
||||
- multiply: 0.01
|
||||
|
||||
- platform: modbus_controller
|
||||
modbus_controller_id: epever
|
||||
id: battery_rated_power
|
||||
name: "battery_rated_power"
|
||||
address: 0x3006
|
||||
unit_of_measurement: "W"
|
||||
register_type: read
|
||||
value_type: U_DWORD_R
|
||||
accuracy_decimals: 1
|
||||
filters:
|
||||
- multiply: 0.01
|
||||
|
||||
- platform: modbus_controller
|
||||
modbus_controller_id: epever id: charging_mode
|
||||
name: "charging_mode"
|
||||
address: 0x3008
|
||||
unit_of_measurement: ""
|
||||
register_type: read
|
||||
value_type: U_WORD
|
||||
accuracy_decimals: 0
|
||||
|
||||
|
||||
|
||||
To minimize the required transactions all registers with the same base address are read in one request.
|
||||
The response is mapped to the sensor based on register_count and offset in bytes.
|
||||
|
||||
**Request**
|
||||
|
||||
+-----------+-----------------------------------------+
|
||||
| data | description |
|
||||
+===========+=========================================+
|
||||
| 0x1 (01) | device address |
|
||||
+-----------+-----------------------------------------+
|
||||
| 0x4 (04) | function code 4 (Read Input Registers) |
|
||||
+-----------+-----------------------------------------+
|
||||
| 0x30 (48) | start address high byte |
|
||||
+-----------+-----------------------------------------+
|
||||
| 0x0 (00) | start address low byte |
|
||||
+-----------+-----------------------------------------+
|
||||
| 0x0 (00) | number of registers to read high byte |
|
||||
+-----------+-----------------------------------------+
|
||||
| 0x9 (09) | number of registers to read low byte |
|
||||
+-----------+-----------------------------------------+
|
||||
| 0x3f (63) | crc |
|
||||
+-----------+-----------------------------------------+
|
||||
| 0xc (12) | crc |
|
||||
+-----------+-----------------------------------------+
|
||||
|
||||
|
||||
**Response**
|
||||
|
||||
+--------+------------+--------------------+--------------------------------------------+
|
||||
| offset | data | value (type) | description |
|
||||
+========+============+====================+============================================+
|
||||
| H | 0x1 (01) | | device address |
|
||||
+--------+------------+--------------------+--------------------------------------------+
|
||||
| H | 0x4 (04) | | function code |
|
||||
+--------+------------+--------------------+--------------------------------------------+
|
||||
| H | 0x12 (18) | | byte count |
|
||||
+--------+------------+--------------------+--------------------------------------------+
|
||||
| 0 | 0x27 (39) | U_WORD | array_rated_voltage high byte |
|
||||
+--------+------------+--------------------+--------------------------------------------+
|
||||
| 1 | 0x10 (16) | 0x2710 (100000) | array_rated_voltage low byte |
|
||||
+--------+------------+--------------------+--------------------------------------------+
|
||||
| 2 | 0x7 (7) | U_WORD | array_rated_current high byte |
|
||||
+--------+------------+--------------------+--------------------------------------------+
|
||||
| 3 | 0xd0 (208) | 0x7d0 (2000) | array_rated_current low byte |
|
||||
+--------+------------+--------------------+--------------------------------------------+
|
||||
| 4 | 0xcb (203) | U_DWORD_R | array_rated_power high byte of low word |
|
||||
+--------+------------+--------------------+--------------------------------------------+
|
||||
| 5 | 0x20 (32) | spans 2 register | array_rated_power low byte of low word |
|
||||
+--------+------------+--------------------+--------------------------------------------+
|
||||
| 6 | 0x0 (0) | | array_rated_power high byte of high word |
|
||||
+--------+------------+--------------------+--------------------------------------------+
|
||||
| 7 | 0x0 (0) | 0x0000CB20 (52000) | array_rated_power low byte of high word |
|
||||
+--------+------------+--------------------+--------------------------------------------+
|
||||
| 8 | 0x9 (09) | U_WORD | battery_rated_voltage high byte |
|
||||
+--------+------------+--------------------+--------------------------------------------+
|
||||
| 9 | 0x60 (96) | 0x960 (2400) | battery_rated_voltage low byte |
|
||||
+--------+------------+--------------------+--------------------------------------------+
|
||||
| 10 | 0x7 (07) | U_WORD | battery_rated_current high word |
|
||||
+--------+------------+--------------------+--------------------------------------------+
|
||||
| 11 | 0xd0 (208) | 0x7d0 (2000) | battery_rated_current high word |
|
||||
+--------+------------+--------------------+--------------------------------------------+
|
||||
| 12 | 0xcb (203) | U_DWORD_R | battery_rated_power high byte of low word |
|
||||
+--------+------------+--------------------+--------------------------------------------+
|
||||
| 13 | 0x20 (32) | spans 2 register | battery_rated_power low byte of low word |
|
||||
+--------+------------+--------------------+--------------------------------------------+
|
||||
| 14 | 0x0 (0) | | battery_rated_power high byte of high word |
|
||||
+--------+------------+--------------------+--------------------------------------------+
|
||||
| 15 | 0x0 (0) | 0x0000CB20 (52000) | battery_rated_power low byte of high word |
|
||||
+--------+------------+--------------------+--------------------------------------------+
|
||||
| 16 | 0x0 (0) | U_WORD | charging_mode high byte |
|
||||
+--------+------------+--------------------+--------------------------------------------+
|
||||
| 17 | 0x2 (02) | 0x2 (MPPT) | charging_mode low byte |
|
||||
+--------+------------+--------------------+--------------------------------------------+
|
||||
| C | 0x2f (47) | | crc |
|
||||
+--------+------------+--------------------+--------------------------------------------+
|
||||
| C | 0x31 (49) | | crc |
|
||||
+--------+------------+--------------------+--------------------------------------------+
|
||||
|
||||
|
||||
|
||||
Note
|
||||
----
|
||||
|
||||
Write support is only implemented for switches.
|
||||
However the C++ code provides the required API to write to a modbus device.
|
||||
|
||||
These methods can be called from a lambda.
|
||||
|
||||
Here is an example how to set config values to for an EPEVER Trace AN controller.
|
||||
The code synchronizes the localtime of MCU to the epever controller
|
||||
The time is set by writing 12 bytes to register 0x9013.
|
||||
Then battery charge settings are sent.
|
||||
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
esphome:
|
||||
name: solarstation-test
|
||||
platform: ESP32
|
||||
board: esp32dev
|
||||
|
||||
## send config values at startup
|
||||
## configure rtc clock and battery charge settings
|
||||
on_boot:
|
||||
priority: -100
|
||||
then:
|
||||
- lambda: |-
|
||||
|
||||
on_boot:
|
||||
## configure controller settings at setup
|
||||
## make sure priority is lower than setup_priority of modbus_controller
|
||||
priority: -100
|
||||
then:
|
||||
- lambda: |-
|
||||
// get local time and sync to controller
|
||||
time_t now = ::time(nullptr);
|
||||
struct tm *time_info = ::localtime(&now);
|
||||
int seconds = time_info->tm_sec;
|
||||
int minutes = time_info->tm_min;
|
||||
int hour = time_info->tm_hour;
|
||||
int day = time_info->tm_mday;
|
||||
int month = time_info->tm_mon + 1;
|
||||
int year = time_info->tm_year % 100;
|
||||
esphome::modbus_controller::ModbusController *controller = id(epever);
|
||||
// if there is no internet connection localtime returns year 70
|
||||
if (year != 70) {
|
||||
// create the payload
|
||||
std::vector<uint16_t> rtc_data = {uint16_t((minutes << 8) | seconds), uint16_t((day << 8) | hour),
|
||||
uint16_t((year << 8) | month)};
|
||||
// Create a modbus command item with the time information as the payload
|
||||
esphome::modbus_controller::ModbusCommandItem set_rtc_command =
|
||||
esphome::modbus_controller::ModbusCommandItem::create_write_multiple_command(controller, 0x9013, 3, rtc_data);
|
||||
// Submit the command to the send queue
|
||||
epever->queue_command(set_rtc_command);
|
||||
ESP_LOGI("ModbusLambda", "EPSOLAR RTC set to %02d:%02d:%02d %02d.%02d.%04d", hour, minutes, seconds, day, month,
|
||||
year + 2000);
|
||||
}
|
||||
// Battery settings
|
||||
// Note: these values are examples only and apply my AGM Battery
|
||||
std::vector<uint16_t> battery_settings1 = {
|
||||
0, // 9000 Battery Type 0 = User
|
||||
0x0073, // 9001 Battery Cap 0x55 == 115AH
|
||||
0x012C, // 9002 Temp compensation -3V /°C/2V
|
||||
0x05DC, // 9003 0x5DC == 1500 Over Voltage Disconnect Voltage 15,0
|
||||
0x058C, // 9004 0x58C == 1480 Charging Limit Voltage 14,8
|
||||
0x058C, // 9005 Over Voltage Reconnect Voltage 14,8
|
||||
0x05BF, // 9006 Equalize Charging Voltage 14,6
|
||||
0x05BE, // 9007 Boost Charging Voltage 14,7
|
||||
0x0550, // 9008 Float Charging Voltage 13,6
|
||||
0x0528, // 9009 Boost Reconnect Charging Voltage 13,2
|
||||
0x04C4, // 900A Low Voltage Reconnect Voltage 12,2
|
||||
0x04B0, // 900B Under Voltage Warning Reconnect Voltage 12,0
|
||||
0x04BA, // 900c Under Volt. Warning Volt 12,1
|
||||
0x04BA, // 900d Low Volt. Disconnect Volt. 11.8
|
||||
0x04BA // 900E Discharging Limit Voltage 11.8
|
||||
};
|
||||
|
||||
// Boost and equalization periods
|
||||
std::vector<uint16_t> battery_settings2 = {
|
||||
0x0000, // 906B Equalize Duration (min.) 0
|
||||
0x0075 // 906C Boost Duration (aka absorb) 117 mins
|
||||
};
|
||||
esphome::modbus_controller::ModbusCommandItem set_battery1_command =
|
||||
esphome::modbus_controller::ModbusCommandItem::create_write_multiple_command(controller, 0x9000, battery_settings1.size() ,
|
||||
battery_settings1);
|
||||
|
||||
esphome::modbus_controller::ModbusCommandItem set_battery2_command =
|
||||
esphome::modbus_controller::ModbusCommandItem::create_write_multiple_command(controller, 0x906B, battery_settings3.size(),
|
||||
battery_settings2);
|
||||
delay(200) ;
|
||||
controller->queue_command(set_battery1_command);
|
||||
delay(200) ;
|
||||
controller->queue_command(set_battery2_command);
|
||||
ESP_LOGI("ModbusLambda", "EPSOLAR Battery set");
|
||||
|
||||
|
||||
|
||||
uart:
|
||||
id: mod_bus
|
||||
tx_pin: 19
|
||||
rx_pin: 18
|
||||
baud_rate: 115200
|
||||
stop_bits: 1
|
||||
|
||||
modbus:
|
||||
#flow_control_pin: 23
|
||||
send_wait_time: 200ms
|
||||
id: mod_bus_epever
|
||||
|
||||
modbus_controller:
|
||||
- id: epever
|
||||
## the Modbus device addr
|
||||
address: 0x1
|
||||
modbus_id: mod_bus_epever
|
||||
command_throttle: 0ms
|
||||
setup_priority: -10
|
||||
update_interval: ${updates}
|
||||
|
||||
sensor:
|
||||
- platform: modbus_controller
|
||||
modbus_controller_id: epever
|
||||
id: array_rated_voltage
|
||||
name: "array_rated_voltage"
|
||||
address: 0x3000
|
||||
unit_of_measurement: "V"
|
||||
register_type: read
|
||||
value_type: U_WORD
|
||||
accuracy_decimals: 1
|
||||
filters:
|
||||
- multiply: 0.01
|
||||
|
||||
- platform: modbus_controller
|
||||
modbus_controller_id: epever
|
||||
id: array_rated_current
|
||||
name: "array_rated_current"
|
||||
address: 0x3001
|
||||
unit_of_measurement: "A"
|
||||
register_type: read
|
||||
value_type: U_WORD
|
||||
accuracy_decimals: 2
|
||||
filters:
|
||||
- multiply: 0.01
|
||||
|
||||
- platform: modbus_controller
|
||||
modbus_controller_id: epever
|
||||
id: array_rated_power
|
||||
name: "array_rated_power"
|
||||
address: 0x3002
|
||||
unit_of_measurement: "W"
|
||||
register_type: read
|
||||
value_type: U_DWORD_R
|
||||
accuracy_decimals: 1
|
||||
filters:
|
||||
- multiply: 0.01
|
||||
|
||||
|
||||
|
||||
|
||||
See Also
|
||||
--------
|
||||
|
||||
- :doc:`/components/sensor/modbus_controller`
|
||||
- :doc:`/components/binary_sensor/modbus_controller`
|
||||
- :doc:`/components/text_sensor/modbus_controller`
|
||||
- :doc:`/components/switch/modbus_controller`
|
||||
- :doc:`/components/number/modbus_controller`
|
||||
- :doc:`/components/output/modbus_controller`
|
||||
- :doc:`EPEVER MPPT Solar Charge Controller Tracer-AN Series</cookbook/tracer-an>`
|
||||
- `Modbus RTU Protocol Description <https://www.modbustools.com/modbus.html>`__
|
||||
- :ghedit:`Edit`
|
112
components/number/modbus_controller.rst
Normal file
112
components/number/modbus_controller.rst
Normal file
@ -0,0 +1,112 @@
|
||||
Modbus Controller Number
|
||||
========================
|
||||
|
||||
.. seo::
|
||||
:description: Instructions for setting up a modbus_controller device sensor.
|
||||
:image: modbus_controller.png
|
||||
|
||||
The ``modbus_controller`` platform creates a Number from a modbus_controller.
|
||||
When the Number is updated a modbus write command is created sent to the device.
|
||||
|
||||
Configuration variables:
|
||||
------------------------
|
||||
|
||||
- **id** (*Optional*, :ref:`config-id`): Manually specify the ID used for code generation.
|
||||
- **name** (**Required**, string): The name of the sensor.
|
||||
- coil: coils are also called discrete outout. Coils are 1-bit registers (on/off values) that are used to control discrete outputs. Read and Write access
|
||||
- discrete_input: discrete input register (read only coil) are similar to coils but can only be read.
|
||||
- holding: Holding Registers - Holding registers are the most universal 16-bit register. Read and Write access
|
||||
- read: Read Input Registers - registers are 16-bit registers used for input, and may only be read
|
||||
- **address**: (**Required**, int): start address of the first register in a range
|
||||
- **value_type**: (**Required**): datatype of the mod_bus register data. The default data type for modbus is a 16 bit integer in big endian format (MSB first)
|
||||
- U_WORD (unsigned float from 1 register =16bit
|
||||
- S_WORD (signed float from one register)
|
||||
- U_DWORD (unsigned float from 2 registers = 32bit)
|
||||
- S_DWORD (unsigned float from 2 registers = 32bit)
|
||||
- U_DWORD_R (unsigend float from 2 registers low word first )
|
||||
- S_DWORD_R (sigend float from 2 registers low word first )
|
||||
- U_QWORD (unsigned float from 4 registers = 64bit
|
||||
- S_QWORD (signed float from 4 registers = 64bit
|
||||
- U_QWORD_R (unsigend float from 4 registers low word first )
|
||||
- S_QWORD_R (sigend float from 4 registers low word first )
|
||||
|
||||
- **skip_updates**: (*Optional*, integer): By default all sensors of of a modbus_controller are updated together. For data points that don't change very frequently updates can be skipped. A value of 5 would only update this sensor range in every 5th update cycle
|
||||
Note: The modbus_controller groups component by address ranges to reduce number of transactions. All compoents with the same address will be updated in one request. skip_updates applies for all components in the same range.
|
||||
- **register_count**: (*Optional*): only required for uncommon response encodings
|
||||
The number of registers this data point spans. Default is 1
|
||||
- **force_new_range**: (*Optional*, boolean): If possible sensors with sequential addresses are grouped together and requested in one range. Setting `foce_new_range: true` enforces the start of a new range at that address.
|
||||
- **offset**: (*Optional*, int): only required for uncommon response encodings
|
||||
offset from start address in bytes. If more than one register is read a modbus read registers command this value is used to find the start of this datapoint relative to start address. The component calculates the size of the range based on offset and size of the value type
|
||||
- **min_value** (*Optional*, float): The minimum value this number can be.
|
||||
- **max_value** (*Optional*, float): The maximum value this number can be.
|
||||
- **step** (*Optional*, float): The granularity with which the number can be set. Defaults to 1
|
||||
- **lambda** (*Optional*, :ref:`lambda <config-lambda>`):
|
||||
Lambda to be evaluated every update interval to get the new value of the sensor.
|
||||
- **write_lambda** (*Optional*, :ref:`lambda <config-lambda>`): Lambda called before send.
|
||||
Lambda is evaluated before the modbus write command is created.
|
||||
- **multiply** (*Optional*, float): multiply the new value with this factor before sending the requests. Ignored if lambda is defined.
|
||||
|
||||
|
||||
All other options from :ref:`Number <config-number>`.
|
||||
|
||||
Parameters passed into the lambda
|
||||
|
||||
- **x** (float): The parsed float value of the modbus data
|
||||
|
||||
- **data** (std::vector<uint8_t): vector containing the complete raw modbus response bytes for this sensor
|
||||
note: because the response contains data for all registers in the same range you have to use `data[item->offset]` to get the first response byte for your sensor.
|
||||
- **item** (const pointer to a SensorItem derived object): The sensor object itself.
|
||||
|
||||
Possible return values for the lambda:
|
||||
|
||||
- ``return <FLOATING_POINT_NUMBER>;`` the new value for the sensor.
|
||||
- ``return NAN;`` if the state should be considered invalid to indicate an error (advanced).
|
||||
|
||||
|
||||
|
||||
**Parameters passed into write_lambda**
|
||||
|
||||
- **x** (float): The float value to be sent to the modbus device
|
||||
|
||||
- **payload** (`std::vector<uint16_t>&payload`): empty vector for the payload. The lamdba can add 16 bit raw modbus register words.
|
||||
note: because the response contains data for all registers in the same range you have to use `data[item->offset]` to get the first response byte for your sensor.
|
||||
- **item** (const pointer to a SensorItem derived object): The sensor object itself.
|
||||
|
||||
Possible return values for the lambda:
|
||||
|
||||
- ``return <FLOATING_POINT_NUMBER>;`` the new value for the sensor.
|
||||
- ``return <anything>; and fill payload with data`` if the payload is added from the lambda then these 16 bit words will be sent
|
||||
- ``return {};`` if you don't want write the command to the device (or do it from the lambda).
|
||||
|
||||
**Example**
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
number:
|
||||
- platform: modbus_controller
|
||||
modbus_controller_id: epever
|
||||
id: battery_capacity_number
|
||||
name: "Battery Cap Number"
|
||||
address: 0x9001
|
||||
register_type: holding
|
||||
value_type: U_WORD
|
||||
lambda: "return x * 1.0; "
|
||||
write_lambda: |-
|
||||
ESP_LOGD("main","Modbus Number incoming value = %f",x);
|
||||
uint16_t b_capacity = x ;
|
||||
payload.push_back(b_capacity);
|
||||
return x * 1.0 ;
|
||||
## multiply is ignored because lamdba is used
|
||||
multiply: 1.0
|
||||
|
||||
|
||||
See Also
|
||||
--------
|
||||
- :doc:`/components/modbus_controller`
|
||||
- :doc:`/components/sensor/modbus_controller`
|
||||
- :doc:`/components/binary_sensor/modbus_controller`
|
||||
- :doc:`/components/switch/modbus_controller`
|
||||
- :doc:`/components/text_sensor/modbus_controller`
|
||||
- :doc:`/components/output/modbus_controller`
|
||||
- https://www.modbustools.com/modbus.html
|
||||
- :ghedit:`Edit`
|
82
components/output/modbus_controller.rst
Normal file
82
components/output/modbus_controller.rst
Normal file
@ -0,0 +1,82 @@
|
||||
Modbus Controller Output
|
||||
========================
|
||||
|
||||
.. seo::
|
||||
:description: Instructions for setting up a modbus_controller device sensor.
|
||||
:image: modbus_controller.png
|
||||
|
||||
The ``modbus_controller`` platform creates a output from a modbus_controller.
|
||||
|
||||
Configuration variables:
|
||||
------------------------
|
||||
|
||||
- **id** (*Optional*, :ref:`config-id`): Manually specify the ID used for code generation.
|
||||
- **name** (**Required**, string): The name of the sensor.
|
||||
- **address**: (**Required**, int): start address of the first register in a range
|
||||
- **value_type**: (**Required**): datatype of the mod_bus register data. The default data type for modbus is a 16 bit integer in big endian format (MSB first)
|
||||
- U_WORD (unsigned float from 1 register =16bit
|
||||
- S_WORD (signed float from one register)
|
||||
- U_DWORD (unsigned float from 2 registers = 32bit)
|
||||
- S_DWORD (unsigned float from 2 registers = 32bit)
|
||||
- U_DWORD_R (unsigend float from 2 registers low word first )
|
||||
- S_DWORD_R (sigend float from 2 registers low word first )
|
||||
- U_QWORD (unsigned float from 4 registers = 64bit
|
||||
- S_QWORD (signed float from 4 registers = 64bit
|
||||
- U_QWORD_R (unsigend float from 4 registers low word first )
|
||||
- S_QWORD_R (sigend float from 4 registers low word first )
|
||||
- **register_count**: (*Optional*): only required for uncommon response encodings
|
||||
The number of registers this data point spans. Default is 1
|
||||
- **write_lambda** (*Optional*, :ref:`lambda <config-lambda>`):
|
||||
Lambda is evaluated before the modbus write command is created. The value is passed in as `float x` and an empty vector is passed in as `std::vector<uint16_t>&payload`
|
||||
You can directly define the payload by adding data to payload then the return value is ignored and the content of payload is used.
|
||||
- **multiply** (*Optional*, float): multiply the new value with this factor before sending the requests. Ignored if lambda is defined.
|
||||
- **offset**: (*Optional*, int): only required for uncommon response encodings
|
||||
offset from start address in bytes. If more than one register is read a modbus read registers command this value is used to find the start of this datapoint relative to start address. The component calculates the size of the range based on offset and size of the value type
|
||||
|
||||
All other options from :ref:`Output <config-output>`.
|
||||
|
||||
|
||||
**Parameters passed into the lambda**
|
||||
|
||||
- **x** (float): The float value to be sent to the modbus device
|
||||
|
||||
- **payload** (`std::vector<uint16_t>&payload`): empty vector for the payload. The lamdba can add 16 bit raw modbus register words.
|
||||
note: because the response contains data for all registers in the same range you have to use `data[item->offset]` to get the first response byte for your sensor.
|
||||
- **item** (const pointer to a SensorItem derived object): The sensor object itself.
|
||||
|
||||
Possible return values for the lambda:
|
||||
|
||||
- ``return <FLOATING_POINT_NUMBER>;`` the new value for the sensor.
|
||||
- ``return <anything>; and fill payload with data`` if the payload is added from the lambda then these 16 bit words will be sent
|
||||
- ``return {};`` if you don't want write the command to the device (or do it from the lambda).
|
||||
|
||||
|
||||
**Example**
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
output:
|
||||
- platform: modbus_controller
|
||||
modbus_controller_id: epever
|
||||
id: battery_capacity_output
|
||||
lambda: |-
|
||||
ESP_LOGD("main","Modbus Output incoming value = %f",x);
|
||||
uint16_t b_capacity = x ;
|
||||
payload.push_back(b_capacity);
|
||||
return x * 1.0 ;
|
||||
address: 0x9001
|
||||
value_type: U_WORD
|
||||
|
||||
|
||||
|
||||
|
||||
See Also
|
||||
--------
|
||||
- :doc:`/components/modbus_controller`
|
||||
- :doc:`/components/sensor/modbus_controller`
|
||||
- :doc:`/components/binary_sensor/modbus_controller`
|
||||
- :doc:`/components/switch/modbus_controller`
|
||||
- :doc:`/components/text_sensor/modbus_controller`
|
||||
- :doc:`/components/number/modbus_controller`
|
||||
- https://www.modbustools.com/modbus.html
|
||||
- :ghedit:`Edit`
|
138
components/sensor/modbus_controller.rst
Normal file
138
components/sensor/modbus_controller.rst
Normal file
@ -0,0 +1,138 @@
|
||||
Modbus Sensor
|
||||
=============
|
||||
|
||||
.. seo::
|
||||
:description: Instructions for setting up a modbus_controller device sensor.
|
||||
:image: modbus.png
|
||||
|
||||
The ``modbus_controller`` sensor platform creates a sensor from a modbus_controller component
|
||||
and requires :doc:`/components/modbus_controller` to be configured.
|
||||
|
||||
|
||||
Configuration variables:
|
||||
------------------------
|
||||
- **id** (*Optional*, :ref:`config-id`): Manually specify the ID used for code generation.
|
||||
- **name** (**Required**, string): The name of the sensor.
|
||||
- **register_type** (**Required**): type of the modbus register.
|
||||
- coil: coils are also called discrete outout. Coils are 1-bit registers (on/off values) that are used to control discrete outputs. Read and Write access
|
||||
- discrete_input: discrete input register (read only coil) are similar to coils but can only be read.
|
||||
- holding: Holding Registers - Holding registers are the most universal 16-bit register. Read and Write access
|
||||
- read: Read Input Registers - registers are 16-bit registers used for input, and may only be read
|
||||
- **address**: (**Required**, int): start address of the first register in a range
|
||||
- **value_type**: (**Required**): datatype of the mod_bus register data. The default data type for modbus is a 16 bit integer in big endian format (MSB first)
|
||||
- U_WORD (unsigned float from 1 register =16bit
|
||||
- S_WORD (signed float from one register)
|
||||
- U_DWORD (unsigned float from 2 registers = 32bit)
|
||||
- S_DWORD (unsigned float from 2 registers = 32bit)
|
||||
- U_DWORD_R (unsigend float from 2 registers low word first )
|
||||
- S_DWORD_R (sigend float from 2 registers low word first )
|
||||
- U_QWORD (unsigned float from 4 registers = 64bit
|
||||
- S_QWORD (signed float from 4 registers = 64bit
|
||||
- U_QWORD_R (unsigend float from 4 registers low word first )
|
||||
- S_QWORD_R (sigend float from 4 registers low word first )
|
||||
|
||||
- **bitmask**: (*Optional*) some values are packed in a response. The bitmask can be used to extract a value from the response. For example, if the high byte value register 0x9013 contains the minute value of the current time. To only exctract this value use bitmask: 0xFF00. The result will be automatically right shifted by the number of 0 before the first 1 in the bitmask. For 0xFF00 (0b1111111100000000) the result is shifted 8 posistions. More than one sensor can use the same address/offset if the bitmask is different.
|
||||
- **skip_updates**: (*Optional*, integer): By default all sensors of of a modbus_controller are updated together. For data points that don't change very frequently updates can be skipped. A value of 5 would only update this sensor range in every 5th update cycle
|
||||
Note: The modbus_controller groups component by address ranges to reduce number of transactions. All compoents with the same address will be updated in one request. skip_updates applies for all components in the same range.
|
||||
- **register_count**: (*Optional*): only required for uncommon response encodings
|
||||
The number of registers this data point spans. Default is 1
|
||||
- **force_new_range**: (*Optional*, boolean): If possible sensors with sequential addresses are grouped together and requested in one range. Setting `foce_new_range: true` enforces the start of a new range at that address.
|
||||
- **lambda** (*Optional*, :ref:`lambda <config-lambda>`):
|
||||
Lambda to be evaluated every update interval to get the new value of the sensor.
|
||||
- **offset**: (*Optional*, int): only required for uncommon response encodings
|
||||
offset from start address in bytes. If more than one register is read a modbus read registers command this value is used to find the start of this datapoint relative to start address. The component calculates the size of the range based on offset and size of the value type
|
||||
For coil or discrete input registers offset is the position of the coil/register because these registers encode 8 coils in one byte.
|
||||
|
||||
- All other options from :ref:`Sensor <config-sensor>`.
|
||||
|
||||
|
||||
This example will send 2 modbus commands (device address 1 assumed)
|
||||
|
||||
0x1 0x4 0x31 0x0 0x0 0x02 x7f 0x37 ( read 2 registers starting at 0x3100)
|
||||
|
||||
0x1 0x3 0x90 0x1 0x0 0x1 0xf8 0xca ( read 1 holding resister from 0x9001 )
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
- platform: modbus_controller
|
||||
modbus_controller_id: traceran
|
||||
id: pv_input_voltage
|
||||
name: "PV array input voltage"
|
||||
address: 0x3100
|
||||
unit_of_measurement: "V" ## for any other unit the value is returned in minutes
|
||||
register_type: read
|
||||
value_type: U_WORD
|
||||
accuracy_decimals: 1
|
||||
filters:
|
||||
- multiply: 0.01
|
||||
|
||||
- platform: modbus_controller
|
||||
modbus_controller_id: traceran
|
||||
id: pv_input_current
|
||||
name: "PV array input current"
|
||||
address: 0x3101
|
||||
unit_of_measurement: "A" ## for any other unit the value is returned in minutes
|
||||
register_type: read
|
||||
value_type: U_WORD
|
||||
accuracy_decimals: 2
|
||||
filters:
|
||||
- multiply: 0.01
|
||||
|
||||
- platform: modbus_controller
|
||||
modbus_controller_id: traceran
|
||||
name: "Battery Capacity"
|
||||
id: battery_capacity
|
||||
register_type: holding
|
||||
address: 0x9001
|
||||
unit_of_measurement: "AH"
|
||||
value_type: U_WORD
|
||||
|
||||
|
||||
The ``modbus`` sensor platform allows you use a lambda that gets called before data is published
|
||||
using :ref:`lambdas <config-lambda>`.
|
||||
|
||||
This example logs the value as parsed and the raw modbus bytes received for this register range
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
# Example configuration entry
|
||||
sensor:
|
||||
- platform: modbus_controller
|
||||
modbus_controller_id: epever
|
||||
id: battery_capacity
|
||||
address: 0x9001
|
||||
name: "Battery Capacity"
|
||||
register_type: holding
|
||||
value_type: U_WORD
|
||||
lambda: |-
|
||||
ESP_LOGI("","Lambda incoming value=%f - data array size is %d",x,data.size());
|
||||
ESP_LOGI("","Sensor properties: adress = 0x%X, offset = 0x%X value type=%d",item->start_address,item->offset,item->sensor_value_type);
|
||||
int i=0 ;
|
||||
for (auto val : data) {
|
||||
ESP_LOGI("","data[%d]=0x%02X (%d)",i++ ,data[i],data[i]);
|
||||
}
|
||||
return x ;
|
||||
|
||||
|
||||
Parameters passed into the lambda
|
||||
|
||||
- **x** (float): The parsed float value of the modbus data
|
||||
|
||||
- **data** (std::vector<uint8_t): vector containing the complete raw modbus response bytes for this sensor
|
||||
note: because the response contains data for all registers in the same range you have to use `data[item->offset]` to get the first response byte for your sensor.
|
||||
- **item** (const pointer to a SensorItem derived object): The sensor object itself.
|
||||
|
||||
Possible return values for the lambda:
|
||||
|
||||
- ``return <FLOATING_POINT_NUMBER>;`` the new value for the sensor.
|
||||
- ``return NAN;`` if the state should be considered invalid to indicate an error (advanced).
|
||||
|
||||
See Also
|
||||
--------
|
||||
- :doc:`/components/modbus_controller`
|
||||
- :doc:`/components/number/modbus_controller`
|
||||
- :doc:`/components/binary_sensor/modbus_controller`
|
||||
- :doc:`/components/text_sensor/modbus_controller`
|
||||
- :doc:`/components/switch/modbus_controller`
|
||||
- :doc:`EPEVER MPPT Solar Charge Controller Tracer-AN Series</cookbook/tracer-an>`
|
||||
- :ghedit:`Edit`
|
54
components/switch/modbus_controller.rst
Normal file
54
components/switch/modbus_controller.rst
Normal file
@ -0,0 +1,54 @@
|
||||
Modbus Switch
|
||||
=============
|
||||
|
||||
.. seo::
|
||||
:description: Instructions for setting up a modbus_controller device sensor.
|
||||
:image: modbus_controller.png
|
||||
|
||||
The ``modbus_controller`` sensor platform creates a sensor from a modbus_controller component
|
||||
and requires :doc:`/components/modbus_controller` to be configured.
|
||||
|
||||
|
||||
Configuration variables:
|
||||
------------------------
|
||||
|
||||
- **id** (*Optional*, :ref:`config-id`): Manually specify the ID used for code generation.
|
||||
- **name** (**Required**, string): The name of the sensor.
|
||||
- **modbus_functioncode** (**Required**): type of the modbus register.
|
||||
- **address**: (**Required**, integer): start address of the first register in a range
|
||||
- **offset**: (*Optional*, integer): not required in most cases
|
||||
offset from start address in bytes. If more than one register is read a modbus read registers command this value is used to find the start of this datapoint relative to start address. The component calculates the size of the range based on offset and size of the value type
|
||||
The value for offset depends on the register type. For holding input registers the offset is in bytes. For coil and discrete input resisters the LSB of the first data byte contains the coil addressed in the request. The other coils follow toward the high-order end of this byte and from low order to high order in subsequent bytes. For the registers offset is the position of the relevant bit.
|
||||
To get the value of the coil register 2 can be retrived using address: 2 / offset: 0 or address: 0 / offset 2
|
||||
- **bitmask** : some values are packed in a response. The bitmask is used to determined if the result is true or false
|
||||
- **skip_updates**: (*Optional*, integer): By default all sensors of of a modbus_controller are updated together. For data points that don't change very frequently updates can be skipped. A value of 5 would only update this sensor range in every 5th update cycle
|
||||
|
||||
|
||||
**Example**
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
switch:
|
||||
- platform: modbus_controller
|
||||
modbus_controller_id: epever
|
||||
id: enable_load_test
|
||||
register_type: coil
|
||||
address: 2
|
||||
name: "enable load test mode"
|
||||
bitmask: 1
|
||||
|
||||
Since offset is not zero the read command is part of a range and will be parsed when the range is updated.
|
||||
The write command to be constructed uses the function code to determine the write command. For a coil it is write single coil.
|
||||
Because the write command only touches one register start_address and offset have to be corrected.
|
||||
The final command will be write_single_coil address 5 (start_address+offset) value 1 or 0
|
||||
|
||||
For holding registers the write command will be write_single_register. Because the offset for holding registers is given in bytes and the size of a register is 16 bytes the start_address is calculated as start_address + offset/2
|
||||
|
||||
See Also
|
||||
--------
|
||||
- :doc:`/components/modbus_controller`
|
||||
- :doc:`/components/sensor/modbus_controller`
|
||||
- :doc:`/components/binary_sensor/modbus_controller`
|
||||
- :doc:`/components/text_sensor/modbus_controller`
|
||||
- https://www.modbustools.com/modbus.html
|
||||
- :ghedit:`Edit`
|
115
components/text_sensor/modbus_controller.rst
Normal file
115
components/text_sensor/modbus_controller.rst
Normal file
@ -0,0 +1,115 @@
|
||||
Modbus Text Sensor
|
||||
==================
|
||||
|
||||
.. seo::
|
||||
:description: Instructions for setting up a modbus_controller modbus text sensor.
|
||||
:image: modbus_controller.png
|
||||
|
||||
The ``modbus_controller`` sensor platform creates a text sensor from a modbus_controller component
|
||||
and requires :doc:`/components/modbus_controller` to be configured.
|
||||
|
||||
|
||||
Configuration variables:
|
||||
------------------------
|
||||
- **id** (*Optional*, :ref:`config-id`): Manually specify the ID used for code generation.
|
||||
- **name** (**Required**, string): The name of the sensor.
|
||||
- **register_type** (**Required**): type of the modbus register.
|
||||
- coil: coils are also called discrete outout. Coils are 1-bit registers (on/off values) that are used to control discrete outputs. Read and Write access
|
||||
- discrete_input: discrete input register (read only coil) are similar to coils but can only be read.
|
||||
- holding: Holding Registers - Holding registers are the most universal 16-bit register. Read and Write access
|
||||
- read: Read Input Registers - registers are 16-bit registers used for input, and may only be read
|
||||
- **address**: (**Required**, integer): start address of the first register in a range
|
||||
- **bitmask**: (*Optional*) some values are packed in a response. The bitmask can be used to extract a value from the response. For example, if the high byte value register 0x9013 contains the minute value of the current time. To only exctract this value use bitmask: 0xFF00. The result will be automatically right shifted by the number of 0 before the first 1 in the bitmask. For 0xFF00 (0b1111111100000000) the result is shifted 8 posistions. More than one sensor can use the same address/offset if the bitmask is different.
|
||||
- **skip_updates**: (*Optional*, integer): By default all sensors of of a modbus_controller are updated together. For data points that don't change very frequently updates can be skipped. A value of 5 would only update this sensor range in every 5th update cycle
|
||||
- **register_count**: (*Optional*): The number of registers this data point spans. Default is 1
|
||||
- **response_size**: (**Required**):response number of bytes of the response
|
||||
- **raw_encode**: (*Optional*, NONE , HEXBYTES, COMMA) If the response is binary it can't be published directly. Since a text sensor only publishes strings the binary data can encoded
|
||||
- HEXBYTES: 2 byte hex string. 0x2011 will be sent as "2011".
|
||||
- COMMA: Byte values as integers, delimited by a coma. 0x2011 will be sent as "32,17"
|
||||
- **force_new_range**: (*Optional*, boolean): If possible sensors with sequential addresses are grouped together and requested in one range. Setting `foce_new_range: true` enforces the start of a new range at that address.
|
||||
- **lambda** (*Optional*, :ref:`lambda <config-lambda>`):
|
||||
Lambda to be evaluated every update interval to get the new value of the sensor
|
||||
- **offset**: (*Optional*, integer): not required in most cases
|
||||
offset from start address in bytes. If more than one register is read a modbus read registers command this value is used to find the start of this datapoint relative to start address. The component calculates the size of the range based on offset and size of the value type
|
||||
|
||||
|
||||
Parameters passed into the lambda
|
||||
|
||||
- **x** (std:string): The parsed float value of the modbus data
|
||||
|
||||
- **data** (std::vector<uint8_t): vector containing the complete raw modbus response bytes for this sensor
|
||||
note: because the response contains data for all registers in the same range you have to use `data[item->offset]` to get the first response byte for your sensor.
|
||||
- **item** (const pointer to a SensorItem derived object): The sensor object itself.
|
||||
|
||||
Possible return values for the lambda:
|
||||
|
||||
- ``return <FLOATING_POINT_NUMBER>;`` the new value for the sensor.
|
||||
- ``return NAN;`` if the state should be considered invalid to indicate an error (advanced).
|
||||
- ``return {};`` if you don't want to publish a new state (advanced).
|
||||
|
||||
|
||||
|
||||
**Example**
|
||||
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
text_sensor:
|
||||
- platform: template
|
||||
name: "RTC Time Sensor"
|
||||
id: template_rtc
|
||||
|
||||
- platform: modbus_controller
|
||||
modbus_controller_id: traceranx
|
||||
name: "rtc clock test"
|
||||
id: rtc_clock_test
|
||||
internal: true
|
||||
register_type: holding
|
||||
address: 0x9013
|
||||
register_count: 3
|
||||
hex_encode: true
|
||||
response_size: 6
|
||||
on_value:
|
||||
then:
|
||||
- lambda: |-
|
||||
ESP_LOGV("main", "decoding rtc hex encoded raw data: %s", x.c_str());
|
||||
uint8_t h=0,m=0,s=0,d=0,month_=0,y = 0 ;
|
||||
m = esphome::modbus_controller::byte_from_hex_str(x,0);
|
||||
s = esphome::modbus_controller::byte_from_hex_str(x,1);
|
||||
d = esphome::modbus_controller::byte_from_hex_str(x,2);
|
||||
h = esphome::modbus_controller::byte_from_hex_str(x,3);
|
||||
y = esphome::modbus_controller::byte_from_hex_str(x,4);
|
||||
month_ = esphome::modbus_controller::byte_from_hex_str(x,5);
|
||||
// Now check if the rtc time of the controller is ok and correct it
|
||||
time_t now = ::time(nullptr);
|
||||
struct tm *time_info = ::localtime(&now);
|
||||
int seconds = time_info->tm_sec;
|
||||
int minutes = time_info->tm_min;
|
||||
int hour = time_info->tm_hour;
|
||||
int day = time_info->tm_mday;
|
||||
int month = time_info->tm_mon + 1;
|
||||
int year = time_info->tm_year - 2000;
|
||||
// correct time if needed (ignore seconds)
|
||||
if (d != day || month_ != month || y != year || h != hour || m != minutes) {
|
||||
// create the payload
|
||||
std::vector<uint16_t> rtc_data = {uint16_t((minutes << 8) | seconds), uint16_t((day << 8) | hour),
|
||||
uint16_t((year << 8) | month)};
|
||||
// Create a modbus command item with the time information as the payload
|
||||
esphome::modbus_controller::ModbusCommandItem set_rtc_command = esphome::modbus_controller::ModbusCommandItem::create_write_multiple_command(traceranx, 0x9013, 3, rtc_data);
|
||||
// Submit the command to the send queue
|
||||
traceranx->queue_command(set_rtc_command);
|
||||
ESP_LOGI("ModbusLambda", "EPSOLAR RTC set to %02d:%02d:%02d %02d.%02d.%04d", hour, minutes, seconds, day, month, year + 2000);
|
||||
}
|
||||
char buffer[20];
|
||||
// format time as YYYY:mm:dd hh:mm:ss
|
||||
sprintf(buffer,"%04d:%02d:%02d %02d:%02d:%02d",y+2000,month_,d,h,m,s);
|
||||
id(template_rtc).publish_state(buffer);
|
||||
|
||||
See Also
|
||||
--------
|
||||
- :doc:`/components/modbus_controller`
|
||||
- :doc:`/components/sensor/modbus_controller`
|
||||
- :doc:`/components/binary_sensor/modbus_controller`
|
||||
- :doc:`/components/switch/modbus_controller`
|
||||
- https://www.modbustools.com/modbus.html
|
||||
- :ghedit:`Edit`
|
BIN
cookbook/images/tracer-an.jpg
Normal file
BIN
cookbook/images/tracer-an.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 49 KiB |
1290
cookbook/tracer-an.rst
Normal file
1290
cookbook/tracer-an.rst
Normal file
File diff suppressed because it is too large
Load Diff
BIN
images/esp32-modbus.jpg
Normal file
BIN
images/esp32-modbus.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.9 MiB |
BIN
images/modbus.png
Normal file
BIN
images/modbus.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 17 KiB |
BIN
images/rs485.jpg
Normal file
BIN
images/rs485.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 168 KiB |
BIN
images/tracer-an.jpg
Normal file
BIN
images/tracer-an.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 49 KiB |
@ -319,6 +319,7 @@ Miscellaneous
|
||||
b-parasite, components/sensor/b_parasite, b_parasite.jpg, Moisture & Temperature & Humidity & Light
|
||||
EZO sensor circuits, components/sensor/ezo, ezo-ph-circuit.png, (pH)
|
||||
Havells Solar, components/sensor/havells_solar, havellsgti5000d_s.jpg, Solar rooftop
|
||||
Modbus Sensor, components/sensor/modbus_controller, modbus.png
|
||||
Nextion, components/sensor/nextion, nextion.jpg, Sensors from display
|
||||
Rotary Encoder, components/sensor/rotary_encoder, rotary_encoder.jpg
|
||||
Tuya Sensor, components/sensor/tuya, tuya.png
|
||||
@ -376,6 +377,7 @@ Binary Sensor Components
|
||||
RDM6300, components/binary_sensor/rdm6300, rdm6300.jpg
|
||||
TTP229, components/binary_sensor/ttp229, ttp229.jpg
|
||||
Tuya Binary Sensor, components/binary_sensor/tuya, tuya.png
|
||||
Modbus Binary Sensor, components/binary_sensor/modbus_controller, modbus.png
|
||||
XPT2046, components/binary_sensor/xpt2046, xpt2046.jpg
|
||||
Custom Binary Sensor, components/binary_sensor/custom, language-cpp.svg
|
||||
|
||||
@ -398,6 +400,7 @@ Output Components
|
||||
SM16716, components/output/sm16716, sm16716.svg
|
||||
SM2135, components/output/sm2135, sm2135.svg
|
||||
MCP4725, components/output/mcp4725, mcp4725.jpg
|
||||
Modbus Output, components/output/modbus_controller, modbus.png
|
||||
Custom Output, components/output/custom, language-cpp.svg
|
||||
Template Output, components/output/template, description.svg
|
||||
|
||||
@ -444,6 +447,7 @@ Switch Components
|
||||
UART Switch, components/switch/uart, uart.svg
|
||||
Custom Switch, components/switch/custom, language-cpp.svg
|
||||
Tuya Switch, components/switch/tuya, tuya.png
|
||||
Modbus Switch, components/switch/modbus_controller, modbus.png
|
||||
BLE Client Switch, components/switch/ble_client, bluetooth.svg
|
||||
Nextion Switch, components/switch/nextion, nextion.jpg
|
||||
|
||||
@ -507,6 +511,7 @@ Text Sensor Components
|
||||
Version, components/text_sensor/version, new-box.svg
|
||||
WiFi Info, components/text_sensor/wifi_info, network-wifi.svg
|
||||
BLE Scanner, components/text_sensor/ble_scanner, bluetooth.svg
|
||||
Modbus Text Sensor, components/text_sensor/modbus_controller, modbus.png
|
||||
Template Text Sensor, components/text_sensor/template, description.svg
|
||||
Custom Text Sensor, components/text_sensor/custom, language-cpp.svg
|
||||
Nextion Text Sensor, components/text_sensor/nextion, nextion.jpg
|
||||
@ -532,6 +537,7 @@ Number Components
|
||||
.. imgtable::
|
||||
|
||||
Number Core, components/number/index, folder-open.svg
|
||||
Modbus Number, components/number/modbus_controller, modbus.png
|
||||
Template Number, components/number/template, description.svg
|
||||
|
||||
Select Components
|
||||
@ -579,6 +585,7 @@ Misc Components
|
||||
TM1651 Battery Display, components/tm1651, tm1651_battery_display.jpg
|
||||
RF Bridge, components/rf_bridge, rf_bridge.jpg
|
||||
Tuya MCU, components/tuya, tuya.png
|
||||
Modbus Controller, components/modbus_controller, modbus.png
|
||||
Exposure Notifications, components/exposure_notifications, exposure_notifications.png
|
||||
RTTTL Buzzer, components/rtttl, buzzer.jpg
|
||||
Prometheus, components/prometheus, prometheus.svg
|
||||
@ -628,6 +635,7 @@ Cookbook
|
||||
IAQ (Indoor Air Quality) Board, cookbook/iaq_board, iaq_board2.jpg
|
||||
Custom UART Text Sensor, cookbook/uart_text_sensor, language-cpp.svg
|
||||
IWOOLE Table Lamp, cookbook/iwoole_rgbw_table_lamp, iwoole_rgbw_table_lamp.png
|
||||
EPEVER Tracer, cookbook/tracer-an, tracer-an.jpg
|
||||
Ilonda Wifi Smart Fish Feeder, cookbook/ilonda-wifi-smart-fish-feeder, ilonda-wifi-smart-fish-feeder-cookbook.jpg
|
||||
|
||||
Do you have other awesome automations or cool setups? Please feel free to add them to the
|
||||
|
Loading…
Reference in New Issue
Block a user