How to implement continuous I2C ADC sampling with alernating inputs? - Page 1
Forum section: electronics / general

author: zapta
author_rank: Super Contributor
timestamp: November 04, 2023, 04:58:54 pm
content: TL;DR, how to do alternate ADC/I2C continuous sampling with minimal firmware involvement on each sampling.I need to interface an ADS1115 ADC (I2C ) with a SMT32H750 MCU such that the ADC samples continuously at 100Hz, alternating between mux input 0 and 1. I am using CubeIDE, HAL, and FreeRTOS.Ideally I would like to do it with DMA, getting on each interrupt 50 or so pairs of samplings but couldn't figure out how to do it without multiple MCU code interventions for each sampling. (I was able to do independent DMA alternate sampling with ADS1261 which uses SPI).My question is, how should I structure my code to minimize firmware intervention on each sampling? (Switching to another I2C ADC, with at least 12 bits, preferably more, is OK)The best I found so far, which is not great, involved calling three HAL function per sampling:Perform in a 100Hz Timer:1. Call HAL function to issue an I2C write transaction to write 0 to the ADC address register.2. Call HAL function to issue an I2C read transaction to read register 0 with the ADC value.3. Call HAL function to issue an I2C write transaction to the ADC config register 1 to select the next input and start a single conversionhttps://www.ti.com/lit/ds/symlink/ads1115.pdf?ts=1699079930304&ref_url=https%253A%252F%252Fwww.ti.com%252Fproduct%252FADS1115

author: Siwastaja
author_rank: Super Contributor
timestamp: November 05, 2023, 06:57:50 pm
content: Why do you think it's not great? Microcontrollers (as opposed to application CPUs) are specifically for relatively low latency interrupt processing. 100Hz interrupt for just triggering a DMA operation (or access one I2C register directly through the peripheral register) is total peanuts, even on the smallest M0 MCUs. For reference, I have done stuff like 500kHz interrupts on H750!Another reference point, I have also accessed four I2C sensors at ~500Hz each, on STM32F2 running at some 100MHz or so, withmuchinferior I2C peripheral which does not have usable DMA and even with interrupts, it felt like bit-banging as it required many ISRs per transaction (like: "now create start condition" - "start condition ISR: now write byte" - and so on). Even that worked fine without CPU time issues.If you have performance issues or find HAL inflexible, just ditch it. OTOH, if it works for you, great.Premature optimization is evil. If your current solution is understandable and reliable, measure its performance and only optimize if there's a problem.

author: zapta
author_rank: Super Contributor
timestamp: November 06, 2023, 04:12:33 am
content: With the SPI ADC I was able to do with one DMA interrupt tens of readings, including channel sequencing, so was surprised with the I2C limitation. I ended up setting a FreeRTOS 100Hz timer that triggers the first I2C transaction and and an interrupt chain for the other two transactions of each ADC reading. All operations were done with DMA so I use about 300 interrupts/sec. It works, and I don't know a better way so will keep it.