{
  "$schema": "https://raw.githubusercontent.com/nobrega8/mbmap-library/main/schema/mbmap-2.schema.json",
  "mbmap": 2,
  "vendor": "Therma",
  "model": "TH 9XRP",
  "models": ["TH 90RP", "TH 91RP", "TH 92RP", "TH 93RP"],
  "vendor_website": "therma.com.br",
  "description": "Programmable temperature controller (ramps and soaks), heating and cooling: process value, set points, alarms, PID settings, control outputs, program execution and serial settings",
  "revision": 1,
  "revised": "2026-11-10",
  "source": "Controladores Programadores para Aquecimento e Resfriamento TH 90 RP, TH 91 RP, TH 92 RP, TH 93 RP (Manual de Operação), 8ª edição 06/2025",
  "sources": [
    {"title": "Controladores Programadores para Aquecimento e Resfriamento, TH 90 RP / 91 RP / 92 RP / 93 RP (Manual de Operação)", "version": "8ª edição 06/2025", "note": "linked in issue #121; table of register addresses, pages 39 to 42", "date": "2025-06"}
  ],
  "notes": [
    "Modbus RTU on the optional RS-485 port (controllers ordered with serial communication). The manual lists registers as 40001 to 40091 (function codes 03, 06 and 16); they are numbered from 1 here, so address 40001 is register 1 and address_base is 1. The manual does not name the factory baud rate, parity or controller number: 9600, no parity and 1 are placeholders. Options are 2400, 4800 or 9600 bit/s, no, odd or even parity, 8 data bits and 1 stop bit.",
    "Values are 16-bit integers, signed where the range includes negative numbers. The manual does not say how decimals are sent: fields with a decimal point (for example some input types) are probably sent without it, so check against the display before applying a scale.",
    "Packed BCD registers (ALD, SETi, SETL, CFPR and AL xy) hold one digit per alarm relay (A = AL1, B = AL2, C = AL3, D unused) and are read in hexadecimal. Registers 40035, 40038, 40049, 40050, 40069 and 40070 are internal or reserved and are not listed.",
    "The serial ID range is 1 to 63 in the register table and 1 to 31 in the parameter description. The parity code order (0 = none, 1 = even, 2 = odd) differs from the TH 9XMP manual.",
    "Registers 40071 to 40088 apply only to programmable (ramp and soak) controllers. Registers 40083 to 40088 act on the segment chosen with PTN and SEGC.",
    "Written from the manufacturer's manual; not tested on a device."
  ],
  "protocol": "rtu",
  "unit_id": 1,
  "baudrate": 9600,
  "parity": "N",
  "databits": 8,
  "stopbits": 1,
  "byte_order": "big",
  "word_order": "big",
  "address_base": 1,
  "x_status": "official",
  "enums": {
    "fault": {"0": "Normal", "1": "ADCF", "2": "CJCE", "3": "Below the measuring range", "4": "Above the measuring range"},
    "inp1": {"0": "Type J", "1": "Type K", "2": "Type R", "3": "Type S", "4": "dP", "5": "dP1", "6": "An", "7": "An1", "8": "An2", "9": "B", "10": "C", "11": "E", "12": "N", "13": "T", "14": "J1", "15": "K1", "16": "T1"}
  },
  "registers": [
    {"name": "Process value (PV)", "group": "Measurements", "area": "holding", "address": 1, "type": "int16", "description": "Measured value; decimals depend on the input type (see notes)"},
    {"name": "Set point (SV)", "group": "Control", "area": "holding", "address": 2, "type": "int16", "access": "RW", "description": "Active set point, between LSPL and USPL"},
    {"name": "Alarm 1 set point", "group": "Alarms", "area": "holding", "address": 3, "type": "int16", "access": "RW", "description": "Alarm 1 set point; the allowed range depends on the alarm mode ALD1"},
    {"name": "Alarm 2 set point", "group": "Alarms", "area": "holding", "address": 4, "type": "int16", "access": "RW", "description": "Alarm 2 set point; the allowed range depends on the alarm mode ALD2"},
    {"name": "Alarm 3 set point", "group": "Alarms", "area": "holding", "address": 5, "type": "int16", "access": "RW", "description": "Alarm 3 set point; the allowed range depends on the alarm mode ALD3"},
    {"name": "Initial ramp (RAMP)", "group": "Control", "area": "holding", "address": 6, "type": "uint16", "access": "RW", "description": "0 to 9999"},
    {"name": "Control relay", "group": "Status", "area": "holding", "address": 7, "type": "bool", "bit": 0},
    {"name": "Alarm 1 relay", "group": "Status", "area": "holding", "address": 7, "type": "bool", "bit": 1},
    {"name": "Alarm 2 relay", "group": "Status", "area": "holding", "address": 7, "type": "bool", "bit": 2},
    {"name": "Alarm 3 relay", "group": "Status", "area": "holding", "address": 7, "type": "bool", "bit": 3},
    {"name": "Auto-tuning active", "group": "Status", "area": "holding", "address": 7, "type": "bool", "bit": 4},
    {"name": "Manual mode", "group": "Status", "area": "holding", "address": 7, "type": "bool", "bit": 5},
    {"name": "Set point 2", "group": "Status", "area": "holding", "address": 7, "type": "bool", "bit": 6},
    {"name": "Fault status", "group": "Status", "area": "holding", "address": 8, "type": "uint16", "enum": "fault"},
    {"name": "Output bargraph", "group": "Status", "area": "holding", "address": 9, "type": "uint16", "description": "Output level, 0 to 100 %", "unit": "%"},
    {"name": "Save to EEPROM", "group": "Commands", "area": "holding", "address": 10, "type": "uint16", "access": "RW", "description": "Write 1 to store the settings written over Modbus; 0 = do not save"},
    {"name": "Remote or program set point (SVR / SVPRG)", "group": "Control", "area": "holding", "address": 11, "type": "uint16", "description": "Remote set point, or the current set point of a programmable controller"},
    {"name": "Alarm 1 timer remaining", "group": "Alarms", "area": "holding", "address": 12, "type": "uint16", "description": "Minutes left on a timed alarm (ALD = 9)"},
    {"name": "Alarm 2 timer remaining", "group": "Alarms", "area": "holding", "address": 13, "type": "uint16", "description": "Minutes left on a timed alarm (ALD = 9)"},
    {"name": "Alarm 3 timer remaining", "group": "Alarms", "area": "holding", "address": 14, "type": "uint16", "description": "Minutes left on a timed alarm (ALD = 9)"},
    {"name": "Auto-tuning", "group": "Control", "area": "holding", "address": 15, "type": "uint16", "access": "RW", "enum": {"0": "Off", "1": "On"}},
    {"name": "Output 1 level (OUT1)", "group": "Control", "area": "holding", "address": 16, "type": "uint16", "access": "RW", "description": "Control output 1 percentage, 0 to 100"},
    {"name": "Proportional band 1 (P1)", "group": "Control", "area": "holding", "address": 17, "type": "uint16", "access": "RW"},
    {"name": "Integral time 1 (I1)", "group": "Control", "area": "holding", "address": 18, "type": "uint16", "access": "RW", "description": "0 to 3600"},
    {"name": "Derivative time 1 (D1)", "group": "Control", "area": "holding", "address": 19, "type": "uint16", "access": "RW", "description": "0 to 900"},
    {"name": "Cycle time 1 (CYT1)", "group": "Control", "area": "holding", "address": 20, "type": "uint16", "access": "RW"},
    {"name": "Dead time (DB1)", "group": "Control", "area": "holding", "address": 21, "type": "uint16", "access": "RW", "description": "5 to 500"},
    {"name": "Motor hysteresis (HYSM)", "group": "Control", "area": "holding", "address": 22, "type": "uint16", "access": "RW", "description": "0 to 10"},
    {"name": "Proportional band 2 (P2)", "group": "Control", "area": "holding", "address": 23, "type": "uint16", "access": "RW", "description": "0 to 2000"},
    {"name": "Integral time 2 (I2)", "group": "Control", "area": "holding", "address": 24, "type": "uint16", "access": "RW", "description": "0 to 3600"},
    {"name": "Derivative time 2 (D2)", "group": "Control", "area": "holding", "address": 25, "type": "uint16", "access": "RW", "description": "0 to 900"},
    {"name": "Cycle time 2 (CYT2)", "group": "Control", "area": "holding", "address": 26, "type": "uint16", "access": "RW"},
    {"name": "Dead zone 1 (GAP1)", "group": "Control", "area": "holding", "address": 27, "type": "uint16", "access": "RW", "description": "0 to 100, or 0 to 10.0 with a decimal input"},
    {"name": "Dead zone 2 (GAP2)", "group": "Control", "area": "holding", "address": 28, "type": "uint16", "access": "RW", "description": "0 to 100, or 0 to 10.0 with a decimal input"},
    {"name": "Output 2 level (OUT2)", "group": "Control", "area": "holding", "address": 29, "type": "uint16", "access": "RW", "description": "Control output 2 percentage, 0 to 100"},
    {"name": "Output 2 reading", "group": "Status", "area": "holding", "address": 30, "type": "uint16", "description": "Output 2 level, 0 to 100 %", "unit": "%"},
    {"name": "Input type (INP1)", "group": "Settings", "area": "holding", "address": 31, "type": "uint16", "access": "RW", "enum": "inp1"},
    {"name": "Measuring range minimum (LSPL)", "group": "Settings", "area": "holding", "address": 32, "type": "int16", "access": "RW", "description": "Lower end of the measuring range"},
    {"name": "Measuring range maximum (USPL)", "group": "Settings", "area": "holding", "address": 33, "type": "int16", "access": "RW", "description": "Upper end of the measuring range"},
    {"name": "Control action (OUD)", "group": "Settings", "area": "holding", "address": 34, "type": "uint16", "access": "RW", "enum": {"0": "Heat", "1": "Cool"}},
    {"name": "Hysteresis 1 (HYS1)", "group": "Settings", "area": "holding", "address": 36, "type": "uint16", "access": "RW", "description": "0 to 100"},
    {"name": "Hysteresis 2 (HYS2)", "group": "Settings", "area": "holding", "address": 37, "type": "uint16", "access": "RW", "description": "0 to 100"},
    {"name": "Alarm modes (ALD)", "group": "Alarms", "area": "holding", "address": 39, "type": "uint16", "access": "RW", "description": "Packed BCD, read as hex: one digit per alarm relay (A = AL1, B = AL2, C = AL3, D unused)"},
    {"name": "Inhibited alarms (SETi)", "group": "Alarms", "area": "holding", "address": 40, "type": "uint16", "access": "RW", "description": "Packed BCD, read as hex: one digit per alarm relay (A = AL1, B = AL2, C = AL3, D unused)"},
    {"name": "LED indication inversion (SETL)", "group": "Alarms", "area": "holding", "address": 41, "type": "uint16", "access": "RW", "description": "Packed BCD, read as hex: one digit per alarm relay (A = AL1, B = AL2, C = AL3, D unused)"},
    {"name": "Alarm 1 hysteresis (HYA1)", "group": "Alarms", "area": "holding", "address": 42, "type": "uint16", "access": "RW", "description": "0 to 1000"},
    {"name": "Alarm 2 hysteresis (HYA2)", "group": "Alarms", "area": "holding", "address": 43, "type": "uint16", "access": "RW", "description": "0 to 1000"},
    {"name": "Alarm 3 hysteresis (HYA3)", "group": "Alarms", "area": "holding", "address": 44, "type": "uint16", "access": "RW", "description": "0 to 1000"},
    {"name": "Set point source (INP2)", "group": "Settings", "area": "holding", "address": 45, "type": "uint16", "access": "RW", "enum": {"0": "Local", "1": "Remote"}},
    {"name": "Signal retransmission (TR)", "group": "Settings", "area": "holding", "address": 46, "type": "uint16", "access": "RW", "enum": {"0": "Off", "1": "PV", "2": "SV"}},
    {"name": "Temperature unit (UNIT)", "group": "Settings", "area": "holding", "address": 47, "type": "uint16", "access": "RW", "enum": {"0": "°C", "1": "°F"}},
    {"name": "Set point 2 (SP2)", "group": "Control", "area": "holding", "address": 48, "type": "int16", "access": "RW", "description": "Between LSPL and USPL"},
    {"name": "Key lock (LCK)", "group": "Settings", "area": "holding", "address": 51, "type": "uint16", "access": "RW", "description": "0 to 5"},
    {"name": "PV offset (PVOS)", "group": "Settings", "area": "holding", "address": 52, "type": "int16", "access": "RW", "description": "-1999 to +9999"},
    {"name": "SV offset (SVOS)", "group": "Settings", "area": "holding", "address": 53, "type": "int16", "access": "RW", "description": "-1999 to +9999"},
    {"name": "Ambient temperature (TA)", "group": "Measurements", "area": "holding", "address": 54, "type": "uint16", "description": "Ambient temperature reading, 0 to 50"},
    {"name": "Digital filter (SOFT)", "group": "Settings", "area": "holding", "address": 55, "type": "uint16", "access": "RW", "description": "0 to 100"},
    {"name": "Analog input scale ANL1", "group": "Settings", "area": "holding", "address": 56, "type": "int16", "access": "RW", "description": "Start of the analog input signal 1"},
    {"name": "Analog input scale ANH1", "group": "Settings", "area": "holding", "address": 57, "type": "int16", "access": "RW", "description": "End of the analog input signal 1"},
    {"name": "Analog input scale ANL2", "group": "Settings", "area": "holding", "address": 58, "type": "int16", "access": "RW", "description": "Start of the analog input signal 2 (remote)"},
    {"name": "Analog input scale ANH2", "group": "Settings", "area": "holding", "address": 59, "type": "int16", "access": "RW", "description": "End of the analog input signal 2 (remote)"},
    {"name": "Motor travel time (RUCY)", "group": "Settings", "area": "holding", "address": 60, "type": "uint16", "access": "RW", "description": "Closed-to-open time of the motor, 5 to 200 s", "unit": "s"},
    {"name": "Analog output CL 01", "group": "Settings", "area": "holding", "address": 61, "type": "uint16", "access": "RW", "description": "Start of control analog output 1, 0 to 100"},
    {"name": "Analog output CH 01", "group": "Settings", "area": "holding", "address": 62, "type": "uint16", "access": "RW", "description": "End of control analog output 1, 0 to 100"},
    {"name": "Analog output CL 02", "group": "Settings", "area": "holding", "address": 63, "type": "uint16", "access": "RW", "description": "Start of control analog output 2, 0 to 100"},
    {"name": "Analog output CH 02", "group": "Settings", "area": "holding", "address": 64, "type": "uint16", "access": "RW", "description": "End of control analog output 2, 0 to 100"},
    {"name": "Retransmission start (CL 03)", "group": "Settings", "area": "holding", "address": 65, "type": "uint16", "access": "RW", "description": "0 to 4095"},
    {"name": "Retransmission end (CH 03)", "group": "Settings", "area": "holding", "address": 66, "type": "uint16", "access": "RW", "description": "0 to 4095"},
    {"name": "Ramp edit enable (HRMP)", "group": "Settings", "area": "holding", "address": 67, "type": "uint16", "access": "RW", "enum": {"0": "Off", "1": "On"}},
    {"name": "Manual key enable (HMAN)", "group": "Settings", "area": "holding", "address": 68, "type": "uint16", "access": "RW", "enum": {"0": "Off", "1": "On"}},
    {"name": "Program run configuration (CFPR)", "group": "Program", "area": "holding", "address": 71, "type": "uint16", "access": "RW", "description": "Packed BCD, read as hex; see the manual"},
    {"name": "Program selection (PRG)", "group": "Program", "area": "holding", "address": 72, "type": "uint16", "access": "RW", "description": "0 to 8"},
    {"name": "Program state", "group": "Program", "area": "holding", "address": 73, "type": "uint16", "enum": {"0": "No program", "1": "Idle", "2": "Running", "3": "Paused", "4": "Waiting"}},
    {"name": "Current segment (SEG)", "group": "Program", "area": "holding", "address": 74, "type": "uint16", "description": "0 to 8"},
    {"name": "Segment time remaining (TMP)", "group": "Program", "area": "holding", "address": 75, "type": "uint16", "access": "RW", "description": "0 to 9999"},
    {"name": "Program control (CTRL)", "group": "Program", "area": "holding", "address": 76, "type": "uint16", "access": "RW", "enum": {"0": "Reset", "1": "Run", "2": "Pause"}},
    {"name": "Wait function (CWAIT)", "group": "Program", "area": "holding", "address": 77, "type": "uint16", "access": "RW", "description": "Meaning of the pause function, see the manual"},
    {"name": "Start segment (SEGP)", "group": "Program", "area": "holding", "address": 78, "type": "uint16", "access": "RW", "description": "Segment where the program starts"},
    {"name": "Set point 2 enable (HSP2)", "group": "Program", "area": "holding", "address": 79, "type": "uint16", "access": "RW", "enum": {"0": "SP 1", "1": "SP 2"}},
    {"name": "Hold and peak enable (HHOLD)", "group": "Program", "area": "holding", "address": 80, "type": "uint16", "access": "RW", "enum": {"0": "Free", "1": "Hold"}},
    {"name": "Program to configure (PTN)", "group": "Program", "area": "holding", "address": 81, "type": "uint16", "access": "RW", "description": "1 to 8"},
    {"name": "Segment to configure (SEGC)", "group": "Program", "area": "holding", "address": 82, "type": "uint16", "access": "RW", "description": "1 to 8"},
    {"name": "Segment set point (SV xy)", "group": "Program", "area": "holding", "address": 83, "type": "int16", "access": "RW", "description": "Set point of the selected segment"},
    {"name": "Segment time (TM xy)", "group": "Program", "area": "holding", "address": 84, "type": "uint16", "access": "RW", "description": "0 to 9999"},
    {"name": "Segment output (OU xy)", "group": "Program", "area": "holding", "address": 85, "type": "uint16", "access": "RW", "description": "0 to 100 %"},
    {"name": "Segment wait band (WA xy)", "group": "Program", "area": "holding", "address": 86, "type": "uint16", "access": "RW", "description": "5 to 9999"},
    {"name": "Segment alarms (AL xy)", "group": "Program", "area": "holding", "address": 87, "type": "uint16", "access": "RW", "description": "Packed BCD, read as hex: one digit per alarm relay (A = AL1, B = AL2, C = AL3, D = 0)"},
    {"name": "Segment continuation (CT xy)", "group": "Program", "area": "holding", "address": 88, "type": "uint16", "access": "RW", "enum": {"0": "End", "1": "Continue"}},
    {"name": "Serial ID (IDNO)", "group": "Settings", "area": "holding", "address": 89, "type": "uint16", "access": "RW", "description": "Controller number for the serial link; the table says 1 to 63, the text 1 to 31", "write_min": 1, "write_max": 63},
    {"name": "Baud rate (BAUD)", "group": "Settings", "area": "holding", "address": 90, "type": "uint16", "access": "RW", "enum": {"0": "2400", "1": "4800", "2": "9600"}},
    {"name": "Parity (PARI)", "group": "Settings", "area": "holding", "address": 91, "type": "uint16", "access": "RW", "enum": {"0": "None", "1": "Even", "2": "Odd"}}
  ]
}
