AD Family Guide

Overview

The AD family is NAI’s line of programmable analog-to-digital (A/D) smart function modules. Where a discrete module asks “is this line on or off?”, an AD module asks “how much?” — it measures a continuously-varying analog voltage (or current) on each channel and converts it to a digital number your software can read. Each channel is a differential input with a field-programmable range, gain, and anti-aliasing/post filtering, backed by FIFO buffering for capturing streams of samples.

This page is the starting point for any AD module. Use it to understand the family, pick the member that fits your resolution, speed, and signal range, wire a source to a channel, and confirm the module is measuring. It’s aimed at engineers acquiring analog signals — temperature, pressure, strain, position, vibration, and voltage/current monitoring — on an NAI board or system.

In a real system, an AD module is the measurement front-end — it digitizes the analog signals feeding a monitoring, control, or data-acquisition system. Concretely, it reads the voltage or current outputs of the sensors and signal conditioning across a platform: pressure and fuel-flow transducers, temperature circuits (thermocouple/RTD), strain gauges and load cells, accelerometers and vibration pickups, position sensors (potentiometers, control-surface and actuator feedback), and power-bus voltage/current monitoring.

Two choices map the module to the job. The range follows the signal — low-level ±10 V instrumentation (AD1 / AD4 / ADE), higher ±50–±100 V signals and buses (AD5 / AD2 / AD6 / ADF), or 4–20 mA current-loop sensors read directly in current mode (AD3 / AD4). The architecture follows the kind of measurement — high-resolution sigma-delta for precision and fast dynamic signals like vibration; simultaneous SAR when channels must be sampled at the same instant (control loops, correlated data); multiplexed SAR to cover many slower channels at once. NAI rolls these modules into data-acquisition and Remote Data Concentrator (RDC) subsystems for mil-aero sensor integration.

(The mirror-image sibling is the DA family, which generates analog outputs — AD measures, DA produces.)

For a short visual introduction to the analog-to-digital family, watch this overview:

AD modules at a glance

ModuleChannelsResolutionSampling architectureInput rangeManual
AD11224-bitSigma-Delta, per-channel (simultaneous), to 256 kHz±10 VAD1 Manual
AD21224-bitSigma-Delta, to 256 kHz±100 VAD2 Manual
AD31224-bitSigma-Delta, to 256 kHz±25 mA (current)AD3 Manual
AD41616-bitSAR, multiplexed (per 8-ch bank), to 400 kHz±10 V (or ±25 mA)AD4 Manual
AD51616-bitSAR, multiplexed, to 400 kHz±50 VAD5 Manual
AD61616-bitSAR, multiplexed, to 400 kHz±100 VAD6 Manual
ADE1616-bitSAR, simultaneous, to 200 kHz±10 VADE Manual
ADF1616-bitSAR, simultaneous, to 200 kHz±100 VADF Manual

Two architectures show up here. Sigma-Delta (AD1–AD3) gives the highest resolution (24-bit) with a dedicated converter per channel. SAR (AD4–AD6, ADE/ADF) is faster; it comes in simultaneous form (ADE/ADF, all channels sampled at the same instant — best for correlated/control-loop data) and multiplexed form (AD4–AD6, one converter shared across a bank of 8 — more channels, but channels are sampled in sequence).

Choosing a member:

  • Highest resolution / precision — AD1–AD3 (24-bit Sigma-Delta).
  • Most channels and fastest throughput — AD4–AD6 (16-ch, 400 kHz, multiplexed).
  • Correlated/simultaneous capture across channels (control loops, parallel acquisition) — ADE/ADF or AD1–AD3.
  • By signal range — ±10 V: AD1, AD4, ADE · ±50 V: AD5 · ±100 V: AD2, AD6, ADF.
  • Measuring current, not voltage — AD3 (±25 mA) or AD4 (switchable to ±25 mA current mode).

Combination modules that include A/D:

ModuleCombinesManual
CME / CMFA/D + D/ACME-CMF Manual

Physical setup

An AD channel is a differential analog input — think of it as a precise voltmeter you connect across your signal. The exact pins are per-module, so always get them from that module’s manual; the pattern is the same for every AD module:

  1. Identify the module’s slot number on your NAI motherboard or system.
  2. Bring the channel inputs out through the breakout board, where the slot’s pins appear as generic IO# numbers.
  3. Map IO# pins to each channel’s high (+) and low (−) inputs — by the pinout in the module’s manual or the module’s overlay card.
  4. Connect the signal you want to measure across the channel’s + and − inputs.

