LabVIEW is a graphical programming environment designed for measurement, instrumentation, and automation applications. Unlike general-purpose programming environments, LabVIEW is built around the concept of connecting software directly to physical systems. One of its major strengths is its hardware interface ecosystem, which provides a consistent programming model for acquiring data from sensors, controlling instruments, and communicating with external devices through interfaces such as serial, USB, Ethernet, and dedicated data-acquisition hardware. Another important advantage is its industrial-style user interface. LabVIEW applications can combine measurement, control, visualization, and operator interaction in a single application, using controls and indicators that resemble those found in laboratory instruments and industrial control panels. These characteristics make LabVIEW particularly suitable for rapidly developing measurement systems, automated test equipment, and laboratory automation applications.
LabVIEW also provides a practical entry point for makers, students, and non-commercial developers through LabVIEW Community Edition, which makes the LabVIEW programming environment available at no cost for eligible non-commercial use. The LabVIEW Hobbyist Toolkit extends this environment to maker-oriented hardware by providing VIs and firmware for interacting with platforms such as Arduino and Raspberry Pi. In addition, commonly used hardware communication components such as NI-DAQmx and NI-VISA can be downloaded and installed separately at no cost. NI-DAQmx provides access to supported NI data-acquisition hardware, while NI-VISA enables communication with instruments and devices through standard interfaces such as USB, serial, and TCP/IP. Together, these components give Community Edition users access to a relatively complete hardware integration stack, ranging from low-cost maker boards to laboratory instruments and dedicated DAQ devices.
To get started, first create an account on the NI website (ni.com). After registration, sign in with your NI account and download the LabVIEW Community Edition installer. At the time of writing, the latest available release used in this project is 2026 Q3 (3.79 GB offline installer). The installation is managed through NI Package Manager, which installs LabVIEW together with the required components. The LabVIEW Hobbyist Toolkit is included with the Community Edition installation, so no separate toolkit installation is required before experimenting with supported maker hardware.
After installation, launch the NI activation interface and sign in using the same NI account used to download the software. Select “Check my account for licenses”, and the NI licensing system will automatically identify and activate the appropriate LabVIEW Community Edition license for your account. The Community Edition license is activated for a period of approximately 400 days. When the activation period expires, the license can be renewed through the NI licensing system, allowing continued use of Community Edition for eligible non-commercial projects.
The LabVIEW Hobbyist Toolkit provides a hardware abstraction layer that connects LabVIEW to maker-oriented platforms such as Arduino and Raspberry Pi. It exposes common hardware APIs for digital I/O, analog I/O, PWM, I2C, SPI, and UART, allowing LabVIEW applications to interact with hardware without implementing board-specific communication from scratch. The toolkit supports two different execution models: with Arduino, LabVIEW communicates with firmware running on the microcontroller and controls its I/O remotely; with Raspberry Pi, LabVIEW code can be deployed to and executed directly on the target. The following sections show how each platform is prepared and connected to LabVIEW.
Using an Arduino board with the LabVIEW Hobbyist Toolkit starts by installing the toolkit firmware on the board. In LabVIEW, open Tools » Hobbyist » Firmware Wizard, select the supported Arduino board and its COM port, and use the wizard to flash the required firmware. Once programmed, the Arduino operates as an I/O device controlled by LabVIEW: toolkit VIs send commands to the firmware over the selected communication interface, and the firmware executes operations such as digital I/O, analog acquisition, PWM, I2C, SPI, and UART access and returns data when required. This approach provides a convenient hardware abstraction layer, but the standard firmware targets older Arduino platforms; for the classic UNO family, the supported target is the Arduino UNO R3.
The Raspberry Pi integration uses a different execution model from Arduino. Instead of keeping the LabVIEW application on the PC and sending individual I/O commands to firmware, LabVIEW can deploy and execute application code on the Raspberry Pi itself. Target preparation starts from Tools » Hobbyist » Target Configuration, where LabVIEW connects to the Raspberry Pi through SSH using its network address and login credentials. The configuration process then installs the required LabVIEW runtime and supporting software on the Raspberry Pi, preparing it as a deployable Hobbyist target. After configuration, LabVIEW code can run locally on the Pi and access its GPIO and peripheral interfaces through the toolkit APIs. This deploy-and-run architecture takes advantage of the Raspberry Pi's Linux-based computing environment.
After installation, the LabVIEW Hobbyist Toolkit appears as a collection of nodes in the Functions palette of the Block Diagram. A hardware session is managed by the Open and Close VIs, with Open implemented as a polymorphic VI providing four connection modes:
- Remote I/O – Serial และ Remote I/O – TCP: Remote I/O executes the LabVIEW application on the host computer and sends commands to firmware running on the target device; Serial uses a COM port, while TCP provides the same command-based model over a network connection.
- Local I/O is intended for targets capable of executing LabVIEW code locally, such as supported Raspberry Pi systems.
- Configurable I/O provides explicit control over the I/O mode and communication interface instead of relying on the default configuration.
Public NI documentation provides relatively little detail on these individual Open VI modes, and much of the architectural information is found in the earlier LINX/MakerHub documentation on which the Hobbyist Toolkit is based. In practice, the Arduino examples included with LabVIEW, as well as most available tutorials and blog posts, focus on the Remote I/O – Serial configuration. In this workflow, LabVIEW connects to an Arduino through its COM port and sends commands to the toolkit firmware previously installed on the board.
The Local I/O and Configurable I/O execution models are not considered in this first revision because they would require LabVIEW code to be deployed and executed within a software environment different from the supported Hobbyist targets. Instead, this project keeps LabVIEW execution on the host computer and focuses exclusively on adapting the Remote I/O model.
The original LabVIEW Hobbyist Toolkit Remote I/O architecture was designed for conventional microcontroller boards, where LabVIEW running on a host computer communicates directly with firmware on the target through a serial or network connection. This model does not map naturally to the UNO Q, which separates application processing on the Debian-based Qualcomm processor from peripheral control on the STM32U585 microcontroller. For the first revision of this project, the Remote I/O concept is therefore adapted into a gateway architecture rather than ported directly. LabVIEW communicates with a gateway service running on the Debian side of the UNO Q, while the gateway translates LabVIEW I/O requests into the UNO Q's native RPC calls to functions exposed by the STM32U585 firmware through Bridge.provide().
To maintain compatibility with the LabVIEW Hobbyist Toolkit programming model, the first revision implements a set of REST endpoints corresponding to the toolkit's commonly used peripheral I/O nodes. The LabVIEW-facing VIs retain the same functional abstraction, while their internal communication is replaced by HTTP requests with JSON payloads. Each REST endpoint is handled by the gateway on the Debian side and mapped to an RPC function exposed by the STM32U585 firmware. The initial API covers digital I/O, analog input, PWM, I2C, SPI, and UART, providing a direct mapping between the original LabVIEW operations and the UNO Q peripheral functions.
The RPC function names use the lv.<peripheral>.<operation> convention so that the interface between the Debian gateway and STM32U585 remains independent of the underlying C++ function names. All digital and analog operations use arrays for channel access, so a single pin or multiple pins can be manipulated with the same RPC invocation.
STM32U585 layer
The STM32U585 is responsible for real-time interaction with the UNO Q header pins and onboard peripherals. This is where the familiar Arduino APIs are executed, e.g. pinMode() is accessible with "lv.digital.read". The mapping is registered during setup():
void setup() {
...
Bridge.provide_safe("lv.digital.read", lvDigitalRead);
Bridge.provide_safe("lv.digital.write", lvDigitalWrite);
Bridge.provide_safe("lv.digital.mode", lvDigitalMode);
Bridge.provide_safe("lv.led.ctrl", lvLedCtrl);
Bridge.provide_safe("lv.analog.read", lvAnalogRead);
...
}The string passed to provide_safe() is the public RPC name. The second argument is the C++ function that executes on the STM32. The lv. prefix indicates that the function is intended for the LabVIEW interface, while the remaining parts identify the peripheral and operation. For example, the RPC function lv.digital.write is implemented using the Arduino digitalWrite() API:
int lvDigitalWrite(
MsgPack::arr_t<int> pins, MsgPack::arr_t<int> values) {
if (pins.size() != values.size()) {
return STATUS_INVALID_ARGUMENT;
}
for (size_t i = 0; i < pins.size(); ++i) {
if (!validDigitalPin(pins[i])) {
return STATUS_INVALID_ARGUMENT;
}
}
for (size_t i = 0; i < pins.size(); ++i) {
digitalWrite(pins[i], values[i] ? HIGH : LOW);
}
return STATUS_OK;
}This handler receives two parallel arrays: one containing pin numbers and one containing output values. It validates the complete request before changing any hardware. A nonzero value is interpreted as HIGH, while zero is interpreted as LOW. The same pattern is used for other Arduino APIs. The RPC interface uses arrays internally because this makes it possible to operate on several pins or channels in one request.
The firmware also performs hardware-specific validation. Digital pins must be in the UNO Q header range D0–D13. Analog channels must be between A0 and A5. PWM output is limited to pins 3, 5, 6, 9, 10, and 11, and the duty cycle is represented as a normalized floating-point value from 0.0 to 1.0.
Every RPC returns an explicit status value:
0means operation completed successfully-1means invalid argument or invalid hardware request.-2means function declared but not implemented
Read operations return a tuple containing the status and the requested value. For example, lv.digital.read may returns (0, [1, 0, 1]) when pins variable is [3,4,5].
In summary, the STM32 layer is an RPC-enabled Arduino firmware layer. Arduino APIs remain responsible for the actual hardware operations, while Arduino_RouterBridge provides a named, validated, message-based interface that can be called from the Linux gateway and, ultimately, from LabVIEW.
Qualcomm QRB2210 layer
The Qualcomm QRB2210 runs Debian Linux and provides the application-processing side of the UNO Q. Instead of directly controlling GPIO hardware, this layer acts as a gateway between LabVIEW and the STM32U585. The gateway is implemented using the Arduino App Lab WebUI Brick. The WebUI Brick provides the HTTP server and allows application-defined REST endpoints to be registered. The gateway creates a WebUI instance on port 7000. Each REST endpoint is then connected to a Python callback:
from arduino.app_bricks.web_ui import WebUI
from arduino.app_utils import App, Bridge
ui = WebUI(
port=7000,
assets_dir_path="/app/assets",
api_path_prefix=""
)
ui.expose_api(
"POST",
"/api/v1/digital/write",
digital_write_callback
)
ui.expose_api(
"POST",
"/api/v1/analog/read",
analog_read_callback
)The gateway operations follow a consistent sequence:
- Receive a JSON request from LabVIEW.
- Validate the JSON structure and values.
- Convert convenient scalar inputs into arrays when required.
- Translate user-facing names or units into firmware-level values.
- Call the corresponding STM32 RPC through
Bridge.call(). - Convert the RPC response into a JSON response.
- Return the device status and any result values to LabVIEW.
Read operations return both the RPC status and the measured value:
def analog_read_callback(body):
channels, error = _entities(body, "channels", "channel")
if error:
return {"status": -1, "error": error}
status, values = Bridge.call("lv.analog.read", channels)
return {
"status": status,
"values": values
}Some conversions are specific to the UNO Q hardware. The onboard RGB LEDs are active-low, so the REST API can use an intuitive request:
{
"led": "LED3_R",
"state": true
}UART requests use the same gateway pattern. The REST API exposes a channel-based interface, while the current firmware implementation maps channel 0 to Serial1. The gateway converts JSON byte arrays into the binary representation expected by the RPC layer when transmitting UART data on D0 and D1.
The WebUI Brick also provides a useful connection callback. When a WebUI client connects, the gateway calls lv.system.running on the STM32. This changes the STM32 display from its booting message to OK. A separate /api/v1/system/connect endpoint provides the same transition for command-line tests and LabVIEW clients that do not use the WebUI connection event.
The Qualcomm layer, therefore, acts as a protocol adapter. This separation is important. The Linux gateway can evolve its REST interface, validation rules, and LabVIEW compatibility without moving hardware behavior into Python. Conversely, new Arduino-based peripheral functions can be added to the STM32 and exposed through a new RPC and REST endpoint without redesigning the entire application.
LabVIEW layer
On the LabVIEW side, the toolkit is organized as a single LabVIEW project (.lvproj file) that provides a consistent interface to the Arduino-compatible APIs implemented on the UNO Q. Instead of exposing the underlying HTTP and JSON communication directly to an application, each Arduino operation is encapsulated as a reusable subVI, such as PinMode, DigitalRead, DigitalWrite, AnalogRead, and also LED control (UNO Q ). Common inputs and outputs, particularly the UNO Q session, are defined using LabVIEW typedefs so that connection information and other shared parameters can be passed consistently between VIs. The project also includes a set of demonstration VIs showing how each API wrapper can be integrated into a LabVIEW application.
Two key subVIs, UNO Q connect.vi and UNO Q disconnect.vi, manage the communication session between LabVIEW and the UNO Q. Communication is built on LabVIEW's HTTP Client library, with commands sent as HTTP POST requests and parameters encoded as JSON. When UNO Q connect.vi is called, it first constructs the server address from the specified base URL and port, then sends a POST request to the /api/v1/system/connect endpoint. The JSON response is decoded and its status field is checked; a value of 0 indicates that the connection has been successfully established. The HTTP client reference, base URL, and connection state are then bundled into the UNO Q Session typedef and passed to subsequent API VIs. UNO Q disconnect.vi performs the corresponding operation at the end of the application and releases the HTTP client resources.
The Demo - blink example VI illustrates an important difference between the UNO Q and a conventional Arduino UNO. The UNO Q contains four RGB LEDs, but they are not all accessed through the same hardware layer. LED1_R through LED2_B are controlled from the Qualcomm/Debian side, while LED3_R through LED4_B are connected to the STM32 and correspond to six STM32 pin IDs, 50 through 55. To avoid exposing these implementation-specific pin numbers to the LabVIEW application, LED control is provided through a dedicated /api/v1/led/control endpoint rather than the general /api/v1/digital/write endpoint. On the LabVIEW side, symbolic names such as LED3_R are defined in an LED typedef enum, so the application can select an LED by name instead of hard-coding the underlying pin ID.
The Demo - blink.vi itself remains intentionally simple and follows the normal LabVIEW dataflow style. UNO Q connect.vi is called before entering the While Loop, the selected LED is controlled repeatedly inside the loop, and UNO Q disconnect.vi is called after the loop terminates. A delay is inserted between updates, while the loop iteration index is used to generate the alternating ON/OFF state. As a result, the UNO Q-specific REST interface and hardware mapping remain hidden inside the toolkit, leaving the user with a compact VI that looks and behaves like a typical LabVIEW hardware-control application.
The Demo - plot.vi example demonstrates analog acquisition using the /api/v1/analog/read endpoint. After establishing the UNO Q session, the VI repeatedly reads the selected analog input inside a While Loop and wires the returned value directly to a LabVIEW Waveform Chart. For this demonstration, an Arduino Multi-purpose Shield V2 from Keyestudio is used, with its onboard potentiometer providing a convenient variable voltage source. This example highlights one of the main benefits of the UNO Q toolkit: once the hardware interface is encapsulated by LabVIEW subVIs, acquired data can be connected directly to LabVIEW's built-in analysis, visualization, logging, and user-interface components. In this case, producing a continuously updated plot requires little more than wiring the value returned by UNO Q AnalogRead.vi to a Waveform Chart terminal. The same approach can be extended to more sophisticated measurement and control applications without requiring the application developer to handle the underlying HTTP requests or JSON messages.
Important:The UNO Q's STM32 analog inputs operate in the 3.3 V domain, unlike the 5 V analog range commonly associated with traditional Arduino UNO boards. When using Arduino shields or external signal sources, verify that the voltage presented to an analog input does not exceed the permitted input range. A higher voltage can cause the ADC reading to saturate and, more importantly, may exceed the device's electrical limits and damage the input circuitry.
ConclusionThis work demonstrates a proof-of-concept architecture for integrating LabVIEW with the UNO Q, but the broader value is in the software architecture rather than the individual LabVIEW VIs themselves. UNO Q combines two processing domains: a Linux-capable Qualcomm processor running Debian and containerized services, and an STM32 running Arduino/Zephyr-based firmware for hardware-level control. By linking these two domains through service-oriented APIs, the system can separate high-level application and networking tasks from lower-level I/O access while still presenting a simple interface to external development environments.
At this stage, the toolkit should be considered a proof of concept (PoC) rather than a complete hardware-support package. Several extensions are still under development:
- Support for multiple frontend environments. Because the hardware functions are exposed as web services, the same backend can potentially be accessed from MATLAB, Python, Node-RED, or other environments. Each frontend can then exploit its own strengths while sharing the same UNO Q service layer.
- Access to Debian-side services and Bricks. Additional endpoints can be introduced to expose services running on the Debian side, particularly Bricks and machine-learning-related capabilities. This would extend the toolkit beyond conventional GPIO and peripheral access.
- Higher-level hardware APIs. More API wrappers can be added for commonly used hardware platforms, including Arduino shields, X-NUCLEO expansion boards, the UNO Q Carrier format such as the UNO Media Carrier, and Modulino modules. These higher-level APIs would reduce the amount of application-specific hardware handling required by the user.








Comments