XN03 - Analog Inputs-Outputs

X-NODE Analog Inputs-Outputs is a module that allows you to generate up to 3 analog/PWM signals and read up to 4 analog signals (3 inputs + 1 potentiometer). The analog signal generation can be used to control proportional systems, PWM signals to control LED drivers, brushed motor drivers, etc. The analog signal reading can be used to create proportional control systems, measure battery and regulator voltage. All through a digital interface (UART/I2C) that is configurable, allowing you to connect multiple X-NODE Analog Inputs-Outputs simultaneously, expanding the number of analog/PWM outputs from 3 up to 381, analog inputs from 3 up to 381, and potentiometers from 1 up to 127.
The X-NODE Analog Inputs-Outputs is a device that operates at 3.3V. Before connecting it to a power source, make sure the voltage does not exceed 3.3V on any of the inputs.
TABLE OF CONTENTS
I. How does it work?
The X-NODE Analog Inputs-Outputs is a module that integrates a single-turn potentiometer, an RGB LED, 3 holes for PWM signal access, and a connection port with 3 analog inputs and 3 analog outputs, 3.3VDC, and GND. The hardware controller allows its use without advanced hardware knowledge, as it is only necessary to send a series of ASCII commands via UART serial communication or using the I2C protocol, making the X-NODE able to communicate with any microcontroller based system, microprocessor, or industrial equipment. The potentiometer has a resistance value of 5 kΩ, a tolerance of ± 20%, and a power rating of 5 mW. The RGB LED can generate up to 16 million color combinations by configuring the intensity parameters of the primary colors (Red, Green, and Blue), with an average consumption of 20 mA and operation in a temperature range from 0 °C to 80 °C. The PWM outputs share the channel with the analog outputs, which should be considered when using these outputs; the resolution is 8 bits and the frequency, in the case of PWM signals, is 1.2 kHz. The analog inputs have a resolution of 10 bits, and the reading uses a multiplexer, so the maximum sampling frequency is up to ~37 ksps for each channel.
X-NODE Analog Inputs-Outputs is compatible with the mikroBUS™ standard from Mikroe® for easy use with a large ecosystem of hardware development kits. It also has JST connectors compatible with the Qwiic® standard from SparkFun® for quick and easy I2C communication between various modules and development boards.
II. Hardware description

9 pin terminal block port for AWG 26 to 18 cables
Single turn potentiometer
JST connectors compatible with Qwiic®
RGB LED indicator
PWM signal access holes
Hardware controller
UART <> I2C communication ports
X-NODE model
X-NODE type
mikroBUS™ standard connectors
Hardware version: A-R2
Main feature on the X-NODE
III. Specifications
Applications
Integration with IoT projects for general purpose use such as reading proporcional signals with actuators and motors. Potentiometer useful for motion control, system activation, or precise component calibration. RGB LED ideal for visual alerts, ambient lighting in smart homes, as well as status indicator in different components, alarms, and sequences.
Features
Single-turn potentiometer with adjustable angle, resistance value of 5 kΩ, tolerance of ± 20%, and power rating of 5 mW. RGB LED capable of generating up to 16 million colors from a PWM signal, with an average consumption of 20 mA and operation in a temperature range from 0 to 80 °C. Connection port with male pins and holes for 3 external analog inputs and 3 outputs, 3.3V, and GND. PWM signal access terminal block.
Interface
UART, I2C
Size
65.09 x 25.38 x 26.98 mm
Voltage
3.3 VDC
IV. Pinout
The following table shows the pinout of the X-NODE Analog Inputs-Outputs with respect to the mikroBUS™ standard (the latter is in the two center columns).

