{ "$schema": "https://raw.githubusercontent.com/nobrega8/mbmap-library/main/schema/mbmap-2.schema.json", "mbmap": 2, "vendor": "Therma", "model": "TH 9XMP", "models": ["TH 90MP", "TH 91MP", "TH 92MP", "TH 93MP"], "vendor_website": "therma.com.br", "description": "Programmable modulating controller (ramps and soaks): process value, set points, alarms, PID settings, program execution, calibration values and identity registers, over Modbus RTU", "revision": 1, "revised": "2026-11-10", "source": "Controladores Microprocessados Modulantes Programáveis TH 90MP, TH 91MP, TH 92MP, TH 93MP (Manual de Operação), 6ª edição (agosto de 2019)", "sources": [ {"title": "Controladores Microprocessados Modulantes Programáveis, TH 90MP / 91MP / 92MP / 93MP (Manual de Operação)", "version": "6ª edição (agosto de 2019)", "note": "linked in issue #122; chapter Protocolo de Comunicação MODBUS RTU, pages 38 to 42", "date": "2019-08"} ], "notes": [ "Modbus RTU on the optional RS-485 port. The manual lists registers 40001 to 40105 (function codes 03, 06 and 16, no broadcast); they are numbered from 1 here, so address 40001 is register 1 and address_base is 1. Reading a reserved address returns 0xFFFF. 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.", "The register table in this edition skips addresses 40025 to 40046 (the page that should list them repeats the first page), so those registers are not included (RP-series controllers have registers there, but the layout may differ).", "Values are 16-bit integers, signed where the range includes negative numbers. The manual does not say how decimals are sent: check against the display before applying a scale.", "Packed BCD registers (CFPR, SEGP and AL xy) are read in hexadecimal. The relay bit order of register 40007 differs from the TH 9XRP manual. The parity codes (0 = none, 1 = odd, 2 = even) are as printed in this manual, whose label for 0 reads NOME (probably none); the TH 9XRP manual lists even before odd.", "Registers 40071 to 40088 act on the segment chosen with PTN and SEGC, and apply only to the programmable series. Registers 40092 to 40099 are calibration values; do not write them without the manual's calibration procedure.", "The software version, model number (A and B) and serial number (A, B and C) are plain 16-bit numbers; the manual does not say how they are formed. 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"}, "blocked": {"0": "Blocked", "1": "Released"} }, "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", "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": "Alarm 3 relay", "group": "Status", "area": "holding", "address": 7, "type": "bool", "bit": 0}, {"name": "Control relay", "group": "Status", "area": "holding", "address": 7, "type": "bool", "bit": 1}, {"name": "Alarm 1 relay", "group": "Status", "area": "holding", "address": 7, "type": "bool", "bit": 2}, {"name": "Alarm 2 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": "Program", "group": "Status", "area": "holding", "address": 7, "type": "bool", "bit": 7}, {"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 (OUTL)", "group": "Control", "area": "holding", "address": 16, "type": "uint16", "access": "RW", "description": "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": "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": "uint16", "access": "RW", "description": "Start of the analog input signal 1 (hexadecimal, see the manual's calibration mode)"}, {"name": "Analog input scale ANH1", "group": "Settings", "area": "holding", "address": 57, "type": "uint16", "access": "RW", "description": "End of the analog input signal 1 (hexadecimal, see the manual's calibration mode)"}, {"name": "Analog input scale ANL2", "group": "Settings", "area": "holding", "address": 58, "type": "uint16", "access": "RW", "description": "Start of the analog input signal 2 (remote) (hexadecimal, see the manual's calibration mode)"}, {"name": "Analog input scale ANH2", "group": "Settings", "area": "holding", "address": 59, "type": "uint16", "access": "RW", "description": "End of the analog input signal 2 (remote) (hexadecimal, see the manual's calibration mode)"}, {"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": "Blocked", "1": "Released"}}, {"name": "Manual key enable (HMAN)", "group": "Settings", "area": "holding", "address": 68, "type": "uint16", "access": "RW", "enum": {"0": "Blocked", "1": "Released"}}, {"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": "1 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 (CWAI)", "group": "Program", "area": "holding", "address": 77, "type": "uint16", "access": "RW", "enum": {"0": "Dual", "1": "Single"}}, {"name": "Start segment (SEGP)", "group": "Program", "area": "holding", "address": 78, "type": "uint16", "access": "RW", "description": "Packed BCD, read as hex; low digits 1 to 8"}, {"name": "Set point 2 enable (HSP2)", "group": "Program", "area": "holding", "address": 79, "type": "uint16", "access": "RW", "enum": "blocked"}, {"name": "Hold function enable (HHLD)", "group": "Program", "area": "holding", "address": 80, "type": "uint16", "access": "RW", "enum": "blocked"}, {"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": "1 to 127; changing it ends communication on the current address", "write_min": 1, "write_max": 127}, {"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": "Odd", "2": "Even"}}, {"name": "Ambient adjustment (AJ-TAM)", "group": "Calibration", "area": "holding", "address": 92, "type": "uint16", "access": "RW", "description": "Calibration value; see the manual's calibration mode"}, {"name": "Adjustment 0 mV (AJ-0mV)", "group": "Calibration", "area": "holding", "address": 93, "type": "uint16", "access": "RW", "description": "Calibration value; see the manual's calibration mode"}, {"name": "Adjustment 60 mV (AJ-60mV)", "group": "Calibration", "area": "holding", "address": 94, "type": "uint16", "access": "RW", "description": "Calibration value; see the manual's calibration mode"}, {"name": "Adjustment 100 ohm (AJ-100R)", "group": "Calibration", "area": "holding", "address": 95, "type": "uint16", "access": "RW", "description": "Calibration value; see the manual's calibration mode"}, {"name": "Adjustment 300 ohm (AJ-300R)", "group": "Calibration", "area": "holding", "address": 96, "type": "uint16", "access": "RW", "description": "Calibration value; see the manual's calibration mode"}, {"name": "Adjustment configuration (AJ-CONF)", "group": "Calibration", "area": "holding", "address": 97, "type": "uint16", "access": "RW", "description": "Calibration value; see the manual's calibration mode"}, {"name": "Other inputs (INP-P)", "group": "Calibration", "area": "holding", "address": 98, "type": "uint16", "description": "Hexadecimal, read only"}, {"name": "Remote input scale (REN-P)", "group": "Calibration", "area": "holding", "address": 99, "type": "uint16", "description": "Hexadecimal, read only"}, {"name": "Software version", "group": "Info", "area": "holding", "address": 100, "type": "uint16", "description": "Plain 16-bit number; how it maps to a version string is not stated"}, {"name": "Model number A", "group": "Info", "area": "holding", "address": 101, "type": "uint16", "description": "First part of the model number"}, {"name": "Model number B", "group": "Info", "area": "holding", "address": 102, "type": "uint16", "description": "Second part of the model number"}, {"name": "Serial number A", "group": "Info", "area": "holding", "address": 103, "type": "uint16", "description": "First part of the serial number"}, {"name": "Serial number B", "group": "Info", "area": "holding", "address": 104, "type": "uint16", "description": "Second part of the serial number"}, {"name": "Serial number C", "group": "Info", "area": "holding", "address": 105, "type": "uint16", "description": "Third part of the serial number"} ] }