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-AQ4 is a 4-channel analog output expansion module for the NORVI X modular controller platform, used for precise control of industrial actuators, VFDs, and process valves. It uses an onboard STM32 microcontroller dedicated to 13-bit DAC management, offloading timing-critical signal generation from the main CPU. Each of the 4 outputs is independently configurable (in software) for 0–10V or 4–20mA, with active filtering and TVS diode protection for noise immunity and surge protection.
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 × 0–10 V/4-20mA analog output channels
- 13-bit DAC resolution
- I²C expansion bus communication
- Onboard DIP switch for I2C address selection, allowing multiple analog input modules on the same bus
- DIP switch addressing
- Plug and play connection to the CPU module through the expansion bus
- Individual LED status indicators per output
- DIN rail mountable enclosure
- 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-AQ4. 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.
- 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.
- Confirm output mode (0–10V vs 4–20mA) in firmware matches the connected load’s expected input type before energizing.
- 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 | 110mA @ 24V DC |
Output Specifications #
| Number of Outputs | 4 Analog Output channels |
| Analog Output Measurement Range | 0–10V / 4–20mA |
| Resolution | 13-bit |
| Output Ranges | 0-10V DC / 4-20mA (Software Configurable) |
| Communication | SPI |
| Output Diagnostics | Individual LED indicators Alert Indicator |
| 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-AQ4. None of the host CPU’s GPIO pins are claimed directly by the analog channels themselves – only SCL and SDA are shared across the I2C bus.
| Expansion Port Pin | Purpose | GPIO / Signal | Source |
| 5 | SCL | IO9 | ESP32-S3 |
| 6 | SDA | IO8 | ESP32-S3 |
The table below lists the GPIO pins reserved for the X-AQ4’s four inputs.
| Terminal | Function |
| AOUT1 | Analog Output 1 |
| AOUT2 | Analog Output 2 |
| AOUT3 | Analog Output 3 |
| AOUT4 | Analog Output 4 |
| AGND x 4 | Analog Ground |
| GND | Ground |
I2C Address Selection #

| Address Selection | ||||
| DIP 1 | DIP 2 | DIP 3 | DIP 4 | Address |
| OFF | OFF | OFF | OFF | 0x5F |
| ON | OFF | OFF | OFF | 0x57 |
| OFF | ON | OFF | OFF | 0x5B |
| ON | ON | OFF | OFF | 0x53 |
| OFF | OFF | ON | OFF | 0x5D |
| ON | OFF | ON | OFF | 0x55 |
| OFF | ON | ON | OFF | 0x59 |
| ON | ON | ON | OFF | 0x51 |
| OFF | OFF | OFF | ON | 0x5E |
| ON | OFF | OFF | ON | 0x56 |
| OFF | ON | OFF | ON | 0x5A |
| ON | ON | OFF | ON | 0x52 |
| OFF | OFF | ON | ON | 0x5C |
| ON | OFF | ON | ON | 0x54 |
| OFF | ON | ON | ON | 0x58 |
| ON | ON | ON | ON | 0x50 |
Note: default all-OFF = 0x5F – unlike the input modules, X-AQ4 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.
Wiring Guide #
GPIO pin assignments for every input are listed in the Hardware Layout and GPIO Map section above; this section covers how to physically wire the module, not the pin numbers themselves.
Power Connection #
The X-AQ4 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.
Analog Output Wiring #
- Each of the four channels outputs 0–10V or 4–20mA (software configurable)
- Connect the load/actuator’s input wire to the appropriate AOUTx terminal
- Connect the load’s return lead to the matching AGND terminal
- Keep output wiring runs separated from AC/high-current wiring to minimize induced noise
- Confirm the output mode set in firmware matches what the connected load expects before energizing

Connecting the Module to the CPU #
- Power off the system.
- Mount the X-AQ4 on the DIN rail next to the CPU module or an adjacent expansion module.
- Seat it firmly onto the expansion bus connector until it locks into place.
- If daisy-chaining multiple I2C-addressable modules, set the DIP switches first (see Section 5) so each has a unique address.
- Wire the actuators/loads to AOUT1 through AOUT4, using the matching AGND terminal as the return for each channel.
- 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-AQ4 connects to the CPU through the shared 50 pin expansion bus. The pins used by this module are SCL, SDA, GND, 24V, and 5V. The remaining pins pass through for other expansion modules.
| 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-AQ4 is driven 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
Figure 3: Arduino IDE Board and Tools Menu Configuration


Figure 4: Upload Settings under the Tools Menu
- 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
Install the Required Library #
Install the Wire library through:
Sketch → Include Library → Manage Libraries
Search for Wire and install it if required.

Figure 5: Opening the Arduino IDE Library Manager
The Libraries are available in the NORVI-X-Version-02 GitHub repository.
Open and Upload the Test Sketch #
- Open the X-AQ4 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 #
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.println(address, HEX);
deviceCount++;
}
}
if (deviceCount == 0) Serial.println("No I2C devices found\n");
else Serial.println("Scanning complete\n");
}Expected address: one of 0x50–0x5F depending on DIP setting.
Analog Output Read Test #
// WRITE DAC CHANNEL
// =========================================================
void write_channel(byte device_address, unsigned int channel, unsigned int value) {
Wire.beginTransmission(device_address);
Wire.write(1 + (channel * 2));
Wire.write(value >> 8);
Wire.write(value & 0xFF);
Wire.endTransmission();
}
// =========================================================
// DAC CONFIG
// =========================================================
void config_dac(byte device_address,
unsigned int c1,
unsigned int c2,
unsigned int c3,
unsigned int c4) {
unsigned int tft = 0;
tft |= (c4 << 3);
tft |= (c3 << 2);
tft |= (c2 << 1);
tft |= c1;
Wire.beginTransmission(device_address);
Wire.write(0x01);
Wire.write(tft);
Wire.endTransmission();
}Validating the Full Test Sketch #
When the complete test sketch runs successfully with the X-AQ4 attached, you should see:
- I2C scan: STM32 bridge appears at the configured address (0x50–0x5F).
- Output verification: Measure each AOUTx terminal with a multimeter while stepping through known DAC values – voltage/current should track proportionally.
- Mode check: Confirm the channel outputs the expected signal type (0–10V or 4–20mA) as configured in firmware, not the other.
- LED indicators: Per-channel status LEDs should reflect active output state.
- No I2C errors: The Serial Monitor shows no failed transmissions or address conflicts.
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 CPU power headroom. |
| Output stays off | Check wiring polarity and confirm AGND is properly connected to the load’s return path. |
| Output stuck at 0V/0mA | Confirm firmware is actually writing to the correct channel address, and that output mode is set correctly. |
| Output value doesn’t match commanded value | Confirm the DAC value scaling and register/command format in firmware matches the module’s actual protocol – recheck against the GitHub sketch. |
| Inconsistent behavior across multiple modules | Confirm each daisy-chained module has a unique I2C address per the DIP switch table. |
| 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. |