V. Usage
For easy and quick use of the X-NODE, you can use the ASCII commands provided by the integrated hardware controller via UART serial communication or, more advanced, through the I2C protocol.
UART Protocol
Configuration
UART communication uses the following configuration:
Baud rate: 115,200 bps
Parity: None
Data bits: 8
Stop bits: 1
Syntax
The UART protocol allows sending instructions in plain ASCII text, each instruction consists of the X-NODE identifier, a command, and a line ending.
Identifier
The ID identifier consists of the X-NODE model, which can be found at point 6 in the Hardware description section, and is complemented by an index, which can be a letter from A to Z, default is A. To connect more than one module of the same model in a system, you must configure a unique identifier for each module, allowing up to 26 modules of the same model to be connected via UART protocol.

Note: From this point on, the default index of the X-NODE XN03 - Analog Inputs-Outputs will be used for the rest of the manual: XN03A.
Command list
XN03A?
Checks if communication was successfully established. Response: OK
XN03A+V
Gets the current firmware version integrated in the X-NODE. Response: XN03A=Version Example: XN03A=2.0.0
XN03A+ID=(A-Z)
Changes the ID index to a different uppercase letter from A to Z. Once changed, to change it again you must use the new ID. Response: OK Example to send: XN03C+ID=H
XN03A+TW=(1-126)
Changes the factory I2C address to a different one. The new address is written in decimal, selecting a value from 1 to 126. Response: OK Example to send: XN03A+TW=28
XN03A+GP
Gets the potentiometer value given by its position. Returns a relative value from 0 to 100. Response: XN03A=VAL Example: XN03A=67
XN03A+S=(Out1/PWM1/Red),(Out2/PWM2/Green),(Out3/PWM3/Blue)
Changes the state of each of the 3 outputs, either directly on the analog output port, PWM access holes, or the RGB LED indicator colors, with values between 0 and 255. Optionally, sending a fourth value between 0 and 255 allows scaling the channels (RGBa). Response: OKExample to send: XN03A+S=0,25,100
XN03A+G(P,1,2,3)
Gets the potentiometer value by its position or the analog inputs (1,2,3). Returns a relative value from 0 to 100. Response: XN03A=VAL Example to send: XN03A+GP Example response: XN03A=67
XN03A+A(P,1,2,3)
Gets the potentiometer value by its position or the analog inputs (1,2,3) with ADC resolution (10 bits). Returns a relative value from 0 to 1023. Response: XN03A=VAL Example to send: XN03A+AP Example response: XN03A=512
Line ending
The X-NODE will only respond to a command when a set of end-of-line characters are sent, each command must end with these characters: <CR+LF>
CR means carriage return.
LF means line feed.
The combination of both characters is a common way computers represent a new line, for example, in a word processor to separate paragraphs.
For the X-NODE, the <CR+LF> characters are used to identify when a command has finished being sent. If the identifier matches the node, if the command exists, and if it is immediately ended with the <CR+LF> characters, then the node will send a response.
Depending on the system, you must configure the sending of these characters in different ways.
UART Example Arduino Framework
// This example allows you to control the intensity of the
// X-NODE's RGB LED using the potentiometer.
#include "Arduino.h"
// Set this value to change the RGB color
const uint8_t rgb_color[] = { 227, 235, 23 };
void setup() {
// Initialize the serial monitor
Serial.begin(115200);
// Initialize UART communication on the MikroBUS port
Serial2.begin(115200, SERIAL_8N1, 9, 10);
}
void loop() {
// Control the intensity of the RGB LED with the XN03 potentiometer
// Clear the buffer
if (Serial2.available()) {
Serial2.read();
}
// Send the command to get the potentiometer position
// The \r\n characters represent the
// <CR+LF> characters in C/C++ programming language
Serial2.print("XN03A+GP\r\n");
// Wait until a response is received
String pot_value = Serial2.readStringUntil('\n');
// If the response starts with the ID
// then communication was successful
if (!pot_value.startsWith("XN03A=")) {
Serial.println("Error");
delay(1000);
return;
}
// Convert the ASCII value to a decimal value
int brightness = pot_value.substring(pot_value.indexOf('=') + 1).toInt();
// Clear the buffer
if (Serial2.available()) {
Serial2.read();
}
// Send the command to change the output values
Serial2.print("XN03A+S=");
Serial2.print(rgb_color[0]);
Serial2.print(",");
Serial2.print(rgb_color[1]);
Serial2.print(",");
Serial2.print(rgb_color[2]);
Serial2.print(",");
Serial2.println(brightness);
// Wait until a response is received
String success = Serial2.readStringUntil('\n');
// If the response is "OK"
// then communication was successful
if (!success.startsWith("OK")) {
Serial.println("Error");
delay(1000);
return;
}
delay(100);
}
I2C Protocol
To establish communication, you must know the I2C address of the X-NODE, the factory value consists of the last two digits of the model after "XN". I2C addresses are usually represented in hexadecimal, while the X-NODE model is in decimal, make sure to use the correct number system.

