PhloemDocs
Markdown
Connector

NI-DAQmx

Stream and drive NI-DAQmx inputs and outputs

Category
Data acquisition
Kind
source
Capabilities
StreamsAssetsCommandsOperationsEntities
Runs on
Linux x64Windows x64

Read analog inputs, counters and digital lines, and drive analog and digital outputs, on National Instruments DAQ hardware. It uses the NI-DAQmx driver already installed on the machine the board is plugged into.

What you get

  • Analog inputs — the channels you tick, at the rate you set, on paths like /nidaqmx/Dev1/ai0.
  • Sensors, not just volts — thermocouples, RTDs, thermistors, 4-20 mA loops, resistance and strain gauges. The board converts them, so readings arrive in degrees, amps or ohms.
  • Accelerometers, microphones, load cells and 4-20 mA out — IEPE inputs, bridge inputs in mV/V, current output for a valve, and analog triggering on a level or a band. These have never been run against an instrument. Read IEPE, bridge and 4-20 mA out — what has been proven below before relying on one.
  • Your own unit in the board — ai0=linear:12.5,3.0 -> psi makes NI-DAQmx convert the channel and report psi to every NI tool on the machine. Usually Calibration is the better choice; see Turning a reading into engineering units.
  • Outputs — analog and digital, set from Trellis via ch.write(path, value). Every write is recorded.
  • Whole digital ports — port0 = 0xA5A5 sets sixteen lines in one clock tick, on any port. A single line is still true/false.
  • Patterns, ramps and pulse trains timed by the board — the board steps through digital states, ramps an analog output (a smooth line, not a staircase), or puts a square wave on a counter pin for a valve, stepper or motor.
  • One range per output — ao0 can be ±10 V while ao1 is 0–5 V.
  • Counters — frequency, period, pulse width, edge counts and quadrature encoders, on the same clock as the analog inputs.
  • Digital inputs — a whole port as one number, or lines as 0/1: clocked with the analog inputs, polled, or read the moment a line changes.
  • Captures around an event — external sample clock, start trigger, reference trigger (keeps data from before the event), pause trigger, and finite captures of exactly N samples.
  • A hardware dead-man — if Phloem stops answering, the board drives the digital outputs you name to the states you name. See The hardware dead-man.
  • Self-test and reset — see Is it alive, and making it behave. Reset is the most destructive thing this connector can do.
  • One board per input, named by NI's Device name (Dev1). A second board is a second input.
  • The whole board in one table — analog inputs, counters, ports and lines are rows, each with the unit it will arrive in.
  • What the board is — model, connection, serial, channel counts, input ranges, what its inputs can measure and how they couple, what its outputs can drive. All read from the board, and used to check every setting.

Setup

  1. Install the NI-DAQmx runtime and connect the board. Phloem detects an NI USB DAQ and offers a draft (device name Dev1 by default).

  2. Open the connector. Everything this machine has is already on the page: a card per chassis or board, a row per filled slot, and its channels.

    • Each cDAQ module shows as you would describe it: slot 2 NI 9203 current ±20 mA 8 AI.
    • The slot is the one the chassis itself reports now, through NI System Configuration. It is never the digit in the module's name. NI names a module <chassis>Mod<N> from the slot it was first seen in, and keeps that name if the card moves. So …Mod5 in slot 3 shows slot 3, with a note on how to update NI-DAQmx's record (Reserve Chassis or Self-Test on the chassis in NI MAX). Channel paths do not change.
    • A module NI MAX knows but the chassis does not see keeps its old slot, with a note.
    • A module the chassis sees but NI-DAQmx has no device for yet shows in its slot with a note: it cannot stream until NI MAX re-detects the chassis.
    • Without NI System Configuration (no NI MAX, or Linux), the slot is NI-DAQmx's record, and the page says so. If neither knows, it shows slot —.
    • Slots start closed. A slot with a ticked channel opens itself. Default board picks the board for an unqualified channel.
  3. Set the rate on the hardware row: a level (Slow, Medium, Fast) on each module's slot line. See Rate levels. The page shows the allowed range, and the measured rate once running.

  4. Click a channel to set it up. Every analog input is listed, one line each: channel, name, live value, and setup. An unset channel reads Not configured; three or more in a row fold into one line.

    The channel dialog asks what the channel Measures (Force), then which Sensor reads it (a bridge). It offers only what that module can do, so a 9203 offers current only. Your choice fills a typical setup you can see and change: a bridge at quarter / 2.5 V with 2 mV/V, a 4-20 mA loop as two points, a thermocouple as type K with the module's cold junction.

    • General — name, unit, signal range, the live reading through the calibration you are typing, and Same setup on to copy it to nearby channels.
    • Calibration — Linear, Sensitivity, Two point or Table, an offset with Zero (the settled reading becomes the offset), and a label. More… opens the full editor for a polynomial, a software thermocouple curve or a formula.
    • Electrical — the hardware range, this sensor's settings, and a bridge's Null and Shunt calibration.

    Apply puts the settings into the input (saved with Save) and writes the calibration at once as a new record; the old one stays in History. On a new input, the calibration is written when you add the input. Cancel leaves nothing behind. Clear channel stops acquiring it.

  5. Tick counters and digital lines on their own rows. Every channel setting is also written out in the Sensor / wiring field below.

  6. Press Test connection. It names the board and reads every ticked channel as configured. Save, and the channels appear on Live.

Rate levels

Each chassis module runs at a level — Slow, Medium or Fast — as in FlexLogger. Rate levels sets the hertz behind each: 1 Hz, 100 Hz and 1 kHz unless you change them. A module starts at the level its kind suits (a temperature card Slow, a bridge card Fast). Changing a level's hertz moves every module on it.

A level is one clock. The three levels are the three analog-input timing engines of a Gen II chassis, so levels cannot ask for a fourth rate.

A module that cannot run at its level's hertz shows its real rate beside the level — Medium · runs at 1.65 kS/s, its floor:

  • A delta-sigma card below its floor (a 9234 or 9237 will not sample below about 1.6 kS/s) runs AT its floor. So does every module on that level, because the level is one clock. FlexLogger does the same. The others read Fast · runs at 1.61 kS/s, Mod8's floor. Every reading is real; nothing is repeated. This does not use an extra rate.
  • A slow card above its ceiling (a 9210 or 9219 on a faster level) runs in a task of its own at its ceiling — Fast · runs at 14.29 S/s, its ceiling. This avoids repeated readings, but it uses an engine and counts as a rate.
  • All delta-sigma modules in an input share one task. A 9234 on Medium beside a 9237 on Fast runs in Fast's task: Medium · runs at 1.65 kS/s, Mod8's floor.

Inputs saved with a rate in hertz (from older versions) keep running at the same rates. The connector finds levels that reproduce them and shows the equivalent level settings, which are saved when you open the setup. If no levels can reproduce them, the fixes offered name every module whose rate would change, and none is applied without your click. Before any update, the app compares per-channel rates; if any would change, the update is held and the dialog lists each module's before → after.

In the fields: rate_levels = slow=1; medium=100; fast=1000, rate_hz = fast, rates = cDAQ1Mod5=slow; cDAQ1Mod8=fast.

A module with no ticked channels keeps its level in rates (cDAQSpaceMod7=medium), as FlexLogger does, so it comes back at that level when you tick a channel again. While unticked it is ignored.

If a module cannot run at the rate you set

Modules sample differently. A scanned card (9221, 9203) takes almost any rate. A delta-sigma card (9237, 9234) will not go below about 1.6 kS/s. A slow card (9210, 9219) will not go above a few tens of samples per second. The connector opens one task per level in use, plus one for a slow card pushed past its ceiling. All are clocked from the chassis backplane, so nothing drifts, and no reading is duplicated.

The slot row shows each module's real rate. That is information, not a warning. A level on a board that is not in a chassis is refused; a standalone board runs at the input's rate.

A chassis has a fixed number of analog-input timing engines: three on a Gen II chassis such as the cDAQ-9178 or cDAQ-9189, one on a cDAQ-9171/9181/9191. Each engine runs one rate. If the modules need more rates than the chassis has engines, the input is refused in setup, in Test connection and at the run:

cDAQ1 has 3 AI timing engines, one sample rate each; 4 rates asked: 1.61 kS/s (cDAQ1Mod8 (the least it samples)), 200 S/s (cDAQ1Mod1), 1 S/s (cDAQ1Mod5), 14.29 S/s (cDAQ1Mod2 (the most it samples)) — set two modules to the same rate.

(Slow, Medium and Fast in use, a 9237 on Fast, and a 9210 on Fast pushed to its ceiling as the fourth.)

The setup shows this as one notice in the chassis card, with up to two fixes as buttons. Each fix moves ONE module onto a level another module already uses, and is offered only if no other module's rate changes. Save is held until it is resolved ("Resolve the conflict above"). Only modules with ticked channels count.

Slower rates are never merged down to fit. A second input does not help: the engines belong to the chassis.

Compared with FlexLogger

FlexLoggerthis connector
AI rate per chassis3 levels (Slow/Medium/Fast), one value eachsame — rate_levels, per input
assigned tothe module's AI subsystemthe module (rates), set on its slot row
delta-sigma below its floorruns at the floor; the whole level at the "lowest common rate"same
shownthe module's "actual rate" beside its levelMedium · runs at 1.65 kS/s, its floor
slow card above its levelnot documenteda task of its own at its ceiling, counted as a rate
a module's rate in hertznot possiblerefused, converted to levels when it can be
delta-sigma modules on two levelsallowedone task, at the higher need
Counter / Digital levelsown levelsnone: counters and clocked lines use the main AI task's clock
downsampling (100 Hz from a delta-sigma card)software, by defaultnone: the card's own rate, recorded as is, shown on the row
unticked module's levelkeptkept, ignored
channels a new input recordsthe ones enabledthe ones ticked; nothing ticked is refused at Start
a module in use elsewhereIn use by {0}cDAQSpaceMod2 is in use by another program — FlexLogger or a script; stop it there
an open thermocouple's readinglogged as read (−176 427 °C)stored as read; the row says Open thermocouple?
channel namesthe physical channel, cDAQSpaceMod8/ai0a new input: every board under the Label, engineA/cDAQSpaceMod1/ai0; an existing input keeps its paths

Notes on the differences:

  • A slow card past its ceiling gets its own task. Sharing a task with faster modules would repeat its readings.
  • Delta-sigma modules share one task. Two would need a shared sync pulse the connector does not route yet.
  • No Counter or Digital levels. Counters and clocked lines follow the main AI task's clock, so they share one timeline.
  • No software downsampling. Phloem records what the card converted, at the rate it converted it.
  • Channel names: an existing input keeps its paths, because calibration, layouts and history are keyed by them. Moving to the new naming is a rename you choose.
  • The simulated 9210 runs about 1 % fast, in FlexLogger too. That is the simulator's clock; a real chassis shares one timebase.
  • After a restart, Phloem keeps one timeline per channel. The stop shows as a gap, and any overlap with the previous run's end is marked.

A TDMS export of these channels carries the properties FlexLogger's log carries: root and group properties (a channel-less Test Information group, then Log), channel statistics (minimum, maximum, NI_ChannelValueAverage, novaluekey, monotony), sensor scale, device and chassis ids, terminal configuration, and the range and channel type in the unit the channel is logged in. The differences:

PropertyFlexLoggerPhloem
root Date Createdlog startwhen the export was written (datetime is the window start)
RunNumber1not written
unit_string°C as one CP-1252 byte°C in UTF-8
wf_samplesthe first chunk's countthe channel's total
monotonynot monotonenot monotone only when readings rose and fell; else none
polynomial scale—no NI_SensorScale and no range
NI_TerminalConfigurationDifferentialthe chosen wiring, or the only one offered; none if left at default with several

Settings checked like FlexLogger

  • Setup and Test connection check the same tasks the run uses. A setting the driver refuses is shown in the form's words, such as SimBr9237 sets one excitation for all its channels — ai0 5 V; ai1 2.5 V — choose one for every channel. The same goes for a filter that differs between a module's channels or is too slow for the rate. A module in use by a running input is not checked.
  • Excitation is a list from the module. For internal excitation you pick from the module's own values (9237: 2.5/3.3/5/10 V; 9234: 0/2 mA; 9219: 0/2.5/5 V and 0/0.5 mA). A value off the list is refused (ai0: SimBr9237 drives 2.5 V, 3.3 V, 5 V or 10 V — 4 V is not one of them). An unset IEPE current is the module's own (2 mA on a 9234). The row and the export show the excitation the board will actually give. External supplies take a number.
  • Slow inputs can be tested. The check waits two sample periods, at least 5 s. Past its time budget it says what it is still reading (Still reading ai0 on SimUn9219, one sample every 20 s (8 s so far)), and the next check gets the answer. The rate field takes hertz only.
  • A standalone board past its limit is shown while you edit, with a fix: SimUn9219 samples at most 100 S/s — 1 kS/s is outside it, with Sample at 100 S/s. It is never changed silently.
  • Filter Auto — adc=auto picks the highest-resolution filter valid at your rate (High resolution, Best 50 Hz, Best 60 Hz, High speed), for every channel of the module. The row shows which it chose.
  • Temperature units, custom RTDs, types A and C. units=degC|degF|K on a thermocouple, RTD or thermistor sets the readings, range and unit (type K in °F: −328 to 2501.6). type=custom,a=,b=,c= on an RTD sets custom Callendar–Van Dusen coefficients. Thermocouple types A (100–2480 °C) and C (0–2315 °C) are supported. A constant cold junction is still written in °C. The cold junction can be the module's sensor, a constant, or another channel.

How tasks start

Counters and clocked digital lines follow the main task's clock (the task at the rate you typed). On a chassis, the connector reserves that task first, learns which timing engine it got, arms the other tasks on it, and starts the main task last, as NI documents. An external clock, reference trigger or pause trigger cannot be shared across several rates, so an input that needs several rates and sets one is refused.

On a chassis that is not time-aware (cDAQ-9171/9174/9178), a delta-sigma module runs on its own oscillator and can drift slightly over a long run; the connector says so when it happens. A cDAQ-9185/9189 supplies that clock itself. Delta-sigma modules run together at the highest rate any of them needs: a 9234 and a 9237 set to 1 kHz and 100 Hz both run at 1.65 kS/s, and each row says why.

A finite capture is a duration: n samples at the rate in the box. A slower task takes proportionally fewer samples, so every task covers the same span.

What is wired to each input

An unticked channel is not configured, so it shows no unit and no range.

A ticked channel with nothing stated is read as what its module measures: a current card in amps, a thermocouple card in °C, a voltage front end in volts. The setup table marks it implied. Saving from the setup writes the measurement into this field, so later versions read it the same way.

The choices offered are what the module physically measures, from the ranges it reports. A module with no current range is not offered current; one with no bridge range is not offered strain; a thermocouple needs a millivolt-scale range. (NI-DAQmx also lists current, RTD and strain for a ±60 V NI 9221 and a ±80 mV NI 9210, which need extra hardware. Phloem offers only what the module does on its own.)

Choosing a bridge or strain measurement fills in the common wiring, a quarter bridge at 2.5 V excitation, where you can see and change it.

State something only when the board cannot know it: a channel wired as something other than its module's default, the thermocouple type, how an input is referenced, what is on a bridge. The channel dialog is the short way. Its Sensor offers only what the module can do. Its Electrical column shows that sensor's settings and holds Apply until required ones are filled. Wiring offers only what the channel's front end reports; coupling only what the module can do. Apply writes the channel's whole entry into this field as key=value pairs.

The field is a list separated by semicolons. An entry with no channel name applies to every channel; an entry starting ai3= applies to that channel only.

voltage,term=diff
ai0=thermocouple,type=K,cjc=builtin
ai1=current,shunt=internal
ai2=rtd,wires=4,excit=0.001

How the input is referenced — term= — matters most, for voltage and current inputs:

term=what it means
defaultlet the board choose (what happens if you say nothing)
diffdifferential — two wires, neither tied to ground. The safe choice for anything floating: a battery, a thermocouple, a sensor with its own supply
rsesingle-ended, measured against the board's own ground
nrsesingle-ended, measured against the board's sense terminal
pseudodiffdifferential with a small path to ground, on boards that offer it

A floating source read single-ended drifts until the reading pins to the top or bottom of the range. It is the most common reason a correctly wired sensor reads nonsense.

The sensors, and what each needs. Anything about your bench rather than the board must be stated. No default could be right.

SensorWriteMust stateDefaults
voltagevoltage,term=diff—the Input range select; empty = the module's own widest range (NI 9221 ±60 V, USB-6421 ±10 V)
currentcurrent,shunt=internal—±20 mA; shunt=default|internal|external, shunt_ohms=249
thermocouplethermocouple,type=K,cjc=builtincjc_val= if cjc=const; cjc_chan= if cjc=chantype K, cold junction from the terminal block, the type's own span (K −200 … 1372 °C, J −210 … 1200 °C, T −200 … 400 °C)
rtdrtd,wires=4,excit=0.001wires=, excit= (amps)Pt3851, 100 Ω at 0 °C, −200–660 °C
thermistorthermistor,excit=0.0001,a=…,b=…,c=…the excitation, and a/b/c from the datasheet4-wire, 0–100 °C
resistanceresistance,wires=4,excit=0.001wires=, excit= (amps)0–1000 Ω
strainstrain,bridge=quarter1,excit_v=2.5bridge=, excit_v= (volts)gauge factor 2.0, 350 Ω, Poisson 0.30, ±1000 µε
builtin_tempbuiltin_temp—the board's own temperature, 0–100 °C
accel ¹accel,sens=100sens= (mV/g, off the sensor)±5 g, internal 4 mA excitation, AC coupled, sens_units=mv/g, units=g
microphone ¹microphone,sens=50sens= (mV/Pa, off the microphone)100 dB SPL, internal 4 mA excitation, AC coupled
bridge ¹bridge,bridge=full,excit_v=2.5bridge= (full/half/quarter), excit_v= (volts)350 Ω, the module's own bridge range (a 9237's ±25 mV/V; ±2 mV/V on a module that states none), units=mv/v; null_v=, gain_adjust= written by the calibration buttons
freq_voltage ¹freq_voltage,threshold=1.5,hysteresis=0.2threshold= (volts), hysteresis= (volts)1 Hz – 100 kHz
lvdt ¹lvdt,sens=50,excit_v=1sens= (sens_units=mv/v/mm|mv/v/mil), excit_v= (volts)±0.1 m, units=m|in (a non-default unit needs min=/max=), 2.5 kHz excitation, wires=4|5
rvdt ¹rvdt,sens=2,excit_v=1sens= (sens_units=mv/v/deg|mv/v/rad), excit_v= (volts)±70°, units=deg|rad, 2.5 kHz excitation, wires=4|5
force_iepeforce_iepe,sens=10sens= (sens_units=mv/n|mv/lb)range = the module's volts ÷ sensitivity (10 mV/N on ±5 V is ±500 N), units=n|lb|kgf, internal 4 mA excitation, AC coupled
velocity_iepevelocity_iepe,sens=100sens= (sens_units=mv/mm/s|mv/in/s, off the sensor)range = the module's volts ÷ sensitivity, units=m/s|in/s, internal 4 mA excitation, AC coupled

¹ Never run on real hardware. See What has been proven, and what has not below before you rely on one.

Range. Add min= and max= in the sensor's own unit — thermocouple,type=K,min=-200,max=1372. The board picks the closest setting that contains it, so a wider range costs resolution and nothing else.

Thermistor range is different. The driver works out what your a/b/c and excitation can represent, and refuses anything outside, naming the bound. The 0–100 °C default suits every ordinary NTC. If it refuses a colder range, that number is the real limit of your part.

Frequency from an analog input. freq_voltage counts how often a signal crosses a voltage and reports hertz. Use it for a tacho coil, flow turbine or optical sensor whose output is not a clean logic edge. threshold= is the crossing level; hysteresis= is how far the signal must fall back before the next crossing counts. State both: zero hysteresis counts noise and reports a frequency several times too high. Its min=/max= are in hertz, not volts.

Accelerometers and microphones (IEPE). The board sends a small current up the sensor cable and reads the signal back on the same wires, with AC coupling removing the DC bias. So the board must support both. An NI-9234 is the usual choice. If the board cannot, you are told which board and what it supports, before anything is recorded.

You must enter the sensitivity printed on the sensor: "100 mV/g" is sens=100; a microphone's "50 mV/Pa" works the same. A wrong value gives readings off by a factor, in the right unit, so there is no default. Write sens_units=v/g for a sensor rated in volts per g. An accelerometer reports in g unless you write units=m/s2.

Bridges — load cells, pressure transducers, torque cells. A bridge channel gives the bridge's output ratio in mV/V, the unit on its datasheet. Turn that into newtons or bar with scaling (next section): a cell rated 2 mV/V at 500 kg is linear:250000,0 -> kg, or whatever your calibration certificate says. The driver's own force/pressure/torque bridge channels are not offered, so there is one place to look when a number is wrong.

State how many arms are active (bridge=quarter, half or full) and the excitation voltage, since both scale every reading. A strain channel uses a different vocabulary (bridge=quarter1), because it also names the gauge arrangement. Each refuses the other's words.

Nulling and shunt calibration. These match FlexLogger's Null offset and Shunt calibration buttons, and the row offers both for a bridge channel.

  • Null offset reads the unloaded bridge and stores the offset on the channel (null_v=…, in volts). It is subtracted from every later reading.
  • Shunt calibration switches a known resistor across one arm (shunt_ohms; a 9237's own is 100 kΩ, or one you wired), measures, and stores a gain correction (gain_adjust=…).
  • Both are saved in the channel's sensor entry, so they survive a restart. Delete the two words to clear them.
  • The null comes first. A shunt taken before the null stores a wrong gain. So a shunt with no stored null is refused, and the button reads Null, then run and does both. Keep the bridge unloaded for both. Pass without_null if your bridge needs no null.
  • A gain correction outside 0.5–1.5 (FlexLogger's window) means a wrong resistor value or arm, so it is refused.
  • On a simulated module, nulling works (the offset comes back near zero) and shunt calibration is refused by the driver.

Coupling. coupling=ac|dc|gnd on a voltage, accelerometer or microphone channel. IEPE channels are AC-coupled unless you say otherwise; everything else stays as the board has it. If the board cannot do it, you are told what it can do.

Cold junction. A thermocouple measures relative to where its wires land, so that point must be measured too. cjc=builtin uses the terminal block's own sensor and is right whenever the hardware has one. cjc=const,cjc_val=23.5 uses a fixed number. cjc=chan,cjc_chan=… reads another channel.

An open thermocouple is stored as it read. A broken or unplugged thermocouple floats to values like 2400 °C or −593 578 °C. The reading is kept exactly as the module gave it, as FlexLogger does. The setup row reads Open thermocouple?, and the log says which channel, once when it starts and once when it ends. Either check triggers it:

  • NI-DAQmx's open-thermocouple detection, on for every thermocouple whose module has it.
  • The type's own range (type K: −200 to 1372 °C). This covers modules without detection. NI's simulated 9210 refuses detection, so only this check runs there.

The board says what it cannot do before recording. A board that does not measure thermocouples is refused by name, with what it does measure. A board with no built-in excitation for an RTD or strain gauge is refused by the NI driver, naming the setting. Add excit_src=external and wire your own supply.

A setting that does not apply to the chosen sensor is refused, not ignored — for example term= on a thermocouple, where the board fixes the wiring.

Turning a reading into engineering units

There are four ways to turn volts into psi, newtons or degrees. Use the first one that applies.

1. Wire it as what it is. For a thermocouple, RTD, thermistor, 4-20 mA transmitter or strain gauge, say so in Sensor / wiring (above). The board converts it, at full rate, with a cold junction it can measure. This is the right answer more often than people expect.

2. Calibrate the channel. For everything else — a load cell's slope and offset, a pressure transducer's two-point fit, a bench correction — use the Calibration column of the channel's dialog (linked from Inputs). It opens on the identity line (slope 1, offset 0) in the board's unit. Press Zero to tare, or enter a slope, a sensitivity (the certificate's "2 mV/V at 5 kN"), two points or a table. A software thermocouple conversion is offered only for a channel that reads volts. Every save is recorded and versioned, and shows raw beside calibrated. It is the only way that keeps the raw number.

3. Let the driver scale it — Channel scaling (at source) with a unit. Write the transform and its unit:

ai0=linear:12.5,3.0 -> psi         # 12.5 x volts + 3.0, and the answer is psi
ai1=poly:0.0,4.2,-0.11 -> N        # 4.2 x V − 0.11 V², in newtons
ai2=linear:6250,-25 -> bar         # a 4-20 mA loop reading 0–100 bar

With a unit, Phloem hands the scale to NI-DAQmx as a custom scale. Choose this over (2) only for these reasons:

  • The board is set up in your unit. Any NI tool on the machine (NI MAX, FlexLogger) sees ai0 as psi.
  • The value is in engineering units before it leaves the board.
  • The board's input range is chosen for the quantity, so it picks the right gain for 0–100 psi rather than for ±10 V.

Without -> unit, the connector applies the same arithmetic after the read. That also happens on channels the driver cannot scale (thermocouple, RTD, thermistor, the board's temperature sensor). Either way it is exactly one conversion. Test connection shows which, per channel.

4. Do it downstream. A Trellis expression or a chart formula. Fine for a one-off, but it is not recorded with the channel.

When NOT to use the source scaling of (3)

Almost always. Compared with (2):

  • Calibration is refused on a channel scaled at source, since there is no raw reading to calibrate. Phloem says so.
  • The raw volts are gone.
  • It is not versioned. A change is a config edit, not a recorded calibration.
  • It is not a sensor type. For a K-type thermocouple, use (1). tc_k: is refused here, and the message says what to write instead.

Use (3) only when the unit itself must be true at the board: other NI tools read the same card, or the signal uses a small part of the board's span. Use Calibration for everything else.

Details worth knowing

  • The scale is registered with NI-DAQmx as phloem_<device>_<leaf>, such as phloem_Dev1_ai0, visible to other NI software. A scale you made in NI MAX with that exact name would be overwritten.
  • Input range stays in volts. Phloem converts it through the scale, so ±10 V stays ±10 V of input.
  • A polynomial must be invertible for the board to pick a range; NI fits the inverse over your input range. A curve that doubles back may land on a neighbouring gain setting.

What the board counts

Counters measure what volts cannot: shaft speed, stage travel, pulse width, time between a command and its confirm. Tick a counter (ctr0) in Channels and it streams beside the analog inputs.

A counter with no Counters entry counts rising edges. For anything else:

WriteMeasuresUnit
edge_countedges, cumulativelycounts
freq,min=10,max=100000frequencyHz
period,min=1e-4,max=1time between like edgess
pulse_width,edge=risinghow long one pulse was high (falling = low)s
two_edge_sep,first=…,second=…time from an edge on one wire to an edge on anothers
ang_encoder,ppr=1024shaft positiondeg (units=rad|ticks)
lin_encoder,dist=1e-5linear positionm (units=in|ticks)
  • An encoder must state its scale: ppr= pulses per revolution, or dist= metres per pulse. A wrong value still looks like degrees.
  • decoding= defaults to x4 (every edge of both channels). An X4 encoder read as x1 reports a quarter of the motion.
  • zidx=on resets the count on the index pulse, with zidx_val= and zidx_phase=.
  • Each counter uses its default terminal. input=/Dev1/PFI8 points it elsewhere. A two-edge separation takes first= and second=; an encoder takes a=, b= and z=.
  • semi_period is not available. It needs one sample per edge, which cannot share the analog clock. Use period and pulse_width.
  • A counter's unit follows what it measures: Hz, deg/rad, s, or counts.

Counters share the analog inputs' clock, so counter sample k and analog sample k are the same instant. An input with counters and no analog channels needs a clock: set Sample clock → source=/Dev1/PFI0, or add an analog channel. Otherwise it tells you.

What the digital lines say

Digital inputs answer yes or no: is the limit switch closed, did the confirm come back. Tick them in Channels, port first, then lines:

TickYou getPath
port0the whole port as one number — the integer its lines form/nidaqmx/Dev1/port0
port0/line3that one line, as 0 or 1 — shown as a state (on / off)/nidaqmx/Dev1/port0/line3
  • A line shows as a lamp in a Number view on Live and Replay. Everywhere else it stays 0 and 1. Give it a scale and it is a plain number.
  • A port stays one channel. Tick the lines you want, and each becomes its own channel.
  • You cannot mix ports and lines in one input. The connector names both and refuses.

How they are sampled

Digital lines are sampled — a select under Timing. The first choice suits almost everyone.

ChoiceWhat happensTimestamps
with the analog clock when there is one, else when askedclocked with the analog channels if there are any, polled if not
on the shared sample clock onlyinsists on the shared sample clock, and says so if there is nonethe board's
when asked, at the sample ratepolls the pins at the sample ratethis computer's
the moment a line changessamples the moment a line changesthis computer's, at the read
  • Clocked puts digital and analog samples at the same instant. Lines with no analog channels can still be clocked: set Sample clock → source=/Dev1/PFI0.
  • Change detection samples on a transition, for a switch that closes once an hour. Name the lines with rising=port0/line0:3 and falling=…, joining groups with + (rising=port0/line0:3+port0/line7). The default is every ticked line, both edges. A board without change detection is refused.
  • Polled and change-detection samples are stamped by this computer when they arrive. The order of transitions is the board's; sub-millisecond timing is not. So these cannot share an input with analog channels or counters. Give the digital lines their own input, or clock them.

When it samples, and what starts it

The Timing block captures around an event. Leave every control on its first choice for the board's own clock, rising edge, running until stopped.

Every list here comes from the board. The pins offered are the ones you can wire: PFI0…PFI15 on a USB-6421, PFI0/PFI1 on a cDAQ chassis, none on a standalone USB-9237 (which then shows no clock or trigger picker). An analog trigger is offered only if the board has both the comparison circuit and an APFI input; the USB-6421 has no APFI, so it gets a pin-edge start only. There is nothing to type, so nothing to misspell.

Sample clock — what paces the samples.

ControlMeans
Sample clock · On-board timebasethe board's own clock (the default)
Sample clock · a pintake the clock off that wire instead
Sample on · rising / fallingwhich edge of that clock a sample is taken on (appears once a pin is chosen)
Run · until stopped / for a set numbercontinuous, or exactly Samples per channel then stop

With an external clock, Sample rate only sizes the buffers. The wire sets the real pace.

Start — what starts it.

ChoiceThenMeans
Immediately, when the input startsbegin as soon as the task is armed (the default)
When a pin edgesOn pin, Edgewait for that edge, then begin
When a signal crosses a levelOn input, Level (V), Edgean analog trigger — offered only when the board has an APFI input
When a signal enters or leaves a bandOn input, Band bottom/top (V), Fire whena window trigger — the question an edge cannot ask: record when the pressure leaves 95–105 psi

Keep samples from before an event — the reference trigger. A start trigger begins recording at the event; a reference trigger keeps what led up to it. It offers the same kinds as Start (none on a board without reference triggering), plus Samples to keep from before, which has no default. It needs Run: for a set number of samples; the rest of the count is what comes after the event.

Pause while a pin is high / low — stops the clock while that line is held.

Analog triggering has not been seen to fire. No available board can take one, and NI does not simulate triggering. What is checked: the settings reach the driver correctly, and a board that cannot do it offers no choice. See What has been proven, and what has not.

Put the sample clock on / Put the start trigger on — route this board's signals out on a pin so another instrument can follow. The reference trigger can be exported too, once set.

More than one module, and what one clock can serve

In a cDAQ chassis, every module is its own DAQmx device, with its own name, measurement types and rate range. The chassis carries the timing engines. All of them are listed in the channel table.

One task has ONE sample clock, and not every pair of modules can share one:

  • Rate range. A delta-sigma module (an NI-9237 bridge card, an NI-9234 IEPE card) has a floor of about a kilosample per second. A slow module (an NI-9210 thermocouple card) has a ceiling of a few tens of samples per second. No rate serves both.
  • How it samples. A simultaneous module has one converter per channel; a scanned module shares one converter across channels.

The setup shows what runs where, per module, before the run. See "If a module cannot run at the rate you set" above. Mixed modules are supported, not refused.

More than one board

One input can record channels from several NI devices. Whether they line up depends on how the boards are connected. There are three cases, and the connector tells you which one you are in.

Write channels on another board with the device in front:

channels = ai0, ai1, cDAQ1Mod2/ai0, Dev2/ctr0

Each channel still arrives on /nidaqmx/<device>/<channel>, so nothing collides.

The Label — one name for every channel. Set Label to what is wired to the board (engineA) and every channel is named under it: /nidaqmx/engineA/ai0. Another module keeps its own name under it, /nidaqmx/engineA/cDAQ1Mod2/ai0, so two modules' ai0 stay separate. Blank keeps the board names. The setup table shows the labelled path before you save. Outputs keep the board name (/nidaqmx/Dev1/ao0). A / in a Label is refused.

Changing the Label of an input with channels renames them. Calibration, names, units, layout tiles, pipelines and setups move with them, after you confirm ("Moves 8 channels, 1 calibration, 2 layout tiles; history before now stays under the old name"). Past recordings keep the old name, and Replay shows "previously /nidaqmx/Dev1/ai0" beside the channel. An export spanning the rename includes both. A rename is refused, with the reason, if a new name is taken or a setup builds the path in a way only its author can change. From a terminal: phloem input rename-prefix "<input>" engineA (--dry-run first).

1. Modules in one cDAQ chassis — works, nothing to declare

Modules in one chassis share its timebase. They run in one task, and sample k on one module is sample k on another, exactly. No wiring, no settings, no "master" to choose. Design your rig around this case if you can.

2. Separate boards with a wire — works, and you have to say so

Two boards on two cables share nothing until you wire a signal between them, and software cannot detect a cable. So wire it, then fill in the Multi-device sync block. It appears only when your ticked channels span two boards with no shared timebase:

  • Master board — whose clock and start the others follow
  • Sample clock wire on pin — master's PFI0 → every other board's PFI0
  • Start trigger wire on pin — master's PFI1 → every other board's PFI1

Pins are named by their leaf (PFI0), and each board uses its own pin of that name.

You will not see this block for boards that are already joined: modules in one cDAQ chassis, boards in one PXI chassis, or two Ethernet cDAQ-9185/9189 chassis that start together over the network. Boards that both list RTSI terminals may have a ribbon cable; that is the one case the page asks about.

Both wires are required. Without the shared start, the boards run at the same rate but with an unknown, hidden offset.

The master is always declared, never guessed from channel order.

3. Separate boards with no wire — refused, with the recipe

Boards that are neither in one chassis nor wired together are refused before anything starts. The message names the boards and gives the ways forward. Their clocks drift apart by hundreds of parts per million.

To record two unsynchronised boards anyway, give each its own input. You get the data, but no sample alignment across boards.

When one board dies mid-run

  • A chassis fails as a whole: one task, one failure.
  • In a wired rig, a follower board's failure leaves a gap on exactly that board's channels. The master and the other boards keep streaming.
  • If the master dies, the input ends, since it is the clock.

What has been proven, and what has not

Proven with two simulated boards: the real driver accepts every step of the wired setup in order, and a read of N samples on the master matches N on the follower.

Not proven: simulated boards have no cable or signal, and triggering is not simulated. So the setup calls are tested, not the alignment. That needs two real boards and a real wire. The chassis case has not been run at all; it is covered by tests only.

A chassis on network time (802.1AS / TSN)

A cDAQ-9185 or cDAQ-9189 can sync over the network (IEEE 802.1AS) to a grandmaster clock, accurate to within a microsecond. Phloem then trusts the chassis's timestamps as they are, and records the input's clock as disciplined, its most trusted alignment.

This happens only when all of these hold. Otherwise the run is timed against this computer's clock as usual.

  • Every board in the input is a module of a cDAQ-9185/9189 (or the chassis itself), and NI-Sync reports each chassis synced to one grandmaster that is not the chassis itself. A chassis alone on a network becomes its own grandmaster and free-runs, so it does not count.
  • The chassis's own sample clock paces the input, not an external clock.
  • Timestamps come from the chassis. If the chassis time is more than a second away from this computer's clock, the run is timed by this computer instead.

The status is checked every 2 s. It is withdrawn the moment a chassis loses sync, reports another grandmaster, or stops answering, and when the input ends. It is not restored for the rest of that run. Restart the input to trust the clock again.

NI-Sync is a separate NI driver, needed on this computer. Without it, nothing is trusted. The stated accuracy (1 µs) comes from the cDAQ-9185 and cDAQ-9189 datasheets ("Network synchronization accuracy <1 µs"). Models not on that list are never trusted.

Per input. Each input's status covers only its own readings. Run each chassis as its own input. One input spanning two chassis is refused unless they share a timebase.

What was verified, and what was not

Verified: on a test machine with only simulated devices (NI-DAQmx 26.5), nothing reports network time, so the connector trusts nothing and times runs as usual.

Not verified: NI cannot simulate a 9185/9189, and the test machine has no grandmaster. Untested: opening a real cDAQ-9189 through NI-Sync; whether the chassis clock is UTC or TAI (37 s ahead; if TAI, the 1 s check rejects it and the log shows about 37 000 ms); and long-run phase lock. Any failure falls back to untrusted, never a false claim.

To test it for real: two cDAQ-9185/9189 chassis and an 802.1AS grandmaster (a TSN switch, a third NI TSN device, or NI-Sync on a PXI timing module), with NI-Sync on the host and chassis firmware ≥ 18.6. Run one input per chassis, feed one signal (say a 10 Hz square wave through a BNC tee) to both, record a minute, and check the edges line up within ±1 µs plus one sample period. Unplug the grandmaster: both inputs should log the loss within 2 s.

Each task is its own clock

An input whose modules run at different rates uses one task per rate. Each task's timestamps are anchored to this computer's clock separately, so each carries its own small error. On a simulated chassis, the 9210's task ran about 1 % fast while the others tracked the host.

So Phloem models each task's clock on its own, per run. A counter or clocked digital line shares the main task's clock. A TSN chassis keeps its trusted network time (above) across all its tasks.

The hardware dead-man

Phloem's other safety features (interlocks, STOP, driving channels to safe values) need Phloem to be running. If it is killed, runs out of memory, or the computer hangs, the board's outputs hold their last value. A valve stays where it was.

The dead-man moves that last step into the board. You give the card a timeout and a state for each digital output. If nothing pets it in time, the card itself drives those lines there.

Set Dead-man timeout (s) in the Outputs block, and a safe state on each digital-output row. Leave the timeout empty for no dead-man.

  • The timeout is how long outputs may hold after petting stops, in seconds. There is no default. It depends on your process.
  • One entry per guarded line: do0=low, do1=high, do2=tristate, spelled as you write the line to command it. tristate is for a line whose safe state comes from a pull resistor on the board it drives.
  • no_change is refused: it would do nothing.
  • Not every NI board has the timer (it is a cDAQ / cRIO / X-series feature). If the board lacks it, the refusal names the board and quotes its answer.

Arming it, and who pets it

Nothing is armed automatically. Four operations:

operationwhat it does
deadman.armPrograms the card and starts the timer
deadman.petResets it — call this at least as often as the timeout
deadman.clearAcknowledges an expiry so the lines can be driven again
deadman.disarmStops the timer; the outputs are left where they are

Petting is not automatic. Whatever pets it should be something that would stop if the computer failed: the safety loop, or the test itself. Then any failure along the way — Phloem killed, the computer hung, the connector crashed or shut down — stops the pets, and the card drives the outputs.

So arming is a commitment: with nothing petting, the stand goes safe one timeout later. Saving the form never arms it.

  • Writing a setpoint does not pet it. Operations run one at a time, so a pet can wait behind a write or a board rescan. Choose a timeout well above your pet interval plus the slowest operation. Below 10 ms is refused; that needs a PLC or FPGA.
  • An expiry latches. Until deadman.clear, writes to the guarded lines are refused, so a person must re-enable the stand.

What the safe state is, and where it should come from

Today you state it twice: in the test (ch.write(path, safe=…), used by STOP and interlocks) and in this field. The connector cannot read the test's value. Keep the two in agreement. If they differ, the dead-man's value is the one that runs when nothing else can.

What an armed dead-man does and does not block

It guards digital output lines only:

While a dead-man is armed
Writing a digital line or portalways allowed — that is what it is for
A hardware-timed digital patternallowed, unless it drives a line the dead-man guards
An analog ramprefused — the dead-man cannot reach an analog output
A pulse trainrefused — nor a counter

The refusals stop you believing the board will make something safe that it will not. See The dead-man and a digital pattern below.

What has been proven, and what has not

On a simulated board, the dead-man configures, arms, reports its timeout, pets, clears and releases, and armed lines still accept setpoints, including a whole-port write.

An actual expiry has never been seen. NI's simulated boards never expire (armed at 100 ms, starved for a second, still not expired). So two claims rest on NI's design, not a test: that an expiry drives the lines, and that the dead-man outlives Phloem being killed. Verify both on your real board before trusting the stand to them.

What each analog output may drive

Analog output range — a select on each analog-output row, from the ranges the board reports. Left at default, an output uses the Input range. Written out, it is <channel>=<min>:<max> in volts:

ao0=-10:10; ao1=0:5

A bare 0:5 sets the default for every output; a named entry overrides one. An unknown channel, or anything that is not a pair of numbers, is refused.

4-20 mA out. Put current: before the range to drive a current loop, the usual way to command a valve position:

ao0=0:5; ao1=current:0.004:0.02

Values are in amps, so 4-20 mA is 0.004:0.02, and every value you command on that channel is in amps. voltage: is allowed for clarity; no type word means volts. A board that cannot drive current is refused, with what it can drive. This has never been run on real hardware — see What has been proven, and what has not.

The range does two things:

  • A setpoint outside it is refused before the board is touched. Capping ao1 at 0:5 means a stray -3 never reaches the valve.
  • The board is set to it. DAQmx picks the smallest hardware range that fits, so a 0–5 V output gets twice the resolution of one at ±10 V where the board has a 0–5 V range.

If this field has an error, no analog output is written at all until it is fixed, and the connector says why. It never falls back to ±10 V.

Ramps the board clocks out

A ramp built from setpoints sent by this computer is a staircase, and the recording shows it. Instead, Phloem can give the board the whole ramp and let its own clock play it, smooth and evenly spaced. On an NI USB-6421, a 1000-sample ramp over 1 second was 245 samples in at 200 ms and complete at 1 s.

How you ask for one. Four operations, all local to this device. The assistant and the cloud cannot call them.

operationwhat it does
command.ramp {path, to, over, from?, rate_hz?}Take that output to to volts over over seconds.
command.waveform {path, samples, rate_hz}Play exactly these numbers, one per clock tick.
…with path as a listSeveral outputs on one clock — see below.
command.stop {to?}End it now. Reports the voltage the output was left at, or drives to if you name one.
command.statusIs one running, how far in, how long left.

rate_hz is samples per second clocked out. It defaults to 1000 and is checked against the board's maximum output rate.

Several outputs, moving together. Give path a list, and to (or samples, or from) a matching list in the same order:

command.ramp {
  path: ["/nidaqmx/Dev1/ao0", "/nidaqmx/Dev1/ao1"],
  to:   [4.0, 1.5],
  over: 2.0
}

They run as one task on one clock, starting together. Two separate commands would start at slightly different, unknown times.

  • over and rate_hz are shared.
  • Channels of different lengths are refused, never padded.
  • All channels must be on the same board.
  • Each keeps its own range, and command.status and command.stop report every channel.

The starting point must be known. An analog output cannot be read back. A ramp starts from the last value Phloem commanded on that channel this session; otherwise it asks for from, rather than jumping from 0 V.

What a running ramp will and will not do — read this before using it

Once loaded, the board plays the ramp whether or not Phloem is alive. An interlock, a killed process or a change of mind does not reach the board. So:

  • It always ends. A ramp is a fixed number of samples, never repeated. There is no continuous option.
  • Nothing longer than 60 seconds. A longer ramp is refused, and the message points at the alternative: drive the output from the host with ordinary setpoints, stepped but stoppable at any time. (60 s is a chosen limit, not a hardware one.)
  • When it ends, the output stays at the final value. A chamber taken to 400 psi stays at 400 psi. Phloem then writes that value as an ordinary setpoint, so it is recorded. For a safe value afterwards, use a safe value on the write channel, or the hardware dead-man.
  • Stopping tells you where it stopped. command.stop reads how far the board got, drives that voltage and reports it. command.stop {to: 0} drives a value you name instead.
  • It cannot run while the hardware dead-man is armed, and vice versa. The dead-man guards digital lines only, so it would not stop the ramp. Disarm the dead-man to ramp, or stop the ramp to arm it.
  • One at a time. A second ramp is refused while one runs.
  • If Phloem is killed outright, the driver stops the ramp. The 60 s limit covers the cases where it does not: the computer wedged but alive, the machine hung with the driver still loaded, or a stop that cannot arrive in time. Then the whole guarantee is: it ends within a minute.

What has been proven, and what has not

Proven on the real driver: the board clocks the ramp at the asked rate and finishes on its own; two outputs in one task hold different ranges (-10/10 and 0/5); a ramp can be stopped part way and reports its progress; a setpoint to a generating channel is refused; a too-long ramp is refused before the board is touched.

Not proven: that any voltage appeared on a pin. The board is simulated and cannot read its outputs back. The buffer contents and settings are covered by tests only. Also untested: a board with several output ranges picking a different range per channel (the test board has only ±10 V).

Pulse trains and PWM

A board's counters can put a square wave on a pin to drive a proportional valve, set a motor speed, step a stepper, open a shutter, or give other instruments a clock. You set a frequency and a duty cycle (the fraction of each cycle the pin is on); the board does the rest.

There are three commands:

  • command.pwm — hold it. "Drive the valve at 30 %." Runs until you stop it. No time limit.
  • command.pulses — count them. "Emit 240 pulses." Exactly that many, then stops.
  • command.pwm_sequence — step through them. "1 kHz, then 2 kHz, then 4 kHz, one per tick of this clock." See below.

Each takes a counter path (/nidaqmx/Dev1/ctr0), the frequency in hertz, and optionally a terminal for a specific pin.

command.pwm    { path: "/nidaqmx/Dev1/ctr0", freq_hz: 1000, duty: 0.25 }
command.pulses { path: "/nidaqmx/Dev1/ctr0", freq_hz: 200, count: 240 }
command.stop   { }
  • duty is required on command.pwm, because the duty cycle is the command. On command.pulses it defaults to 50 %.
  • command.stop and command.status cover pulse trains and ramps.

An exact division instead of a frequency

A frequency is rounded to what the board's timebase can divide to: 3 kHz off 100 MHz is exact, 3.3 kHz is 3300.33 Hz. For a clock other instruments follow, that rounding becomes drift. So you can state the division instead:

command.pwm { path: "/nidaqmx/Dev1/ctr0",
              ticks: { source: "/Dev1/100MHzTimebase", low: 50000, high: 50000 } }

The pin is low for low ticks and high for high, so the period is exactly low + high ticks: 100 000 ticks of 100 MHz is 1 kHz. ticks replaces freq_hz and duty; giving both is refused. The answer reports the resulting frequency for the board's named timebases. For a terminal carrying a wire, freq_hz comes back null. The duty cycle is always exact.

A train per tick — stepping through setpoints

command.pwm_sequence gives the board a whole profile and a clock to step it, for a stepper's acceleration, a fan curve or a sweep:

command.pwm_sequence {
  path:  "/nidaqmx/Dev1/ctr0",
  clock: "/Dev1/ai/SampleClock",
  rate_hz: 100,
  steps: [ {freq_hz: 1000, duty: 0.5},
           {freq_hz: 2000, duty: 0.5},
           {freq_hz: 4000, duty: 0.5} ]
}

Each tick of clock moves to the next step. clock is required: a counter has no clock of its own. Use the recording's sample clock (as above), another counter's output, or a wire.

0 % and 100 % are not pulse trains

duty must be strictly between 0 and 1. Fully closed is no train: stop it, and the pin rests at its idle state. Fully open is a level: hold a digital line with ch.write, or wire the valve to a counter whose idle state is on and leave it stopped. Phloem refuses both ends and says where to go instead.

Where the pin rests when the train stops

The counter's idle state, set once on the counter's output row (Rests low / Rests high; written out, ctr0=low; ctr1=high). The default is low, the de-energised state. Write ctr0=high if your stand is wired the other way.

That level applies to everything that ends a train: a stop, a finite train finishing, the tool session ending, and this computer being killed. It is part of how the channel is created, so it does not depend on Phloem being alive. A command cannot override it. Every answer repeats the idle state in use.

Why there is no time limit, when a ramp has one

A ramp is a movement that should finish; a pulse train like "hold this valve at 30 %" has no natural end. A ramp also has a slower, stoppable fallback (host setpoints). A 1 kHz square wave has no such fallback, so a time limit would remove the feature. Instead, a train stops when you stop it or when the tool session ends, and command.pulses is always finite.

The dead-man does not cover a counter, so the two are refused together

The dead-man drives digital output lines, and a counter output is not one. So while a dead-man is armed, a pulse train is refused, and while a train runs, arming a dead-man is refused. Stop the train or disarm the dead-man. This should lift once a board supports counter expiration states; the test board does not.

One counter, one job

/nidaqmx/Dev1/ctr0 is the same path a counter reading uses, because it is one physical counter: either counting or generating. Asking for both is refused ("the specified resource is reserved"). A dedicated frequency-output pin, where a board has one, is /nidaqmx/Dev1/freqout.

What has been proven, and what has not

Proven on the real driver: a train starts on a counter, and the driver reports back the frequency, duty cycle, idle state and output terminal it was given; both idle states reach the driver correctly; routing to a chosen pin works; a second task on a busy counter is refused, including a counter reading; 0 %, 100 % and zero frequency are refused before the board is touched.

Not proven: no pulse has ever been observed. The test board is simulated, cannot read outputs back, and does not simulate counter timing. Continuous vs. finite, the pulse count, and call order are covered by tests only.

Driving the digital lines

A line is on or off; a port is the number its lines form.

Write toWithWhat happens
/nidaqmx/Dev1/port0/line3true / falsethat one line goes high or low
/nidaqmx/Dev1/port041381, or "0xA5A5"every line of the port at once, bit 0 = line 0
/nidaqmx/Dev1/do3true / falsethe old spelling of port0/line3; still works
  • Every port and every line is in the command list.
  • A port write is one clock tick, so a valve manifold's pattern changes together.
  • Hex goes in quotes ("0xA5A5"), since JSON has no hex. "0b1010_0101" and plain numbers work too.
  • A value too wide for the port is refused. A 16-line port takes at most
    1. The driver itself would silently drop the extra bits; Phloem refuses and names the port and the widest value.

Patterns the board clocks out

command.pattern gives the board a list of states and a rate, and the board steps through them:

command.pattern { path: "/nidaqmx/Dev1/port0", samples: ["0x0001","0x0002","0x0004"], rate_hz: 1000 }

Like a ramp (see Ramps the board clocks out):

  • It is finite, never repeated.
  • It is limited to 60 seconds. For longer, drive the lines with ordinary writes.
  • It is one at a time; a board has one digital timing engine.
  • When it ends, the lines hold the last state, and Phloem writes that state again so it is recorded.

Stopping part way reports how many states the board got through, and what the lines now hold.

Making it wait for something. Add trigger and the board holds the pattern until an edge arrives on that terminal, then starts within one clock tick:

command.pattern {
  path: "/nidaqmx/Dev1/port0",
  samples: ["0x01", "0x03", "0x02", "0x00"],
  rate_hz: 1000,
  trigger: "/Dev1/PFI0"
}

Use { "source": "/Dev1/PFI0", "edge": "falling" } for a falling edge; a bare terminal means rising. Pair it with Put the start trigger on above, and the pattern starts with the recording. Without a trigger, the pattern starts when the command arrives, which has no guaranteed latency.

command.status says waiting_for while armed and not yet fired. command.stop disarms it, even before it fires.

Not proven: NI's simulated boards do not simulate triggering, so an armed pattern starts at once there. A terminal the board cannot route is refused.

The dead-man and a digital pattern

Here the dead-man guards the very lines being driven, so:

  • An ordinary digital write is never refused, even on a guarded line. That is what the dead-man is for.
  • A pattern on lines the dead-man does not guard is allowed. A dead-man on do0 says nothing about port1.
  • A pattern that shares lines with the dead-man is refused, naming those lines. Stop the pattern, disarm the dead-man, or use other lines.

The reason: nobody knows which one wins the pins when the dead-man fires during a pattern. The driver accepts both, and simulated boards never expire. Until it is measured on real hardware, the overlap is refused.

What has been proven, and what has not

Proven on the real driver: a whole port and a single line are written the same way; every line is reachable; the board reports a 16-line port that can be clocked; a pattern of 2000 states at 1 kHz took 2.014 seconds, so the board really paces it; stopped 400 ms into a 5-second pattern, it reported 392 states done.

Not proven: no line has ever been observed, since a simulated board cannot read its outputs back. What a dead-man expiry does to a running pattern is also unknown, so that combination is refused.

Is it alive, and making it behave

Two operations for the board as a whole.

Self-test

Self-test runs NI's own brief check of the board and reports exactly what the driver said: pass or fail, plus its message. It changes nothing.

A pass reads like this:

device        Dev1
product_type  USB-6421
passed        true
status        0
message       —

A failure keeps the driver's sentence, which NI's documentation refers to:

passed        false
status        -200126
message       DAQmx error -200126: The device self-test failed.

If another program has the device open (FlexLogger, LabVIEW, another Phloem session), the self-test cannot run, and you get an error saying so. That is not a failed board: close the other program.

A simulated board always passes, and the answer says so whenever the board is simulated.

Reset

Reset returns the board to its power-on state, for when the card is wedged. It is the most destructive thing this connector can do:

  • Every task on the board stops, in every program on the machine. Any recording from this board must be restarted. A LabVIEW or FlexLogger session using it loses it too.
  • Every output goes to its power-on value, not your last command and not any safe state. A valve held at 30 % is no longer held.
  • All signal routing is cleared, so anything following an exported clock or trigger stops.

Only a person or a Trellis script can reset, never the assistant.

Before the reset, Phloem stops any ramp, pulse train or pattern it was running on that board, and lists them in the answer. Other boards are left alone. Phloem also forgets the last voltage it commanded on that board, so the next ramp asks where to start.

A reset is refused while the dead-man is armed. A reset clears the timer and drops the lines to power-on states, leaving the stand unguarded with nothing looking wrong. Disarm the dead-man first.

What has been proven, and what has not

Proven on the real driver: the self-test runs and answers (status 0 on a simulated Dev1, with the simulated caveat), and a reset really aborts a running task — the next read returned -88709: … a task has been aborted or a device has been removed from the system.

Not proven on hardware, covered by tests only: a failing self-test, the "device in use" case, and that the board's real name reaches the driver.

IEPE, bridge and 4-20 mA out — what has been proven

These have never been run against an instrument:

  • IEPE accelerometer and microphone inputs (accel, microphone)
  • bridge inputs — load cells, pressure transducers, torque cells (bridge)
  • 4-20 mA current output (ao0=current:0.004:0.02)
  • analog triggering — both level= and window=
  • LVDT / RVDT position and IEPE force inputs (lvdt, rvdt, force_iepe). These are one step further back: no available board offers them, so testing shows only the board's refusal.

The first four are set up and checked by NI-DAQmx on a simulated board of the right type, which reports every setting back. That is more than "the board refused it", but it is not a correct reading.

What has been checked (NI-DAQmx 26.5.0):

featureboardwhat the driver reports back
IEPE accelerometerUSB-9234accelerometer; AC coupling; internal excitation; 100 mV/g; units of g — and it streams
IEPE microphoneUSB-9234microphone; AC coupling; 50 mV/Pa; 100 dB SPL
bridgeUSB-9237, USB-9219bridge; full bridge; internal 2.5 V excitation; 350 Ω; units of V/V
4-20 mA outUSB-9265current output; range 0.004 to 0.02
analog triggerPCIe-6363level and window both accepted; the window edges come back rounded to the board's own trigger resolution
  • The driver selects AC coupling for IEPE itself, unasked.
  • The trigger's window edges come back rounded, so they reached real trigger circuitry.
  • Each call matches NI's documented entry point and arguments, and is pinned by tests.
  • A board that cannot do these refuses by name, before recording.

Check your excitation. Ask a USB-9234 for 4 mA of IEPE excitation (NI's default) and it silently gives 2 mA; 10 or 20 mA also give 2 mA. A USB-4431 refuses and lists the two values it accepts. If excitation matters to your sensor, state it (excit=0.002) and check the module's datasheet.

Not checked — needs a real instrument:

  • That the numbers are right. A simulated board outputs a test waveform whatever the settings. A wrong constant would give readings off by a factor, in the right unit.
  • That the excitation actually flows.
  • That 0.02 is twenty milliamps into a real loop, or that the board's compliance voltage suits your loop.
  • That a trigger fires when it should. NI does not simulate triggering.
  • That bridge=quarter matches the arm your gauge is actually in.

In short: if your board supports one of these, the connector will set it up, and it may well be right first time. Check the first readings against something you trust. If your board does not support it, you will be told.

Simulated boards

NI MAX can create a simulated board that exists only in software. It answers like a real board and gives a clean sine wave on every input. That is useful before hardware arrives, and a trap after, because the numbers look reasonable.

So Phloem labels it everywhere it names the board: the board picker, Test connection, and the connector's log. For example: Dev1 — USB-6421 (16 AI channels) · SIMULATED — no hardware attached; readings are synthetic. A real board shows nothing extra. If NI-DAQmx is too old to say, Phloem says that instead.

On a simulated board, as NI documents:

  • Triggering is not simulated. A triggered task starts at once.
  • Counters always read zero.
  • Digital ports count up — 0, 257, 514, 771, … — however you sample them, so change detection fires on that.

Notes

  • Readings are spaced by the board's sample clock. Each block is anchored to this computer's clock when it is read, so it can sit up to one read interval off absolute time. A chassis on network time anchors on its own clock (see A chassis on network time).
  • For engineering units, see Turning a reading into engineering units: wire the sensor as what it is if you can, use Calibration if you cannot, and use Channel scaling (at source) only when the unit must be true at the board. Software thermocouple conversion (tc_k:) is refused here; the board does that itself.
  • The outputs offered are the ones the board has: its analog outputs, at the range you set (or the board's limits if none), and its digital lines. A board with no analog output offers none.
  • Every output write is recorded.
  • A setpoint is a command, not a safety-rated action. Its timing has no upper bound. Anything where a late write is a hazard belongs on a PLC or FPGA, with the hardware dead-man as the backstop.
  • Write a digital line with its port: port0/line3. line3 alone is refused.
  • Without the NI-DAQmx runtime, the connector says so.

#Connection fields

Every field the Add input form shows for this connector.

FieldTypeRequiredDefault
Device
The board, as NI-DAQmx names it. Pick it from the list — it is read off this machine.
Dev1
TextYes—
Label
engineA
Text——
Channel pathsOne of
module · board
——
Channels
What to stream. Tick the inputs, counters and digital lines in the table below.
ai0:3
Text——
Sample rate
A level (slow, medium, fast) or a number of hertz. Modules without their own rate run at this one.
fast
TextYesfast
Input range
The volts the analog inputs are read on — the board's own list. A smaller range that still contains the signal gives more resolution.
One of
——
Sensors (per channel)
What is wired to each input, and how. Set it on the channel row.
voltage,term=diff; ai0=thermocouple,type=K,cjc=builtin
Text——
Rate levels
The hertz behind each level. Set it with Rate levels in the setup.
slow=1; medium=100; fast=1000
Text—slow=1; medium=100; fast=1000
Rates (per module)
Each module's level — slow, medium or fast. Set it on the module's slot row.
cDAQ1Mod5=slow; cDAQ1Mod8=fast
Text——
Counters (per counter)
What each counter you ticked measures. Set it on the counter row.
ctr0=ang_encoder,ppr=1024; ctr1=freq,min=10,max=100000
Text——
Sample clock
What paces the samples. The board's own clock, or a pin another instrument drives it from.
One of
——
Sample onOne of
rising · falling
—rising
Run
A reference trigger (below) needs a set number: 'how much after the event' is the rest of that count.
One of
continuous · finite
—continuous
Samples per channel
10000
Number——
Start
What starts the recording. Only what this board can do is offered.
One of
——
On pinOne of——
On inputOne of——
EdgeOne of
rising · falling
—rising
Level (V)
2.5
Number——
Band bottom (V)Number——
Band top (V)Number——
Fire when the signal isOne of
entering · leaving
—entering
Keep samples from before an event
A reference trigger has been recording all along and keeps what led up to the event. Needs 'Run: for a set number of samples'.
One of
——
Event on pinOne of——
Event on inputOne of——
EdgeOne of
rising · falling
—rising
Level (V)Number——
Band bottom (V)Number——
Band top (V)Number——
Fire when the signal isOne of
entering · leaving
—entering
Samples to keep from before
There is no default — this number is the reason to use a reference trigger.
2000
Number——
Pause while a pin isOne of
——
…isOne of
high · low
—high
Digital lines are sampledOne of
auto · clock · on_demand · change_detection
—auto
Rising edges onText——
Falling edges onText——
Inverted lines
Digital lines read inverted, joined by +, as Channels names them (port0/line3+port1).
Text——
Put the sample clock on
So a second instrument can follow this one.
One of
——
Put the start trigger onOne of
——
Put the reference trigger onOne of
——
Clock source board
The board whose clock and start the others follow — the end of the wire the signal comes OUT of.
One of——
Sample clock wire on pin
The same pin name at both ends: out on the clock source board, in on every other board.
One of——
Start trigger wire on pin
A second wire. A shared rate without a shared start is a constant, invisible offset.
One of——
Analog output range (per channel)
What each analog output may drive. Set it on the output row.
ao0=-10:10; ao1=0:5
Text——
Counter output idle state (per counter)
Where each counter's output pin rests when it is NOT pulsing. Set it on the counter's output row.
ctr0=low; ctr1=high
Text——
Dead-man timeout (s)
How long the outputs may hold after this computer stops answering, before the CARD drives them to the safe states set on the output rows. Empty = no dead-man.
2
Number——
Dead-man safe states (per line)
What each digital output is driven to when the dead-man fires. Set it on the output row.
do0=low; do1=high
Text——
Scaling on the device (per channel)
Only for hardware that must scale before it emits, or when the unit has to be true at the BOARD. Otherwise set a calibration in the channel's dialog.
ai1=linear:12.5,3.0 -> psi
Text——

Updated