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 -> psimakes NI-DAQmx convert the channel and reportpsito 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 = 0xA5A5sets sixteen lines in one clock tick, on any port. A single line is stilltrue/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 —
ao0can be ±10 V whileao1is 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
Install the NI-DAQmx runtime and connect the board. Phloem detects an NI USB DAQ and offers a draft (device name
Dev1by default).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…Mod5in slot 3 showsslot 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.
- Each cDAQ module shows as you would describe it:
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.
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.
Tick counters and digital lines on their own rows. Every channel setting is also written out in the
Sensor / wiringfield below.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
| FlexLogger | this connector | |
|---|---|---|
| AI rate per chassis | 3 levels (Slow/Medium/Fast), one value each | same — rate_levels, per input |
| assigned to | the module's AI subsystem | the module (rates), set on its slot row |
| delta-sigma below its floor | runs at the floor; the whole level at the "lowest common rate" | same |
| shown | the module's "actual rate" beside its level | Medium · runs at 1.65 kS/s, its floor |
| slow card above its level | not documented | a task of its own at its ceiling, counted as a rate |
| a module's rate in hertz | not possible | refused, converted to levels when it can be |
| delta-sigma modules on two levels | allowed | one task, at the higher need |
| Counter / Digital levels | own levels | none: counters and clocked lines use the main AI task's clock |
| downsampling (100 Hz from a delta-sigma card) | software, by default | none: the card's own rate, recorded as is, shown on the row |
| unticked module's level | kept | kept, ignored |
| channels a new input records | the ones enabled | the ones ticked; nothing ticked is refused at Start |
| a module in use elsewhere | In use by {0} | cDAQSpaceMod2 is in use by another program — FlexLogger or a script; stop it there |
| an open thermocouple's reading | logged as read (−176 427 °C) | stored as read; the row says Open thermocouple? |
| channel names | the physical channel, cDAQSpaceMod8/ai0 | a 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:
| Property | FlexLogger | Phloem |
|---|---|---|
root Date Created | log start | when the export was written (datetime is the window start) |
RunNumber | 1 | not written |
unit_string | °C as one CP-1252 byte | °C in UTF-8 |
wf_samples | the first chunk's count | the channel's total |
monotony | not monotone | not monotone only when readings rose and fell; else none |
| polynomial scale | — | no NI_SensorScale and no range |
NI_TerminalConfiguration | Differential | the 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, withSample at 100 S/s. It is never changed silently. - Filter Auto —
adc=autopicks 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|Kon 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 |
|---|---|
default | let the board choose (what happens if you say nothing) |
diff | differential — two wires, neither tied to ground. The safe choice for anything floating: a battery, a thermocouple, a sensor with its own supply |
rse | single-ended, measured against the board's own ground |
nrse | single-ended, measured against the board's sense terminal |
pseudodiff | differential 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.
| Sensor | Write | Must state | Defaults |
|---|---|---|---|
voltage | voltage,term=diff | — | the Input range select; empty = the module's own widest range (NI 9221 ±60 V, USB-6421 ±10 V) |
current | current,shunt=internal | — | ±20 mA; shunt=default|internal|external, shunt_ohms=249 |
thermocouple | thermocouple,type=K,cjc=builtin | cjc_val= if cjc=const; cjc_chan= if cjc=chan | type K, cold junction from the terminal block, the type's own span (K −200 … 1372 °C, J −210 … 1200 °C, T −200 … 400 °C) |
rtd | rtd,wires=4,excit=0.001 | wires=, excit= (amps) | Pt3851, 100 Ω at 0 °C, −200–660 °C |
thermistor | thermistor,excit=0.0001,a=…,b=…,c=… | the excitation, and a/b/c from the datasheet | 4-wire, 0–100 °C |
resistance | resistance,wires=4,excit=0.001 | wires=, excit= (amps) | 0–1000 Ω |
strain | strain,bridge=quarter1,excit_v=2.5 | bridge=, excit_v= (volts) | gauge factor 2.0, 350 Ω, Poisson 0.30, ±1000 µε |
builtin_temp | builtin_temp | — | the board's own temperature, 0–100 °C |
accel ¹ | accel,sens=100 | sens= (mV/g, off the sensor) | ±5 g, internal 4 mA excitation, AC coupled, sens_units=mv/g, units=g |
microphone ¹ | microphone,sens=50 | sens= (mV/Pa, off the microphone) | 100 dB SPL, internal 4 mA excitation, AC coupled |
bridge ¹ | bridge,bridge=full,excit_v=2.5 | bridge= (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.2 | threshold= (volts), hysteresis= (volts) | 1 Hz – 100 kHz |
lvdt ¹ | lvdt,sens=50,excit_v=1 | sens= (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=1 | sens= (sens_units=mv/v/deg|mv/v/rad), excit_v= (volts) | ±70°, units=deg|rad, 2.5 kHz excitation, wires=4|5 |
force_iepe | force_iepe,sens=10 | sens= (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_iepe | velocity_iepe,sens=100 | sens= (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
sensorentry, 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_nullif 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
ai0aspsi. - 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 asphloem_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:
| Write | Measures | Unit |
|---|---|---|
edge_count | edges, cumulatively | counts |
freq,min=10,max=100000 | frequency | Hz |
period,min=1e-4,max=1 | time between like edges | s |
pulse_width,edge=rising | how long one pulse was high (falling = low) | s |
two_edge_sep,first=…,second=… | time from an edge on one wire to an edge on another | s |
ang_encoder,ppr=1024 | shaft position | deg (units=rad|ticks) |
lin_encoder,dist=1e-5 | linear position | m (units=in|ticks) |
- An encoder must state its scale:
ppr=pulses per revolution, ordist=metres per pulse. A wrong value still looks like degrees. decoding=defaults tox4(every edge of both channels). An X4 encoder read asx1reports a quarter of the motion.zidx=onresets the count on the index pulse, withzidx_val=andzidx_phase=.- Each counter uses its default terminal.
input=/Dev1/PFI8points it elsewhere. A two-edge separation takesfirst=andsecond=; an encoder takesa=,b=andz=. semi_periodis not available. It needs one sample per edge, which cannot share the analog clock. Useperiodandpulse_width.- A counter's unit follows what it measures:
Hz,deg/rad,s, orcounts.
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:
| Tick | You get | Path |
|---|---|---|
port0 | the whole port as one number — the integer its lines form | /nidaqmx/Dev1/port0 |
port0/line3 | that 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
scaleand 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.
| Choice | What happens | Timestamps |
|---|---|---|
| with the analog clock when there is one, else when asked | clocked with the analog channels if there are any, polled if not | |
| on the shared sample clock only | insists on the shared sample clock, and says so if there is none | the board's |
| when asked, at the sample rate | polls the pins at the sample rate | this computer's |
| the moment a line changes | samples the moment a line changes | this 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:3andfalling=…, 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.
| Control | Means |
|---|---|
| Sample clock · On-board timebase | the board's own clock (the default) |
| Sample clock · a pin | take the clock off that wire instead |
| Sample on · rising / falling | which edge of that clock a sample is taken on (appears once a pin is chosen) |
| Run · until stopped / for a set number | continuous, 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.
| Choice | Then | Means |
|---|---|---|
| Immediately, when the input starts | begin as soon as the task is armed (the default) | |
| When a pin edges | On pin, Edge | wait for that edge, then begin |
| When a signal crosses a level | On input, Level (V), Edge | an analog trigger — offered only when the board has an APFI input |
| When a signal enters or leaves a band | On input, Band bottom/top (V), Fire when | a 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'sPFI0 - Start trigger wire on pin — master's
PFI1→ every other board'sPFI1
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.tristateis for a line whose safe state comes from a pull resistor on the board it drives. no_changeis 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:
| operation | what it does |
|---|---|
deadman.arm | Programs the card and starts the timer |
deadman.pet | Resets it — call this at least as often as the timeout |
deadman.clear | Acknowledges an expiry so the lines can be driven again |
deadman.disarm | Stops 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 port | always allowed — that is what it is for |
| A hardware-timed digital pattern | allowed, unless it drives a line the dead-man guards |
| An analog ramp | refused — the dead-man cannot reach an analog output |
| A pulse train | refused — 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
ao1at0:5means a stray-3never 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.
| operation | what 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 list | Several 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.status | Is 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.
overandrate_hzare shared.- Channels of different lengths are refused, never padded.
- All channels must be on the same board.
- Each keeps its own range, and
command.statusandcommand.stopreport 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.stopreads 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 { }
dutyis required oncommand.pwm, because the duty cycle is the command. Oncommand.pulsesit defaults to 50 %.command.stopandcommand.statuscover 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 to | With | What happens |
|---|---|---|
/nidaqmx/Dev1/port0/line3 | true / false | that one line goes high or low |
/nidaqmx/Dev1/port0 | 41381, or "0xA5A5" | every line of the port at once, bit 0 = line 0 |
/nidaqmx/Dev1/do3 | true / false | the 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
- 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
do0says nothing aboutport1. - 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=andwindow= - 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):
| feature | board | what the driver reports back |
|---|---|---|
| IEPE accelerometer | USB-9234 | accelerometer; AC coupling; internal excitation; 100 mV/g; units of g — and it streams |
| IEPE microphone | USB-9234 | microphone; AC coupling; 50 mV/Pa; 100 dB SPL |
| bridge | USB-9237, USB-9219 | bridge; full bridge; internal 2.5 V excitation; 350 Ω; units of V/V |
| 4-20 mA out | USB-9265 | current output; range 0.004 to 0.02 |
| analog trigger | PCIe-6363 | level 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=quartermatches 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.line3alone is refused. - Without the NI-DAQmx runtime, the connector says so.
#Connection fields
Every field the Add input form shows for this connector.
| Field | Type | Required | Default |
|---|---|---|---|
| Device The board, as NI-DAQmx names it. Pick it from the list — it is read off this machine. Dev1 | Text | Yes | — |
LabelengineA | Text | — | — |
| Channel paths | One 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 | Text | Yes | fast |
| 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 on | One 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 channel10000 | Number | — | — |
| Start What starts the recording. Only what this board can do is offered. | One of | — | — |
| On pin | One of | — | — |
| On input | One of | — | — |
| Edge | One of rising · falling | — | rising |
Level (V)2.5 | Number | — | — |
| Band bottom (V) | Number | — | — |
| Band top (V) | Number | — | — |
| Fire when the signal is | One 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 pin | One of | — | — |
| Event on input | One of | — | — |
| Edge | One of rising · falling | — | rising |
| Level (V) | Number | — | — |
| Band bottom (V) | Number | — | — |
| Band top (V) | Number | — | — |
| Fire when the signal is | One 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 is | One of | — | — |
| …is | One of high · low | — | high |
| Digital lines are sampled | One of auto · clock · on_demand · change_detection | — | auto |
| Rising edges on | Text | — | — |
| Falling edges on | Text | — | — |
| 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 on | One of | — | — |
| Put the reference trigger on | One 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