Configuration
Communication speed: 100 kHz
Address: 7 bits
Write
To write to a register of the X-NODE Digital Inputs, the I2C controller must perform the following operations:
Send a start condition: The controller generates a logic low (0) on the SDA pin while SCL remains high (1).
Send the X-NODE address: The controller sends the 7-bit address.
Send the operation type: The controller indicates whether the operation is read (0) or write (1).
Wait for an acknowledge (ACK) signal: The controller waits to receive a logic low (0) as confirmation (Acknowledgment) that a target with the previously sent address exists on the I2C BUS. If no response (1) is received, it means there was a communication error or the address is incorrect.
Write n bytes of data: The controller will write in 8 bit (1 byte) sequences, most significant bit first (MSB), n number of bytes to write to the register, the target will send an acknowledge (ACK) signal for each byte written.
Send a stop condition: The controller must release the I2C BUS by generating a logic high (1) on the SDA pin while SCL is high (1).
Read
To read from a register of the X-NODE Digital Inputs, the I2C controller must perform the following operations:
Send a start condition: The controller generates a logic low (0) on the SDA pin while SCL remains high (1).
Send the X-NODE address: The controller sends the 7 bit address.
Send the operation type: The controller indicates whether the operation is read (0) or write (1).
Wait for an acknowledge (ACK) signal: The controller waits to receive a logic low (0) as confirmation (Acknowledgment) that a target with the previously sent address exists on the I2C BUS. If no response (1) is received, it means there was a communication error or the address is incorrect.
Read n bytes of data: The target will send 8 bit (1 byte) sequences, most significant bit first (MSB), n number of bytes, upon receiving a byte, the controller must generate an acknowledge (ACK) signal to request 1 more byte, or a not acknowledge (NACK) signal to indicate that the transmission has ended and request the target to release the BUS.
Send a stop condition: The controller must release the I2C BUS by generating a logic high (1) on the SDA pin while SCL is high (1).
Register list
In an I2C target, registers are memory addresses that allow configuring or obtaining data from the target. There are two types of operations: read (R) and write (W).
O1_RED
0x01
R/W
1 to 4
The first byte represents the O-1 (red) DAC channel, the second the O-2 (green) channel, the third the O-3 (blue) channel, sending a 4th byte allows scaling the channel intensities (RGBa)
O2_GREEN
0x02
R/W
1 to 3
The first byte represents the O-2 (green) DAC channel, the second the O-3 (blue) channel, sending a 3rd byte allows scaling the intensities of channels O-2 and O-3 (GBa), the first channel is unaffected.
O3_BLUE
0x03
R/W
1 to 2
The first byte represents the O-3 (blue) DAC channel, sending a 2nd byte allows scaling the intensity of channel 3 (Ba), channels O-1 and O-2 are unaffected.
IN_POT
0x10
R
1
Returns the ADC value of the potentiometer scaled from 0 (0x00) to 100 (0x64)
IN1
0x11
R
1
Returns the ADC value of channel I-1 scaled from 0 (0x00) to 100 (0x64)
IN2
0x12
R
1
Returns the ADC value of channel I-2 scaled from 0 (0x00) to 100 (0x64)
IN3
0x13
R
1
Returns the ADC value of channel I-3 scaled from 0 (0x00) to 100 (0x64)
ADC_POT
0x20
R
2
Returns the ADC value of the potentiometer, with 10-bit resolution, 0 (0x00) to 1023 (0x3FF).
ADC1
0x21
R
2
Returns the ADC value of channel I-1, with 10-bit resolution, 0 (0x00) to 1023 (0x3FF).
ADC2
0x22
R
2
Returns the ADC value of channel I-2, with 10-bit resolution, 0 (0x00) to 1023 (0x3FF).
ADC3
0x23
R
2
Returns the ADC value of channel I-3, with 10-bit resolution, 0 (0x00) to 1023 (0x3FF).
STAT
0x37
R
1
XNODE status, 0x00 if there are no errors, any other value means communication error.
FW
0x38
R
3
Firmware version, in major, minor, and patch: 0x02.0x00.0x00
UART_ID
0x39
R/W - NV
1
Allows reading and writing the ID index to a different uppercase letter from A (0x41) to Z (0x5A)
TW_ADD
0x3A
R/W - NV
1
Allows reading and writing the device's I2C address to a different one from 1 (0x01) to 126 (0x7D). A reset or power-on sequence must happen for this changes to be applied
UART_EN
0x3B
W
1
Enables (0x01) or disables (0x00) the device's UART interface.
SLEEP
0x3C
W
1
Enables (0x01) or disables (0x00) the device's deep sleep, the device will wake up if the controller writes the device's I2C address on the BUS.
RESET
0x3D
W
1
Writing 0x01 resets the device.
WHO_AM_I
0x3E
R
2
The first byte is the XNODE model, the second byte is the hardware revision
Non-volatile registers (NV)
Non-volatile registers are stored in the device's EEPROM memory, meaning they will retain the values written to them even if the device is powered off.
OUT1, OUT2, OUT3 register structure:

IN_POT, IN1, IN2, IN3 register structure:

ADC_POT, ADC1, ADC2, ADC3 register structure:

I2C Example Arduino Framework
// This example allows you to control the intensity of the
// X-NODE's RGB LED using the potentiometer.
#include <Arduino.h>
#include <Wire.h>
// Set this value to change the RGB color
const uint8_t rgb_color[] = { 227, 235, 23 };
void setup() {
// Initialize the serial monitor
Serial.begin(115200);
// Set the I2C communication pins
Wire.setPins( 12, 13 );
// Initialize I2C communication
Wire.begin();
}
void loop() {
// Control the intensity of the RGB LED with the XN03 potentiometer
uint8_t bytes_recv = 0;
uint8_t pot = 0;
// Send start condition + address
// + operation type
Wire.beginTransmission(0x03);
// Write the potentiometer register address (0x1E)
Wire.write(0x10);
// Check if the operation was successful
if (Wire.endTransmission() != 0) {
Serial.println("Error requesting register");
delay(1000);
return;
}
// Send start condition + address
// + operation type + number of bytes to read
bytes_recv = Wire.requestFrom(0x03, 1);
// Confirm that 1 byte was received
if (bytes_recv != 1) {
Serial.println("Error reading register");
delay(1000);
return;
}
pot = Wire.read();
// Send start condition + address
// + operation type
Wire.beginTransmission(0x03);
// Write the channel 1 register address (0x01)
Wire.write(0x01);
// Write the value for channel 1 (red)
Wire.write(rgb_color[0]);
// Writing sequentially assigns the value for channel 2 (green)
Wire.write(rgb_color[1]);
// Channel 3 (blue)
Wire.write(rgb_color[2]);
// And the intensity
Wire.write(pot);
if (Wire.endTransmission() != 0){
Serial.println("Error writing RGB value");
delay(1000);
}
delay(100);
}
VI. Downloads
Last updated