{
  "$schema": "https://raw.githubusercontent.com/nobrega8/mbmap-library/main/schema/mbmap-2.schema.json",
  "mbmap": 2,
  "vendor": "Novus",
  "model": "DigiRail-2A",
  "models": ["DigiRail-2A"],
  "vendor_website": "novus.com.br",
  "description": "Two-channel universal analog input module (thermocouple, Pt100, mV, V, mA) with Modbus RTU over RS485: channel values, status flags, input configuration, indication limits and tags",
  "revision": 1,
  "revised": "2026-10-31",
  "source": "Novus DigiRail-2A communication manual (Portuguese)",
  "sources": [
    {"title": "DigiRail-2A Módulo de Entradas Analógicas Universais - Manual de Comunicação", "url": "https://github.com/user-attachments/files/34218828/Manual_Comunicacao_DigiRail-2A_PT.pdf", "note": "linked in issue #86; tables 1-7"}
  ],
  "notes": [
    "Factory defaults: address 247, 1200 bit/s, even parity, 1 stop bit. Pressing the RCom button puts the module in diagnostic mode for one minute with address 246, 1200 bit/s, even parity.",
    "Functions 03 (read holding registers), 04 (read input registers) and 06 (write single register). The manual lists no write-multiple function, so each setting is written on its own.",
    "The channel values are also in input registers 0-1 (percent) and 5-6 (engineering unit); this map reads the same values from the holding registers, which hold the configuration too.",
    "Novus recommends configuring the module with its DigiConfig software; the configuration registers are listed so the settings can be checked.",
    "The manual does not say how many decimal places the engineering-unit values have: they follow the module's configuration (the indication limits for linear inputs).",
    "The manual does not give the character order of the tags; this map assumes the first character is in the high byte.",
    "Written from the manufacturer's manual; not tested on a device."
  ],
  "protocol": "rtu",
  "unit_id": 247,
  "baudrate": 1200,
  "databits": 8,
  "parity": "E",
  "stopbits": 1,
  "byte_order": "big",
  "word_order": "big",
  "address_base": 0,
  "x_status": "official",
  "enums": {
    "baud_rate": {"0": "1200", "1": "2400", "2": "4800", "3": "9600", "4": "19200", "5": "38400", "6": "57600", "7": "115200"},
    "parity": {"0": "None", "1": "Odd", "2": "Even"},
    "input_type": {"-1": "Disabled", "0": "Thermocouple J", "1": "Thermocouple K", "2": "Thermocouple T", "3": "Thermocouple E", "4": "Thermocouple N", "5": "Thermocouple R", "6": "Thermocouple S", "7": "Thermocouple B", "8": "Pt100", "9": "0-50 mV", "10": "0-20 mV", "11": "-10 to 20 mV", "12": "0-5 V", "13": "0-10 V", "18": "0-20 mA", "19": "4-20 mA"},
    "temperature_unit": {"0": "°C", "1": "°F"},
    "off_on": {"0": "Off", "1": "On"},
    "model": {"1": "DigiRail-2A", "3": "DigiRail-2R", "4": "DigiRail-4C"}
  },
  "registers": [
    {"name": "Channel 1 value (percent)", "group": "Measurements", "area": "holding", "address": 9, "type": "uint16", "scale": 0.0016129, "unit": "%", "access": "R", "description": "Linear 0-62000 over the input range, before conversion to the engineering unit (also input register 0)"},
    {"name": "Channel 2 value (percent)", "group": "Measurements", "area": "holding", "address": 10, "type": "uint16", "scale": 0.0016129, "unit": "%", "access": "R", "description": "Linear 0-62000 over the input range, before conversion to the engineering unit (also input register 1)"},
    {"name": "Channel 1 value", "group": "Measurements", "area": "holding", "address": 14, "type": "int16", "access": "R", "description": "In the configured engineering unit, -31000 to 31000 (also input register 5)"},
    {"name": "Channel 2 value", "group": "Measurements", "area": "holding", "address": 15, "type": "int16", "access": "R", "description": "In the configured engineering unit, -31000 to 31000 (also input register 6)"},

    {"name": "Channel 1 sensor error", "group": "Status", "area": "holding", "address": 7, "type": "bool", "bit": 0, "access": "R"},
    {"name": "Channel 1 Pt100 excitation wire error", "group": "Status", "area": "holding", "address": 7, "type": "bool", "bit": 1, "access": "R"},
    {"name": "Channel 1 underflow", "group": "Status", "area": "holding", "address": 7, "type": "bool", "bit": 2, "access": "R"},
    {"name": "Channel 1 overflow", "group": "Status", "area": "holding", "address": 7, "type": "bool", "bit": 3, "access": "R"},
    {"name": "Channel 1 unit flag", "group": "Status", "area": "holding", "address": 7, "type": "bool", "bit": 4, "access": "R", "enum": "temperature_unit"},
    {"name": "Channel 2 sensor error", "group": "Status", "area": "holding", "address": 7, "type": "bool", "bit": 8, "access": "R"},
    {"name": "Channel 2 Pt100 excitation wire error", "group": "Status", "area": "holding", "address": 7, "type": "bool", "bit": 9, "access": "R"},
    {"name": "Channel 2 underflow", "group": "Status", "area": "holding", "address": 7, "type": "bool", "bit": 10, "access": "R"},
    {"name": "Channel 2 overflow", "group": "Status", "area": "holding", "address": 7, "type": "bool", "bit": 11, "access": "R"},
    {"name": "Channel 2 unit flag", "group": "Status", "area": "holding", "address": 7, "type": "bool", "bit": 12, "access": "R", "enum": "temperature_unit"},

    {"name": "Channel 1 input type", "group": "Channel 1", "area": "holding", "address": 21, "type": "int16", "access": "RW", "enum": "input_type", "write_min": -1, "write_max": 21},
    {"name": "Channel 1 temperature unit", "group": "Channel 1", "area": "holding", "address": 26, "type": "uint16", "access": "RW", "enum": "temperature_unit", "write_min": 0, "write_max": 1, "description": "Used for thermocouple and Pt100 inputs"},
    {"name": "Channel 1 user offset", "group": "Channel 1", "area": "holding", "address": 31, "type": "int16", "access": "RW", "write_min": -16000, "write_max": 16000, "description": "Small correction added to the indication"},
    {"name": "Channel 1 square root", "group": "Channel 1", "area": "holding", "address": 36, "type": "uint16", "access": "RW", "enum": "off_on", "write_min": 0, "write_max": 1, "description": "Linear inputs (mV, V, mA) only"},
    {"name": "Channel 1 linear low limit", "group": "Channel 1", "area": "holding", "address": 41, "type": "int16", "access": "RW", "write_min": -31000, "write_max": 31000, "description": "Indication at the bottom of a linear input range"},
    {"name": "Channel 1 linear high limit", "group": "Channel 1", "area": "holding", "address": 42, "type": "int16", "access": "RW", "write_min": -31000, "write_max": 31000, "description": "Indication at the top of a linear input range"},
    {"name": "Channel 1 indication low limit", "group": "Channel 1", "area": "holding", "address": 51, "type": "int16", "access": "R", "description": "Lowest value the channel can show (sensor limit or linear low limit)"},
    {"name": "Channel 1 indication high limit", "group": "Channel 1", "area": "holding", "address": 52, "type": "int16", "access": "R", "description": "Highest value the channel can show (sensor limit or linear high limit)"},

    {"name": "Channel 2 input type", "group": "Channel 2", "area": "holding", "address": 22, "type": "int16", "access": "RW", "enum": "input_type", "write_min": -1, "write_max": 21},
    {"name": "Channel 2 temperature unit", "group": "Channel 2", "area": "holding", "address": 27, "type": "uint16", "access": "RW", "enum": "temperature_unit", "write_min": 0, "write_max": 1, "description": "Used for thermocouple and Pt100 inputs"},
    {"name": "Channel 2 user offset", "group": "Channel 2", "area": "holding", "address": 32, "type": "int16", "access": "RW", "write_min": -16000, "write_max": 16000, "description": "Small correction added to the indication"},
    {"name": "Channel 2 square root", "group": "Channel 2", "area": "holding", "address": 37, "type": "uint16", "access": "RW", "enum": "off_on", "write_min": 0, "write_max": 1, "description": "Linear inputs (mV, V, mA) only"},
    {"name": "Channel 2 linear low limit", "group": "Channel 2", "area": "holding", "address": 43, "type": "int16", "access": "RW", "write_min": -31000, "write_max": 31000, "description": "Indication at the bottom of a linear input range"},
    {"name": "Channel 2 linear high limit", "group": "Channel 2", "area": "holding", "address": 44, "type": "int16", "access": "RW", "write_min": -31000, "write_max": 31000, "description": "Indication at the top of a linear input range"},
    {"name": "Channel 2 indication low limit", "group": "Channel 2", "area": "holding", "address": 53, "type": "int16", "access": "R", "description": "Lowest value the channel can show (sensor limit or linear low limit)"},
    {"name": "Channel 2 indication high limit", "group": "Channel 2", "area": "holding", "address": 54, "type": "int16", "access": "R", "description": "Highest value the channel can show (sensor limit or linear high limit)"},

    {"name": "Input filter", "group": "Configuration", "area": "holding", "address": 6, "type": "uint16", "access": "RW", "write_min": 0, "write_max": 20, "description": "Higher values smooth noisy readings"},
    {"name": "Baud rate", "group": "Communication", "area": "holding", "address": 2, "type": "uint16", "access": "RW", "enum": "baud_rate", "write_min": 0, "write_max": 7},
    {"name": "Modbus address", "group": "Communication", "area": "holding", "address": 3, "type": "uint16", "access": "RW", "write_min": 1, "write_max": 247},
    {"name": "Parity", "group": "Communication", "area": "holding", "address": 4, "type": "uint16", "access": "RW", "enum": "parity", "write_min": 0, "write_max": 2},
    {"name": "Diagnostic mode timer", "group": "Communication", "area": "holding", "address": 61, "type": "uint16", "scale": 0.1, "unit": "s", "access": "RW", "write_min": 0, "write_max": 60, "description": "Used by DigiConfig"},

    {"name": "Serial number", "group": "Identity", "area": "holding", "address": 0, "type": "uint32", "access": "R", "role": "serial"},
    {"name": "Firmware version", "group": "Identity", "area": "holding", "address": 5, "type": "uint16", "scale": 0.01, "access": "R", "role": "firmware", "description": "204 is version 2.04"},
    {"name": "Model", "group": "Identity", "area": "holding", "address": 62, "type": "uint16", "access": "R", "enum": "model", "role": "model"},
    {"name": "Device tag", "group": "Identity", "area": "holding", "address": 126, "type": "string", "length": 5, "access": "RW"},
    {"name": "Channel 1 tag", "group": "Identity", "area": "holding", "address": 131, "type": "string", "length": 5, "access": "RW"},
    {"name": "Channel 2 tag", "group": "Identity", "area": "holding", "address": 136, "type": "string", "length": 5, "access": "RW"},
    {"name": "Channel 1 unit tag", "group": "Identity", "area": "holding", "address": 141, "type": "string", "length": 5, "access": "RW", "description": "Unit text for a linear input"},
    {"name": "Channel 2 unit tag", "group": "Identity", "area": "holding", "address": 146, "type": "string", "length": 5, "access": "RW", "description": "Unit text for a linear input"}
  ]
}
