Skip to content

NISystemsEngineering/cRIO-Python-AI-Workflows

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

NI cRIO Python Development Workflows

This repository demonstrates four development workflows for the National Instruments cRIO platform using Python. Each workflow builds on the previous, progressing from pure local simulation through hybrid FPGA/DAQmx control to fully remote operation with live data streaming.

Workflows at a glance

# DAQmx location FPGA control Where Python runs
1 Dev machine (simulated cDAQ) → real cRIO None Dev machine, then cRIO
2 cRIO (via SSH) LabVIEW interactive VI cRIO (SSH)
3 cRIO (via SSH) Python nifpga (SSH) cRIO (SSH)
4 Remote machine → cRIO via gRPC Python nifpga (SSH) Split: FPGA on cRIO, DAQmx on dev machine

Project layout

ni9220acquisition.py                            # Workflow 1 – DAQmx demo (dev machine with simulated cDAQ)
.bashrc                                         # cRIO shell encoding fix (copy to /home/admin/)
PythonFPGAControl/
  analog-input.py                               # Workflow 4 – gRPC DAQmx client (runs on dev machine)
  stubs/                                        # Generated gRPC/protobuf stubs (nidaqmx, nidevice, etc.)
  source/
    cRIO Code/                                  # Deploy all files here to /home/admin/PythonFPGAControl/ on cRIO
      ni9220acquisition.py                      # Workflow 1 – cRIO variant (physical channel default)
      ai.py                                     # Workflow 2/3 – cRIO-local DAQmx with termchart plotting
      fpga_interface_sine-pwm.py                # Workflow 3 – interactive nifpga CLI (sine-pwm.lvbitx)
      sine-pwm.lvbitx                           # FPGA bitfile for Workflow 3
      grpc-device-server                        # NI gRPC Device Server binary (Workflow 4)
    LabVIEW Project/
      fpga_interface.py                         # Workflow 2 – FPGA offset-control CLI (criosineshift bitfile)
      fpga_interface_pwm-sine.py                # Workflow 3 – alternate nifpga CLI with input validation
      cRIO Sine Shift.lvproj                    # LabVIEW project for the sine-shift FPGA VI
      FPGA Bitfiles/                            # Compiled .lvbitx bitfiles for LabVIEW project VIs
    gRPC Client/Client/
      analog-input.py                           # Workflow 4 – alternate gRPC client copy
      stubs/                                    # Protobuf stubs co-located with the alternate client
    Reference Material/                         # NI 9381 example LabVIEW projects and bitfiles

Workflow 1: Simulated cDAQ → real cRIO DAQmx acquisition

Goal: Write and validate DAQmx acquisition code on a dev machine using a simulated cDAQ chassis, then deploy the same script unchanged to a cRIO with real C-Series hardware.

Dev machine (simulated hardware)

  1. Open NI MAX and create a simulated cDAQ chassis (e.g. NIcDAQ-9177) with an NI 9220 module in Slot 1.
  2. Run ni9220acquisition.py from the repo root. The default channel NIcDAQ-9177/Mod1/ai0 matches the simulated chassis.
python ni9220acquisition.py

The script runs a continuous analog input task at 10 kS/s, prints block-level min/max/avg and effective throughput, and stops on q + Enter or Ctrl+C.

Deploy to cRIO (real hardware)

  1. Copy PythonFPGAControl/source/cRIO Code/ni9220acquisition.py to the cRIO. Its default channel is Mod1/ai0, matching a real cRIO slot layout.
  2. SSH into the cRIO and run:
ssh admin@<crio-hostname>
python /home/admin/PythonFPGAControl/ni9220acquisition.py

Adjust physical_channel in the script if your NI 9220 is in a different slot.

A terminal-plotting variant (ai.py) is also available on the cRIO for visual output via termchart:

python /home/admin/PythonFPGAControl/ai.py

Workflow 2: LabVIEW interactive FPGA VI + Python DAQmx on cRIO (SSH)

Goal: Run an FPGA VI interactively from LabVIEW while a Python DAQmx task running on the cRIO acquires data. Python is invoked remotely from a dev machine over SSH.

Setup

  1. Open PythonFPGAControl/source/LabVIEW Project/cRIO Sine Shift.lvproj in LabVIEW.
  2. Deploy and run the FPGA VI interactively on the cRIO target (LabVIEW handles the bitfile download and FPGA session).
  3. In a separate terminal on your dev machine, SSH into the cRIO and run the Python DAQmx acquisition script:
ssh admin@<crio-hostname>
python /home/admin/PythonFPGAControl/ai.py

FPGA offset control (optional)

While LabVIEW holds the FPGA session, you can still adjust FPGA output parameters from Python using fpga_interface.py — but only when LabVIEW is not holding an exclusive FPGA lock. The script accepts a sine-wave offset (0–4) or stop:

python /home/admin/PythonFPGAControl/fpga_interface.py
# Enter: 0, 1, 2, 3, 4, or stop

This targets criosineshift_FPGATarget_NI9381AdvancedIO.lvbitx on RIO0.


Workflow 3: Python nifpga FPGA control + Python DAQmx on cRIO (SSH)

Goal: Control the FPGA entirely from Python using the nifpga driver on the cRIO, while simultaneously running a DAQmx acquisition task — all invoked remotely over SSH from a dev machine. No LabVIEW runtime is required.

Deploy files to cRIO

scp -r "PythonFPGAControl/source/cRIO Code/"* admin@<crio-hostname>:/home/admin/PythonFPGAControl/

Run FPGA control (SSH into cRIO)

ssh admin@<crio-hostname>
python /home/admin/PythonFPGAControl/fpga_interface_sine-pwm.py

The interactive CLI loads sine-pwm.lvbitx on RIO0 and accepts the following commands:

Command Effect
sine Switch FPGA output to sine wave mode
pwm Switch FPGA output to PWM mode
scale X Set amplitude scale (0.0–5.0)
duty X Set PWM duty cycle (0.0–1.0)
stop Halt FPGA loop and close session

Run DAQmx acquisition simultaneously (second SSH session)

Open a second SSH connection to the cRIO and run:

python /home/admin/PythonFPGAControl/ai.py

Both processes run concurrently on the cRIO. The FPGA generates the signal; DAQmx acquires it.


Workflow 4: Python nifpga on cRIO (SSH) + remote DAQmx via gRPC with live plot

Goal: Control the FPGA from Python on the cRIO over SSH, while DAQmx acquisition is driven entirely from a dev machine using the NI gRPC Device Server. Acquired data streams back to the dev machine and is displayed in a Matplotlib plot.

cRIO setup

  1. Deploy everything from PythonFPGAControl/source/cRIO Code/ to the cRIO (see Workflow 3 deploy command above).
  2. Start the NI gRPC Device Server on the cRIO:
ssh admin@<crio-hostname>
/home/admin/PythonFPGAControl/grpc-device-server

The server listens on port 31763 by default.

  1. In a second SSH session, start FPGA control:
python /home/admin/PythonFPGAControl/fpga_interface_sine-pwm.py

Dev machine: remote DAQmx acquisition with live plot

Install dependencies on the dev machine:

cd PythonFPGAControl/stubs
pip install poetry && poetry install
pip install matplotlib numpy

Run the gRPC client:

python PythonFPGAControl/analog-input.py [server_ip] [server_port] [physical_channel]

# Example:
python PythonFPGAControl/analog-input.py crio-9049 31763 Mod1/ai0

The client creates a finite analog input task on the cRIO (1000 samples at 1 kS/s), reads the data over gRPC, and displays it in a Matplotlib window — all without NI-DAQmx installed on the dev machine.


Requirements

Dev machine

  • Python 3.9–3.11 (<3.12 required by gRPC stubs package)
  • nidaqmx — NI-DAQmx Python API (Workflow 1 dev/simulation only)
  • grpcio >= 1.49.1, numpy, matplotlib — Workflow 4 gRPC client
  • NI MAX — for creating simulated cDAQ chassis (Workflow 1)
  • LabVIEW with FPGA module — for building/deploying .lvbitx bitfiles and running interactive VI (Workflow 2)

cRIO (Linux RT)

  • nidaqmx — NI-DAQmx Python API
  • nifpga — NI FPGA Python API
  • termchart — terminal plotting (required by ai.py only)
  • NI cRIO runtime and NI-DAQmx support installed via NI Package Manager

Install gRPC stub dependencies on the dev machine:

cd PythonFPGAControl/stubs
pip install poetry
poetry install

NI environment setup

  • NI MAX (dev machine): create a simulated cDAQ chassis with an NI 9220 in Slot 1 to develop and test Workflow 1 without hardware.
  • NI-DAQmx: install on both the dev machine (Workflow 1) and the cRIO.
  • NI cRIO Linux RT runtime: install on the target device.
  • LabVIEW FPGA module: required to build and deploy .lvbitx bitfiles and to run the interactive VI in Workflow 2.
  • cRIO shell encoding: copy .bashrc from the repo root to /home/admin/ on the cRIO to set LANG=C.UTF-8 and avoid encoding issues in the Linux RT shell.

Hardware channel reference

Script Where it runs Default channel How to adjust
ni9220acquisition.py (repo root) Dev machine NIcDAQ-9177/Mod1/ai0 physical_channel variable
source/cRIO Code/ni9220acquisition.py cRIO Mod1/ai0 physical_channel variable
source/cRIO Code/ai.py cRIO Mod1/ai0 add_ai_voltage_chan() call
PythonFPGAControl/analog-input.py Dev machine Mod1/ai0 PHYSICAL_CHANNEL constant or CLI arg
FPGA scripts cRIO RIO0 fpgaTarget variable

Notes

  • FPGA scripts hardcode the bitfile path /home/admin/PythonFPGAControl/<bitfile>.lvbitx. Update bitfilePath in the script if your cRIO deploy path differs.
  • Workflows 2 and 3 are mutually exclusive per FPGA session: only one process can hold the FPGA open at a time. LabVIEW (Workflow 2) and nifpga (Workflow 3) cannot both control the FPGA simultaneously.
  • The Workflow 4 gRPC client uses a finite acquisition (1000 samples). Increase samps_per_chan and num_samps_per_chan in analog-input.py for longer captures.
  • Available compiled bitfiles are in PythonFPGAControl/source/LabVIEW Project/FPGA Bitfiles/. The sine-pwm demo uses sine-pwm.lvbitx in source/cRIO Code/.

About

NI cRIO Python development workflows: DAQmx simulation, LabVIEW FPGA, nifpga, and remote gRPC acquisition

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors