Skip to content

Modbus RTU & RS-485 Meter Engine

The Modbus RTU Engine is the primary data-acquisition subsystem of the Aslandi Edge Converter. It manages serial communication across the isolated RS-485 physical bus, sequentially polling connected energy meters and validating frame integrity.


1. Physical Bus Configuration (Channel 0)

In production release v1, communication is strictly bound to Bus Channel 0 (Waveshare Pico-2CH-RS485 transceiver Channel 0 via RP2350 UART0):

ParameterSpecificationNotes
Physical LayerRS-485 Differential (A / B lines)Requires 120 Ω termination resistor at both bus ends.
Baud Rate9600 bps (configurable 4800–115200)Default factory baseline is 9600.
Data Framing8 Data Bits, No Parity, 1 Stop Bit (8N1)Compliant with LEM-60 and DTSU666 standards.
Bus ChannelChannel 0 exclusivelyChannel 1 is formally disabled in release v1.
Capacity LimitUp to 50 energy metersTested on 50-meter simulated and physical bus networks.
Response Timeout200 ms per slave device3 retries before flagging communication timeout.
flowchart LR
    subgraph Converter["Converter (RP2350)"]
        UART0["UART0 Controller"]
        TXEN["GPIO GPIO_RS485_TX_EN"]
        RS485["Waveshare Transceiver (Ch 0)"]
        UART0 --- RS485
        TXEN --> RS485
    end

    subgraph RS485Bus["RS-485 Daisy Chain (Channel 0)"]
        M1["Meter 1 (Addr 0x01)"]
        M2["Meter 2 (Addr 0x02)"]
        M50["Meter 50 (Addr 0x32)"]
        RS485 === M1
        M1 === M2
        M2 === M50
    end

2. Supported Meter Profiles & Register Maps

A. Zamel LEM-60 (Single-Phase Meter)

  • Modbus Function: 0x03 (Read Holding Registers) or 0x04 (Read Input Registers).
  • Endianness: Big-Endian (MSB first) 32-bit Float or 32-bit Integer.
ParameterModbus AddressTypeUnitMultiplier / Scale
Active Energy Import0x000032-bit uintkWh$0.01\text{ kWh}$
Active Energy Export0x000232-bit uintkWh$0.01\text{ kWh}$
Voltage L10x000416-bit uintV$0.1\text{ V}$
Current L10x000516-bit uintA$0.01\text{ A}$
Active Power0x000632-bit intW$1\text{ W}$
Frequency0x000816-bit uintHz$0.1\text{ Hz}$

B. CHINT DTSU666 (Three-Phase Meter)

  • Modbus Function: 0x03 (Read Holding Registers) / 0x04 (Read Input Registers).
  • Format: IEEE 754 32-bit Floating Point (High word first).
ParameterModbus AddressTypeUnitDescription
Total Active Energy0x2000Float32kWhCombined L1 + L2 + L3 imported energy
Total Reactive Energy0x200AFloat32kVARhCombined reactive power import
Voltage L1 / L2 / L30x200C - 0x2010Float32VPhase voltages (RMS)
Current L1 / L2 / L30x2012 - 0x2016Float32APhase currents (RMS)
Total Active Power0x2018Float32kWNet three-phase active power
Total Power Factor0x2022Float32-Cos phi network power factor

3. Polling Cycle & Timeout Handling

flowchart TD
    Start["Poll Timer Fires (e.g. every 60s)"] --> SelectMeter["Select Next Meter from Registry (1..N)"]
    SelectMeter --> PreparePacket["Build Modbus Request Frame + CRC16"]
    PreparePacket --> Send["Assert TX_EN, Transmit over RS-485, Deassert TX_EN"]
    Send --> WaitResponse{"Response Received within 200 ms?"}
    
    WaitResponse -->|Yes| ValidateCRC{"Valid CRC16 & Slave ID?"}
    ValidateCRC -->|Yes| ParseValues["Parse Registers, Apply Scale & Timestamp"]
    ParseValues --> Enqueue["Push to Telemetry Buffer"]
    
    WaitResponse -->|"No / Timeout"| IncRetry{"Retry Count < 3?"}
    ValidateCRC -->|CRC Error| IncRetry
    
    IncRetry -->|Yes| Send
    IncRetry -->|No| FlagFault["Record Device Offline Alarm"]
    
    Enqueue --> HasMore{"More Meters in List?"}
    FlagFault --> HasMore
    HasMore -->|Yes| SelectMeter
    HasMore -->|No| SleepUntilNext["Yield FreeRTOS Task until Next Cycle"]
  • Bus Collision Prevention: Strict 3.5-character silent interval ($t_{3.5}$) enforced between consecutive frame transmissions.
  • Fail-Safe Isolation: A malfunctioning or unresponsive meter on the bus does not block the polling loop. After 3 timed-out attempts ($600\text{ ms}$ total), the meter is marked with a communication fault flag and the polling task immediately advances to the next device.