Overview #
NORVI X is a next generation modular industrial controller designed to power smart automation and IoT solutions. Built around a CPU module and a range of plug and play expansion modules, the platform scales from a handful of I/O points up to 200, giving system integrators, OEMs, and industrial engineers a flexible foundation for automation, remote monitoring, and data acquisition projects.
The NORVI X-RTD4 is a high-precision 4-channel RTD (Resistance Temperature Detector) expansion module for this platform. It uses a single MAX31865 RTD-to-digital converter (15-bit resolution) shared across all four RTD inputs through an analog multiplexer, with an onboard STM32 MCU handling the multiplexing and bridging results to the host CPU over the shared I2C expansion bus. This offloads RTD conversion work from the main controller. It supports both PT100 and PT1000 sensors, selectable via DIP switch. The X-RTD4 is not standalone; it must be paired with a NORVI X CPU module (e.g. CPU ESPS3 X1).
This guide covers everything needed to confidently install, wire, and commission the module, including safety requirements, technical specifications, terminal and address configuration, wiring steps, software setup, diagnostic test code, and troubleshooting.
Key Features #
- 4 independent RTD input channels, sequentially scanned through a shared MAX31865 converter
- High-precision 15-bit RTD-to-digital conversion
- Onboard STM32 MCU acting as an internal SPI-to-I2C bridge, offloading processing from the main CPU
- PT100 / PT1000 selectable via dedicated DIP switch
- I2C address configurable via 4-way DIP switch (16 selectable addresses)
- Status LED per input channel
- DIN rail mountable enclosure with spring terminals
- Plug and play connection to the CPU module through the expansion bus
- CE / EMC compliant (EN 61131-2:2007, EN 61010-1:2010+A1:2019, EN IEC 61010-2-201:2018, 2014/30/EU)
Safety Information #
Warning: Disconnect all power sources before installing, wiring, or servicing the NORVI X-RTD4. Failure to do so may result in electric shock or damage to the equipment.
- Install and wire this module only if you are a qualified electrician or trained technician familiar with industrial control equipment.
- Confirm the host CPU is running from a regulated 24 V DC supply, since the module draws its power through the expansion port rather than a separate connection.
- This module reads low-level resistance signals from RTDs – keep sensor wiring running short and separated from AC power, relay, or motor wiring to avoid measurement noise and error.
- Mount the module on a DIN rail inside a suitably rated enclosure. It carries an IP20 protection rating and is not designed for direct outdoor or wash down exposure.
- Keep the operating environment within minus 40 to plus 85 degrees C and avoid condensing humidity.
- Do not connect or disconnect the module from the expansion bus while the system is powered.
- Follow all local and national electrical codes applicable to industrial control panel wiring.
Technical Specifications #
Electrical #
| Rated Supply Voltage | 24V DC |
| Current Consumption | 80mA @ 24V DC |
Input Specifications #
| Input Channels | 4 independent RTD channels |
| Resolution | 15-bit |
| RTD Types | PT100 or PT1000 (DIP-selectable) |
| Converter | MAX31865 RTD-to-digital converter (shared via analog multiplexer) |
| Communication | SPI |
| Output Diagnostics | Individual LED indicators Alert Indicator |
| Power supply | 24V DC, shared with CPU through the expansion port |
| Communication bus | Internal expansion bus (I2C) |
| Connector Type | Spring terminal |
STM32F103C8T6 Specifications #
| Specification | Details |
|---|---|
| Architecture | ARM Cortex-M3 |
| Operating Voltage | 2.0 V to 3.6 V |
| CPU Frequency | 72 MHz |
| Flash Memory | 64 KB |
| SRAM | 20 KB |
| USB | For Debugging Only |
| Communication | I²C Interface |
Hardware Layout & GPIO Map #
The table below lists the terminals on the X-T4 and how they map into the ADS1115 ADC. Unlike relay or digital I/O modules, none of the host CPU’s GPIO pins are claimed by the sensor channels themselves – only SCL and SDA are shared across the I2C bus.
| Terminal | Function |
|---|---|
| RTD1+ | Positive Input – Channel 1 |
| RTD1- | Negative Input – Channel 1 |
| RTD2+ | Positive Input – Channel 2 |
| RTD2- | Negative Input – Channel 2 |
| RTD3+ | Positive Input – Channel 3 |
| RTD3- | Negative Input – Channel 3 |
| RTD4+ | Positive Input – Channel 4 |
| RTD4- | Negative Input – Channel 4 |
| GND | Ground |
Each channel is a 2-wire RTD input. Connect each RTD’s two leads across the RTD_n+ and RTD_n- terminals for that channel; GND is the shared reference.
I2C Address Selection
| DIP 1 | DIP 2 | DIP 3 | DIP 4 | Address |
|---|---|---|---|---|
| OFF | OFF | OFF | OFF | 0x3F |
| ON | OFF | OFF | OFF | 0x3E |
| OFF | ON | OFF | OFF | 0x3D |
| ON | ON | OFF | OFF | 0x3C |
| OFF | OFF | ON | OFF | 0x3B |
| ON | OFF | ON | OFF | 0x3A |
| OFF | ON | ON | OFF | 0x39 |
| ON | ON | ON | OFF | 0x38 |
| OFF | OFF | OFF | ON | 0x37 |
| ON | OFF | OFF | ON | 0x36 |
| OFF | ON | OFF | ON | 0x35 |
| ON | ON | OFF | ON | 0x34 |
| OFF | OFF | ON | ON | 0x33 |
| ON | OFF | ON | ON | 0x32 |
| OFF | ON | ON | ON | 0x31 |
| ON | ON | ON | ON | 0x30 |
Note: default all-OFF = 0x3F – unlike the input modules, X-RTD4 has a full 16-address range; the DIP-selectable addresses apply when the module is daisy-chained with other I2C-addressed NORVI expansion modules on the same bus.
RTD Type Selection
| OFF | PT1000 |
| ON | PT100 |
RTD TYPE SELECTOR
| Parameter | PT100 | PT1000 |
|---|---|---|
| Resistance at 0°C | 100 Ω | 1000 Ω (1 kΩ) |
| Resistance change per °C | ~0.385 Ω/°C | ~3.85 Ω/°C |
| Lead-wire effect | Higher | Lower |
| Signal strength | Lower | Higher |
| Temperature measurement principle | Platinum | Platinum |
Wiring Guide #
GPIO pin assignments for the I2C bus are listed in the Expansion Port table below (Section 6.4); this section covers how to physically wire the module, not the pin numbers themselves.
Power Connection #
No separate supply needed. Receives 24V DC from the CPU through the shared expansion port, provided the CPU has a regulated 24V DC source with adequate current headroom.
RTD Input Wiring #
- Each of the four channels is a 2-wire RTD input.
- Connect each RTD’s two leads across the RTD_n+ and RTD_n- terminals for that channel.
- GND provides the shared reference for all four channels.
- Keep RTD wiring runs short, and route them separately from AC power, relay, or motor wiring to minimize induced noise on the signal.
- Because this is a 2-wire (not 3- or 4-wire) RTD connection, the resistance of the lead wires themselves adds to the measured resistance – keep lead lengths short and roughly equal if using multiple channels, since long 2-wire runs can introduce measurable temperature error that 3-/4-wire wiring would cancel out
- Confirm each thermistor’s resistance at a known temperature (e.g. room temperature) with a multimeter before wiring, to catch a faulty sensor early.

Mounting and Connecting the Module #
- Power off the entire system before touching any wiring or seating the module.
- Mount the X-RTD4 on the DIN rail next to the CPU module (or next to another expansion module already in the chain) and seat it firmly onto the expansion bus connector.
- Set the I2C address using the onboard DIP switches, and set the RTD type switch to match your sensors.
- Wire your RTDs to the RTD1 through RTD4 terminal pairs, with GND as the shared reference.
- Power the system back on.
- Upload the module’s test sketch from the NORVI GitHub repository to confirm each channel reads correctly before wiring it into your final control logic.

Expansion Port (50 pin) #
The X-RTD4 connects to the CPU through the shared 50-pin expansion bus. The pins actually used by this module are SCL, SDA, GND, 5V, and 24V. The rest pass through for other modules on the same bus.
| PIN INDEX | Purpose | GPIO | SOURCE |
|---|---|---|---|
| 1 | MOSI | IO11 | ESP32-S3 |
| 2 | MISO | IO13 | |
| 3 | SCLK | IO12 | |
| 4 | GND | —- | |
| 5 | SCL | IO9 | |
| 6 | SDA | IO8 | |
| 7 | GND | —- | |
| 8 | RX1 | IO18 | |
| 9 | TX1 | IO17 | |
| 10 | GND | —- | |
| 11 | D+ | —- | |
| 12 | D- | —- | |
| 13 | GND | —- | |
| 14 | CS1 | P1_0 | PCA9539 I2C Address 0x75 |
| 15 | CS2 | P0_7 | |
| 16 | CS3 | P0_6 | |
| 17 | CS4 | P0_5 | |
| 18 | IO1 | IO1 | ESP32-S3 |
| 19 | IO2 | IO2 | |
| 20 | IO4 | IO4 | |
| 21 | IO5 | IO5 | |
| 22 | IO6 | IO6 | |
| 23 | IO7 | IO7 | |
| 24 | IO10 | IO10 | |
| 25 | IO11 | IO35 | |
| 26 | IO12 | IO36 | |
| 27 | IO13 | IO37 | |
| 28 | IO14 | IO14 | |
| 29 | RS485_TX | IO15 | |
| 30 | GND | —- | |
| 31 | GND | —- | |
| 32 | RS485_RX | IO16 | |
| 33 | P1_1 | P1_1 | PCA9539 I2C Address 0x75 |
| 34 | P1_2 | P1_2 | |
| 35 | IO21 | IO21 | ESP32-S3 |
| 36 | GND | —- | |
| 37 | GND | —- | |
| 38 | P1_3 | P1_3 | PCA9539 I2C Address 0x75 |
| 39 | P1_4 | P1_4 | |
| 40 | P1_5 | P1_5 | |
| 41 | IO39 | IO39 | ESP32-S3 |
| 42 | IO40 | IO40 | |
| 43 | NC | —- | |
| 44 | NC | —- | |
| 45 | NC | —- | |
| 46 | GND | —- | |
| 47 | 5V | 5V | |
| 48 | GND | GND | |
| 49 | 24V | 24V | |
| 50 | 24V | 24V |
Software Setup (Arduino IDE) #
The NORVI X-T4 is read through the host CPU using the Arduino IDE with the ESP32 board package. Firmware examples and required libraries are maintained in the NORVI GitHub repository.
Board Configuration #
- Install Arduino IDE
Install the Arduino IDE and add ESP32 board support:
Tools → Board → Boards Manager → ESP32
- Connect the Controller
Connect the NORVI X CPU to your computer using the USB interface.
- Select Board and Port
Configure the board and communication port:
- Tools → Board → ESP32 Arduino → ESP32S3 Dev Module
- Tools → Port → Select the corresponding COM/serial port


