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-R8 is a 8 channel relay output expansion module built for this platform. It provides electrically isolated relay outputs suitable for industrial control, automation, and power switching applications. Relay outputs are controlled through a PCA9538 I2C I/O expander, which keeps the module simple to add without using up extra MCU pins on the CPU module.
The X-R8 is not a standalone device. It needs to be paired with a NORVI X CPU module, such as the CPU ESPS3 X1, to be programmed and operated.
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 #
- 8 electromechanical relay outputs, each with its own COM and NO terminal, wired independently
- Controlled through a PCA9538 I2C I/O expander, so only two GPIOs, SCL and SDA, are used from the CPU
- Suitable for both AC and DC load switching
- Rated switching current of 5 A per channel, up to 250 V AC or 30 V DC
- Onboard DIP switch for I2C address selection, allowing multiple relay modules on the same bus
- DIN rail mountable enclosure with spring terminals
- Plug and play connection to the CPU module through the expansion bus
- One status LED per input channel
- CE / EMC compliant (EN 61131-2:2007, EN 61010-1:2010+A1:2019, EN IEC 61010-2-201:2018, 2014/30/EU)
Safety Information #
- 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.
- Never exceed the rated switching voltage of 250 V AC or 30 V DC, or the rated switching current of 5 A on any channel.
- 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 #
| Number of Outputs | 8 x relay outputs |
| Output Type | Single pole normally open relay |
| Isolation voltage | 750 Vrms between open contacts |
| Rated switching voltage | 250 V AC / 30 V DC |
| Maximum switching voltage | 277 V AC |
| Rated switching current | 5 A |
| Limiting continuous current | 5 A |
| Breaking capacity (max) | 1250 VA (AC) / 750 W (DC) |
| Initial contact resistance | 30 mΩ or less (5 VDC, 100 mA) |
| Mechanical endurance | 10 x 10⁶ operations |
| Power supply | 24V DC, shared with CPU through the expansion port |
| Communication bus | Internal expansion bus (I2C) |
| Status Indicators | 8 LED output indicators |
| Connector Type | Spring terminal |
Hardware Layout & GPIO Map #
The table below lists the terminals on the X-R8 and how they map into the PCA9538 port expander. Unlike the direct GPIO input modules, none of the host CPU’s GPIO pins are claimed by the input channels themselves, only SCL and SDA are shared across the I2C bus.

| Terminal | Function |
|---|---|
| NO1 | Relay 1 normally open |
| COM1 | Relay 1 common |
| NO2 | Relay 2 normally open |
| COM2 | Relay 2 common |
| NO3 | Relay 3 normally open |
| COM3 | Relay 3 common |
| NO4 | Relay 4 normally open |
| COM4 | Relay 4 common |
| NO5 | Relay 5 normally open |
| COM5 | Relay 5 common |
| NO6 | Relay 6 normally open |
| COM6 | Relay 6 common |
| NO7 | Relay 7 normally open |
| COM7 | Relay 7 common |
| NO8 | Relay 8 normally open |
| COM8 | Relay 8 common |
Each channel is a single pole, normally open contact. To switch a load, wire the load in series between the COM terminal and the field supply, and connect the NO terminal to the load itself, so the circuit only closes when that channel is energized.
I2C Address Selection #
The X-R8 connects to the host CPU’s I2C bus using SCL on IO9 and SDA on IO8. DIP switches 3 and 4 are not used for addressing. Set each stacked R8 module to a different address so the CPU can talk to them individually on the shared I2C bus.

| Address Selection | ||||
|---|---|---|---|---|
| DIP 1 | DIP 2 | DIP 3 | DIP 4 | Address |
| OFF | OFF | × | × | 0x73 |
| ON | OFF | × | × | 0x72 |
| OFF | ON | × | × | 0x71 |
| ON | ON | × | × | 0x70 |
Wiring Guide #
GPIO pin assignments for the I2C bus are listed in the Expansion Port table below. This section covers how to physically wire the module, not the pin numbers themselves.
Power Connection #
The X-R8 requires no separate power supply. It receives 24V DC from the CPU module through the shared expansion port connector, provided the CPU is powered from a regulated 24V DC source rated at least 1 A.
Relay Output Wiring #
- Each of the eight channels is an isolated, normally open contact.
- Connect one side of the field supply to the COM terminal of the channel you are using.
- Connect the load itself between the NO terminal and the return of the field supply.
- The load only receives power when that relay channel is switched on by the firmware.
- Keep AC and DC wiring runs separated and clearly labeled if the panel uses both.
- Confirm total load current draw stays within your enclosure and supply design limits, not just the per channel rating.

