{
 "manufacturer": "Eastron",
 "manufacturer_slug": "eastron",
 "model": "SDM230-DI",
 "model_slug": "sdm230-di",
 "short_model": "SDM230-DI",
 "aliases": [
  "SDM230 DI"
 ],
 "equipment_type": "Energy meter",
 "applies_to": "Eastron SDM230-DI single-phase 100 A DIN-rail meter with two digital inputs and RS485 Modbus RTU, manual 2025 V1.00.",
 "summary": "The SDM230-DI is a single-phase, direct-connected (up to 100 A) DIN-rail energy meter with two digital inputs and an RS485 Modbus RTU port. Measurements, demand and energy totals are 32-bit IEEE floats in input registers (function 04); settings are held in holding registers (function 03 read, 16 write). This map covers the electrical values, import/export and resettable energy, demand, RS485 settings and the measurement-mode selector.",
 "transport": [
  "RTU"
 ],
 "defaults": {
  "unit_id": 1,
  "baud": 9600,
  "parity": "None",
  "data_bits": 8,
  "stop_bits": 1,
  "tcp_port": null
 },
 "addressing": {
  "convention": "Modicon",
  "note": "Registers are printed Modicon style (30001, 40003, six-digit 463777...) next to the hex start address sent on the wire. Wire address = printed number minus 30001 / 40001 / 400001; the manual's example reads 40003 at start address 0x0002."
 },
 "default_word_order": "ABCD",
 "firmware": null,
 "source": {
  "title": "SDM230-DI User Manual",
  "doc_number": "2025 V1.00",
  "revision_date": "2025-06-04",
  "url": "https://www.eastrongroup.com/eastrongroup/2025/06/17/eastronsdm230-diusermanualv1.00.pdf",
  "pages": "Chapter 5, pp. 16-23 (PDF pages 19-26)"
 },
 "notes": [
  "Word order: the manual states that floats are sent big-endian with the first register holding the high 16 bits, and its example returns 42 70 00 00 for 60 minutes. All floats here are ABCD.",
  "The input table footnote says total kWh/kVArh is import plus export; the measurement-mode register (463777) can change how the meter forms its total, so check that setting if totals look wrong.",
  "Left out: Int64 energy (Wh / VArh, from 310001) and Int32 scaled readings (from 310251), because the manual states big-endian order only for floats.",
  "Left out: DI-1/DI-2 counters (40770/40772) and serial number (464513), unsigned 32-bit values with no stated word order.",
  "The reset register also lists a kWh reset code, but the code is blank in the manual, so only the demand (0000) and DI-count (0006) codes are given.",
  "Demand footnote: the manual says the power-sum demand is calculated for 'import – export' (en dash) without saying whether that means net import minus export or both directions combined; check on a live meter if the sign matters."
 ],
 "registers": [
  {
   "table": "input_register",
   "address": 0,
   "documented": "30001",
   "name": "Voltage",
   "description": "Line-to-neutral RMS voltage.",
   "data_type": "FLOAT32",
   "length": 2,
   "word_order": "ABCD",
   "scale": 1,
   "units": "V",
   "access": "R",
   "values": null,
   "bits": null,
   "offset": 0
  },
  {
   "table": "input_register",
   "address": 6,
   "documented": "30007",
   "name": "Current",
   "description": "",
   "data_type": "FLOAT32",
   "length": 2,
   "word_order": "ABCD",
   "scale": 1,
   "units": "A",
   "access": "R",
   "values": null,
   "bits": null,
   "offset": 0
  },
  {
   "table": "input_register",
   "address": 12,
   "documented": "30013",
   "name": "Active power",
   "description": "",
   "data_type": "FLOAT32",
   "length": 2,
   "word_order": "ABCD",
   "scale": 1,
   "units": "W",
   "access": "R",
   "values": null,
   "bits": null,
   "offset": 0
  },
  {
   "table": "input_register",
   "address": 18,
   "documented": "30019",
   "name": "Apparent power",
   "description": "",
   "data_type": "FLOAT32",
   "length": 2,
   "word_order": "ABCD",
   "scale": 1,
   "units": "VA",
   "access": "R",
   "values": null,
   "bits": null,
   "offset": 0
  },
  {
   "table": "input_register",
   "address": 24,
   "documented": "30025",
   "name": "Reactive power",
   "description": "",
   "data_type": "FLOAT32",
   "length": 2,
   "word_order": "ABCD",
   "scale": 1,
   "units": "VAr",
   "access": "R",
   "values": null,
   "bits": null,
   "offset": 0
  },
  {
   "table": "input_register",
   "address": 30,
   "documented": "30031",
   "name": "Power factor",
   "description": "Sign follows current direction: negative means reverse flow.",
   "data_type": "FLOAT32",
   "length": 2,
   "word_order": "ABCD",
   "scale": 1,
   "units": "",
   "access": "R",
   "values": null,
   "bits": null,
   "offset": 0
  },
  {
   "table": "input_register",
   "address": 36,
   "documented": "30037",
   "name": "Phase angle",
   "description": "",
   "data_type": "FLOAT32",
   "length": 2,
   "word_order": "ABCD",
   "scale": 1,
   "units": "Degrees",
   "access": "R",
   "values": null,
   "bits": null,
   "offset": 0
  },
  {
   "table": "input_register",
   "address": 70,
   "documented": "30071",
   "name": "Frequency",
   "description": "",
   "data_type": "FLOAT32",
   "length": 2,
   "word_order": "ABCD",
   "scale": 1,
   "units": "Hz",
   "access": "R",
   "values": null,
   "bits": null,
   "offset": 0
  },
  {
   "table": "input_register",
   "address": 72,
   "documented": "30073",
   "name": "Import active energy",
   "description": "",
   "data_type": "FLOAT32",
   "length": 2,
   "word_order": "ABCD",
   "scale": 1,
   "units": "kWh",
   "access": "R",
   "values": null,
   "bits": null,
   "offset": 0
  },
  {
   "table": "input_register",
   "address": 74,
   "documented": "30075",
   "name": "Export active energy",
   "description": "",
   "data_type": "FLOAT32",
   "length": 2,
   "word_order": "ABCD",
   "scale": 1,
   "units": "kWh",
   "access": "R",
   "values": null,
   "bits": null,
   "offset": 0
  },
  {
   "table": "input_register",
   "address": 76,
   "documented": "30077",
   "name": "Import reactive energy",
   "description": "",
   "data_type": "FLOAT32",
   "length": 2,
   "word_order": "ABCD",
   "scale": 1,
   "units": "kVArh",
   "access": "R",
   "values": null,
   "bits": null,
   "offset": 0
  },
  {
   "table": "input_register",
   "address": 78,
   "documented": "30079",
   "name": "Export reactive energy",
   "description": "",
   "data_type": "FLOAT32",
   "length": 2,
   "word_order": "ABCD",
   "scale": 1,
   "units": "kVArh",
   "access": "R",
   "values": null,
   "bits": null,
   "offset": 0
  },
  {
   "table": "input_register",
   "address": 80,
   "documented": "30081",
   "name": "Apparent energy",
   "description": "",
   "data_type": "FLOAT32",
   "length": 2,
   "word_order": "ABCD",
   "scale": 1,
   "units": "kVAh",
   "access": "R",
   "values": null,
   "bits": null,
   "offset": 0
  },
  {
   "table": "input_register",
   "address": 82,
   "documented": "30083",
   "name": "Ah",
   "description": "Accumulated ampere-hours.",
   "data_type": "FLOAT32",
   "length": 2,
   "word_order": "ABCD",
   "scale": 1,
   "units": "Ah",
   "access": "R",
   "values": null,
   "bits": null,
   "offset": 0
  },
  {
   "table": "input_register",
   "address": 84,
   "documented": "30085",
   "name": "Total active power demand",
   "description": "Footnoted as 'import – export' in the manual; see notes.",
   "data_type": "FLOAT32",
   "length": 2,
   "word_order": "ABCD",
   "scale": 1,
   "units": "W",
   "access": "R",
   "values": null,
   "bits": null,
   "offset": 0
  },
  {
   "table": "input_register",
   "address": 86,
   "documented": "30087",
   "name": "Max total active power demand",
   "description": "Footnoted as 'import – export' in the manual; see notes.",
   "data_type": "FLOAT32",
   "length": 2,
   "word_order": "ABCD",
   "scale": 1,
   "units": "W",
   "access": "R",
   "values": null,
   "bits": null,
   "offset": 0
  },
  {
   "table": "input_register",
   "address": 88,
   "documented": "30089",
   "name": "Import active power demand",
   "description": "",
   "data_type": "FLOAT32",
   "length": 2,
   "word_order": "ABCD",
   "scale": 1,
   "units": "W",
   "access": "R",
   "values": null,
   "bits": null,
   "offset": 0
  },
  {
   "table": "input_register",
   "address": 90,
   "documented": "30091",
   "name": "Import active power max demand",
   "description": "",
   "data_type": "FLOAT32",
   "length": 2,
   "word_order": "ABCD",
   "scale": 1,
   "units": "W",
   "access": "R",
   "values": null,
   "bits": null,
   "offset": 0
  },
  {
   "table": "input_register",
   "address": 92,
   "documented": "30093",
   "name": "Export active power demand",
   "description": "",
   "data_type": "FLOAT32",
   "length": 2,
   "word_order": "ABCD",
   "scale": 1,
   "units": "W",
   "access": "R",
   "values": null,
   "bits": null,
   "offset": 0
  },
  {
   "table": "input_register",
   "address": 94,
   "documented": "30095",
   "name": "Export active power max demand",
   "description": "",
   "data_type": "FLOAT32",
   "length": 2,
   "word_order": "ABCD",
   "scale": 1,
   "units": "W",
   "access": "R",
   "values": null,
   "bits": null,
   "offset": 0
  },
  {
   "table": "input_register",
   "address": 258,
   "documented": "30259",
   "name": "Current demand",
   "description": "",
   "data_type": "FLOAT32",
   "length": 2,
   "word_order": "ABCD",
   "scale": 1,
   "units": "A",
   "access": "R",
   "values": null,
   "bits": null,
   "offset": 0
  },
  {
   "table": "input_register",
   "address": 264,
   "documented": "30265",
   "name": "Max current demand",
   "description": "",
   "data_type": "FLOAT32",
   "length": 2,
   "word_order": "ABCD",
   "scale": 1,
   "units": "A",
   "access": "R",
   "values": null,
   "bits": null,
   "offset": 0
  },
  {
   "table": "input_register",
   "address": 342,
   "documented": "30343",
   "name": "Total kWh",
   "description": "Import plus export active energy.",
   "data_type": "FLOAT32",
   "length": 2,
   "word_order": "ABCD",
   "scale": 1,
   "units": "kWh",
   "access": "R",
   "values": null,
   "bits": null,
   "offset": 0
  },
  {
   "table": "input_register",
   "address": 344,
   "documented": "30345",
   "name": "Total kVArh",
   "description": "Import plus export reactive energy.",
   "data_type": "FLOAT32",
   "length": 2,
   "word_order": "ABCD",
   "scale": 1,
   "units": "kVArh",
   "access": "R",
   "values": null,
   "bits": null,
   "offset": 0
  },
  {
   "table": "input_register",
   "address": 384,
   "documented": "30385",
   "name": "Resettable total active energy",
   "description": "Partial counter.",
   "data_type": "FLOAT32",
   "length": 2,
   "word_order": "ABCD",
   "scale": 1,
   "units": "kWh",
   "access": "R",
   "values": null,
   "bits": null,
   "offset": 0
  },
  {
   "table": "input_register",
   "address": 386,
   "documented": "30387",
   "name": "Resettable total reactive energy",
   "description": "Partial counter.",
   "data_type": "FLOAT32",
   "length": 2,
   "word_order": "ABCD",
   "scale": 1,
   "units": "kVArh",
   "access": "R",
   "values": null,
   "bits": null,
   "offset": 0
  },
  {
   "table": "holding_register",
   "address": 2,
   "documented": "40003",
   "name": "Demand period",
   "description": "0 to 60 minutes; 0 updates demand every second. Default 60.",
   "data_type": "FLOAT32",
   "length": 2,
   "word_order": "ABCD",
   "scale": 1,
   "units": "min",
   "access": "RW",
   "values": null,
   "bits": null,
   "offset": 0
  },
  {
   "table": "holding_register",
   "address": 14,
   "documented": "40015",
   "name": "Key parameter programming authorization (KPPA)",
   "description": "Read 0/1 authorization state; write the password to unlock key settings.",
   "data_type": "FLOAT32",
   "length": 2,
   "word_order": "ABCD",
   "scale": 1,
   "units": "",
   "access": "RW",
   "values": {
    "0": "Not authorized",
    "1": "Authorized"
   },
   "bits": null,
   "offset": 0
  },
  {
   "table": "holding_register",
   "address": 18,
   "documented": "40019",
   "name": "Parity / stop bits",
   "description": "RS485 framing. Default one stop bit, no parity.",
   "data_type": "FLOAT32",
   "length": 2,
   "word_order": "ABCD",
   "scale": 1,
   "units": "",
   "access": "RW",
   "values": {
    "0": "1 stop bit, no parity",
    "1": "1 stop bit, even parity",
    "2": "1 stop bit, odd parity",
    "3": "2 stop bits, no parity"
   },
   "bits": null,
   "offset": 0
  },
  {
   "table": "holding_register",
   "address": 20,
   "documented": "40021",
   "name": "Modbus address",
   "description": "Node address 1 to 247. Default 1.",
   "data_type": "FLOAT32",
   "length": 2,
   "word_order": "ABCD",
   "scale": 1,
   "units": "",
   "access": "RW",
   "values": null,
   "bits": null,
   "offset": 0
  },
  {
   "table": "holding_register",
   "address": 24,
   "documented": "40025",
   "name": "Password",
   "description": "Range 0000 to 9999. Default 1000.",
   "data_type": "FLOAT32",
   "length": 2,
   "word_order": "ABCD",
   "scale": 1,
   "units": "",
   "access": "RW",
   "values": null,
   "bits": null,
   "offset": 0
  },
  {
   "table": "holding_register",
   "address": 28,
   "documented": "40029",
   "name": "Baud rate",
   "description": "Default 9600.",
   "data_type": "FLOAT32",
   "length": 2,
   "word_order": "ABCD",
   "scale": 1,
   "units": "",
   "access": "RW",
   "values": {
    "0": "2400",
    "1": "4800",
    "2": "9600",
    "3": "19200",
    "4": "38400",
    "6": "115200"
   },
   "bits": null,
   "offset": 0
  },
  {
   "table": "holding_register",
   "address": 58,
   "documented": "40059",
   "name": "Automatic scrolling display",
   "description": "0 to 30 s; 0 disables scrolling. Default 0.",
   "data_type": "FLOAT32",
   "length": 2,
   "word_order": "ABCD",
   "scale": 1,
   "units": "s",
   "access": "RW",
   "values": null,
   "bits": null,
   "offset": 0
  },
  {
   "table": "holding_register",
   "address": 60,
   "documented": "40061",
   "name": "Backlight time",
   "description": "0 to 121; 0 keeps backlight on, 121 keeps it off. Default 60.",
   "data_type": "FLOAT32",
   "length": 2,
   "word_order": "ABCD",
   "scale": 1,
   "units": "min",
   "access": "RW",
   "values": null,
   "bits": null,
   "offset": 0
  },
  {
   "table": "holding_register",
   "address": 768,
   "documented": "40769",
   "name": "DI filter time",
   "description": "Digital input debounce time, 0 to 255 ms. Default 100.",
   "data_type": "UINT16",
   "length": 1,
   "word_order": null,
   "scale": 1,
   "units": "ms",
   "access": "RW",
   "values": null,
   "bits": null,
   "offset": 0
  },
  {
   "table": "holding_register",
   "address": 61456,
   "documented": "461457",
   "name": "Reset",
   "description": "Write a code to clear stored values.",
   "data_type": "UINT16",
   "length": 1,
   "word_order": null,
   "scale": 1,
   "units": "",
   "access": "W",
   "values": {
    "0": "Reset maximum demand",
    "6": "Reset DI counts"
   },
   "bits": null,
   "offset": 0
  },
  {
   "table": "holding_register",
   "address": 63776,
   "documented": "463777",
   "name": "Measurement mode",
   "description": "How the meter forms its total energy.",
   "data_type": "UINT16",
   "length": 1,
   "word_order": null,
   "scale": 1,
   "units": "",
   "access": "RW",
   "values": {
    "1": "Total = import",
    "2": "Total = import + export",
    "3": "Total = import - export"
   },
   "bits": null,
   "offset": 0
  },
  {
   "table": "holding_register",
   "address": 63792,
   "documented": "463793",
   "name": "Running time",
   "description": "Accumulated operating time in hours.",
   "data_type": "FLOAT32",
   "length": 2,
   "word_order": "ABCD",
   "scale": 1,
   "units": "h",
   "access": "RW",
   "values": null,
   "bits": null,
   "offset": 0
  },
  {
   "table": "holding_register",
   "address": 64514,
   "documented": "464515",
   "name": "Meter code",
   "description": "Model identification code (hex).",
   "data_type": "UINT16",
   "length": 1,
   "word_order": null,
   "scale": 1,
   "units": "",
   "access": "R",
   "values": null,
   "bits": null,
   "offset": 0
  },
  {
   "table": "holding_register",
   "address": 64644,
   "documented": "464645",
   "name": "Software version",
   "description": "High byte and low byte form version XX.YY.",
   "data_type": "UINT16",
   "length": 1,
   "word_order": null,
   "scale": 1,
   "units": "",
   "access": "R",
   "values": null,
   "bits": null,
   "offset": 0
  },
  {
   "table": "holding_register",
   "address": 64646,
   "documented": "464647",
   "name": "Program number",
   "description": "Firmware program identifier (hex).",
   "data_type": "UINT16",
   "length": 1,
   "word_order": null,
   "scale": 1,
   "units": "",
   "access": "R",
   "values": null,
   "bits": null,
   "offset": 0
  }
 ],
 "integration": {
  "summary": "Read two-register floats with function 04: voltage at 0x0000, current 0x0006, active power 0x000C, import/export kWh at 0x0048/0x004A. Write settings with function 16 after unlocking with the password in the KPPA register.",
  "minimum_registers": [
   {
    "table": "input_register",
    "address": 0,
    "why": "Voltage"
   },
   {
    "table": "input_register",
    "address": 6,
    "why": "Current"
   },
   {
    "table": "input_register",
    "address": 12,
    "why": "Active power"
   },
   {
    "table": "input_register",
    "address": 30,
    "why": "Power factor"
   },
   {
    "table": "input_register",
    "address": 70,
    "why": "Frequency"
   },
   {
    "table": "input_register",
    "address": 72,
    "why": "Import kWh"
   },
   {
    "table": "input_register",
    "address": 74,
    "why": "Export kWh"
   }
  ],
  "enable": "Modbus RTU is always on at the RS485 terminals. To change key settings, write the password (default 1000) as a float to 40015 (KPPA) first; a read of 40015 returns 1 when unlocked.",
  "watchdog": null,
  "quirks": [
   "Settings such as address and baud code are 32-bit floats over two registers; DI filter time, reset, measurement mode, meter code, version and program number are single 16-bit registers.",
   "Power factor carries a sign for current direction: positive for forward current, negative for reverse."
  ],
  "setup": [
   "Defaults: address 1, 9600 bps, 8 data bits, no parity, 1 stop bit.",
   "Address 1-247; up to 64 meters per bus and 1000 m cable per the manual.",
   "Comm settings can also be changed from the front-panel setup menu."
  ],
  "gotchas": [
   "The Int64 energy and Int32 reading blocks (310001 onwards) are not mapped because their word order is not documented; use the float registers."
  ]
 },
 "page": "https://easymodbus.com/modbus-register-maps/eastron/sdm230-di",
 "address_note": "address = 0-based Modbus wire (PDU) address; documented = as printed in the source.",
 "note": "Re-typed from the manufacturer's public documentation (see source) and verified against it. Registers vary by firmware and options; verify against the live device before writing."
}
