Author Topic: Is it possible to synchronize the ADC and a multiplexer channel sweep on STM32 ?  (Read 1010 times)

0 Members and 1 Guest are viewing this topic.

Offline ArteTopic starter

  • Contributor
  • Posts: 16
  • Country: fr
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 ?
« Last Edit: February 28, 2024, 07:25:06 pm by Arte »
 

Online pcprogrammer

  • Super Contributor
  • ***
  • Posts: 3710
  • Country: nl
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.

Offline ArteTopic starter

  • Contributor
  • Posts: 16
  • Country: fr
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...
 

Online pcprogrammer

  • Super Contributor
  • ***
  • Posts: 3710
  • Country: nl
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.

Online Berni

  • Super Contributor
  • ***
  • Posts: 4957
  • Country: si
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)
 

Offline Jeroen3

  • Super Contributor
  • ***
  • Posts: 4078
  • Country: nl
  • Embedded Engineer
    • jeroen3.nl
You can sample an unconnected or internal channel (eg: intvref) in the sequence first instead of throwing away good samples. I assume your muxes will switch within one adc conversion time.
Using timers to trigger ADC and DMA is trivial. You don't even have to sync them with hardware features, writing the registers within a protected code block is enough. (timer bus clocks are slow!)
 

Offline MasterT

  • Frequent Contributor
  • **
  • Posts: 785
  • Country: ca
Considering 8-bits noise-free performance of the adc ST uCPUs, makes sense to consider external adc with switching input matrix,
like ad7124/ad7193 + 4x 4052 to multiplex 8 uo to 32. ADC has GPIO that drives MUX, controled over SPI
 
The following users thanked this post: harerod

Offline ArteTopic starter

  • Contributor
  • Posts: 16
  • Country: fr
Thanks a lot for the help.
And yeah good point on sampling intvref during mux switching. To be honest I was thinking of sampling a different ADC pin but was trying to keep the question isolated. But, monitoring the intvref stability may have its merits.
Also I'm not too worried about bit depth in this application, 6 bits is decent, 7 is good. So if the STM32H7B0xB is supposed to do 16 bits at 3MHz, things should work out even if it doesn't quite hold up to what the datasheet claims in practice. And an AD7124 single handedly doubles the BOM cost ! But I can see that being useful in other use cases yeah, thanks for the suggestion.
 

Online pcprogrammer

  • Super Contributor
  • ***
  • Posts: 3710
  • Country: nl
With the suggested phase setup there is no need to sample another channel with the ADC. Only complicates the setup more.

At compare moment 1 sample the input with the ADC and on compare moment 2 switch the multiplexer. By lowering the timer frequency you can adjust it to match the multiplexer settling time.

I looked at the reference manual and noticed it uses the DMAMUX system, which allows for more possibilities, but makes it a bit more complex to setup.

Offline MasterT

  • Frequent Contributor
  • **
  • Posts: 785
  • Country: ca
More details necessary to give reasonable advise. Sampling rate, output impedance of the sensors, dynamic range, distance between boards. Settling time of the MUX may be much higher than expected, and SAR adc requires buffer or caps on inputs, though H7 likely have OPA on board that may simplify interfacing
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf