System designHow-to

Load a recipe table into a custom vision UI without dependency errors

Load a recipe table into a custom vision UI without dependency errors: flatten it to a string in a Run LabVIEW step, or call a helper VI that reads it.

LumaSpec Vision9 min read Share on LinkedIn

On this page 9 sections
  1. 01Why the import refuses the custom UI
  2. 02Choose the route
  3. 03Route 1: pass the table as a flattened string
  4. 04Route 2: dynamically call a helper VI
  5. 05Worked example: sizing the string for a 12 x 8 recipe table
  6. 06Deploy without the path trap
  7. 07When the custom UI is the wrong tool
  8. 08Checks before you ship
  9. 09Questions

A custom operator screen for your inspection keeps failing to import: the environment rejects a user interface VI that carries subVI dependencies, and the recipe-table reader you wired into it is exactly that. The fix is a wiring change, not a setting. You stop linking the file reader statically and move the read to run time, either as a flattened string handed over by an inspection step or as a dynamically called helper VI. This guide shows both wirings, works the numbers that prove the table itself is never the problem, and lists the checks that keep the fix alive on the deployed machine.

Why the import refuses the custom UI

An inspection environment that hosts a custom UI treats that VI as a unit it must deploy on its own. Every subVI statically linked into the UI is a dependency the environment would have to carry and manage, so it refuses the import instead. A UI that reads a recipe file links file-I/O subVIs, and the import stops with a dependency error the moment you add one.

The way out is to keep the UI's statically linked list empty by reading the file somewhere else: inside the inspection, which hands the UI a string, or inside a helper VI that the UI loads at run time through VI Server, whose primitives do not register as dependencies.

One boundary first: if the recipes already exist inside the inspection and you only need to pick between them, none of this is needed. Switching recipes from operator buttons and RS232 selection with one command code per recipe work without touching the dependency question. What follows is for recipes that live outside the inspection, in a file your own interface owns.

Choose the route

String from a Run LabVIEW step Dynamically called helper VI
Where the file is read Inside the inspection Inside the helper VI, loaded by the UI
How the data crosses Flattened string, unflattened in the UI Native 2D array across the connector pane
Relative speed Slower: step launch overhead plus flatten and unflatten Faster: one call, native types
What deployment demands Nothing beyond the inspection itself The helper VI at a known path on the target

Decide on one question: can you guarantee the helper VI sits at a known path on the deployed machine? If yes, take the dynamic call. It skips the run-step launch overhead and the flatten/unflatten round trip, and the UI receives native data types instead of a string it must rebuild. If the target machine is imaged by someone else, or software rollouts ignore your file layout, take the string route and keep the whole read inside the inspection.

Route 1: pass the table as a flattened string

  1. In a Run LabVIEW step, read the recipe file into a 2D array of strings.
  2. Flatten that array to a string inside the same step and return the string as a step output.
  3. Map the string to a variable the inspection passes to the custom UI.
  4. In the custom UI, unflatten the string back into the 2D array and wire it to the table indicator.
  5. Re-import the inspection. The UI still contains no subVIs of its own, so the dependency check passes.

The flatten and unflatten operations must use the same data type on both sides. A mismatch does not throw an error; it hands you an empty or scrambled table, which is worse. The test is direct: write a table with values you know, 12.5 in one corner cell and 0.25 in the opposite one, then compare cell by cell after the round trip.

Route 2: dynamically call a helper VI

The UI loads a helper VI that reads the file and returns the data in its native form. The load runs through VI Server primitives, which the importer does not count as subVI dependencies, and that is the entire trick. It is also the faster route: no run-step launch each cycle and no flatten/unflatten detour.

  1. Build the helper VI; call it ReadRecipeTable.vi, a name chosen here, not one that matters to the tools. It reads the recipe file, returns the table as a 2D array of strings on its connector pane, and carries an error in/error out pair.
  2. In the custom UI's block diagram, set the path to the helper VI. Hard-coding it works; wiring it from a control lets commissioning repoint it without an edit.
  3. Use the Is First Call? primitive to open the VI reference exactly once.
  4. Keep the reference alive in the shift register of a while loop that only runs once.
  5. Call the helper through a Call By Reference Node. Its connector pane must match the helper exactly; a mismatch throws at run time, not at import.
  6. Close the reference in the UI's cleanup state, so a stopped run leaves no open reference behind.

The open-reference-and-call pattern is the same one behind calling a camera SDK DLL from LabVIEW. Once the UI holds the table it can start the inspection automatically from your custom program, and later push live exposure or gain changes with the runtime camera parameter control pattern.

Worked example: sizing the string for a 12 x 8 recipe table

The inputs, illustrative of a typical line: 12 recipes as rows, 8 parameters as columns — exposure, gain, threshold, upper and lower limits and the like. The longest cell formats to 10 characters, for example 12345.6789. A comma separates cells, 1 byte, and each row ends with carriage return and line feed, 2 bytes.

size ≈ rows × columns × (longest cell + 1) + rows × line end

The arithmetic:

  • 12 × 8 = 96 cells
  • 96 × (10 + 1) = 1,056 bytes
  • 12 × 2 = 24 bytes
  • 1,056 + 24 = 1,080 bytes, about 1.1 KB

The count assumes a comma after every cell, so it runs about 12 bytes high, which is the safe direction for a size estimate. Doubling both dimensions gives 24 × 16 = 384 cells, so 384 × 11 = 4,224 bytes plus 24 × 2 = 48 bytes: 4,272 bytes, about 4.3 KB.

