Modbus RTU Debug Control
Modbus RTU Debug Control
Applies to FastBee IoT Platform — ESP32 Firmware Default adaptation: Generic domestic Modbus RTU relay module (flash-on type)
Current Version Notes
- The Lite edition disables Modbus RTU by default; for Modbus master, use Standard/Full firmware or enable
FASTBEE_ENABLE_MODBUS=1in custom builds and re-verify memory and long-term stability. - Modbus slave editing, mapping, and deletion are all done in the Web page; deletion shows a confirmation dialog first, then deletes after confirmation.
- Motor slave device control panels provide forward, stop, reverse default button styles, suitable for quick direction control debugging.
- Modbus RTU configuration, slaves, and mappings are saved in
/config/protocol.json; backup or restore individually under "Device Config > Advanced Config > Config Import/Export" as "Communication Protocol". - After importing
protocol.json, restart the device to ensure serial port, master task, and slave mappings are re-initialized from the new configuration.
Modbus debugging is primarily done on the "Communication Protocol / Modbus RTU" page; for interlocking, create poll or control rules on the "Peripheral Execution" page.
| Area | Field | Example Value / State |
|---|---|---|
| Status Overview | Risk Level | Low |
| Status Overview | Active Tasks | 0 |
| Status Overview | Timeout Rate | 0% |
| Status Overview | Total Polls / Success / Fail / Timeout | 0 / 0 / 0 / 0 |
| Basic Config | Enable Modbus RTU | Enabled |
| Basic Config | Peripheral Config Selection | Select configured RS485/UART peripheral |
| Basic Config | Transfer Type | Passthrough (Raw HEX frames) |
| Basic Config | DE Pin (RS485) | 14 |
| Slave Name | Type | Slave Address | Device Info | Enable | Operations |
|---|---|---|---|---|---|
| Temp & Humidity | Collection | 2 | FC04 @0 x2 [2 mappings] | ON | Edit / Map / Delete |
| PM25-10 | Collection | 1 | FC03 @0 x2 [2 mappings] | ON | Edit / Map / Delete |
| Weather Louver | Collection | 4 | FC03 @500 x8 [6 mappings] | ON | Edit / Map / Delete |
| Name | Status | Trigger | Target Peripheral | Action | Stats | Operations |
|---|---|---|---|---|---|---|
| ADC Voltage Read & Report | Disabled | Timer Trigger | ADC Analog Convert | Sensor Data Read -> ADC Analog Convert | Triggered: 1 | Run Once / Edit / Enable / Delete |
| ADC Voltage Below 2.30V Close Relay | Disabled | Event Trigger | - | Set LOW | Triggered: 1 | Run Once / Edit / Enable / Delete |
| ADC Voltage Above 2.50V Open Relay | Disabled | Event Trigger | - | Set HIGH | Triggered: 1 | Run Once / Edit / Enable / Delete |
| ADC Voltage Display on 7-Segment | Disabled | Timer Trigger | - | Display Number | Triggered: 1 | Run Once / Edit / Enable / Delete |
| NTP Time Sync | Disabled | Platform Trigger (MQTT) | - | NTP Sync | Triggered: 1 | Run Once / Edit / Enable / Delete |
| OLED Temp & Humidity Display | Disabled | Timer Trigger | - | OLED Custom Display | Triggered: 1 | Run Once / Edit / Enable / Delete |
| OLED Custom Display - Button Trigger Device Info | Disabled | Event Trigger | - | OLED Custom Display | Triggered: 1 | Run Once / Edit / Enable / Delete |
| OLED Custom Display - Timer Mixed | Disabled | Timer Trigger | - | OLED Custom Display | Triggered: 1 | Run Once / Edit / Enable / Delete |
| OLED Custom Display - MQTT Message | Disabled | Platform Trigger (MQTT) | - | OLED Custom Display | Triggered: 1 | Run Once / Edit / Enable / Delete |
| OTA Upgrade | Disabled | Platform Trigger (MQTT) | - | OTA Upgrade | Triggered: 1 | Run Once / Edit / Enable / Delete |
When debugging, first stabilize reading a single slave reliably, then expand to multi-slave polling; for control actions, then connect to peripheral execution rules and observe logs.
When encountering timeouts or exception codes, troubleshoot layer by layer following the closed-loop diagram: physical layer first, then serial parameters and slave mapping, and finally peripheral execution control actions and business rules.
| Data Area | Address Notation | Common Function Codes | Read/Write | FastBee Config Focus |
|---|---|---|---|---|
| Coils | 00001+ | FC01 read, FC05 write single, FC0F write multiple | Read/Write | Commonly used for relays, digital outputs. |
| Discrete Inputs | 10001+ | FC02 | Read only | Commonly used for digital input states. |
| Holding Registers | 40001+ | FC03 read, FC06 write single, FC10 write multiple | Read/Write | Commonly used for parameters, settings, control registers. |
| Input Registers | 30001+ | FC04 | Read only | Commonly used for measured values. |
| RTU Request Frame | Slave / Func / Addr / Value / CRC | Determined by device manual | - | Manual address often differs from protocol address by 1; verify on-site. |
Before configuring registers, check the mapping map for three things: does the function code match the target data area, is the manual address a display address or protocol address, and does the address in FastBee API need to be decremented by 1. Most "off-by-one reading" or "can read but not write" issues stem from these three places.
| Page/API Action | REST API | Common FC | Data Area | Troubleshooting Focus |
|---|---|---|---|---|
| Refresh Status | GET /api/modbus/status | - | Connection state | Confirm serial parameters, bus direction, and slave online first. |
| Switch Coil | POST /api/modbus/coil | FC05 / FC0F | Coils | Confirm if coil address needs to be decremented by 1. |
| Read Register | POST /api/modbus/read | FC03 / FC04 | Holding/Input Registers | Verify function code, start address, quantity, and byte order. |
| Write Parameter | POST /api/modbus/write | FC06 / FC10 | Holding Registers | Confirm device allows writes; verify in safe state first. |
| Native Private Frame | POST /api/modbus/native | 0xB0 / Native | Device private frame | Verify vendor protocol, CRC, and response format. |
When initiating control from the Web panel or REST API, use the diagram above to quickly locate the corresponding function code and data area. First confirm API parameters match the function code, then check address offset, serial parameters, and slave response.
Table of Contents
- Overview
- Prerequisites
- Modbus RTU Basic Configuration
- Debug & Control Panel
- REST API Reference
- Modbus Function Code Reference
- Typical Usage Scenarios
- FAQ & Troubleshooting
- Technical Specifications & Limits
1. Overview
The Modbus Debug & Control Panel is a built-in Modbus RTU operation tool in the FastBee IoT Platform, integrated in the "Protocol Config > Modbus RTU" tab of the Web management interface.
It is implemented based on standard Modbus RTU function codes and pre-adapted for generic domestic Modbus RTU relay modules (flash-on type), supporting their native instruction set. It also supports standard Modbus RTU digital I/O modules (e.g., Zhongsheng Tech 4-channel relay), supporting FC 0x06 register mode control. Main features:
- Relay module coil switch control (native toggle instruction 0x5500)
- Flash-on delay control (hardware timing, FC 0x05 address 0x0200+channel)
- Hardware register delay (FC 0x06 write delay value, device auto-toggles after delay)
- Batch ON/OFF/toggle operations (native all-toggle 0x5A00 / register batch control)
- Discrete Input (DI) status reading
- Slave device address management (broadcast read/write)
- Slave device baud rate configuration (FC 0xB0 proprietary / FC 0x06 register mode)
- Communication debugging and device troubleshooting
Supported Modbus Function Codes
| Function Code | Name | Purpose |
|---|---|---|
| FC 0x01 | Read Coils | Read coil states |
| FC 0x02 | Read Discrete Inputs | Read discrete input states |
| FC 0x03 | Read Holding Registers | Read holding registers (including broadcast read address) |
| FC 0x05 | Write Single Coil | Write single coil / native toggle / flash-on delay |
| FC 0x06 | Write Single Register | Write single holding register |
| FC 0x0F | Write Multiple Coils | Write multiple coils (batch ON/OFF) |
| FC 0x10 | Write Multiple Registers | Write multiple holding registers (including broadcast write address) |
| FC 0xB0 | Set Baud Rate (Proprietary) | Modify slave baud rate (relay board proprietary) |
2. Prerequisites
2.1 Hardware Connection
ESP32 Modbus Slave Device
┌──────────┐ ┌──────────────┐
│ TX Pin ├───────────→│ RX (A+/B-) │
│ RX Pin ├←───────────│ TX (A+/B-) │
│ DE Pin ├───────────→│ DE (Optional) │
│ GND ├────────────│ GND │
└──────────┘ └──────────────┘- RS485 Module: Requires DE (direction control) pin connection. If using auto-transceiver RS485 module, set DE pin to
-1. - TTL Direct: Suitable for TTL-level Modbus devices, no DE pin needed.
- Power: Ensure slave devices share common ground with ESP32.
2.2 Software Configuration
- Firmware uploaded to ESP32, file system synced
- ESP32 connected to WiFi, Web interface accessible via browser
- Go to Protocol Config page in Web interface
2.3 Peripheral Configuration
In the Modbus RTU tab, first select or configure a UART peripheral:
| Parameter | Description | Typical Value |
|---|---|---|
| Peripheral Config Selection | Select configured UART peripheral instance | Dropdown |
| DE Pin (RS485) | RS485 direction control pin number | 14 (set -1 if no DE) |
| Timeout (ms) | Communication response timeout | 1000 |
| Transfer Type | JSON structured / passthrough raw frames | JSON |
| Work Mode | MQTT command mode / active poll mode | Active Poll Mode |
Important: After configuring basic parameters, click the "Save" button at the bottom of the page, then restart the device for changes to take effect.
3. Modbus RTU Basic Configuration
3.1 Master Poll Tasks
In the "Master Poll Tasks" table, configure periodic data collection tasks:
| Field | Description | Range |
|---|---|---|
| Slave Address | Target device Modbus address | 1-247 |
| Function Code | Read method | 0x01/0x02/0x03/0x04 |
| Start Address | Register/coil start address | 0-65535 |
| Quantity | Number of registers/coils to read | 1-125 |
| Interval (sec) | Poll period | 1-65535 |
| Label | Human-readable task name | Custom text |
| Mapping | Number of register-to-sensor mappings | 0-N |
| Enable | Whether to activate this task | Checkbox |
3.2 Master Running Status
The page displays real-time Master mode runtime statistics:
- Running State: Current state machine state (idle/sending/waiting for response, etc.)
- Total Polls: Cumulative poll requests initiated
- Success: Count of correct responses received
- Failed: Communication errors (CRC errors, abnormal responses, etc.)
- Timeout: Count of no slave response
4. Debug & Control Panel
The debug and control panel is located below the "Master Running Status" area in the Modbus RTU tab, titled "Modbus Debug & Control".
Prerequisite: Modbus RTU must be in Master mode and successfully initialized; otherwise all operations return errors.
4.1 Connection Parameters
At the top of the panel is the basic connection parameter configuration area; all control operations depend on these parameters:
Slave Address
- Position: Top-left input box
- Purpose: Specify the Modbus slave device address to operate
- Range: 1 - 247
- Default: 1
- Note: Must match the slave device factory or custom address. If unsure, use "Read Address" in device parameter configuration (broadcast read, no need to know current address).
Channel Count
- Position: Bottom-left dropdown
- Purpose: Set coil grid display channel count; also affects batch operation range
- Options: 1 / 2 / 4 / 8 (default) / 16 / 32
- Note: Should match the actual coil/relay channel count of the slave device. E.g., 8-channel relay board select 8.
Coil Base Address
- Position: Top-right input box
- Purpose: Coil start Modbus address offset
- Range: 0 - 65535
- Default: 0
- Note: Most relay module coils start from address 0. Actual coil address =
base address + channel number. E.g., base address 100, CH0 corresponds to coil address 100, CH3 corresponds to 103.
Auto Refresh
- Position: Bottom-right checkbox
- Purpose: When enabled, auto-read coil states from slave every 3 seconds and update grid
- Default: Off
- Note: Suitable for scenarios requiring real-time coil state monitoring. Communication errors during auto-refresh do not show popups (silent mode) to avoid frequent interruptions.
4.2 Coil Status Grid
Below the connection parameters is the coil status grid area, displaying each channel's state as cards.
Interface Description
- Each channel displayed as a square card, format
CHn+ state (ON/OFF) - Green background (
coil-on): Coil is ON - Gray background (
coil-off): Coil is OFF - Cards being operated show semi-transparent loading effect
Operation Methods
- Click any coil card: Execute toggle operation
- Operation flow:
- System sends native toggle instruction (value 0x5500) via FC 0x05 to corresponding coil address
- Device toggles coil state at hardware level
- System reads back current actual state via FC 0x01
- Update grid display
- Show "Operation Successful" notification
Notes
- When first entering the panel, all coils in the grid display as OFF (gray) by default; click "Refresh Status" or enable "Auto Refresh" to get actual states
- Toggle uses device native instruction (0x5500), requiring only one write communication + one read-back communication for faster response
- Native toggle instruction is executed by device hardware; ESP32 does not need to pre-read state and invert
4.3 Batch Control
Below the coil grid, four operation buttons:
All ON
- Function Code: FC 0x0F (Write Multiple Coils)
- Behavior: Write all channels' coils to ON state in one operation
- Parameters: Controlled by "Channel Count" and "Coil Base Address"
All OFF
- Function Code: FC 0x0F (Write Multiple Coils)
- Behavior: Write all channels' coils to OFF state in one operation
Toggle All
- Function Code: FC 0x05 (Native toggle instruction)
- Frame Format:
[SlaveAddr, 0x05, 0x00, 0x00, 0x5A, 0x00, CRC] - Behavior:
- Send value 0x5A00 (all-toggle instruction) via FC 0x05 to coil base address
- Device hardware toggles all channel states
- Read back all coils' actual state via FC 0x01
- Update grid display
- Advantage: Only one write communication (native instruction), no need to read each then toggle
Refresh
- Function Code: FC 0x01 (Read Coils)
- Behavior: Read all coils' current state from slave, update grid display
- Note: Does not change any coil state; pure read operation
4.4 Flash-On Delay Control
Below the batch control buttons, implements "turn on then auto-off" hardware timing operations (flash-on/flash-off function).
Important Distinction: Delay timing is executed by relay board hardware, not ESP32 software timer. After sending the command, even if ESP32 loses power, the relay board will still auto-close when time expires.
Operation Elements
| Element | Description |
|---|---|
| Channel Dropdown | Select target channel (CH0 - CHn) |
| Delay Input | Set auto-off wait time, unit: x100ms |
| Start Delay Button | Execute flash-on control operation |
Operation Flow
- Select target channel from dropdown (e.g., CH3)
- Set delay value in input (e.g.,
50, meaning 50 x 100ms = 5 seconds) - Click "Start Delay" button
- System executes:
- Send value
(delayValue << 8)via FC 0x05 to address0x0200 + channel - Relay board immediately turns on the channel upon receiving the command
- Hardware timer expires, auto-close the channel
- Send value
Parameter Range
| Parameter | Range | Default | Description |
|---|---|---|---|
| Channel | 0 to (Channel Count - 1) | CH0 | Corresponding coil channel |
| Delay Value | 1 - 255 | 50 | Unit x100ms |
Delay Value Conversion Table
| Delay Value | Actual Time |
|---|---|
| 1 | 100ms |
| 10 | 1 second |
| 50 | 5 seconds |
| 100 | 10 seconds |
| 200 | 20 seconds |
| 255 | 25.5 seconds (maximum) |
Technical Details
- Hardware delay: Timed by relay board internal MCU, higher precision than software timer
- Frame Format:
[SlaveAddr, 0x05, 0x02, Channel, DelayValue, 0x00, CRC]- Address =
0x0200 + channel(high byte 0x02, low byte = channel number) - Value =
(delayUnits << 8) | 0x00(high byte = delay value, low byte = 0x00)
- Address =
- ESP32 does not need to stay online during delay; relay board executes independently
- Maximum delay 25.5 seconds; for longer delays, use other approaches
4.5 Device Parameter Configuration
At the bottom of the panel, collapsed by default. Click "Device Parameter Configuration" title to expand. Used to read and modify the slave device's own communication parameters.
4.5.1 Address Management
Used to read or modify the slave device's Modbus address. Uses broadcast method (slave address 0x00) for communication, no need to know the current address.
Address Register
- Input: Specify the holding register address storing the device address
- Default:
0(i.e., 0x0000) - Note: Generic domestic relay modules default address register is 0x0000. Different devices may vary; consult device manual.
Read Address
- Button: "Read"
- Function Code: FC 0x03 (Read Holding Registers)
- Slave Address: Broadcast address 0x00 (auto-used, no manual setting needed)
- Behavior: Read current Modbus address from specified address register
- Result: Display
Current: <address value>below button - Note: Uses broadcast read; only one slave device should be connected on the bus, otherwise multiple devices responding simultaneously causes communication conflict
Set New Address
- Input: Fill in new Modbus address
- Range: 1 - 255
- Button: "Set"
- Function Code: FC 0x10 (Write Multiple Registers)
- Slave Address: Broadcast address 0x00 (auto-used)
- Behavior: Write new address value to address register via broadcast
- Note: UI shows "Broadcast Write (FC 0x10), 1-255"
Warning: After changing slave address, the "Slave Address" parameter at the top of the panel must be updated to the new address; otherwise subsequent operations cannot communicate.
4.5.2 Baud Rate Configuration
Used to modify the slave device's communication baud rate. Uses FC 0xB0 proprietary instruction, no register address needed.
Operation Elements
| Element | Description |
|---|---|
| Baud Rate Dropdown | Select target baud rate: 1200/2400/4800/9600/19200/115200 |
| Set Button | Execute write operation |
Function Code
FC 0xB0 (Relay board proprietary instruction)
Frame Format
[SlaveAddr, 0xB0, 0x00, 0x00, BaudCode, 0x00, CRC]Baud Rate Code Mapping
| Baud Rate | Code Value |
|---|---|
| 1200 | 0 |
| 2400 | 1 |
| 4800 | 2 |
| 9600 | 3 |
| 19200 | 4 |
| 115200 | 5 |
- Note: UI shows "FC 0xB0 Proprietary Instruction"
Warning: After changing baud rate, ESP32's Modbus RTU serial configuration (baud rate in peripheral settings) must also be updated, then save and restart; otherwise mismatched baud rates prevent communication.
4.5.3 Discrete Input Reading
Used to read the slave device's digital input port states.
Operation Elements
| Element | Description |
|---|---|
| Input Count | Number of discrete inputs to read, range 1-32 |
| Input Base Address | Discrete input start address, default 0 |
| Read Button | Execute read operation |
Function Code
FC 0x02 (Read Discrete Inputs)
Result Display
After successful read, each input's state displayed as colored tags below the button:
- Green
INn:ON: Input is HIGH (signal present) - Gray
INn:OFF: Input is LOW (no signal)
5. REST API Reference
All APIs require login authentication (Bearer Token or Session Cookie).
| Page/API Action | REST API | Common FC | Data Area | Troubleshooting Focus |
|---|---|---|---|---|
| Refresh Status | GET /api/modbus/status | - | Connection state | Confirm serial parameters, bus direction, and slave online first. |
| Switch Coil | POST /api/modbus/coil | FC05 / FC0F | Coils | Confirm if coil address needs to be decremented by 1. |
| Read Register | POST /api/modbus/read | FC03 / FC04 | Holding/Input Registers | Verify function code, start address, quantity, and byte order. |
| Write Parameter | POST /api/modbus/write | FC06 / FC10 | Holding Registers | Confirm device allows writes; verify in safe state first. |
| Native Private Frame | POST /api/modbus/native | 0xB0 / Native | Device private frame | Verify vendor protocol, CRC, and response format. |
The REST API section is best read alongside the diagram above: coil interfaces correspond to Coils data area, register read/write interfaces correspond to Holding/Input Registers, device parameters and proprietary commands may use private frames or specific function codes.
5.1 Coil Control API
POST /api/modbus/coil/control — Single Coil Control
Permission: config.edit
| Parameter | Type | Required | Description |
|---|---|---|---|
| slaveAddress | int | Yes | Slave address (1-247) |
| channel | int | Yes | Channel number (0-based) |
| coilBase | int | No | Coil base address, default 0 |
| action | string | No | on/off/toggle, default toggle |
Toggle operation note: Uses device native toggle instruction (FC 0x05, value 0x5500), then reads back state.
Success Response:
{
"success": true,
"data": {
"channel": 0,
"coilAddress": 0,
"state": true,
"action": "toggle"
}
}POST /api/modbus/coil/batch — Batch Coil Control
Permission: config.edit
| Parameter | Type | Required | Description |
|---|---|---|---|
| slaveAddress | int | Yes | Slave address (1-247) |
| channelCount | int | Yes | Channel count (1-32) |
| coilBase | int | No | Coil base address, default 0 |
| action | string | Yes | allOn/allOff/allToggle |
allToggle operation note: Uses device native all-toggle instruction (FC 0x05, address=coilBase, value 0x5A00), then reads back state.
Success Response:
{
"success": true,
"data": {
"channelCount": 8,
"action": "allOn",
"states": [true, true, true, true, true, true, true, true]
}
}POST /api/modbus/coil/delay — Flash-On Delay Control
Permission: config.edit
| Parameter | Type | Required | Description |
|---|---|---|---|
| slaveAddress | int | Yes | Slave address (1-247) |
| channel | int | Yes | Channel number (0-based) |
| delayBase | int | No | Delay address base, default 0x0200 (512) |
| delayUnits | int | Yes | Delay value (1-255), unit x100ms |
| delayMode | int | No | 0=FC05 flash-on (default), 1=software delay, 2=hardware register delay |
| ncMode | bool | No | NC normally-closed mode |
| coilBase | int | No | Coil base address |
| mode | string | No | coil/register, control mode |
delayMode=0 (default): Uses FC 0x05 flash-on instruction (relay board proprietary), address=delayBase+channel, value=delayUnits<<8.
delayMode=1: Software delay, write ON first, ESP32 software timer writes OFF after expiry.
delayMode=2: Hardware register delay, write value>1 to channel register, device auto-toggles after (N-1)×0.01s delay. Suitable for modules supporting register delay toggle like Zhongsheng Tech.
When device is configured with
delayMode=2, API auto-uses hardware register delay mode; no need to manually specify delayMode parameter.
Success Response:
{
"success": true,
"data": {
"channel": 3,
"delayAddress": 515,
"delayUnits": 50,
"delayMs": 5000
}
}Notes:
- Actual Modbus address =
delayBase + channel(e.g., 0x0200 + 3 = 0x0203) - Actual written value =
delayUnits << 8(e.g., 50 → 0x3200) - Hardware delay is executed by relay board; ESP32 only sends the instruction
GET /api/modbus/coil/status — Query Coil Status
Permission: config.view or config.edit
| Parameter | Type | Required | Description |
|---|---|---|---|
| slaveAddress | int | Yes | Slave address (1-247) |
| channelCount | int | No | Channel count, default 8 |
| coilBase | int | No | Coil base address, default 0 |
Success Response:
{
"success": true,
"data": {
"channelCount": 8,
"coilBase": 0,
"states": [false, true, false, false, true, false, false, false]
}
}5.2 Device Parameter API
POST /api/modbus/device/address — Read/Set Slave Address
Permission: config.edit
| Parameter | Type | Required | Description |
|---|---|---|---|
| slaveAddress | int | Yes | Current slave address (uses broadcast 0x00 for both read/write) |
| addressRegister | int | No | Address register, default 0 (0x0000) |
| newAddress | int | No | New address (1-255). Omit for read, fill for set |
Read note: Sends FC 0x03 to read address register via broadcast address 0x00.
Set note: Sends FC 0x10 to write new address to address register via broadcast address 0x00.
Read Response:
{
"success": true,
"data": { "currentAddress": 1, "register": 0 }
}Set Response:
{
"success": true,
"data": { "previousAddress": 1, "newAddress": 5, "register": 0 }
}POST /api/modbus/device/baudrate — Set Baud Rate
Permission: config.edit
| Parameter | Type | Required | Description |
|---|---|---|---|
| slaveAddress | int | Yes | Slave address (1-247) |
| baudRate | int | Yes | Baud rate |
| mode | int | No | 0=FC 0xB0 proprietary (default), 1=FC06 write register |
| baudRateReg | int | No | FC06 mode baud rate register address (default 0x0033) |
| baudCode | int | No | Directly specify baud rate code value |
mode=0 (default): Uses FC 0xB0 proprietary instruction, frame format [SlaveAddr, 0xB0, 0x00, 0x00, BaudCode, 0x00, CRC]. Baud rate codes: 0=1200, 1=2400, 2=4800, 3=9600, 4=19200, 5=115200.
mode=1: Uses FC 0x06 write holding register (standard Modbus, compatible with Zhongsheng Tech and similar brands). Baud rate codes: 0=4800, 1=9600, 2=14400, 3=19200, 4=38400, 5=56000, 6=57600, 7=115200.
When device is configured with
baudRateMode=1, API auto-uses FC06 register mode; no need to manually specify mode parameter.
Success Response:
{
"success": true,
"data": { "baudRate": 9600, "baudCode": 1, "mode": "register", "register": 51 }
}GET /api/modbus/device/inputs — Read Discrete Inputs
Permission: config.view or config.edit
| Parameter | Type | Required | Description |
|---|---|---|---|
| slaveAddress | int | Yes | Slave address (1-247) |
| inputCount | int | No | Input count, default 4 |
| inputBase | int | No | Input base address, default 0 |
Success Response:
{
"success": true,
"data": {
"inputCount": 4,
"inputBase": 0,
"states": [false, true, false, true]
}
}5.3 General Register & Status API
GET /api/modbus/status — Get Modbus Running Status
Permission: config.view
Returns current Modbus mode, communication statistics, task overview, etc. (500ms internal cache). Commonly used for Web panel real-time status display.
Success Response (Example):
{
"success": true,
"data": {
"mode": "master",
"running": true,
"stats": { "txCount": 123, "rxCount": 120, "timeoutCount": 3 },
"tasks": [ /* Master poll task runtime states */ ]
}
}POST /api/modbus/write — Queue Write Single Holding Register (FC 0x06, enqueued)
Permission: config.edit
| Parameter | Type | Required | Description |
|---|---|---|---|
| slaveAddress | int | Yes | Slave address (1-247) |
| regAddress | int | Yes | Register address |
| value | int | Yes | Write value (0-65535) |
Difference from
/api/modbus/register/write: this interface enqueues the write request (scheduled by Modbus scheduler), suitable for non-blocking master control scenarios; the latter uses one-shot interface to send directly and wait for response.
Success Response: {"success": true, "message": "Write request queued"}
GET /api/modbus/register/read — Read Holding/Input Registers (one-shot)
Permission: config.view or config.edit
| Parameter | Type | Required | Description |
|---|---|---|---|
| slaveAddress | int | Yes | Slave address (1-247) |
| startAddress | int | Yes | Start register address |
| quantity | int | Yes | Quantity (1-125) |
| functionCode | int | No | 3=Holding (default) / 4=Input |
Success Response:
{
"success": true,
"data": {
"count": 4,
"startAddress": 0,
"values": [100, 200, 0, 1]
}
}POST /api/modbus/register/write — Write Single Holding Register (FC 0x06, one-shot)
Permission: config.edit
| Parameter | Type | Required | Description |
|---|---|---|---|
| slaveAddress | int | Yes | Slave address (1-247) |
| registerAddress | int | Yes | Register address |
| value | int | Yes | Write value (0-65535) |
After successful write, if the register falls within a Modbus slave's coilBase control range, MQTT control report is auto-published.
Success Response:
{ "success": true, "data": { "register": 5, "value": 100 } }POST /api/modbus/register/batch-write — Batch Write Holding Registers (FC 0x10)
Permission: config.edit
| Parameter | Type | Required | Description |
|---|---|---|---|
| slaveAddress | int | Yes | Slave address (1-247) |
| startAddress | int | Yes | Start register address |
| values | string (JSON array) | Yes | Values array to write, e.g., "[100,200,300]", length 1-125 |
Success Response:
{
"success": true,
"data": { "startAddress": 0, "quantity": 3, "values": [100,200,300] }
}5.4 Motor Control API
POST /api/modbus/motor/control — Modbus Motor Control (forward/reverse/stop/speed/pulse)
Permission: config.edit
| Parameter | Type | Required | Description |
|---|---|---|---|
| slaveAddress | int | Yes | Slave address (1-247) |
| action | string | Yes | forward/reverse/stop/setSpeed/setPulse/readStatus |
| value | int | No | Write value for setSpeed/setPulse |
| registers | string (JSON array) | No | Override default register mapping [forward, reverse, stop, speed, pulse] (default [0x0000,0x0001,0x0002,0x0005,0x0007], compatible with YF-53, etc.) |
Preferentially reads register mapping from device config motorRegs; if device is not configured, uses default or registers parameter override. readStatus reads speed/pulse register range for frontend panel status refresh.
Success Response (forward example):
{
"success": true,
"data": { "action": "forward", "register": 0, "value": 1 }
}5.5 Error Response Format
All APIs return unified format on operation failure:
{
"success": false,
"error": "Error description",
"errorCode": "TIMEOUT"
}Error Code Reference:
| errorCode | HTTP Status | Description |
|---|---|---|
TIMEOUT | 504 | Slave not responding; check wiring and address |
CRC_ERROR | 502 | CRC check failed; possible line interference |
EXCEPTION | 502 | Slave returned exception code (with exceptionCode field) |
NOT_INITIALIZED | 503 | Modbus not initialized or not enabled |
BUSY | 503 | Bus busy (another operation in progress); retry later |
Modbus Exception Codes:
| exceptionCode | Meaning |
|---|---|
| 0x01 | Illegal function — Function code not supported |
| 0x02 | Illegal data address — Address does not exist |
| 0x03 | Illegal data value — Data value invalid |
| 0x04 | Slave device failure — Internal slave fault |
6. Modbus Function Code Reference
6.1 FC 0x01 — Read Coils
- Purpose: Read slave coil (DO output) states
- Panel use case: "Refresh Status", "Auto Refresh", state readback after toggle operations
- Data meaning: Each coil 1 bit, 0=OFF, 1=ON
6.2 FC 0x02 — Read Discrete Inputs
- Purpose: Read slave digital input (DI) states
- Panel use case: Device Parameters > Discrete Inputs > Read
- Data meaning: Each input 1 bit, 0=OFF, 1=ON
6.3 FC 0x03 — Read Holding Registers
- Purpose: Read slave holding register values
- Panel use case: Broadcast read device address (slave address 0x00, register 0x0000)
- Data meaning: Each register is 16-bit unsigned integer
6.4 FC 0x05 — Write Single Coil / Native Instruction Carrier
- Purpose: Control single coil ON/OFF; also serves as carrier for relay board native instructions
- Panel use cases:
- Standard ON/OFF: Value 0xFF00 = ON, 0x0000 = OFF
- Native toggle: Value 0x5500, sent to target coil address, device auto-toggles state
- Native all-toggle: Value 0x5A00, sent to coil base address (address 0), device toggles all channels
- Flash-on delay: Address = 0x0200 + channel, value = (delay << 8), device hardware timer turns on then off
- Frame Format:
[SlaveAddr, 0x05, AddrH, AddrL, ValueH, ValueL, CRC]
6.5 FC 0x06 — Write Single Register
- Purpose: Write single holding register
- Panel use case: Reserved interface (not directly used by current UI)
- Frame Format:
[SlaveAddr, 0x06, AddrH, AddrL, ValueH, ValueL, CRC]
6.6 FC 0x0F — Write Multiple Coils
- Purpose: Write multiple coils in one operation
- Panel use case: "All ON" / "All OFF"
- Feature: One frame writes all channels, more efficient than individual FC 0x05
6.7 FC 0x10 — Write Multiple Registers
- Purpose: Write multiple holding registers in one operation
- Panel use case: Broadcast write new device address (slave address 0x00, register 0x0000)
6.8 FC 0xB0 — Set Baud Rate (Proprietary)
- Purpose: Modify relay board slave communication baud rate
- Panel use case: Device Parameters > Baud Rate Config > Set
- Frame Format:
[SlaveAddr, 0xB0, 0x00, 0x00, BaudCode, 0x00, CRC] - Baud Rate Codes: 0=1200, 1=2400, 2=4800, 3=9600, 4=19200, 5=115200
- Note: This is a relay board proprietary instruction, not part of standard Modbus protocol. Non-similar devices may not support it.
Scenario: Control 4-Channel Standard Relay Module (Zhongsheng Tech, etc.)
Device: Standard Modbus RTU 4-channel relay module (e.g., Zhongsheng Tech digital I/O series), default address 1, baud rate 38400, holding register control.
Device Configuration:
| Parameter | Value | Description |
|---|---|---|
| Device Type | relay | Relay |
| Slave Address | 1 | Default address |
| Channel Count | 4 | 4-channel relay |
| Coil Base Address | 0 | Registers start from 0 |
| Control Mode | Register Mode | FC03/FC06 |
| Batch Register | 52 (0x0034) | All ON/All OFF register |
| Delay Mode | 2 (Hardware Register) | Device built-in delay |
| Baud Rate Mode | 1 (FC06 Register) | Standard write register for baud rate config |
| Baud Rate Register | 51 (0x0033) | Baud rate setting register |
| Address Register | 50 (0x0032) | Address setting register |
Holding Register Function Definitions:
| Protocol Address | PLC Address | Function Description |
|---|---|---|
| 0x0000-0x0003 | 40001-40004 | Channel 1-4 control (0=off, 1=on, >1=delay toggle) |
| 0x0030 | 40049 | Communication detection time (N×0.1s) |
| 0x0031 | 40050 | Input state auto-upload control |
| 0x0032 | 40051 | RS485 address/station number (1-255) |
| 0x0033 | 40052 | Baud rate setting |
| 0x0034 | 40053 | Batch control (0=all off, 1=all on) |
| 0x0035 | 40054 | Bit-wise control channel 1-16 |
| 0x003D | 40062 | Parity setting (0=none, 1=odd, 2=even) |
| 0x0096-0x0099 | 40151-40154 | Channel 1-4 control mode setting |
Baud Rate Code Mapping (Register 0x0033):
| Code | Baud Rate |
|---|---|
| 0 | 4800 |
| 1 | 9600 |
| 2 | 14400 |
| 3 | 19200 |
| 4 | 38400 (factory default) |
| 5 | 56000 |
| 6 | 57600 |
| 7 | 115200 |
Hardware Register Delay:
Write value > 1 to channel register; device auto-toggles after (N-1)×0.01s delay:
- Write 1: Immediately turn on
- Write 0: Immediately turn off
- Write 501: Delay (501-1)×0.01 = 5 seconds then toggle
- Write 1001: Delay (1001-1)×0.01 = 10 seconds then toggle
Operation Steps:
- Change Modbus RTU baud rate to 38400 in peripheral management (device factory default)
- Save configuration and restart ESP32
- "4-Channel Relay" control panel visible on device control page
- Click relay card to switch ON/OFF
- Delay control: Select channel and delay value, click "Start Delay"; device hardware timer auto-closes
Scenario 1: Control 8-Channel Relay Module
Device: Generic domestic Modbus RTU 8-channel relay board, address 1, baud rate 9600, coil addresses starting from 0.
Operation Steps:
- Confirm Modbus RTU basic config saved and device restarted
- In debug & control panel set:
- Slave Address:
1 - Channel Count:
8 - Coil Base Address:
0
- Slave Address:
- Click "Refresh Status" → Grid shows 8 channels' current state
- Click a gray channel card → Relay toggles ON (turns green)
- Click again → Relay toggles OFF (turns gray)
Scenario 2: Corridor Light Flash-On Delay
Requirement: Light turns on for 5 seconds after switch press, then auto-off.
Operation Steps:
- Set flash-on delay control area:
- Select target channel (e.g., CH0)
- Delay value input
50(50 x 100ms = 5 seconds)
- Click "Start Delay"
- Result: CH0 relay immediately closes (light on), 5 seconds later relay board hardware auto-disconnects (light off)
Longer Delay Examples:
- Need 10 second delay → Input
100 - Need 20 second delay → Input
200 - Maximum 25.5 second delay → Input
255
Scenario 3: Modify Slave Address
Requirement: Change device address to 5 (can operate without knowing current address).
Operation Steps:
- Expand "Device Parameter Configuration"
- Confirm address register is
0(generic domestic relay board default) - Click "Read" → Shows
Current: 1below (read via broadcast address 0x00, no need to know current address) - Enter
5in "New Address" - Click "Set" → Write via broadcast address 0x00 + FC 0x10, operation successful
- Immediately change "Slave Address" at top of panel to
5
Note: During broadcast read/write, only one slave device should be connected on the bus. Multiple devices cause communication conflicts.
Scenario 4: Batch Initialization
Requirement: Turn off all relays in one click (device power-on safety check).
Operation Steps:
- Configure connection parameters
- Click "All OFF" button
- All channels in grid turn gray
Scenario 5: Read Sensor DI States
Requirement: View current states of 4 digital input sensors.
Operation Steps:
- Expand "Device Parameter Configuration"
- Input count:
4, input base address:0 - Click "Read"
- Status tags displayed below: IN0:ON IN1:OFF IN2:OFF IN3:ON, etc.
8. FAQ & Troubleshooting
Q1: "Operation Failed" after clicking coil card
Possible causes & troubleshooting:
| Check Item | Troubleshooting Method |
|---|---|
| Slave address error | Use broadcast read address function to confirm device actual address |
| Wiring connection issue | Check TX/RX wiring, whether RS485 A+/B- are reversed |
| Baud rate mismatch | ESP32 peripheral config baud rate must match slave |
| DE pin configuration | RS485 module needs correct DE pin number |
| Device not powered | Confirm slave device power is normal |
| Modbus not initialized | Check if RTU config saved and ESP32 restarted |
| Device does not support 0x5500 | Non-generic relay boards may not support native toggle instruction |
Q2: Status reads normally but cannot control (write operations fail)
Possible causes:
- Slave device coils are read-only (some device status coils are not writable)
- Coil address incorrect (some device coils do not start from 0)
- Slave returns exception code 0x02 (address invalid); check device manual for coil address range
Q3: "Modbus busy, try again" message
Cause: Another Modbus operation is in progress (e.g., poll task, other API request).
Solution: Wait 1-2 seconds and retry. The bus is half-duplex; only one operation at a time.
Q4: Flash-on delay not working
Possible causes:
- Device does not support flash-on function (non-generic relay board) → Check device manual for 0x0200 address range support
- Delay value out of range (must be 1-255) → UI limits this; note when calling API
- Channel number error → Confirm channel is in range 0 to (channel count - 1)
Q5: Auto refresh not working
Troubleshooting:
- Confirm checkbox is checked
- Check browser console for JS errors
- Confirm Modbus is not frequently in BUSY state
Q6: Device not responding after baud rate change
Cause: Slave baud rate has changed (via FC 0xB0 proprietary instruction), but ESP32 side still uses old baud rate.
Solution:
- Change UART peripheral baud rate to new value in peripheral management
- Save Modbus RTU configuration
- Restart ESP32
Q7: Status reading very slow after selecting 16 or 32 channels
Cause: FC 0x01 reading multiple coils requires longer communication time, and slave processing is also slower.
Recommendation: Only select the device's actual channel count; avoid reading non-existent coils causing errors or delays.
Q8: Broadcast read address returns error
Possible causes:
- Multiple slave devices connected on bus → Only one device should be connected during broadcast operations
- Device does not support broadcast address 0x00 → Non-generic relay boards may not support it
- Line issues causing response loss
9. Technical Specifications & Limits
System Limits
| Item | Limit |
|---|---|
| Max channel count | 32 (single write coil upper limit) |
| Flash-on delay range | 1 - 255 (x100ms, i.e., 100ms - 25.5s) |
| Slave address range | 1 - 255 (control operations), 0x00 (broadcast read/write address) |
| Coil/register address range | 0 - 65535 |
| Auto refresh interval | Fixed 3 seconds |
| API concurrency limit | Modbus bus supports only one operation at a time |
Device Native Instruction Summary
| Instruction | FC | Address | Value | Description |
|---|---|---|---|---|
| Single channel toggle | 0x05 | Coil address | 0x5500 | Hardware toggle specified channel |
| All channel toggle | 0x05 | Coil base address | 0x5A00 | Hardware toggle all channels |
| Flash-on delay | 0x05 | 0x0200+ch | (delay<<8) | Hardware delay on then auto-off |
| Read address | 0x03 | 0x0000 | - | Broadcast (0x00) read device address |
| Set address | 0x10 | 0x0000 | New address | Broadcast (0x00) write new address |
| Set baud rate | 0xB0 | - | BaudCode | Proprietary instruction to modify baud rate |
Communication Parameters
| Parameter | Description |
|---|---|
| Protocol | Modbus RTU (serial binary) |
| Checksum | CRC-16/Modbus |
| Default timeout | 1000ms (configurable) |
| Default retries | 2 (configurable) |
| Inter-frame delay | 5ms (configurable) |
Internationalization Support
The Lite edition uses Chinese UI by default and removes language switch entries to reduce first-screen resources and runtime loading pressure; the full edition can retain multi-language resources.
Browser Compatibility
Supports all modern browsers (Chrome, Firefox, Edge, Safari); Chrome-based browsers recommended for best experience.
Appendix A: Modbus RTU Frame Structure
Frame structure troubleshooting should reference the "Modbus RTU Register Mapping Map" earlier: first confirm slave address and function code, then confirm whether the Addr field uses protocol address. Many relay board manuals list 00001, 40001 as human-readable addresses; actual RTU frame addresses may be 0x0000.
Request Frame (Master -> Slave)
| Slave Address | Function Code | Data | CRC Low | CRC High |
| 1 byte | 1 byte | N bytes | 1 byte | 1 byte |Normal Response Frame (Slave -> Master)
| Slave Address | Function Code | Data | CRC Low | CRC High |
| 1 byte | 1 byte | N bytes | 1 byte | 1 byte |Exception Response Frame (Slave -> Master)
| Slave Address | Func Code+0x80 | Exception Code | CRC Low | CRC High |
| 1 byte | 1 byte | 1 byte | 1 byte | 1 byte |Appendix B: Relay Board Native Instruction Frame Examples
Toggle Channel 3 (Slave Address 1)
Request: 01 05 00 03 55 00 [CRC]
Response: 01 05 00 03 55 00 [CRC]Toggle All Channels (Slave Address 1)
Request: 01 05 00 00 5A 00 [CRC]
Response: 01 05 00 00 5A 00 [CRC]Flash-On Channel 2, Delay 5 Seconds (Slave Address 1)
Request: 01 05 02 02 32 00 [CRC]
│ │ │ │ │ └─ Low byte 0x00
│ │ │ │ └──── High byte 0x32 (50 x 100ms = 5s)
│ │ │ └─────── Channel 2
│ │ └────────── 0x02 (Delay address high byte)
│ └───────────── FC 0x05
└──────────────── Slave address 1Broadcast Read Device Address
Request: 00 03 00 00 00 01 [CRC]
Response: 00 03 02 00 01 [CRC] → Address = 1Broadcast Set New Address to 5
Request: 00 10 00 00 00 01 02 00 05 [CRC]
Response: 00 10 00 00 00 01 [CRC]Change Baud Rate to 9600 (Slave Address 1)
Request: 01 B0 00 00 03 00 [CRC]
│ │ │ │ │ └─ Fixed 0x00
│ │ │ │ └──── Code 3 = 9600
│ │ │ └─────── Fixed 0x00
│ │ └────────── Fixed 0x00
│ └───────────── FC 0xB0
└──────────────── Slave address 1Appendix C: Quick Checklist
Before first use, confirm each item:
