Hi all,
We've got a project that involves reading up to 6 ADC values simultaneously with a speed of minimum 20KHz per channel. All data channels has to be synced with each other up to an accuracy of ~±100uS. The data-width required is 12-16bits. The 20KHz reading frequency should be quite stable, but a small jitter is acceptable.
With a fast calculation this would sum up to ~20000*6*16 = 1,92MBit/s or 240kByte/s.
As we are using the IMX6UL in another project (with one internal ADC-channel in use) I was wondering if anyone has done or been successfull in modifying the driver to suit this purpose?
We now read our one channel though Sysfs via file-read which is very slow, we can only get sample rates up to around 1KHz while already utilizing 25% of the processor time. Also the sample jitter simultaneously gets really big because of highly differing read-times.
Another approach I was thinking of is adding an external ADC through SPI, but it would be so much easier if directly using the already present internal ADC. Just as the calculation showed a raw data stream of ~240kB/s, I don't think that this would be impossible at all. The data-stream would go to a ring-buffer in RAM and HD-write (FLASH) is only enabled by user input.
Kind regards and all help appreciated,
Jonas Nyberg
Hi Jonas, we are planning to do the same: high-speed sampling of 2 analogue inputs using the internal ADC. Can you advice what path you ended-up following? What have been the results? Thanks!
Hi Gert,
do you need a particular sample rate? It looks like the i.MX6UL(L) ADCs cannot be triggered by a timer. So the only option to control the sample rate is adjusting the ADC frequency, sample time and conversion time.
For higher performance, I would suggest using the SDMA (custom script). Using SDMA usually means to capture a number of samples (e.g. 64, 128, 256, ...) and then raise an interrupt to the ARM CPU. This can greatly reduce the number of required context switches (between user space, kernel and ARM IRQ) and so increase the performance.
Please provide some further details about your application if your problem still exists.
regards
Christian
Hi Christian, many thanks for your kind reply.
A few more details:
So far I havent had an answer on the question if it can actually be done....
We run Linux OS on the NXP chip
Many thanks for any guidance you can give on this - Gert
Hi Gert,
> 1. we like to sample complete vibration time-waveforms, sampled at 64kHz
lets try some calculations for the sample rate. I use the following clock frequencies from my system:
Single Conversion Time = SFCAdder + AverageNum x (BCT + LSTAdder) = 0.150 µs + 1 x (0.75 µs + 0.090 µs) = 0.99 µs
So the maximum sample rate for this conditions would be 1 / 1 µs = 1 MHz. Now lets try to find suitable parameters for 64 kHz. Lets decrease the ADC frequency:
After further adjusting the sample time (LstAdder) and the AverageNum, you should be able to get something around 64 kHz (but only approximately, not exactly).
> 2. preferably this is done on both ADC inputs simultaneously
One ADC cannot convert multiple channels simultaneously. Depending on the i.MX6UL(L) model you are using, you may have to ADCs. These ADCs are not coupled in hardware, but you should be able to start conversions on both ADCs with only some CPU cycles delay. For instance the SDMA is clocked with 66 MHz. Even if you would need 10 SDMA clock cycles to start the 2nd channel, this would be 0.15 µs (about 1% of the conversion time).
> 3. the length of the time-waveform would be max. 2 seconds = 128k samples
The count field in a SDMA buffer descriptor is limited to 16 bit (65535). But in a custom script this wouldn't matter. Only the size of the memory allocated by kmalloc must be big enough, that shouldn't be a problem.
> 4. I've been reading the nxp manual on this chip but didn't read about the sdma also able to work with the ADC.
In IMX6ULLRM.pdf, section 3.3 – "SDMA event mapping", you can see that both ADCs have event lines connected to the SDMA. I think the SDMA scripts provided by NXP are not usable for ADC, but you could write you own ones. In my current project, I use ADC1 together with the SDMA.
> 5. I also haven't found a ready driver which can pick-up complete time-waveforms at a high frequency
Similar answer as for question 4: The provided driver (vf610_adc) is not suitable for this. If you have some experience in writing Linux drivers, you could write you own driver which receives the 2x128k samples from the SDMA (after the conversion has been completed).
> 6. We would want to pick-up such a time waveform once / minute.
If you are able to process the data within this time, this shouldn't be an issue.
Conclusion:
I assume that your application can be implemented using both ADCs together with the SDMA. There is no pre-built solution for your task, so you would have to build you own. If I would do the task myself, I would calculate about 2 weeks full time for this (I have already some experience with Linux device drivers and also with SDMA). If you start from zero, I would calculate much more.
If you want to go this way, for SDMA development you have 3 options:
regards
Christian
Hi again,
Anyone have any experience with this?
I also saw that a newer driver version of the Vf610 adc should be compatible with the continuous capture mode now?
Would it then be faster if the driver and adc capture would work independently and your own program would only read the results at a set read rate, for example 20KHz. Although not via sysfs.
Kind regards and all help appreciated,
Jonas
Hi Jonas
in general one can also consider option with EIM connection. Using sysfs may be slow,
for reducing delays one can try to write small adc application in assembler.
Best regards
igor
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------
Hi Igor,
Thanks for your reply. Yes I have noticed that sysfs is very slow. How about accessing the memory/registers that holds the values directly from my C++ program?
Or does a sysfs read first trigger a read command and then store the value and then read it? I read somewhere that the current driver doesn't support continous read.
Br,
Jonas