Experimental Notes on the National Instruments NI 4462, and data-capture under Linux, using C.
The National Instruments NI PCI-4462 is a 4-channel differential-input 24-bit data-capture PCI card.
The signal:noise ratio is genuinely impressive: (118 dB dynamic range, and 6 gain settings for input ranges from ±316 mV to 42.4 V). It can sample at up to 204.8k samples/second on all 4 channels in parallel, and may beexternally triggered.
Although it is normally used in LabView under Windows, there is a a C-library, DAQmx. The underlying ADC is a pair of AK5394A delta-sigma ICs.
The NI4462 can not do jitterless triggering, fast turarnound between tasks, sampling-at-will (one sample per falling-edge clock input), or disable the internal hardware/software low-pass filter. We didn't know that when we purchased it!
We solved the installation problem, wrote some programs for it, and learned about, documented, and (sometimes) worked-around its quirks. It's all released below; software is GPLv3+ (with the necessary exemption for libdaqmx).
Kernel: NI provide a binary-blob Linux kernel driver which only supports old 32-bit kernels. We hacked it to run under kernel 2.6.29 (supplied with Mandriva 2009.1, the only kernel/distro that could simultaneously support both the NI4462
and the motherboard's ethernet chip). Here's what we did. A particular "highlight" is that the NI Kernel Abstraction Layer (nikal.c) relies on init_mm, a symbol which was unexported after
2.6.28; a workaround is to patch nikal.c, with the following:
struct mm_struct *init_mm_hack = ( struct mm_struct * ) 0xc04e41a0; // grep init_mm /proc/kallsyms
#define init_mm (*init_mm_hack) //Never compile this on a different kernel
100MHz Clock export: There is no "officially supported" way to export the constant free-running master 100MHz clock (nor the 10/20 MHz clocks) from the NI4462. However, with a soldering iron and a FIN1001/FIN1002 pair, this is possible.
For details, see this post and this photo.
Sample clock export: It's much easier to export the sample-clock, or the trigger, using the RTSI interface; details are in my experimental notes below.
These are the main programs written to use the NI4462. There are also soeme utilities and experiments described in the README.txt:
- ni4462_test - for experimentation, characterisation and data capture. It configures the NI 4462 in various modes, setting up the voltage-range, input-channel(s), sample-frequency, sample-count, input-coupling,
terminal-mode and triggering, and is then used for data-capture. This file is also commented in great detail, serving as example documentation and exploration of the NI DAQmx C-library.
- ni4462_capture - used for our IR camera; less customisable than ni4462_test. Outputs statistical summary data, rather than raw reads.
- ni4462_check - a simple shell-script to check for the presence of the NI 4462 device (by lspci). (see also nilsdev.)
- ni4462_voltmeter - a simple wrapper for ni4462_test to act like a voltmeter.
- ni4462_speak_noise - a simple wrapper for ni4462_test, that causes the noise std-dev to be spoken once per second. Useful as a hands-free "multimeter"
- ni4462_characterise - measure the exact value of the trigger delay, and characterise the ADC input pulse-response (also uses the PulseBlaster hardware).
Here are my Lab Notes. These can be used to form the missing counterpart to the manual. All the data and plots is included in the tarball below. Some highlights include:
- List of "Gotchas" - traps for the unwary, when using this device.
- Tips - further explanations (by experiment)
- Experiment on triggering and synchronising the device. The PFI trigger input is in fact a "gate", not a "trigger", and has a 5us jitter.
- How to export the master 100MHz clock. How to export other signals via RTSI (and which RTSI signals are available on this device.
- Some noise measurements.
- Identification of bugs: eg looping over taskCommit() will eventually crash.
- Tests and measurements of the precise filter delay.
- Blocking vs non-blocking reads. There are at least 16 permutations to configure DAQmxReadAnalogF64(), not all of which work.
- Measurement of the performance of the Task*() functions. For example, taskStart...taskStop takes an entire 1ms. Rather sub-optimal if we expect to re-trigger (and re-sync) every 100 samples.
- Pre-amp saturation measurements.
- Many different measurements of the digital/timing performance (raw data and plot files included).
- Many different measurements of the analog performance (raw data and plot files included).
- General thoughts on the ADC.
An ideal 200kHz ADC should take one instantaneous measurement (per channel) every falling-edge of the clock-input. It should accept any arbitrary and irregular pattern of trigger pulses, subject only to the constraint that the trigger pulses
be at least 5us apart. The measurement should be an average of the signal over the previous ~1us (so that for example, a sharp spike that ended 10us ago does not affect this sample. Any low-pass filtering should be configurable. For our application,
the NI4462 has 3 major problems:
- It's impossible to have a small group of samples (say 100) in a given task, associated with a single trigger pulse, and then be ready for the next group immediately. The inter-task spacing is at least 200 samples wide. This means we have to
give up on synchronisation during the experiment, and just take 2M samples in a single task and with a single trigger. The timing source and ADC cannot be stay synchronised (within 0.1 sample) for that long, except by the clock-export modification above.
- The offset between the falling edge of PFI0 and the sample-clock has a jitter of up to 5us. Rather than start the sample-clock on receipt of the trigger pulse, the NI4462 actually free-runs the sample clock at 200kHz, constantly discarding the
data; then after a trigger, it just keeps the next N samples.
- The NI4462 forces the Nyquist rule of low-pass filtering (both in the analog front-end and the digital side). That would be fine if we cared about the frequency spectrum of a constant stream of data. But it makes the device useless for multiplexed
inputs (one sample per pixel, moving the the next pixel between samples), and it also assumes (mathematically speaking) that we know nothing about the phase of the sample clock wrt the signal. In our case, we are trying to read the amplitude of a sawtooth
wave and we know exactly what the phase relationship is, but the Sigma-Delta ADC cannot take advantage of this, so the information is discarded.
In summary, we really need the NI4462 to be built on a 24-bit version of the AD7677, or LTC2378-20!
- Prerequisites: to install NI's kernel driver, see this howto. Also, install NI's libnidaqmx. This will only work on a 32-bit system.
- [Alternatively, build with the daqmx_dummy.c file ("make dummy") - this supports a limited subset of fake DAQmx() calls to allow ni4462_test to build, even on 64-bit without having libnidaqmx installed.]
- For ni4462_characterise, the PulseBlaster, Arduino, and maths parts of the PhD software release are also required, as is the corresponding hardware.
- To install this software, simply: make && sudo make install. Then run, for example, ni4462_test.
- This is Free Software released under the GNU GPL v3+ (except for the exemption to allow linking with the proprietary libdaqmx). Please feel free to take it, modify it, package it etc.
- Author: Richard Neill. Do ask if you would like further information and assistance.
This was originally written as part of my PhD Infrared Camera system. It should be applicable for wider usage.
Other programs in the same release may also be useful, especially the pulseblaster, arduino, and mathematics sections.
Some selected files, from the tarball:
Return to all programs, site home.