Skip to main content

Modbus Interface

Overview

This document describes the Modbus TCP/IP interface for controlling the LED strips and SMC buttons of SEHx01/SEH11 devices. The Modbus interface operates in parallel with the existing MQTT control. Both interfaces can be used simultaneously.

Physical Interface

ParameterValue
ProtocolModbus
InterfaceTCP/IP
Device ID1 (configurable)

Register Overview

Holding Registers (Function 03/06/16)

The controller supports 5 LED strips (LED_STRIP_1 through LED_STRIP_5). Each strip can contain multiple segments. Up to 8 segments per strip are configurable. Each segment supports up to 3 colors.

Global Registers

RegisterDescriptionData TypeRangeR/W
0Modbus Device IDUINT161-247R/W
2Apply/TriggerUINT160/1W
3Reserved---
4Reserved---

Apply/Trigger (Register 2): After writing all desired strip/segment registers, register 2 must be set to 1 to apply the changes. The register is automatically reset to 0 after the changes are applied.


Strip Registers

Each strip occupies a block of 100 registers. The base address for strip N (N = 1..5) is calculated as:

Base Address = 100 * N

OffsetDescriptionData TypeRangeR/W
0ActiveUINT160/1R/W
1Segment CountUINT160-8R/W
2-9Reserved---

Segment Registers

Within a strip block, each segment occupies 11 registers. The base address for segment M (M = 0..7) within strip N is:

Segment Base Address = (100 _ N) + 10 + (M _ 11)

OffsetDescriptionData TypeRangeR/W
0StartLEDUINT160-311R/W
1StopLEDUINT160-311R/W
2EffectUINT16see EffectsR/W
3SpeedUINT161-246R/W
4Color 1 - RedUINT160-255R/W
5Color 1 - GreenUINT160-255R/W
6Color 1 - BlueUINT160-255R/W
7Color 2 - RedUINT160-255R/W
8Color 2 - GreenUINT160-255R/W
9Color 2 - BlueUINT160-255R/W
10Color 3 - RedUINT160-255R/W
11Color 3 - GreenUINT160-255R/W
12Color 3 - BlueUINT160-255R/W

SMC Button Control (Holding Registers)

In addition to the LED strips, the connected SMC buttons can also be controlled via Modbus. This corresponds to the existing MQTT control (topic /Set/Data/Smc). Both paths internally generate the same SMC command and can be used in parallel.

The SMC block occupies a dedicated register range starting at base address 1000 and has its own Apply trigger, independent of the LED Apply (register 2).

RegisterDescriptionData TypeRangeR/W
1000SMC AddressUINT16see belowR/W
1001SMC CommandTypeUINT160-2 (see below)R/W
1002SMC OffsetUINT160-5 (see below)R/W
1003Button ModeUINT160-2R/W
1004QuantityUINT160-65535R/W
1005ColorUINT160-7R/W
1006Ring EffectUINT16see Ring EffectsR/W
1007Text char 0UINT160-255 (ASCII)R/W
1008Text char 1UINT160-255 (ASCII)R/W
1009Text char 2UINT160-255 (ASCII)R/W
1010Text char 3UINT160-255 (ASCII)R/W
1011Special CommandUINT16see Special CommandsR/W
1012Button RotationUINT160-1R/W
1013Assign AddressUINT16see belowR/W
1014-1019Reserved---
1020SMC Apply/TriggerUINT160/1W
1100-1228Hub Polling ChannelsUINT16see belowR/W

Following the MQTT protocol, CommandType (register 1001) and Offset (register 1002) are kept as two separate fields. Together they select which payload registers are evaluated on Apply. The hub polling channels occupy a separate block (registers 1100-1228), described further below.

SMC Address (Register 1000): Target address of the command.

ValueMeaning
0HUB (SEH itself)
0xFFFFALL_SENSORS (broadcast to all buttons)
otherSpecific button address (device address)

SMC CommandType (Register 1001): Mirrors the CommandType field of the MQTT protocol.

ValueCommandType
0- (idle, nothing sent)
1SET_PARAMETER
2SET_STATUS

The SMC protocol additionally defines GET_STATUS, SET_UPDATE, GET_INTERNAL_STATUS and SET_INTERNAL_STATUS. These are not yet mapped and can be added later.

SMC Offset (Register 1002): Mirrors the Offset field of the MQTT protocol.

ValueOffset
0(none / empty)
1PRE_BUTTON_MODE
2POST_BUTTON_MODE
3BUTTON_ROTATE
4SPECIAL_COMMANDS
5ADDRESS_TO_BE_ASSIGNED