A few things hold for every AD module:

  • Inputs are differential. Wire your source to the channel’s + (high) and − (low) inputs. For a single-ended source, tie its return to the channel’s low input and to the module’s analog reference/ground.
  • Range and polarity are software-set per channel (naibrd_AD_SetRangePolarity). Pick bipolar (±) for signals that swing negative, unipolar for one-sided signals, and choose the smallest range that still covers your signal — a smaller range uses more of the converter’s bits, giving finer resolution.
  • Don’t exceed the input range. Over-range and open-input conditions are flagged in status (open/over-voltage), and grossly over-range signals can damage the front end. Match the module’s range to your signal.
  • Current measurement is wired in series. On AD3 (and AD4 in current mode), the channel measures the current flowing through it, so it goes in series with the loop — not across a voltage.

Worked examples (use your module’s pinout for the actual pins):

  • Measuring a ±10 V sensor (e.g. a position or pressure transducer). Wire the sensor output to the channel’s + input and its return to the channel’s input. Set the channel bipolar, ±10 V range, then read the channel. A reading near 0 V at rest and swinging with the sensor confirms it.
  • Measuring a 4–20 mA current-loop sensor (AD3, or AD4 in current mode). Put the channel in series with the loop, set the channel to current mode (NAIBRD_AD_MODE_CURRENT), and read the current directly.

Software

There’s nothing AD-specific about which software you run. The NAI SSK (naibrd library) is identical across every OS and architecture — PetaLinux, VxWorks, DEOS, Windows. What OS you’re on is determined by your motherboard/SBC, not by the AD module. The only family-specific part is which API functions you call: AD modules use the naibrd_AD_* calls.

Where to find what you need:

  • Which functions/registers to call — the specific module’s manual (e.g. AD1 Manual) documents every naibrd_AD_* register (range/polarity, mode, sample rate, filtering, FIFO, status).
  • Building and deploying on your platformConnecting to Boards covers the toolchain, deployment, and terminal access for PetaLinux/ARM Linux, VxWorks, DEOS, and Windows.
  • Launching the app on the board itselfRunning Applications from the Target walks through loading and launching your executable on the target.

Example — a 68ARM2 SBC with an AD1 module: pull the naibrd_AD_* calls from the AD1 Manual, set up the ARM Linux toolchain per Connecting to Boards, then load and launch an AD sample on the target per Running Applications from the Target.

Confirm communication

An AD module has no output to loop back, so the self-test is built into the module itself.

Built-in test (no wiring). Every AD module runs a power-on BIT and a continuous background BIT that checks each channel against an internal stimulus to 0.2 % full-scale accuracy — no external signal required. Confirm the power-on BIT completed and that no faults are latched:

naibrd_AD_CheckPowerOnBITComplete(cardIndex, module, &complete);  /* power-on BIT done?     */
naibrd_AD_SetModuleBITEnable(cardIndex, module, NAI_TRUE);         /* ensure background BIT on */
naibrd_AD_GetStatus(cardIndex, module, channel, &status);         /* any BIT/summary faults? */

If power-on BIT is complete and the BIT/summary status is clean, your board connection, SSK, and the module’s measurement path are all confirmed. The AD Summary sample app drives exactly this — reading latched BIT and summary status across channels and clearing it.

Known-voltage sanity read (step up — proves you can read real data). Tie a channel’s inputs to a voltage you know (a channel shorted to its reference should read ~0 V), set its range/polarity, and read it back:

naibrd_AD_SetRangePolarity(cardIndex, module, channel, NAIBRD_AD_POLARITY_BIPOLAR, range);
naibrd_AD_GetData(cardIndex, module, channel, &volts);   /* should match the known input */

A reading that matches your known input confirms the full path end-to-end, including a real channel.

Features

Each AD operation works per channel (some per module) through the naibrd_AD_* API. The blocks below group the calls by what you’re doing — think of them like the controls on ESP2’s AD tab — with the SSK 1.x and 2.x signatures side by side. (The 1.x → 2.x rename is visible throughout: nai_ad_* enum types became naibrd_ad_*, GetVoltage/GetCurrent merged into GetData with a mode argument, SetRange became SetRangePolarity, SetLatch became per-channel SetLatchChannel, and so on.)