The decision follows directly. A table in the low kilobytes moves in milliseconds on any PC-class controller, so data size never chooses between the two routes. The choosing question stays the deployment one: helper VI at a guaranteed path on the target means take the dynamic call; no guaranteed path means take the flattened string.

Deploy without the path trap

A path hard-coded on the bench must exist at the same absolute path on the deployed system, unless the UI takes the path as an input or builds it at run time from the location of the UI itself. Building the path relative to the UI is the sturdier option: drive letters change between bench and line, folder names rarely do.

When the call fails at run time, it fails at the Call By Reference Node, and two causes cover nearly every case: the path does not exist on that machine, or the connector pane does not match the helper VI. Check that the file exists at the configured path before opening the reference, and the error message names the real problem.

The acceptance test for the whole fix: remove the static calls, re-import the inspection, and confirm the import reports zero unresolved dependency warnings. Run one cycle and check the table shows the file's current values, not defaults left from an earlier version. If the custom UI also triggers runs, sequence the handshake so the inspection waits for the UI; the ready-gate failure that drops the first images is a separate stumble with its own fix.

When the custom UI is the wrong tool

A custom UI earns its keep when operators pick from a table you maintain, when you need controls the standard screen lacks, or when one screen drives several cameras. If the standard operator interface covers the job, skip the build. And if one camera and a short recipe list cover the part, a vision sensor holds the recipes on the device and the dependency question never comes up:

Smart cameras & vision sensorsHikrobot MV-SC3050XC-16M-ATN-H 5 MP color vision sensorMV-SC3050XC-16M-ATN-H
Interface
Fast Ethernet
Resolution
5 MP
Sensor format
1/1.45"
Shutter
Global
$1,809.00View part

When you do need the UI, a vision controller is the platform. The models below cover the range from a compact single-camera cell to a multi-camera line:

Vision controllersHikrobot MV-VC2140-128G40-1T VC2100 Vision Controller, N97, 8GB+128G SSD+ 1THDDMV-VC2140-128G40-1T
LAN ports
3-4 LAN ports
USB 3 ports
2 USB 3 ports
$1,679.00View part
Vision controllersHikrobot MV-VC3301H-128G66 I3-8100, 8GB+128G SSD, No PoE, PCIe expansion supported, Incl. VM6200Pro licenseMV-VC3301H-128G66
LAN ports
5+ LAN ports
USB 3 ports
3-4 USB 3 ports
$2,419.00View part
Vision controllersHikrobot MV-VC5525-256G70-NN VC5000 Vision Controller, 12th-I5, 32GB+256G SSD, Supported PCIEMV-VC5525-256G70-NN
LAN ports
5+ LAN ports
USB 3 ports
3-4 USB 3 ports
$4,479.00 · quotedView and quote

The MV-VC3301H-128G66 includes the VM6200Pro inspection software license, and the MV-VC5525-256G70-NN adds PoE camera ports and 8 built-in light channels. Browse the vision controllers to pick the port count and memory that fit, and hand results to a host application as data, not images, following smart camera LabVIEW integration. For sensors and mounts, the smart cameras page is the entry point.

Checks before you ship

Run this list after wiring either route, then again on the deployed machine:

  • Re-import the inspection with the UI in place; the import must report zero unresolved dependency warnings.
  • Load a table with known corner values and compare cell by cell after the round trip.
  • Edit one cell in the recipe file, retrigger the load, and confirm the new value appears; this proves the read is live, not a cached copy.
  • Rename the recipe file once and confirm the UI reports a clear file error instead of showing an empty table.
  • On the deployed machine, resolve the helper VI path, configured or dynamic, and run one full cycle.
  • Keep the flatten and unflatten data types identical on both sides, pinned in version control with the helper VI.

A check that fails points at the wiring, not at the recipe idea. More integration patterns sit on the systems topic page.

Questions

Why does the inspection reject a custom UI that only reads one file?

The importer requires the custom user interface VI to deploy as a self-contained unit, so every statically linked subVI counts as a dependency it has to refuse. A file reader drags file-I/O subVIs into that list and the import stops. Moving the read to run time, as a flattened string or a dynamically called helper VI, keeps the statically linked list empty and the import passes.

Is the dynamically called helper VI faster than the Run LabVIEW step route?

Yes, for two structural reasons: the UI skips launching a separate step on each load, and it skips the flatten and unflatten round trip, receiving native data across the connector pane instead. For a table in the low kilobytes both routes finish well inside a typical inspection cycle, so the difference only becomes measurable at high trigger rates or with very large tables.

Where must the helper VI sit on the deployed machine?

At the same absolute path as on the development machine, unless the custom UI takes the path as an input or builds it at run time from its own location. The relative approach survives drive-letter changes between bench and line. Whichever you choose, run one full inspection cycle on the deployed machine before sign-off, because a missing path fails only there.

Can the custom UI write edited recipe values back to the file?

Yes, with the same pattern: give the helper VI a second mode that saves the edited table when the operator confirms, and keep the file format fixed so the inspection reads it unchanged. Ini files are a related format worth checking in your release notes, since storing recipes as ini variables was the planned direction for newer service releases.

How large can the recipe table grow before the string route breaks down?

Apply the sizing rule: rows times columns times the longest cell plus one separator, plus one line end per row. A 12 by 8 table of 10-character cells is about 1.1 KB and a 24 by 16 table about 4.3 KB. Even tables in the hundreds of kilobytes transfer in milliseconds on a PC-class controller, so growth rarely forces the choice; the helper VI's deployment path decides first.