Electronics > Microcontrollers

Is it possible to synchronize the ADC and a multiplexer channel sweep on STM32 ?

(1/2) > >>

Hello. I face the following situation:

A STM32 (STM32H7B0 in my case, though if a general solution exists, all the better) is connected via a limited number of lanes (say, 8 ) to a board with analog sensors, that has e.g 32 analog values to report continuously. I would like to get continuous readings of these sensors with no involvement from the CPU past setting things up.
I design both the main (with MCU) and peripheral (with sensors) boards.

By adding analog multiplexers on the peripheral board, things fit, 2 lanes for power, 1 lane for analog, 5 lanes for channel selection: you can read all 32 signals.
The issue is then, how to automate the acquisition of sensor values ? Ideally we would want the multiplexer channel to be endlessly swept (the 5 channel selection lanes to automatically present a %32 counter), to connect the ADC to the DMA in an endless conversion mode, typically to a ring buffer of the appropriate size, in such a fashion that the sensor ID - memory location pairings be constant.

Assuming no oversampling, since the multiplexer has a transition period (much lower than the ADC conversion period), we would like to end up with the following in memory:
[reading for channel 0b00000]-[thrown away]-[reading for channel 0b00001]-[thrown away]-[reading for channel 0b00010]-[thrown away]-[reading for channel 0b00011]-etc.

One way I can imagine this working is by synchronizing the PWM and the ADC. If every channel is launched at the same time as the ADC conversion, with a period the appropriate multiple of the ADC conversion period, and things don't drift (as far as I know, nothing in this isn't synchronous to a clock, so no reason for anything to drift), the PWM can output what's effectively a counter over arbitrary digital lanes, accomplishing what precedes.

I am not sure how to do this however - I'm not very familiar with clocks and synchronization in embedded. Is it possible to bind PWMs and the ADC to the same clock and ensure that they all start synchronously ?
How do I even do this considering their control registers are separate ?
Or can I maybe bind them to a clock and configure them appropriately then control the clock start-up myself - perhaps by generating my own clock signal via PWM to feed back into them somehow ?

How fast does the sampling need to be?

I'm not familiar with the STM32H7B0 in terms of the DMA capability and the way it is setup but it might be possible to sync two timers and have them trigger DMA channels.

One DMA channel for doing the conversions with the ADC and write the result to a 32 word circular buffer. The other DMA channel needs to read data from another 32 word circular buffer and write the data to a GPIO port to set the 5 bits for the channel selection. The used IO pins have to be in the same port for it to work.

The two timers, or maybe a single timer with two compare channels have to trigger with a phase difference to allow the multiplexer to settle.

While writing this the idea of using compare channels makes more sense. It is rather easy to create two "pulses" this way to trigger the two DMA channels.

I have done something similar to make a sine wave with coupled square waves at different phases. Might be helpful. Take a look at it here.

Thanks. I didn't know DMA could be connected to GPIOs directly on STM32s... That does sound very promising then. Looking into compare channels now, also not familiar with these. For all my bit-banging needs so far, I was on RP2040 and could use PIOs, so that was easy mode, never had to learn advanced timer features...

Yep it offers lots of possibilities. Maybe not as easy and sophisticated as RP2040, but still.

Another thought on this is to use two timers in series. The first one counts 0,1,2,3 and has compares to trigger the two DMA channels and the second timer counts from 0 to 31 to make the data for the multiplexer. For this the second DMA uses the CNT register as source and the GPIO as destination. The first DMA does the ADC conversion into the circular buffer.

Synchronizing an ADC to PWM via a timer event is pretty common in a lot of MCUs, since it is a feature commonly needed in motor control applications.

For the STM32 you need to enable an event output on a timer, then set the ADC to do a conversion start or injected conversion start when it sees a edge on the event channel connected to the timer.

Tho the way i did it with a STM32 was simply with interrupts. I had the ADC to scan trough all the channels and have it generate an interrupt on the end of the conversion sequence. This meant it converted say 8 channels in sequence. Then inside the interrupt handler i can toggle the GPIO pins that switch the external analog MUX over, then start the conversion sequence again. If you need to wait the external MUXes to stabilize then you can insert a extra dummy channel (like read the internal temperature sensor) at the start of the conversion sequence and give it a unusually long sampling time. So once it finishes the slow dummy conversion it will rapid fire the 8 channels in close succession and finish the seqence.

This way you minimize down time since you only do 9 conversions where 8 of them are useful and only 1 is padding. That 1 padding conversion can also be individually adjusted in timing to fit the MUX speed. This also improves throughput since you can have 8 muxes that you switch simultaneously, rather than one big mux you switch every sample. If you can afford a bit more offten interrupts, you could even be switching MUXes that are not being currently sampled by the ADC in the background. Removing the need for the 1 dummy conversion all together. Since STMs don't have a multichannel sample and hold anyway, the ADC can only sample 1 channel at the same time. (Tho some STMs do have 3 ADCs, so those can sample and hold capture 3 channels simultaneously)


[0] Message Index

[#] Next page

There was an error while thanking
Go to full version
Powered by SMFPacks Advanced Attachments Uploader Mod