- Configure Board Settings
Under the Tools menu, configure the following settings:
| Setting | Selection |
|---|---|
| USB CDC On Boot | Enabled |
| Flash Size | 16MB (128Mb) |
| PSRAM | QSPI PSRAM |
Test Code Examples #
Required Libraries #
Install these via Arduino IDE → Sketch → Include Library → Manage Libraries before compiling any of the examples below:
- Wire
- SPI
- TFT_eSPI
- CST816S
- Free_Fonts
Install the Required Library #
Install the Wire library through:
Sketch → Include Library → Manage Libraries
Search for Wire and install it if required.

The Libraries are available in the NORVI-X-Version-02 GitHub repository.
Open and Upload the Test Sketch #
- Open the X-RTD4 test sketch from the NORVI GitHub repository.
- Verify the board and port selections.
- Click Upload to upload the test sketch to the NORVI X CPU.
I2C Bus Scan #
Run this first after wiring and setting the DIP switch address.
void I2C_SCAN() {
byte error, address;
int deviceCount = 0;
Serial.println("Scanning...");
for (address = 1; address < 127; address++) {
Wire.beginTransmission(address);
error = Wire.endTransmission();
if (error == 0) {
Serial.print("I2C device found at address 0x");
if (address < 16) Serial.print("0");
Serial.print(address, HEX);
Serial.println(" !");
deviceCount++;
delay(1);
} else if (error == 4) {
Serial.print("Unknown error at address 0x");
if (address < 16) Serial.print("0");
Serial.println(address, HEX);
}
}
if (deviceCount == 0) Serial.println("No I2C devices found\n");
else Serial.println("Scanning complete\n");
}RTD Channel Read – templated skeleton (unconfirmed protocol) #
#define RTD_SLAVE_ADDR 0x3F // update to match your DIP setting
uint8_t rtdType = 1; // 0 = PT100, 1 = PT1000
uint8_t channelsToRead[2] = {1, 2}; // up to 2 channels per request
uint8_t crc8(uint8_t *data, int len) {
uint8_t crc = 0x00;
while (len--) {
uint8_t extract = *data++;
for (uint8_t i = 8; i; i--) {
uint8_t sum = (crc ^ extract) & 0x01;
crc >>= 1;
if (sum) crc ^= 0x8C;
extract >>= 1;
}
}
return crc;
}
void readRTD() {
Wire.beginTransmission(RTD_SLAVE_ADDR);
Wire.write(0x01); // command byte
Wire.write(rtdType);
Wire.write(channelsToRead[0]);
Wire.write(channelsToRead[1]);
if (Wire.endTransmission() != 0) {
Serial.println("I2C TX FAIL");
return;
}
delay(15);
uint8_t totalBytes = 2 * 12; // 12 bytes per channel
Wire.requestFrom(RTD_SLAVE_ADDR, totalBytes);
if (Wire.available() != totalBytes) {
Serial.println("I2C RX FAIL");
return;
}
for (int idx = 0; idx < 2; idx++) {
uint8_t buf[12];
for (int i = 0; i < 12; i++) buf[i] = Wire.read();
if (crc8(buf, 11) != buf[11]) {
Serial.print("CRC ERROR Channel "); Serial.println(buf[1]);
continue;
}
float temp, res;
memcpy(&temp, &buf[2], 4);
memcpy(&res, &buf[6], 4);
uint8_t ch = buf[1];
uint8_t fault = buf[10];
Serial.print("Ch "); Serial.print(ch);
Serial.print(" Temp: "); Serial.print(temp);
Serial.print(" Res: "); Serial.print(res);
Serial.print(" Fault: "); Serial.println(fault);
}
}Validating the Full Test Sketch #
When the complete test sketch runs successfully with the X-T4 attached, you should see:
- I2C scans on the X-RTD4 appear at its configured address (0x3F–0x30 depending on DIP setting) alongside any other I2C devices on the bus.
- All four channels return stable, non-zero readings that change when a sensor is warmed/cooled/disconnected.
- Non-zero readings that change when a sensor is warmed/cooled/disconnected; temperature values track ambient sensibly.
- No I2C errors – the Serial Monitor shows no failed transmissions or address conflicts while the test runs.
Troubleshooting #
| Symptom | Suggested Action |
|---|---|
| Module not detected on I2C scan | Reseat module, confirm DIP address doesn’t conflict, check CPU power headroom |
| Reads incorrect/erratic temperature | Confirm RTD type DIP switch (PT100 vs PT1000) matches the sensor actually wired |
| One or more channels stuck/no reading | Check RTD wiring at RTD_n+/RTD_n-/GND; automatic fault detection may indicate an open sensor |
| Address conflict with another I2C module | Change DIP setting so each module on the bus is unique |
| Readings offset from actual by a consistent amount | Check 2-wire lead resistance – long runs add measurable error; consider shorter leads |
| Device not responding at all | Check micro-USB debug port for STM32-side diagnostic output before assuming a wiring fault |
| System resets unexpectedly under load | Check CPU power supply current rating, especially with multiple expansion modules attached |
