State of Raspberry Pi ADC support in 2023........ - Page 1
Forum section: electronics / projects

author: Smokey
author_rank: Super Contributor
timestamp: August 17, 2023, 11:10:53 pm
content: The original Raspberry Pi was released in 2012. It has had essentially the same expansion interface this whole time.As of now in 2023, there appear to be a whole two (2!) analog to digital chips that are supported on expansion boards.MPC3008 = 8 Channel, 10b, SAR, SPI (200ksps)ADS1015/ADS1115 = 4 Channel, 12b/16b, SD, I2C (3.2ksps)(There is also a board that has a STM32F030 configured as an 8-channel 12b ADC, but that doesn't really count)Out of the literally thousands of ADC chip options, why those parts? And why ONLY those parts? Why no 12b or 16b parts with SPI and a higher sample rate?The strange thing is that it's not like it's just one company making expansion boards and that just happens to be the parts they used. There are multiple companies that make ADC expansion boards and they all use those same two parts.Yes, I know... I should stop complaining and go make my own board and software support for whatever parts I want... It's just strange that "The RPi Community" is so limited in expansion options here.If you know of other parts with software support, point them out. It would be great if there was at least a 12b SAR ADC with decent sample rate suport.https://learn.adafruit.com/raspberry-pi-analog-to-digital-converters/overviewhttps://www.ourpcb.com/raspberry-pi-adc.htmlUpdate:(Potentially) Ads7138 = 8 Ch, 12b, SAR, I2C (140ksps)https://github.com/nesteroff/ads7138-linux-driverhttps://www.ti.com/product/ADS7138https://www.ti.com/lit/ds/symlink/ads7138.pdf

author: thm_w
author_rank: Super Contributor
timestamp: August 17, 2023, 11:44:41 pm
content: I would assume if there is a linux driver for it its not too hard to implement?https://stackoverflow.com/questions/63618710/how-to-talk-to-this-a-d-converter-in-linux-ads7138But I don't see any low cost modules for this one.I would look around at what modules are available for what you want to do, then check if linux driver exists. Then you'll just have to have a few jumper cables going to the raspi header.https://iosoft.blog/2020/06/11/fast-data-capture-raspberry-pi/https://hackaday.io/project/20455-20msps-adc-raspberrypi-hathttps://digibird1.wordpress.com/raspberry-pi-as-an-oscilloscope-10-msps/

author: langwadt
author_rank: Super Contributor
timestamp: August 17, 2023, 11:52:38 pm
content: because making boards for parts that already have a driver is easythey don't want to bother with distributing or getting a new driver into the distribution

author: Smokey
author_rank: Super Contributor
timestamp: August 17, 2023, 11:53:02 pm
content: Quote from: thm_w on August 17, 2023, 11:44:41 pmSweet. That looks like a good option. Bummer it's I2C, but I think it will still work. I'll have to try that dude's driver and see if it works. I'm making my own board so no problems there. Thanks!(Potentially) Ads7138 = 8 Ch, 12b, SAR, I2C (140ksps)https://www.ti.com/product/ADS7138https://github.com/nesteroff/ads7138-linux-driverhttps://www.ti.com/lit/ds/symlink/ads7138.pdf

author: PCB.Wiz
author_rank: Super Contributor
timestamp: August 18, 2023, 04:43:08 am
content: Quote from: Smokey on August 17, 2023, 11:10:53 pmIf 12b is ok, there are a shipload of small MCUs with 8b ADC's that can talk UART to the Pi. Often they are cheaper than dedicated ADC's (eg that Ads7138 is not exactly cheap)If you need 14b/16b or more, then the MCU offerings thin out rapidly.

author: Smokey
author_rank: Super Contributor
timestamp: August 18, 2023, 07:14:07 am
content: Quote from: PCB.Wiz on August 18, 2023, 04:43:08 amUsing a microcontroller just as an ADC for another processor adds unnecessarily complexity in this/most cases. The RPi is already doing all the required processing. It can directly control a dedicated ADC fine without having another device to program and support. If you had the need for additional real time processing like motor control, or additional peripherals like quad encoder interfacing or something, then ya, go with the co-processor. But you probably don't need the Raspberry Pi then.

author: Nominal Animal
author_rank: Super Contributor
timestamp: August 18, 2023, 12:59:22 pm
content: The Raspberry Pi Foundation and community tend to not be pleasant to work with for an outsider (based on my own experience and that of many Linux developers I've discussed about it). Thus, drivers for widely used existing Arduino ADC modules tend to be written by Raspberry Pi enthusiasts only.There are common and cheapish modules such asADS1232/ADS1234for 24-bit, 10 or 80 SPS, with two or four differential inputs, and a serial output that you can read using SPI (SCK+MISO), but which is not compatible with having other SPI devices on the same bus. You can also easily just bit-bang the interface. There are no registers, it is configured using the pins, including the gain; maximum input voltage range is ±2.5V (each input being within 0V and the positive supply rail, but maximum differential input is between -2.5V and +2.5V). If you configure the DOUT pin as an input and set an interrupt on the falling edge, you get an interrupt when the conversion is ready, and can just clock the bits out using the SCLK pin. The inputs are high impedance (at maximum voltage range, draw just 3 nA of current maximum), so you can use a voltage divider to scale higher input voltages down.ADS1256(24-bit, 30kSPS) four differential channel, eight single-ended channel boards are also available at eBay etc., and it has a SPI-compatible interface. These have been popular in China. Waveshare makes aboardthat has both C and Python examples for Raspberry Pi users.In general, I would suggest you look at interesting ADC modules created for Arduino users first, then check if someone has written a Raspberry Pi driver for one.

author: Karel
author_rank: Super Contributor
timestamp: August 18, 2023, 02:26:10 pm
content: Pay attention.Most dedicated ADC chips don't have some kind of (FIFO)buffer and they usually require that an available samplemust be read by the host before the next sample arrives.So, if the ADC is running at, for example, 1KHz, The "data ready" pin output of the ADC signals 1000 times per second.This pin should be connected to a GPIO pin of the host which triggers an interrupt.In practice, generating 1000 hardware interrupts per second and using a multitasking OS that doesn't supportinterrupt priorities and nested interrupts, causes delays in the servicing of the interrupt and thus lost samples.As a result, data integrity cannot be guaranteed. The only reliable solution is the use of a dedicated MCU (or FPGA)between the ADC and the host. That MCU runs some non-hosted code that can easily deal with the high interrupt rateand buffers the samples so that they can be transported to the host in bulk.Rationale: the Linux kernel can only handle one hardware interrupt at a time. If your interrupt arrives just after another hardwareinterrupt, your interrupt will be handled only when that other interrupt has finished. If that other interrupt takes too much time,a new sample has arrived before you could read the sample before.For hobby projects and/or low samplerates, the missing samples are not a problem but for professional use this is usually notacceptable (for example medical devices like ECG and EEG).And yes, I know about "FIQ" (Fast Interrupt) in Linux but that requires advanced Linux kernel programming skills and if I remember well,the FIQ is already in use on the RPI for other purposes...

author: Scottie
author_rank: Contributor
timestamp: August 18, 2023, 02:45:39 pm
content: I have only started tinkering with Industrial IO in linux, but it looks promising.Take a peak at some of ADI's sample projects:https://wiki.analog.com/resources/tools-software/linux-software/kuiper-linux/project-list

author: dobsonr741
author_rank: Frequent Contributor
timestamp: August 18, 2023, 02:46:25 pm
content: When it comes to fast data acq no need to stay with the Linux kernel. The Circle bare metal framework gives you precise control, including DMA and all the high perf toptions you need to integrate with any ADC.Circle on github:https://github.com/rsta2/circleDocs:https://circle-rpi.readthedocs.io/en/latest/index.html

author: Nominal Animal
author_rank: Super Contributor
timestamp: August 18, 2023, 05:59:56 pm
content: For higher bandwidths (say, up to 200 Mbit/s = 25 Mbytes/s of data), I like to use high-speed USB, and especially Teensy 4.0. Its own internal ADC can do 1 MS/s at 12 bits (with about 10 effective bits), and 1.8 MS/s at 8 bits. I also like to pair that with a much slower 16-bit or better, external ADC, with an internal or on-board voltage reference module. Mostly, I do this with Linux SBCs and switches and such, not so often with desktop stuff, so I assume it is kinda-sorta comparable to some Raspberry Pi users' needs.If suitably buffered (with an opamp), the two ADCs can be connected to the same input source, so I can use the slower external ADC for precise voltage measurements when it is stable, but detect the presence of noise or spikes at up to 100 kHz or so. The higher accuracy external ADC can also be used to "calibrate" the internal ADC readings, especially if both support more than one input, and one of those inputs can be used for at least two calibration voltage levels via a simple analog multiplexer circuit: as long as both sample the same voltage after the multiplexer, the exact voltage and losses in the multiplexer do not matter, as we are calibrating the fast-but-not-so-precise ADC against the more precise ADC.One use case is to use one an instrumentation amplifier or dedicated current sense amplifier with a low-value current sense resistor, and one channel to measure the voltage drop over the current sense resistor, and a second channel to measure the voltage after the current sense resistor, to keep track of the supply voltage and current draw by some device. This use case is actually pretty important, because many SBCs have "spiky" current draw, and not enough filtering on their supply lines, requiring much beefier power supplies to work reliably than one would estimate based on theiraveragepower draw. The depth of the spikes, and their effect on the supply voltage, vary from SBC to SBC, so any mitigation/filtering will also vary. Measuring it is the first step. It will also tell if there is a possible power supply cause to glitches sometimes seen in SBCs, or whether it is something else (especially software/driver issue). Which is why short sampling windows do not suffice, and we actually need to stream the data continuously to a computer, and why I use Teensy 4 for this: it has a native high-speed USB interface (480 Mbit/s), and even using the standard USB Serial interface available in the Arduino/Teensyduino environment can do 200+ Mbit/s reliably long-term (in one direction) in my own testing.

author: Smokey
author_rank: Super Contributor
timestamp: August 18, 2023, 11:30:29 pm
content: Quote from: Karel on August 18, 2023, 02:26:10 pmYa, that is an excellent use case for a coprocessor doing the ADC conversions. The buffering and interrupt issues could certainly be a problem. I'll have to look into that more. Good call. Thanks.

author: SpacedCowboy
author_rank: Frequent Contributor
timestamp: August 20, 2023, 04:44:19 pm
content: So here's something I recently ran across, which was new to me. I was going to post in the FPGA forums about it eventually (since I'm interfacing to an FPGA), but this seems an appropriate place too. The Raspberry Pi (all versions) have something called the SMI ("Secondary Memory Interface") which is an 8080/6800 bus interface on alt-1 of the GPIOs. If you use the full bus, it takes pretty much all the GPIOs but you can trim it down to what you need.The SMI has DMA, so once you set it up, it will happily deliver you data - and in fact there's a kernel module overlay which provides user-space control over where the data is sent / received.The bus can run at up to 125MHz - though the GPIOs on the Pi are only rated to 75MHz, so caveat emptor, and a further constraint is that there seems to be a firmware problem when the combined CPU, GPU, and SMI busses are all trying to over-saturate the limited internal bus bandwidth - so don't push it *too* far. Still, it can apparently reliably transport 5-600 mbit/sec of data into user-space on the Pi. You have control over the setup/hold/etc. parts of the signalling down to 4ns resolution.This is sort of a revelation to me, because if you don't want the turnaround time latency of USB, there really wasn't much of a way to get data into the Pi at high speed, as far as I knew. For the record, the approach I've been taking is:Use the most-recent kernel on a Pi3 or above - that gets you (as standard) the RT_PREEMPT kernel, which responds to interrupts in ~50uS. I'm currently using a Pi4, but planning on trying a Pi zero 2W - which has the same chip as the Pi3 as soon as it arrives. Being able to use a $15 chip for this would be useful to meHave the Pi in control of the bus and have an interrupt-request GPIO that signals there's data to be readThe Pi can then send data to address A0 at any time it's not handling an interrupt request (I need bi-directional data)On receiving an interrupt, the Pi sends a direct (non-DMA, immediate) read to address A1, which reads out as the number of words available to readAfter reading the value, set up a DMA request to read that many words from address A2The different addresses make it easy for remote logic to figure out what to doData duly arrives in the user-space buffer along with either an interrupt to say so, or a notification via epollThe process for testing this was fairly simple - as I said, get the latest kernel from r-pi, and doCode:dtoverlay smidtoverlay smi-devThen you have a /dev/smi interface (and you've lost most of your GPIO, the default setup uses the entire SMI bus). Here's a test I did using the above, reading data at ~50MBytes/sec into a user-space buffer. Ok this isn't an exhaustive test - it only reads 200 bytes - but it shows that it works in principle... The maths here is:4 uS for 100 transfers @ 16-bits per transfer => (1000000/4) * 100 * 2 => 50,000,000 bytes/sec.If you're really lucky, your peripheral will have an 8080/6800 bus available, and you can talk directly. I'm not that lucky - I have an FPGA with some logic on it interfacing to another bus. There are ADC's out there which will integrate directly though, in factthe first placeI found out about the SMI was using an ADC as the peripheral... This site doesn't use the /dev/smi interface though, he's actually memory-mapping the SMI registers and writing to them directly.I'm currently trying to decide between using this and high-speed USB (via an FT232H on the FPGA) to bridge the gap to the Pi. I want the Pi to be relatively free of CPU load (which both provide), I want low-ish latency (USB Is probably fine, even if it's ~2x on turnaround) and USB is more "known about" than this interface, but it does seem pretty simple to use (getting a Pi set up to do that test above took about an hour, and that was stumbling about trying to figure stuff out that I hadn't used before).I am somewhat shocked that an interface which is pretty standard (8080/6800), is high-bandwidth, is easy to interface to, and is on every Pi for the last decade isn't more widely known... I guess SPI and I2C are more common use-cases because there's little-to-no documentation about it in the commonly-found data sheets on the Pi. I've attached a relatively-hard-to-find PDF of the bus signalling in case you're interested...Enjoy

author: SpacedCowboy
author_rank: Frequent Contributor
timestamp: August 20, 2023, 04:45:30 pm
content: Gah. No matter what I select on the image option when attaching it, I can never get it to appear inline. Oh well - it's still fairly obvious what ought to be where...

author: Smokey
author_rank: Super Contributor
timestamp: August 20, 2023, 11:20:06 pm
content: Quote from: SpacedCowboy on August 20, 2023, 04:45:30 pmhttps://www.eevblog.com/forum/news/(how-to)-testing-inline-image-attachments/msg5021542/#msg5021542

author: NiHaoMike
author_rank: Super Contributor
timestamp: August 21, 2023, 04:49:05 am
content: For more modest requirements, up to 768kSps, it's possible to use the I2S input.

author: Smokey
author_rank: Super Contributor
timestamp: August 23, 2023, 12:13:00 am
content: Quote from: NiHaoMike on August 21, 2023, 04:49:05 amI thought that was exclusively digital audio. What sort of hoops do you need to jump through to get ADC data over I2S, or are you suggesting using an audio MIC input chip or something that already knows how to talk I2S?

author: NiHaoMike
author_rank: Super Contributor
timestamp: August 23, 2023, 03:02:24 am
content: Quote from: Smokey on August 23, 2023, 12:13:00 amThere are ADCs that natively output I2S. At least some of them will be perfectly happy being DC coupled as long as the input voltage stays within range.

author: Smokey
author_rank: Super Contributor
timestamp: August 23, 2023, 03:11:58 am
content: Quote from: NiHaoMike on August 23, 2023, 03:02:24 amThat's interesting.. Digikey has 13 ADC parts that use I2S, but only one is under $37. (with lots out of stock or discontinued)This one is only $4.51 in 1s. 2-channel, 32bit, 192kHz:https://www.mouser.com/ProductDetail/Asahi-Kasei-Microdevices/AK5522VN?qs=vvQtp7zwQdMGuFrShWk0gw%3D%3DI need at least 4 channels for the thing I'm trying to do at the moment, but if you only needed two, and you didn't mind having to write some linux code to grab the raw samples from the audio system, that seems like a plausible solution.