Read a channel — set range/mode and read the measurement

What it does: set a channel’s input range and polarity, choose voltage or current mode (AD3/AD4), then read the converted value in engineering units. Latch first for a coherent cross-channel snapshot.

Applies to: all AD modules; current mode on AD3/AD4.

Relevant APIs:

/* SSK 1.x */
nai_status_t naibrd_AD_SetRange(int32_t cardIndex, int32_t module, int32_t channel, nai_ad_range_mode_t mode, float64_t range);
nai_status_t naibrd_AD_GetRange(int32_t cardIndex, int32_t module, int32_t channel, nai_ad_range_mode_t* p_outmode, float64_t* p_outrange);
nai_status_t naibrd_AD_SetMode(int32_t cardIndex, int32_t module, int32_t channel, nai_ad_mode_t mode);
nai_status_t naibrd_AD_GetVoltage(int32_t cardIndex, int32_t module, int32_t channel, float64_t* p_outvoltage);
nai_status_t naibrd_AD_GetCurrent(int32_t cardIndex, int32_t module, int32_t channel, float64_t* p_outcurrent);
nai_status_t naibrd_AD_SetLatch(int32_t cardIndex, int32_t module, bool_t latched);
/* SSK 2.x */
nai_status_t naibrd_AD_SetRangePolarity(int32_t cardIndex, int32_t module, int32_t channel, naibrd_ad_polarity_t polarity, float64_t range);
nai_status_t naibrd_AD_GetRangePolarity(int32_t cardIndex, int32_t module, int32_t channel, naibrd_ad_polarity_t* p_outpolarity, float64_t* p_outrange);
nai_status_t naibrd_AD_SetMode(int32_t cardIndex, int32_t module, int32_t channel, naibrd_ad_mode_t mode);
nai_status_t naibrd_AD_GetData(int32_t cardIndex, int32_t module, int32_t channel, naibrd_ad_mode_t mode, float64_t* p_outvoltage);
nai_status_t naibrd_AD_SetLatchChannel(int32_t cardIndex, int32_t module, int32_t channel, bool_t latched);

Exercise it: AD BasicOps (SSK 2.x) · AD BasicOps (SSK 1.x) · ESP2 “AD” tab.

Filtering & sample rate

What it does: set the module sample rate and the per-channel digital low-pass filter break frequency to match your signal bandwidth and reject noise/aliasing.

Applies to: all AD modules.

Relevant APIs:

/* SSK 1.x */
nai_status_t naibrd_AD_SetSampleRate(int32_t cardIndex, int32_t module, uint32_t rate);
nai_status_t naibrd_AD_GetSampleRate(int32_t cardIndex, int32_t module, uint32_t* p_outrate);
nai_status_t naibrd_AD_SetBreakFrequency(int32_t cardIndex, int32_t module, int32_t channel, uint32_t freq);
nai_status_t naibrd_AD_GetBreakFrequency(int32_t cardIndex, int32_t module, int32_t channel, uint32_t* p_outfreq);
/* SSK 2.x */
nai_status_t naibrd_AD_SetSampleRate(int32_t cardIndex, int32_t module, uint32_t rate);
nai_status_t naibrd_AD_GetSampleRate(int32_t cardIndex, int32_t module, uint32_t* p_outrate);
nai_status_t naibrd_AD_SetFilterBreakFrequency(int32_t cardIndex, int32_t module, int32_t channel, uint32_t freq);
nai_status_t naibrd_AD_GetFilterBreakFrequency(int32_t cardIndex, int32_t module, int32_t channel, uint32_t* p_outfreq);

Exercise it: AD BasicOps · ESP2 “AD” tab.

FIFO buffered capture

What it does: capture a stream of samples into the on-module FIFO (optionally triggered and time-stamped) and read them back for high-rate or post-processed acquisition.

Applies to: all AD modules.

Relevant APIs:

/* SSK 1.x */
nai_status_t naibrd_AD_GetFIFOCount(int32_t cardIndex, int32_t module, int32_t channel, uint32_t* p_outcount);
nai_status_t naibrd_AD_ReadFIFORaw32(int32_t cardIndex, int32_t module, int32_t channel, uint32_t count, uint32_t p_outdata[], uint32_t* p_outread);
nai_status_t naibrd_AD_SetFIFOTrigCtrl(int32_t cardIndex, int32_t module, int32_t channel, nai_ad_fifo_trig_t ctrl);
nai_status_t naibrd_AD_SoftwareTrigger(int32_t cardIndex, int32_t module);
nai_status_t naibrd_AD_ClearFIFO(int32_t cardIndex, int32_t module, int32_t channel);
/* SSK 2.x */
nai_status_t naibrd_AD_GetFIFOCount(int32_t cardIndex, int32_t module, int32_t channel, uint32_t* p_outcount);
nai_status_t naibrd_AD_ReadFIFO(int32_t cardIndex, int32_t module, int32_t channel, uint32_t count, float64_t p_outdata[], uint32_t* p_outread);
nai_status_t naibrd_AD_SetFIFOTrigCtrl(int32_t cardIndex, int32_t module, int32_t channel, naibrd_ad_fifo_trig_t ctrl);
nai_status_t naibrd_AD_SoftwareTrigger(int32_t cardIndex, int32_t module);
nai_status_t naibrd_AD_ClearFIFO(int32_t cardIndex, int32_t module, int32_t channel);

Exercise it: AD FIFO (SSK 2.x) · ESP2 “AD” tab.

Health, status & limits

What it does: run/monitor Built-In Test, read per-channel status, and set the threshold-detect and saturation limits that flag when a signal crosses or saturates.

Applies to: all AD modules.

Relevant APIs:

/* SSK 1.x */
nai_status_t naibrd_AD_CheckPowerOnBITComplete(int32_t cardIndex, int32_t module, bool_t* p_outpbitComplete);
nai_status_t naibrd_AD_GetStatus(int32_t cardIndex, int32_t module, int32_t channel, nai_ad_status_type_t type, nai_status_bit_t* p_outstatusBit);
nai_status_t naibrd_AD_ClearStatus(int32_t cardIndex, int32_t module, int32_t channel, nai_ad_status_type_t type);
nai_status_t naibrd_AD_SetThresholdDetect(int32_t cardIndex, int32_t module, int32_t channel, nai_ad_threshold_detect_id_type_t thresholdID, float64_t thresholdset, float64_t thresholdclear);
nai_status_t naibrd_AD_SetSaturationControl(int32_t cardIndex, int32_t module, int32_t channel, nai_ad_saturation_control_type_t saturationType, bool_t enable);
/* SSK 2.x */
nai_status_t naibrd_AD_CheckPowerOnBITComplete(int32_t cardIndex, int32_t module, bool_t* p_outpbitComplete);
nai_status_t naibrd_AD_GetChanMappedStatus(int32_t cardIndex, int32_t module, int32_t channel, naibrd_ad_chan_mapped_status_type_t statusType, nai_status_bit_t* p_outstatusBit);
nai_status_t naibrd_AD_ClearChanMappedStatus(int32_t cardIndex, int32_t module, int32_t channel, naibrd_ad_chan_mapped_status_type_t statusType);
nai_status_t naibrd_AD_SetThresholdDetect(int32_t cardIndex, int32_t module, int32_t channel, naibrd_ad_threshold_detect_id_type_t thresholdID, float64_t thresholdSet, float64_t thresholdClear);
nai_status_t naibrd_AD_SetSaturationControl(int32_t cardIndex, int32_t module, int32_t channel, naibrd_ad_saturation_control_type_t saturationType, bool_t enable);

Exercise it: AD Summary · ESP2 “AD” tab.

Try it out

Reading a channel is the same regardless of which sample you run. Every NAI sample starts with the standard connection flow — naiapp_RunBoardMenu() opens or loads a board connection, then naiapp_query_CardIndex() and naiapp_query_ModuleNumber() pick the board and module slot (opened under the hood by naibrd_OpenDevice()), giving you the cardIndex / module / channel coordinates every naibrd_AD_* call takes. When you write your own program, you do the same — see Opening a Software Handle to Your Board.

Configuring a channel and reading a measurement looks like this (the calls the AD BasicOps sample uses):

/* SSK 1.x */
int32_t maxCh = naibrd_AD_GetChannelCount(modId);
 
/* Configure channel 0 for a bipolar reading at your range */
naibrd_AD_SetRange(cardIndex, module, 0, NAI_AD_RANGE_MODE_BIPOLAR, range);
 
/* Read the measured value in engineering units (volts) */
naibrd_AD_GetVoltage(cardIndex, module, 0, &volts);
 
