NI Acquisition Strategies

On articles related with NI-DAQs and python code, you can see different ways to interact with the DAQ when acquiring analog samples. You will see the use of either QTimers or Threads or NI callback functions.

Note: quick note about the use of the word DAQ throughout this article: DAQ stands for Digital AcQuisition board and it is the instrument used to translate sensor and signal data into a digital format that is sent to a computer to process that data. DAQs have ADCs (Analog to Digital Converters) that are responsible to convert analog to digital signals, and/or DACs (Digital to Analog Converters) that are used to generate analog signals. The concepts of this article are related mainly with the ADC part of the DAQ, but I am going to use the word DAQ since the concepts are more in scope with on how the software interacts with the DAQ than the ADC.

The reader with no experience in programming might get confused reading those articles, and can question what and when to use QTimers, Threads or callback functions. The goal with this article is to hopefully clarify some of these approaches and understand which one is more suitable for your application.

Remember that are pros and cons with any approach, and the way to go is to understand what each technique has to offer and select the one that works best with your application requirements and constraints.

I am going to focus on the acquisition of analog samples, since that is the one that can be the most confusing to set up properly. However, the techniques explained here can be applied in a similar way if your analog outputs or digital inputs/outputs need to be done in a determinist way.

Nyquist and Sampling Rate

Let's Observe Aliasing

Reflections

Anti-Aliasing Filters

If you read the previous sections you know how important it is to sample your signals at the correct sampling rate, otherwise you will get wrong data of your analog input.

When doing the program that will acquire the samples on a normal laptop it can be a challenge to run them at the required sampling rates mainly because you have a lot of programs running in your operating system and your application will most likely not be deterministic.

There are a couple of ways to tackle this problem:

  • If you have access to a RTOS (Real-Time Operating System) (e.g.: RTLinux, or RTAI) you can run your application on the kernel level with deterministic timings.
  • Or try to get a DAQ that has the ability to acquire samples at faster rates for you, and deliver those samples later to your application running on the user level in a normal Operating System (OS).

The code below runs in a normal Operating System, using the NI-DAQ ability to acquire samples at faster rates and deliver those samples to your application that runs at manageable timings at the user level. We can abstract this concept with the diagram below.

  • We will set up the NI-DAQ to acquire at a sampling rate of 2kHz (0.5ms) and after collecting 200 samples we can then use the user level program to get the data and render or process it at a rate of 10Hz (100ms).

The code below is also done in python to make it easier to understand, follow and reproduce. However, similar concepts apply if you do the code in another programming languages (e.g.: C/C++, C#, or Java).

I will be showing 3 different approaches to acquire the data from the NI-DAQ:

  • NI callback functions (Link)
  • QTimers from Qt (Link)
  • Threads: make sure that you read [REF 5] if you are not familiar with threads in Python

The beginning of the code for all 3 approaches is exactly the same:

  • Create an NI Task
  • Configure the NI Task
  • Configure sampling rate and acquisition type
  • Create a stream reader object

After this point is when each approach sets up the task that gets the information from the NI-DAQ accordingly.

NI Callback Function

QTimers

Threads

In summary:

  • Which technique should you use? Use the technique that works best with the rest of the code that you are developing.
  • In terms of being deterministic, the 3 solutions rely on the NI-DAQ to do the heavy lifting, and they are all running at manageable timings at the user level.
  • Callbacks and Threads can be used in a GUI or console application
  • QTimers are only available with PyQt but they can also be used in a console application as long as you create a QtWidgets object and initiate the timer accordingly. I will leave the skeleton code for this case under the Python Files section -> ni_daq_consoleConcurrency_QTimer.py.

Besides QTimers and QThreads, Qt offers other techniques to work with threads (e.g.: QThreadPool, QRunnable, QtConcurrent, and WorkerScript). Check this link if you are interested to understand how to choose an appropriate approach for your application.

NI-DAQ Functions Used

References

Index