I am seeking clarity from everything I've gathered in my couple weeks of working with the Revolution Pi Connect+ and AIO module. Specifically, I have knowledge gaps when it comes to reading an analog signal with fidelity.
First, my understanding is that the AIO module is capable of sampling rates much faster than what the process image can read. It is not clear to me exactly why this is, but I've taken it as a fact that whatever communication is happening between the process image and the AIO module, it limits the actual maximum sampling rate at around 125 Hz. For this reason, the sample rate must be chosen below 125 Hz for the AIO within PiCtory. I have done this.
I then want to access every single measured value on all four analog input channels. For example, if I were to select 80 Hz as my sample rate, and I acquired data for exactly one minute, I should have exactly 60 seconds * 80 samples per second * 4 channels = 19200 samples. No more and no less. Moreover, I should be able to take it as fact that all 4800 samples of a given channel were measured at 0.0125 second equally spaced intervals in time. This is what I mean by acquiring a signal with fidelity.
However, every program, library, or example I have seen acquires data by running some sort of capture code within some loop. Whether one queries a specific hex location inside /dev/piControl0 via IOCTL system calls, or one uses a higher level library such as revpimodio2, in the end, there is some programed loop running to obtain data from the AIO. This concerns me because the system is not a real-time system. Any loop running on the pi's CPU will run much faster than the maximum 125 Hz sample rate, and I will obtain many repeated values I will not be able to distinguish from their single unique values in time. Any delay I build into my loop to try and match my chosen sample rate will inevitably have jitter due to the non-real-time system's changing CPU priorities. In the end, my current understanding of the system does not lend confidence in obtaining signals with fidelity.
Can anyone point me to some resources or examples which can help increase my understanding and thereby confidence that I can perform signal processing with fidelity?
BACKGROUND: I typically use the MCC118 DAQ Hat (https://www.mccdaq.com/DAQ-HAT.aspx) on the raspberry pi. This device is capable of 100 kHz analog acquisition. It works by jamming all measured values into a real time buffer. My task as the developer is then to simply grab the data accumulated within this buffer and clear it, and to ensure I do this routinely before the buffer runs out of memory. The buffer query is then looped in my program, and it returns a list of all recorded values accumulated between the last query and the present one. Because this query loop is ran on a non-real-time system, the returned list does not have a guaranteed length. This is easy to deal with in my processing loop. However, I was looking for something a bit more industrially hardened, and decided to try the Revolution Pi. However, the revolution pi does not seem to operate in the way I am use to. My present understanding is that there is no real time buffer, and I only have access to the present value being measured at the AIO channel terminal at the time I query it. This means that the temporal spacing of my recorded values deviates as a function of the unknown CPU prioritization, rather than any type of real-time clock cycles on the A-to-D device in the AIO module itself. Do I have a misunderstanding?
Reading signal from AIO with fidelity?
Re: Reading signal from AIO with fidelity?
Hi Jacob,
thanks for your detailed description of what you want to archive with the RevPi and AIO extension module.
The module communication is handled by our kernel driver piControl which runs with rt priority. As you already noticed all IO data is exposed cyclically via /dev/piControl. The cycle time depends on the number and type of your extension modules and is stored in the process image variable RevPiIOCycle (read with piTest -r RevPiIOCycle). For each AIO module the cycle time will increase about 4 ms. A bit more context was explained here: https://revolutionpi.com/forum/viewtopi ... 2205#p8175
Nicolai
thanks for your detailed description of what you want to archive with the RevPi and AIO extension module.
The module communication is handled by our kernel driver piControl which runs with rt priority. As you already noticed all IO data is exposed cyclically via /dev/piControl. The cycle time depends on the number and type of your extension modules and is stored in the process image variable RevPiIOCycle (read with piTest -r RevPiIOCycle). For each AIO module the cycle time will increase about 4 ms. A bit more context was explained here: https://revolutionpi.com/forum/viewtopi ... 2205#p8175
Nicolai
Re: Reading signal from AIO with fidelity?
Thank you for this reply, Nicolai. However, you have only shown my how to determine the actual sample period (rounded down to the nearest ms). This does not seem to solve my issue or clarify anything further for me. You have told me the cycle time at which /dev/piControl0 is updated, but not how to read /dev/piControl0 at this identical frequency.
In the end, my realized sample rate is actually the period at which I query /dev/piControl0, not the period at which this file is updated by the piControl driver. I make my periodic queries of this file via some program I write. Whatever program I write, regardless of the language it's written in, will not be given real time priority. Thus, my real sample rate is not real time. Here is an example:
`piTest -r RevPiIOCycle` repeatedly returns `1 Byte-Value of RevPiIOCycle: 5 dez (=05 hex)`. I have taken this to mean the cycle period at which /dev/piControl0 is updated is somewhere between 5 and 6 ms (i.e. on the interval [5, 6) in units of ms). Say the actual cycle time is 5.36 ms or a sample rate of 187 Hz. If I am able to query /dev/piControl0 every 6 ms, or an actual sample rate of 167 Hz, with a reasonable amount of jitter, I create a beat frequency of 20 Hz with the actual sample rate within the process image. This means I would miss a sample every 9th or so data point. In other words, there exists a periodicity in which /dev/piControl0 is updated twice between queries such that I miss one of the values. A similar situation occurs if I am able to query /dev/piControl0 every 5 ms, or an actual sample rate of 200 Hz, with reasonable jitter, except in this case, I read the same value twice every so often. In fact, the only way I can actually get a signal with fidelity is by querying /dev/piControl0 every 5.36 ms, which is not possible as my script is not given real-time priority (this is easily shown by getting the time at each query).
I have played with the kernel's inotify API to see if I can simply detect whenever /dev/piControl0 is updated (i.e. written to by the piControl driver) but I cannot detect these write events. I easily detect read and write events that I initiate from other scripts, but I cannot see when the process image updates bytes within this file. This seems like the only way I would be able to collect data with fidelity. If I can trigger reading /dev/piControl0 every time it is updated. Note that I do not want to read its contents only after it changes, as I may have an analog value that remains constant for some period of time. Instead, I need to monitor every time piControl writes to /dev/piControl0, then query my values of interest directly afterward. Though this still raises the concern that piControl actually has a sample beat frequency with the actual AIO analog-to-digital sample rate. In other words, I chose 80 Hz in PiCtory, but piControl actually reads the value somewhere between 167 and 200 Hz (i.e. the process image's sample rate is faster than the A-to-D, therefore there will be repeated values). It does not appear to be possible to sync the A-to-D sample rate with the process image communication rate, similar to the way I cannot sync my query rate to the process image communication rate.
In the end, my realized sample rate is actually the period at which I query /dev/piControl0, not the period at which this file is updated by the piControl driver. I make my periodic queries of this file via some program I write. Whatever program I write, regardless of the language it's written in, will not be given real time priority. Thus, my real sample rate is not real time. Here is an example:
`piTest -r RevPiIOCycle` repeatedly returns `1 Byte-Value of RevPiIOCycle: 5 dez (=05 hex)`. I have taken this to mean the cycle period at which /dev/piControl0 is updated is somewhere between 5 and 6 ms (i.e. on the interval [5, 6) in units of ms). Say the actual cycle time is 5.36 ms or a sample rate of 187 Hz. If I am able to query /dev/piControl0 every 6 ms, or an actual sample rate of 167 Hz, with a reasonable amount of jitter, I create a beat frequency of 20 Hz with the actual sample rate within the process image. This means I would miss a sample every 9th or so data point. In other words, there exists a periodicity in which /dev/piControl0 is updated twice between queries such that I miss one of the values. A similar situation occurs if I am able to query /dev/piControl0 every 5 ms, or an actual sample rate of 200 Hz, with reasonable jitter, except in this case, I read the same value twice every so often. In fact, the only way I can actually get a signal with fidelity is by querying /dev/piControl0 every 5.36 ms, which is not possible as my script is not given real-time priority (this is easily shown by getting the time at each query).
I have played with the kernel's inotify API to see if I can simply detect whenever /dev/piControl0 is updated (i.e. written to by the piControl driver) but I cannot detect these write events. I easily detect read and write events that I initiate from other scripts, but I cannot see when the process image updates bytes within this file. This seems like the only way I would be able to collect data with fidelity. If I can trigger reading /dev/piControl0 every time it is updated. Note that I do not want to read its contents only after it changes, as I may have an analog value that remains constant for some period of time. Instead, I need to monitor every time piControl writes to /dev/piControl0, then query my values of interest directly afterward. Though this still raises the concern that piControl actually has a sample beat frequency with the actual AIO analog-to-digital sample rate. In other words, I chose 80 Hz in PiCtory, but piControl actually reads the value somewhere between 167 and 200 Hz (i.e. the process image's sample rate is faster than the A-to-D, therefore there will be repeated values). It does not appear to be possible to sync the A-to-D sample rate with the process image communication rate, similar to the way I cannot sync my query rate to the process image communication rate.