/* Latch all channels first for a coherent snapshot (module-level in 1.x) */
naibrd_AD_SetLatch(cardIndex, module, NAI_TRUE);
/* SSK 2.x */
int32_t maxCh = naibrd_AD_GetChannelCount(modId);
 
/* Configure channel 0 for a bipolar reading at your range */
naibrd_AD_SetRangePolarity(cardIndex, module, 0, NAIBRD_AD_POLARITY_BIPOLAR, range);
 
/* Read the measured value in engineering units (volts) */
naibrd_AD_GetData(cardIndex, module, 0, NAIBRD_AD_MODE_VOLTAGE, &volts);
 
/* For a coherent snapshot, latch the channel first (per-channel in 2.x) */
naibrd_AD_SetLatchChannel(cardIndex, module, 0, NAI_TRUE);

For buffered, high-rate capture, the module’s FIFO stores a stream of samples you read with naibrd_AD_ReadFIFORaw() — see the FIFO sample below.

Run it: AD BasicOps (SSK 2.x) · AD FIFO (SSK 2.x) · AD BasicOps (SSK 1.x). For the full set of AD sample apps — and how to build and run them — see the sample-application guides: Using NAI SSK 2.x Sample Applications · Using NAI SSK 1.x Sample Applications.

Hardware capabilities and status monitoring

This section covers what the AD hardware provides and what you can monitor — for how to drive each operation (with the 1.x/2.x APIs), see Features above.

Hardware capabilities. Every AD module backs those operations with a fixed anti-aliasing filter plus a programmable digital low-pass filter per channel, FIFO buffering with triggering and optional time-stamping, simultaneous latch for coherent cross-channel snapshots, and continuous + power-on BIT that self-tests each channel against an internal stimulus (to 0.2 % full-scale) with no external signal.

Statuses you can monitor programmatically. AD modules expose a set of status registers, most in both real-time (current) and latched (sticky until cleared) forms:

StatusWhat it tells youExample constant / call
SummaryWhether any fault is set on a channel — one bit per channel, the single register to pollNAIBRD_AD_STATUS_SUMMARY_LATCHED
BITBuilt-In Test detected a channel faultNAIBRD_AD_STATUS_BIT_LATCHED, naibrd_AD_GetStatus
Power-on BITThe startup self-test completedNAIBRD_AD_STATUS_POWER_ON_BIT_REALTIME, naibrd_AD_CheckPowerOnBITComplete
Open / over-voltageAn input is open or beyond its rangeNAIBRD_AD_STATUS_OPEN_OVERVOLT_REALTIME
Voltage-reading accuracyA channel’s reading is outside its accuracy specNAIBRD_AD_STATUS_VOLTAGE_READING_ACCURACY_REALTIME
Anti-aliasing filterFilter health/statusNAIBRD_AD_STATUS_ANTI_ALIASING_FILTER_REALTIME

Read these per channel with naibrd_AD_GetChanMappedStatus (2.x) / naibrd_AD_GetStatus (1.x), or poll the bit-mapped summary register to check the whole module at once. The AD Summary sample is built around this. ESP2’s status panel shows the same statuses interactively if you’d rather watch them in a GUI first.

Common pitfalls

  • The reading is tiny or pinned — wrong range/polarity. A signal that swings negative needs bipolar; a range much larger than your signal wastes resolution and reads coarse. Set naibrd_AD_SetRangePolarity to fit the signal.
  • A channel reads garbage or rails — open or over-range input. Check the open/over-voltage status; an unconnected differential input floats, and a signal beyond the module’s range over-ranges (and can damage the front end). Note AD1/ADE report open inputs; AD2/AD3 do not.
  • Single-ended source wired with no reference. A differential input needs both legs — tie the source return to the channel’s input (and the module’s analog reference), or the reading drifts.
  • Trying to measure current on a voltage-only module. Current mode exists only on AD3 and AD4; calling naibrd_AD_SetMode(..., CURRENT) elsewhere returns NAI_ERROR_NOT_SUPPORTED.
  • Channels not sampled together when you needed them to be. Multiplexed modules (AD4–AD6) sample in sequence. If you need a coherent cross-channel snapshot, use a simultaneous module (AD1–AD3, ADE/ADF) and/or enable latch (naibrd_AD_SetLatchChannel).
  • Aliasing / noisy readings at speed. Set the per-channel filter break frequency (naibrd_AD_SetFilterBreakFrequency) appropriately for your signal bandwidth.