Mounting and Connecting the Module #
- Power off the entire system before touching any wiring or seating the module.
- Mount the X-R8 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.
- The default I2C address is 0x73 with both DIP switches OFF. Leave as is for a single X-R8. If adding more than one I2C addressed module to the same bus, set a unique address on each.
- Wire your field loads to the RO1 through RO8 terminals, connecting each load in series with the COM and NO terminals of the channel you are using. Confirm the load current and voltage stay within the rated switching limits of 5 A, 250V AC or 30V DC.
- Power the system back on.
- Upload the module’s test sketch from the NORVI GitHub repository to confirm each relay channel switches correctly before wiring it into your final control logic.
Expansion Port (50 pin) #
The X-R8 connects to the CPU through the shared 50 pin expansion bus. The pins actually used by this module are SCL, SDA, GND, 24V, and 5V. 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 | PCA9538 Reset |
| 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-R8 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 ModuleTools → 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
- WiFi
- SPI
- PCA9538
- TFT_eSPI
- CST816S
- Free_Fonts
Install the Required Library #
Install the Wire library through:
Search for Wire and install it if required.

Open and Upload the Test Sketch #
- Open the X-R8 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, to confirm the PCA9538 on the X-R8 is being detected before testing relay switching itself.
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");
}
}The expected result, depending on the DIP switch setting, is a device found at 0x70, 0x71, 0x72, or 0x73.
Relay Toggle Test #
A simple sequence that switches each of the eight channels on and then off through the PCA9538, useful for visually confirming which physical terminal corresponds to which channel before wiring real loads.
#include <PCA9538.h>
#include <Wire.h>
#define PCA9538_ADDR 0x73
PCA9538 io(PCA9538_ADDR);
void setup()
{
Serial.begin(115200);
pinMode(21, OUTPUT);
digitalWrite(21, HIGH);
Wire.begin(8, 9);
for (int i = 1; i <= 8; i++)
io.pinMode(i, OUTPUT);
Serial.println("NORVI X-R8 READY");
}
void loop()
{
for (int i = 1; i <= 8; i++)
{
io.digitalWrite(i, HIGH);
Serial.print("Relay ");
Serial.print(i);
Serial.println(" ON");
delay(1000);
io.digitalWrite(i, LOW);
}
}Validating the Full Test Sketch #
When the complete test sketch runs successfully with the X-R8 attached, you should see:
- I2C scan: The PCA9538 on the X-R8 appears at its configured address, 0x73 by default, alongside any other I2C devices on the bus.
- Relay outputs: Each of the eight channels switches on and off in sequence, either logged to the Serial Monitor or shown on the CPU module’s display if the sketch includes that step.
- Display and touch: If the CPU module’s display libraries are included in the same sketch, the TFT initializes and touch input responds as expected.
- No I2C errors: The Serial Monitor shows no failed transmissions or address conflicts while the relay test runs.
If a channel does not switch, or the PCA9538 does not appear on the I2C scan, stop and check the wiring and DIP switch address before connecting field loads, rather than troubleshooting through the display or WiFi portions of the sketch first.
Troubleshooting #
| Symptom | Suggested Action |
|---|---|
| Module not detected on I2C scan | Reseat the module on the expansion bus, confirm the DIP switch address does not conflict with another module, and check the CPU is powered with sufficient current headroom. |
| Relay does not switch despite firmware command | Confirm the I2C address in your sketch matches the DIP switch setting, and rerun the I2C bus scan to confirm the PCA9538 is still responding. |
| Relay clicks but load does not switch | Check the load current and voltage against the rated switching limits, and confirm wiring is through COM and NO, not just one terminal. |
| Wrong channel activates | Confirm the register bit order in your firmware matches the physical channel order (RO1 to RO8). |
| Address conflict with another I2C module | Change the DIP switch setting on one of the modules so each device on the bus has a unique address. |
| Relay chatters or does not hold | Check for a loose connection on the expansion bus connector, or insufficient power headroom on the shared 24V supply. |
| System resets unexpectedly under load | Check the CPU’s power supply current rating, especially when several expansion modules are attached to the same bus. |
| TFT display blank or not working | Check three settings under Tools: USB CDC On Boot set to Enabled, Flash Size set to 16MB (128Mb), and PSRAM set to QSPI PSRAM. |