Electronics > Beginners
help with rapid ADC data aquizition
rstofer:
I first mentioned the external ADCs and now that it has come up again, it's important to figure out if the sampling and transfers can be automagic. If there needs to be a major exchange of commands just to transfer a single sample, DMA isn't going to work. DMA wants a stream of data, not chit-chat.
It will be worth the time to figure out whether the internal ADCs are adequate because they likely can be connected through DMA. Nevertheless, this needs to be proven.
In a perfect world, the foreground task wouldn't be involved with transfer at any stage. It would simply set up the DMA registers and sit back and watch (for the next DMA register update).
This whole project is going to be built around data flow, not some superloop of code.
tooki:
--- Quote from: jhpadjustable on December 09, 2019, 06:58:02 pm ---
--- Quote from: tooki on December 09, 2019, 12:43:34 pm ---Arduino’s raison d’être is to make it easy for beginners to, well, begin. It’s quite uncalled for to disparage beginners for not being experts in electronics and/or programming.
--- End quote ---
It's a fair cop. I've toned it down.
--- End quote ---
:-+ Thank you!
--- Quote from: mikerj on December 09, 2019, 10:03:06 pm ---
--- Quote from: tooki on December 09, 2019, 12:43:34 pm ---
--- Quote from: jhpadjustable on December 07, 2019, 03:40:44 pm ---Your Arduino mate was doing it wrong. He would have had better luck if he batched up a whole sector of data before writing it out, and I bet he was also formatting the output as text instead of binary. (But the Arduino fans don't usually think at this level...)
--- End quote ---
Arduino’s raison d’être is to make it easy for beginners to, well, begin. It’s quite uncalled for to disparage beginners for not being experts in electronics and/or programming.
--- End quote ---
Arduino makes it easy and fast to do things the wrong way. OTOH replace the Arduino ecosystem with a conventional C compiler and decent editor, and the boards and shields are cheap and useful for all sorts of things.
--- End quote ---
No doubt. But nonetheless, getting it done at all is still hugely valuable as a learning tool. I can say confidently that without Arduino, I would never, ever have even begun dabbling with MCUs, because as a non-programmer, I would never have been able to successfully interface with all the chips and components for which ready-made Arduino libraries exist. My programming skills are too basic to be able to implement interface timing, etc. Also, the Arduino ecosystem has produced hundreds of little breakout boards with (usually) decent minimal viable circuits. I can’t really say how many n00b mistakes I would have made if I’d had to try and get just the bare chips and stuff working. And finally, Arduino really brought down the cost of entry, given that historically, dev boards, EPROM programmers, IDEs, etc cost a lot of money. Would eBay be chock full of $2 ISP programmers if Arduino hadn’t come along? Maybe, but I doubt it.
So Arduino is fantastic for getting people into MCUs. And then, little by little, one can transition to using fewer premade components and libraries. (For example, I’m now starting to use bare Atmega chips instead of Arduino nanos, etc.) But many of us never will move past Arduino, simply because we aren’t programmers and don’t really aspire to be. And that’s OK. Don’t deny and begrudge us our successes just because it’s not the “optimal” way to solve a problem.
Nominal Animal:
Excellent points, rstofer.
It looks like Teensy 3.2, 3.5, and 3.6 (but not LC or 4.0) have sufficiently accurate SAR ADCs (two of them!) to get 200,000 samples/second. One does need to reduce the number of samples averaged (from the default 32) to 16 or less, but that should still leave at least 12 meaningful bits in the result, I think; I haven't verified this.
I don't think there is a way to DMA data from different analog input pins using a single ADC. I could be wrong, though.
I would try a periodic interrupt that triggers the next conversion on the current ADC, then reads the conversion result from the other ADC, and selects the input pin for the next-next sample (the current ADC). It has no waits or anything like that, so even a high-sounding rate like 200,000 interrupts per second should work okay.
I do not know if the overhead of such an interrupt is too much for SD card transfers. The interrupt can only occur between byte transfers, so it is a matter of if the interrupt causes stretches a SPI clock cycle between bytes too long.
20 channels is pushing Teensy 3.2 to its limits (and half of those analog input pins are on pads underneath, which are a bit tricky to connect to), but might work fine on a 3.5 or 3.6, as they have a much higher clock rate, and the analog pins are easier to access. I don't have a 3.5 or 3.6 myself to test, though.
I took a looksee at the AD7606 datasheet.
It turns out AD7606 can do 200 ksamples/second per channel, and can support both ±10V and ±5V analog voltage ranges when powered from 5V (AVcc) while the logic voltage levels are 3.3V (Vdrive). Darned interesting to my needs as well; I wonder why I haven't encountered it before! The modules at fleabay are suspiciously cheap compared to the chips themselves, although they look a lot like the circuit note.
It is completely controlled by logic-state pins (i.e., no command input, and only output is sample data; mode is set by tying control pins high or low), and is rather simple to operate. It has three main modes: serial output, byte output/8-bit parallel output, and 16-bit parallel output.
To trigger a new sample (all channels are sampled simultaneously), you pull CONVST(s) high. Within 45ns, the AD7606s pull BUSY high. It will stay high for up to 4.2us (longer if oversampling is enabled). When an AD7606 pulls BUSY back low, the samples are available.
To read the 8 samples in serial mode:
SCLK is high. The microcontroller pulls CS low for the AD7606, and waits 35ns or longer. Then, it starts pulsing SCLK (down) 128 times at a maximum frequency of 15 MHz (and duty cycle between 40% and 60%, so this must be a single noninterrupted SPI transaction). On each rising edge of SCLK, the microcontroller receives the next bit on the DOUTA pin. After the 128 bits, the microcontroller pulls CS high.
The byte mode is very similar:
RD and CS are high. The microcontroller pulls CS low, and RD low for at least 30ns, for the AD7606. On each rising edge of RD, the next 8 bits are available on DB7:0. RD must be low for at least 30ns, and high for at least 15ns, so the max RD rate is about 20MHz at 3.3V VDRIVE logic levels. After the 16 bytes (rising edges of RD), the microcontroller pulls CS high.
The 16-bit parallel mode supports a linked CS and RD mode:
RD and CS are is high. The microcontroller pulls both low, and waits for at least 30ns (at 3.3V VDRIVE), then reads the sample from DB15:0, and pulls both high again. After at least 22ns, it can repeat this for the second channel; and repeat for all eight channels.
In the byte mode, an inline assembly routine on Teensy 3.2/3.5/3.6 can read the eight samples in about 1us per AD7606.
With three AD7606s/24 channels, and using an interrupt (the AD7606s can share the data lines, as long as only one has its CS low at any time), this is 30,000 interrupts per second, and 30ms or so of execution time, per second. Not bad at all. Whether the latencies caused by the 1us interrupts are too much jitter for the SD cards, I do not know. (It is equivalent to about 25 cycles of the SD card SPI clock running at 25MHz, but only occurs between byte transfers, not mid-byte.)
So, it seems to me, trying out the built-in ADCs on a Teensy 3.5 or a 3.6 would be the way to go.
If they don't give good enough results, I'd go for the AD7606s, unless something better is found.
If the code to handle both the sampling and the SD card storage on a single Teensy is too complicated, then I'd use two, connecting the two using UART for commands, and SPI for sample data. Then, the one storing the data to an SD card can definitely use DMA for the data (being SPI slave), and having enough RAM for buffering the data, can use the standard SdFat library to write the data to a standard FAT filesystem on the SD card, with a loop that just tries to keep up with the DMA. (The DMA is connected to a completion interrupt, which sets up the next chunks, with at least a dozen or so such chunks in your buffer.)
Teensy 4.0 should be able to control three AD7606s in byte mode. The data pins would be 16-23 (DB0 pin 19, 18, 17, 16, 22, 23, 20, DB7 pin 21); pins 0 and 1 for UART; pins 10-13 for SPI; CONVST on pin 14 and RD on pin 15; and the three CSs, three BUSYs and RESET somewhere on pins 2-9. There are an additional ten pins on the bottom of Teensy 4.0 on pads, but they're a bit tricky to solder to, but if used, would allow expanding to a fourth AD7606 for 32 channels. Teensy 4.0 would be the SPI master, although only providing CS, SCK, and MOSI/data out. The CONVST pin would be a PWM or timer output, for optimal sampling stability while still allowing precise sample rate control.
The UART is used to set the sample rate and select the channels sampled (well, ALL are sampled, but only some are forwarded), with say a single-byte "OK" or "Error" acknowledgement (for simplicity and ease of use).
The nice thing is that if connected to USB, it could switch to USB mode, and since Teensy 4.0 has a 480Mbit/s USB interface, could provide up to the maximum 200,000 samples/second per channel for all 24 connected channels, making the same thing useful as a AD7606 data acquisition controller.
If my Christmas budget allows (I'm broke :-[), I'll get a couple of those AD7606 modules off fleabay, and try them with my Teensy 4.0.
powerfly:
Just wow, I am surprised by the sheer number of replies from so many different members. Thank you so much for all being willing to help me along with my little project. I think I'm going to read the thread again as I definitely did not understand all of the comments above and some of it is a bit too much for me to take in just from reading it once.
My coding is very much beginner level so I'm not even sure what all of the terms discussed mean. If you could elaborate more on technical terms or provide links that describe them that would be helpful.
I'm really hoping that some pre-existing code is freely available as I've seen similar things for an Arduino:
https://forum.arduino.cc/index.php?topic=228549.0&fbclid=IwAR3U5bL_cAvS-P9N1w4Eq5ZJuPOiywBqPmLKXwgcUpS0Ki7DqYYJMuFkP50
https://github.com/greiman/SdFat/blob/master/examples/AnalogBinLogger/AnalogBinLogger.ino
In the links I've posted it's apparently possible to get 40 kHz 10 bit data to an uno, and by looking at the code (github link), I think a much higher rate is possible. The best option at the moment for my needs seems to be the T3.6, which I now have available to me (as well as a T4.0).
Does anyone know if there is an equivalent code to the one above but for ARM based processors such as those on the teensy 3.6? I currently don't have anyway near the coding capability to construct code like the one above and this project isn't primarily about coding, and I have a deadline for it. As the T3.6 has 23 analog in ports which are at least 13 bit, and at least initially I'll be using 8 pins or less it should be able to handle the 12bit 10kHz rate. It's just getting it done in the timeframe with my lack of coding experience may prove challenging.
Edit: I've been reading throught the thread, and looking up the definition of some of the terms and think I have a better idea of what they mean.
There a still many things I'm unsure of because of my lack of experience. I don't know how to set up a buffer, I don't know whether I should use a file system and if I do use one which one I should use etc.
Does the T3.6 have DMA channels built in, are they a software thing or are they external pieces of hardware?
As this is my first major coding project, it would be really helpful if someone knows of any script similar to the arduino one above. I don't even know where to start in constructing code with buffer systems, DMAs or anything similar.
powerfly:
does anyone have experience with coding of that type? Or know of any existing available code of that type?
If that doesn't work I might just have to limit myself to maxing out the RAM and stopping and dumping that to a card and hope that that is good enough, as I'm not sure I have the time to learn how to make a code and then make a functioning code on how to make DMA buffers and stuff :(
Navigation
[0] Message Index
[#] Next page
[*] Previous page
Go to full version