08-26-2026 10:53 PM
Background
I'm an intern with about one month of LabVIEW experience and I've been handed a relay test project on my own, so I'm learning as I go. Apologies in advance if some of this is basic — I'd rather ask than keep guessing.
Hardware: ADLINK PCIe-7396, 12 ports × 8 channels, driving relays. LabVIEW version: [fill in — e.g. 2019 32-bit] Driver: ADL7396— ADLINK DAQ version]
What the VI does
Single VI, tab control with two pages:
Tab 1 – Operator Dashboard: port selector (0–11), DI/DO direction, an 8-box boolean control array that writes to the selected port, and 12 read-back indicator arrays.
Tab 2 – Engineer Settings: card identity, error display, write/read counters, and a sequential LED walk test.
Channel names are stored in a tab-separated text file, 12 rows × 8 columns, where the row number is the port number. Selecting a different port should load that row's names into the display.
Problem 1 — File dialog appears every time I save port names
When the operator edits a channel name, my save code runs and LabVIEW pops the "save as" dialog asking where to put PortNames.txt, every single time. I want it to write silently to a fixed location next to the VI.
I build the path with Current VI's Path → Strip Path → Build Path, wrapped in a small subVI. Is the dialog appearing because the path isn't reaching the write VI's file path input, or is there something else that triggers it? And is putting the file next to the VI the right approach, or should this live somewhere else once the app is built into an EXE?
Problem 2 — Reading the file back when the port selection changes
I'd like the channel names to reload from the text file whenever the port number changes. Right now I write to the file but I'm not confident about the read-back path, and I sometimes end up with blank rows or an off-by-one row.
Is Read Delimited Spreadsheet → Index Array (row = port number) the normal way to do this, or is there a better pattern for small per-port config like this? Would a config INI file or a TDMS file be a more appropriate choice than a plain text file?
Problem 3 — Counting successful vs failed writes
I want a running count of successful and failed writes and reads, shown on the engineer tab, so I can tell whether my code is actually reaching the card. My understanding is: take the error cluster out of the Digital Output VI, unbundle the status boolean, invert it, convert to 0/1, and accumulate in a shift register.
Does that hold up in practice? Some driver calls seem to return no error even when nothing physically moves, so I'm not sure an error-free call really proves a successful write. Is there a more reliable success criterion — reading the port back and comparing to what was commanded, for example?
Problem 4 — Serial number entry without a barcode scanner
I was considering a barcode scanner for unit serial numbers, but I may not get one. For manual entry, what do people use to stop typos — a format mask, Match Pattern validation, a checksum on the serial itself? I'd like the logged serial to be trustworthy since it's the only link between a test result and a physical unit.
Problem 5 — General design review
Broader questions from someone still finding their footing:
My code is currently one large block diagram with several sections side by side. At what point should this be split into subVIs, and what's a sensible way to divide it?
For a tab-based operator/engineer split, is an event structure with a single While loop the standard approach, or should the two tabs run as separate parallel loops?
I have hardcoded channel constants in a few places that pin operations to one port regardless of the selector. What's the usual way to make the channel follow a front-panel control on ADLINK cards — a control wired in, or indexing a handle array?
Is there a recommended way to gate access to an engineer tab (password, key switch, page Disabled property)?
Problem 6 — Example code
Can anyone point me at a reference example of a simple hardware test panel that reads and writes a per-port configuration file? Something I can read through and learn the structure from would help more than another isolated snippet. NI Example Finder entries or community posts both welcome.
Thanks for any guidance. Happy to post screenshots of the block diagram if that helps — I know a description only goes so far.
Solved! Go to Solution.
08-27-2026 02:12 AM - edited 08-27-2026 02:14 AM
Hi Fine,
@FineSoFine wrote:
Problem 1 — File dialog appears every time I save port names
When the operator edits a channel name, my save code runs and LabVIEW pops the "save as" dialog asking where to put PortNames.txt, every single time. I want it to write silently to a fixed location next to the VI.
I build the path with Current VI's Path → Strip Path → Build Path, wrapped in a small subVI. Is the dialog appearing because the path isn't reaching the write VI's file path input, or is there something else that triggers it? And is putting the file next to the VI the right approach, or should this live somewhere else once the app is built into an EXE?
@FineSoFine wrote:
Problem 2 — Reading the file back when the port selection changes
I'd like the channel names to reload from the text file whenever the port number changes. Right now I write to the file but I'm not confident about the read-back path, and I sometimes end up with blank rows or an off-by-one row.
Is Read Delimited Spreadsheet → Index Array (row = port number) the normal way to do this, or is there a better pattern for small per-port config like this? Would a config INI file or a TDMS file be a more appropriate choice than a plain text file?
When it comes to "per port config" I would consider an INI file instead, using the port number/name as a section key…
@FineSoFine wrote:
Problem 3 — Counting successful vs failed writes
I want a running count of successful and failed writes and reads, shown on the engineer tab, so I can tell whether my code is actually reaching the card. My understanding is: take the error cluster out of the Digital Output VI, unbundle the status boolean, invert it, convert to 0/1, and accumulate in a shift register.
Does that hold up in practice? Some driver calls seem to return no error even when nothing physically moves, so I'm not sure an error-free call really proves a successful write. Is there a more reliable success criterion — reading the port back and comparing to what was commanded, for example?
Typically an "error-free call" should be good enough to signal a successful operation - depending on the quality of your device and driver…
@FineSoFine wrote:
Problem 4 — Serial number entry without a barcode scanner
I was considering a barcode scanner for unit serial numbers, but I may not get one. For manual entry, what do people use to stop typos — a format mask, Match Pattern validation, a checksum on the serial itself? I'd like the logged serial to be trustworthy since it's the only link between a test result and a physical unit.
@FineSoFine wrote:
Problem 5 — General design review
Broader questions from someone still finding their footing:
My code is currently one large block diagram with several sections side by side. At what point should this be split into subVIs, and what's a sensible way to divide it?
For a tab-based operator/engineer split, is an event structure with a single While loop the standard approach, or should the two tabs run as separate parallel loops?
I have hardcoded channel constants in a few places that pin operations to one port regardless of the selector. What's the usual way to make the channel follow a front-panel control on ADLINK cards — a control wired in, or indexing a handle array?
Is there a recommended way to gate access to an engineer tab (password, key switch, page Disabled property)?
The shown block diagram is just bad:
Tab containers are just containers in the front panel: why do you think you need separate loops in the block diagram to handle their content???
I would place the whole code into scrap and start over with a simple state machine! There are "init states", "operating states", "UI handling states"… (All you need is a large while loop with one case structure inside.)
To gate access you typically ask for passwords. When the correct password is given you can enable controls or show the "engineering" tab…
(We prefer some hardware on our production machines using RFID keys with some data items stored in the key.)
08-27-2026 02:21 AM
Thank You, For Replying my inquiries GerdW