Valid combinations: On Apply, CommandType and Offset together determine which payload registers are evaluated.

CommandTypeOffsetAddressPayload registers
SET_PARAMETERPRE_BUTTON_MODEanyButton Mode, Quantity, Color, Ring Effect, Text (1003-1010)
SET_PARAMETERPOST_BUTTON_MODEanyButton Mode, Quantity, Color, Ring Effect, Text (1003-1010)
SET_PARAMETERBUTTON_ROTATEanyButton Rotation (1012)
SET_PARAMETER(none)HUB (0)Hub Polling Channels (1100-1228)
SET_STATUSSPECIAL_COMMANDSanySpecial Command (1011)
SET_STATUSADDRESS_TO_BE_ASSIGNEDanyAssign Address (1013)

Button Mode (Register 1003):

ValueMeaning
0DISABLED
1ENABLED
2LONGPRESS_ENABLED

Color (Register 1005):

ValueMeaningValueMeaning
0COLOFF4COLYELLOW
1COLRED5COLMAGENTA
2COLGREEN6COLCYAN
3COLBLUE7COLWHITE

Ring Effect (Register 1006):

ValueMeaningValueMeaning
0SOLID_RING94ANIMATED_ARROW_UP
1FLASH_RING95ANIMATED_ARROW_DOWN
2CONFIRM96ANIMATED_ARROW_LEFT
84POINT_ANIMATED_CLOCK97ANIMATED_ARROW_RIGHT
85CIRCLE_ANIMATED_CLOCK102SOLID_ARROW_UP_LEFT
86SOLID_ARROW_UP103SOLID_ARROW_UP_RIGHT
87SOLID_ARROW_DOWN104SOLID_ARROW_DOWN_LEFT
88SOLID_ARROW_LEFT105SOLID_ARROW_DOWN_RIGHT
89SOLID_ARROW_RIGHT106FLASH_ARROW_UP_LEFT
90FLASH_ARROW_UP107FLASH_ARROW_UP_RIGHT
91FLASH_ARROW_DOWN108FLASH_ARROW_DOWN_LEFT
92FLASH_ARROW_LEFT109FLASH_ARROW_DOWN_RIGHT
93FLASH_ARROW_RIGHT

Special Command (Register 1011): Only effective when CommandType = SET_STATUS and Offset = SPECIAL_COMMANDS.

ValueMeaning
0PRE_PRESSED_STATE
1POST_PRESSED_STATE
2REBOOT
4SHOW_CURRENT_ADDRESS
5SELF_TRIGGER
6LONG_PRESSED_STATE

Text (Register 1007-1010): Up to 4 ASCII characters for the button display, one character per register (register 1007 = first character). The character is stored in the low byte; the high byte is ignored. Unused characters (value 0) are internally padded with @. Only relevant for ring effects with text display.

Button Rotation (Register 1012): Only effective when CommandType = SET_PARAMETER and Offset = BUTTON_ROTATE. Sets the display/button orientation.

ValueMeaning
0BUTTON_ROTATION_NORMAL
1BUTTON_ROTATION_UPSIDEDOWN

Assign Address (Register 1013): Only effective when CommandType = SET_STATUS and Offset = ADDRESS_TO_BE_ASSIGNED. Assigns a device address to the addressed button(s).

ValueMeaning
0NEXT (auto-assign next free address)
otherExplicit device address to assign

Hub Polling Channels (Register 1100-1228): Only effective when CommandType = SET_PARAMETER, Offset = (none) and Address = HUB (0). Defines which button addresses the HUB (SEH) actively polls. Up to 128 addresses are supported.

RegisterDescriptionData TypeRange
1100Polling Channel CountUINT160-128
1101Polling Channel 0UINT16button address
1102Polling Channel 1UINT16button address
............
1228Polling Channel 127UINT16button address

Polling channel K is located at register 1101 + K (K = 0..127). Register 1100 holds the number of valid channels. As a single Modbus request is limited to ~123 registers, a long channel list must be written in multiple Function-16 requests before setting the Apply trigger (register 1020).

The maximum number of polling addresses that can actually be used is product-dependent and may be lower than the 128 registers reserved here.

SMC Apply/Trigger (Register 1020): After writing the SMC registers, register 1020 must be set to 1 to send the command to the buttons. The register is automatically reset to 0. The SMC Apply is independent of the LED Apply (register 2).


Input Registers (Function 04) - Status/Read-Only

RegisterDescriptionData TypeRange
0Firmware Version MajorUINT160-255
1Firmware Version MinorUINT160-255
2Firmware Version PatchUINT160-255
3Number of Configured StripsUINT160-5
4Strip 1 - Length (LEDs)UINT160-312
5Strip 2 - Length (LEDs)UINT160-312
6Strip 3 - Length (LEDs)UINT160-312
7Strip 4 - Length (LEDs)UINT160-312
8Strip 5 - Length (LEDs)UINT160-312
9Power Supply Limit (W×10)UINT160-65535
10Total Active LEDsUINT160-65535
11Error CodeUINT160-4

Error Codes:

CodeMeaning
0No error
1No network
2No MQTT connection
3No configuration
4Normal operation

SMC Button Status (Input Registers)

The states of the connected SMC buttons can be read back via input registers. This corresponds to the button feedback published over MQTT on /Pub/Data/Smc. The SMC status range starts at input register address 100.

Because Modbus has no server-initiated push, status changes must be detected by polling (see also the Notes section). To avoid reading the full status block cyclically, the SMC Event Counter is provided.

SMC Event Counter

RegisterDescriptionData TypeRange
100SMC Event CounterUINT160-65535

The counter is incremented on every SMC button status change and wraps around at 65535. A client can poll this single register cheaply and only re-read the button status blocks when the value has changed. Registers 101-109 are reserved.

Button Status Registers

The number of mapped buttons equals MAX_SMC_COUNT. This value depends on the build target (e.g. 5 for standard variants, up to 128 for certain devices). Each button occupies a block of 4 registers. The base address for button K (K = 0 .. MAX_SMC_COUNT-1) is calculated as:

Button Base Address = 110 + (K * 4)

OffsetDescriptionData TypeRange
0Button AddressUINT160-65535
1Press CountUINT160-65535
2Press StateUINT16see below
3Reserved--

A Button Address of 0 indicates an unused/empty slot.

Press State (Offset 2):

ValueMeaning
0PRE_PRESSED_STATE
1POST_PRESSED_STATE
3LONGPRESS_STATE
ButtonAddressPress CountPress State
0110111112
1114115116
2118119120
............
K110 + K×4111 + K×4112 + K×4

Available LED Effects

Effect IDNameDescription
1StaticAll LEDs lit at constant color
2BlinkOn/off blinking
3FlashQuick bright pulses
4Leading LinesRunning lines forward
5Leading Lines ReverseRunning lines backward
6MultipickerCycling through multiple colors
7PickAnimation from center outward
8PlaceAnimation from outside to center
200Knight RiderBouncing bar animation

Register Mapping - Example

Activate Strip 1, Segment 0 (green, static)

The following registers must be written (Function 16 - Write Multiple Registers):

RegisterValueDescription
1001Strip 1 Active = true
1011Strip 1 Segment Count = 1
1100Segment 0: StartLED = 0
11120Segment 0: StopLED = 20
1121Segment 0: Effect = Static
113200Segment 0: Speed = 200
1140Segment 0: Color1 R = 0
115150Segment 0: Color1 G = 150
1160Segment 0: Color1 B = 0
1170Segment 0: Color2 R = 0
1180Segment 0: Color2 G = 0
1190Segment 0: Color2 B = 0
1200Segment 0: Color3 R = 0
1210Segment 0: Color3 G = 0
1220Segment 0: Color3 B = 0
21Apply/Trigger

This corresponds to the following MQTT message:

{
"LED_STRIP_1": {
"Active": true,
"Segments": [
{
"StartLED": 0,
"StopLED": 20,
"Effect": 1,
"Speed": 200,
"Colors": [{ "R": 0, "G": 150, "B": 0 }]
}
]
}
}

SMC Button: Set PRE_BUTTON_MODE (all buttons, green, flashing ring)

The following registers must be written (Function 16 - Write Multiple Registers):

RegisterValueDescription
10000xFFFFAddress = ALL_SENSORS (broadcast)
10011CommandType = SET_PARAMETER
10021Offset = PRE_BUTTON_MODE
10031Button Mode = ENABLED
10045Quantity = 5
10052Color = COLGREEN
10061Ring Effect = FLASH_RING
10201SMC Apply/Trigger

This corresponds to the following MQTT message:

{
"Address": "ALL_SENSORS",
"CommandType": "SET_PARAMETER",
"Offset": "PRE_BUTTON_MODE",
"Payload": "ENABLED/5/COLGREEN/FLASH_RING/@@@@"
}

SMC Button: Trigger Special Command (PRE_PRESSED_STATE, all buttons)

RegisterValueDescription
10000xFFFFAddress = ALL_SENSORS (broadcast)
10012CommandType = SET_STATUS
10024Offset = SPECIAL_COMMANDS
10110Special Command = PRE_PRESSED_STATE
10201SMC Apply/Trigger

This corresponds to the following MQTT message:

{
"Address": "ALL_SENSORS",
"CommandType": "SET_STATUS",
"Offset": "SPECIAL_COMMANDS",
"Payload": "PRE_PRESSED_STATE"
}

SMC Button: Set Button Rotation (all buttons, upside down)

RegisterValueDescription
10000xFFFFAddress = ALL_SENSORS (broadcast)
10011CommandType = SET_PARAMETER
10023Offset = BUTTON_ROTATE
10121Button Rotation = BUTTON_ROTATION_UPSIDEDOWN
10201SMC Apply/Trigger

This corresponds to the following MQTT message:

{
"Address": "ALL_SENSORS",
"CommandType": "SET_PARAMETER",
"Offset": "BUTTON_ROTATE",
"Payload": "BUTTON_ROTATION_UPSIDEDOWN"
}

SMC Button: Assign Address (all buttons, address 0x1000)

RegisterValueDescription
10000xFFFFAddress = ALL_SENSORS (broadcast)
10012CommandType = SET_STATUS
10025Offset = ADDRESS_TO_BE_ASSIGNED
10130x1000Assign Address = 0x1000
10201SMC Apply/Trigger

This corresponds to the following MQTT message:

{
"Address": "ALL_SENSORS",
"CommandType": "SET_STATUS",
"Offset": "ADDRESS_TO_BE_ASSIGNED",
"Payload": "1000"
}

Set register 1013 to 0 to assign the next free address automatically (MQTT payload "NEXT").

SMC HUB: Configure Polling Channels (poll buttons 0x1000-0x1003)

RegisterValueDescription
10000Address = HUB
10011CommandType = SET_PARAMETER
10020Offset = (none)
11004Polling Channel Count = 4
11010x1000Polling channel 0
11020x1001Polling channel 1
11030x1002Polling channel 2
11040x1003Polling channel 3
10201SMC Apply/Trigger

This corresponds to the following MQTT message:

{
"Address": "HUB",
"CommandType": "SET_PARAMETER",
"Offset": "",
"Payload": "1000/1001/1002/1003"
}

Address Calculation - Quick Reference

Strip N Base Address:    100 * N          (N = 1..5)
Strip N Active: 100 * N + 0
Strip N Segment Count: 100 * N + 1
Segment M Base Address: 100 * N + 10 + (M * 11) (M = 0..7)

SMC block (holding): selector 1000-1002, payload 1003-1013, Apply = 1020
SMC hub polling (holding): count 1100, channel K = 1101 + K (K = 0..127)
SMC event counter (input): 100
SMC status (input): button K base = 110 + (K * 4) (K = 0 .. MAX_SMC_COUNT-1)
StripActiveSeg CountSeg 0Seg 1Seg 2Seg 3
1100101110121132143
2200201210221232243
3300301310321332343
4400401410421432443
5500501510521532543

Notes

  • Parallel MQTT/Modbus Operation: Both interfaces write to the same LED strips. The most recently received command (whether MQTT or Modbus) determines the current state.
  • Power Limit: The power limit applies globally. Segments that would exceed the power limit will not be activated (identical behavior to MQTT).
  • StopLED >= StartLED: If StopLED < StartLED, StopLED is automatically set to StartLED.
  • Colors: The sum of R+G+B per color is limited to a maximum of 180 (per-LED current limiting).
  • Unused Colors: Set unused color registers (Color 2, Color 3) to 0/0/0.
  • Apply Register: Changes to strip/segment registers only take effect when 1 is written to register 2 (Apply). This allows atomic configuration of multiple strips/segments.
  • SMC Control: The SMC block (from register 1000) has its own Apply trigger (register 1020), independent of the LED Apply (register 2). LED and SMC commands can thus be triggered separately.
  • SMC Parallel to MQTT: Modbus and MQTT SMC commands internally generate the same SMC command and are placed into the same send queue. The most recently received command determines the button state.
  • SMC Addressing: 0xFFFF addresses all buttons (broadcast), 0 the HUB (SEH itself), any other value a specific button.
  • SMC Status: The button status input registers (from address 110) reflect the most recently received button feedback. A Button Address of 0 marks an unused slot.
  • Status Change Notification: Modbus has no server-initiated push; the server only answers requests. Status changes are detected by polling the SMC Event Counter (register 100) and re-reading the button blocks when it changed. For true push notifications use the MQTT channel (/Pub/Data/Smc), which runs in parallel.