Author Topic: Averaging Multichannel ADC data on STM32F4  (Read 6770 times)

0 Members and 1 Guest are viewing this topic.

Offline ZeroResistanceTopic starter

  • Frequent Contributor
  • **
  • Posts: 585
  • Country: gb
Averaging Multichannel ADC data on STM32F4
« on: October 02, 2017, 08:15:53 am »
I am reading 4 adc channels of the STM32F407VG on a STM32F4 Discovery Board.

Currently with CubeMX I've got the 4 adc channels initialized and the ADC is scanning and converting these 4 channels continuously and using DMA to transfer the result to a buffer in memory.

However the buffer is only 4 elements and each channel is stored seperately in each element of the buffer.

But this is not what I want, I would like to perform averaging on the ADC values, typically I would like to store the ADC values coming from each channel in a 16 element or 32 element buffer and perform a rolling average on them.

Is there a way to do this with DMA and with least CPU intervention?

TIA
 

Offline mikerj

  • Super Contributor
  • ***
  • Posts: 3240
  • Country: gb
Re: Averaging Multichannel ADC data on STM32F4
« Reply #1 on: October 02, 2017, 09:56:18 am »
There is no way to perform the averaging autonomously, it has to be done in software.   You simply make the DMA buffer as large as it needs to be (i.e. channels * samples * 2 bytes) and then perform the averaging when the DMA transfer has completed.  The samples will be stored in channel scan order e.g. if scanning channels 1-4:

Chan 1
Chan 2
Chan 3
Chan 4
Chan 1
Chan 2
Chan 3
Chan 4
etc.

The averaging could look something like this:
Code: [Select]
uint16_t i = ADC_SAMPLES;
uint16_t *dma = dmabuffer;
uint32_t chan1 = 0;
uint32_t chan2 = 0;
uint32_t chan3 = 0;
uint32_t chan4 = 0;

do {
    chan1 += *dma++;
    chan2 += *dma++;
    chan3 += *dma++;
    chan4 += *dma++;
} while (--i > 0 );

chan1 /= ADC_SAMPLES;
chan2 /= ADC_SAMPLES;
chan3 /= ADC_SAMPLES;
chan4 /= ADC_SAMPLES;


If speed is critical you could save some cycles by unrolling the loop, either partially or fully if the number of samples is reasonably low.
 
The following users thanked this post: ZeroResistance

Offline xani

  • Frequent Contributor
  • **
  • Posts: 400
Re: Averaging Multichannel ADC data on STM32F4
« Reply #2 on: October 02, 2017, 10:06:52 am »
For longer rolling averages it would probably make sense to use function like EWMA which doesn't grow with length of data.

There is no way to perform the averaging autonomously, it has to be done in software.
Well, there is, via RC filter ;). But realistically it would be nice to at least have an opamp before it.

 
The following users thanked this post: ZeroResistance

Offline ZeroResistanceTopic starter

  • Frequent Contributor
  • **
  • Posts: 585
  • Country: gb
Re: Averaging Multichannel ADC data on STM32F4
« Reply #3 on: October 02, 2017, 10:24:12 am »
Thanks for the info mikerj

What you are trying to say is instead of using Circular DMA use Normal DMA and also increase the size of the DMA buffer.

So I get something like what you showed
Chan1, Chan2, Chan3, Chan4, Chan1, Chan2 .... and so on
Now suppose I need 16 sets of readings for Chan1 to Chan4 and 2 bytes each per channel. so that would make a 16 * 4 * 2 = 128 byte buffer.

So if the the 128byte buffer overflows do I have to set the DMA manually back to the start of the buffer?

Also you are doing this averaging after the needed 16 samples per channel are acquired right?
 

Offline ZeroResistanceTopic starter

  • Frequent Contributor
  • **
  • Posts: 585
  • Country: gb
Re: Averaging Multichannel ADC data on STM32F4
« Reply #4 on: October 02, 2017, 10:27:25 am »
Many thanks for the suggestion on EWMA.
 

Offline mikerj

  • Super Contributor
  • ***
  • Posts: 3240
  • Country: gb
Re: Averaging Multichannel ADC data on STM32F4
« Reply #5 on: October 02, 2017, 12:02:05 pm »
Thanks for the info mikerj

What you are trying to say is instead of using Circular DMA use Normal DMA and also increase the size of the DMA buffer.

Yes, this is how I have implemented this on an STM32F103.

So I get something like what you showed
Chan1, Chan2, Chan3, Chan4, Chan1, Chan2 .... and so on
Now suppose I need 16 sets of readings for Chan1 to Chan4 and 2 bytes each per channel. so that would make a 16 * 4 * 2 = 128 byte buffer.

So if the the 128byte buffer overflows do I have to set the DMA manually back to the start of the buffer?

You will need to re-start the DMA after the transfer has completed.  How and when you do this depend on how often you want a new filtered ADC value.  For maximum throughput you could use the end of transfer interrupt to start a new DMA transfer in a second buffer whilst averaging the values in the first (i.e. double buffering).

Also you are doing this averaging after the needed 16 samples per channel are acquired right?

Yes, you acquire the samples and then average them.

In the system I was working on we used oversampling to gain some more resolution.  The DMA was started by a timer interrupt and the averaging was performed in the end of transfer interrupt.  IIRC there was 5 or 6 ADC channels, 64 samples from each channel and the calculations were quite fast, less than 50 microseconds with full C optimisations enabled.  Our clock speed was fairly low as well, only about 33MHz.
 
The following users thanked this post: ZeroResistance

Offline ZeroResistanceTopic starter

  • Frequent Contributor
  • **
  • Posts: 585
  • Country: gb
Re: Averaging Multichannel ADC data on STM32F4
« Reply #6 on: October 02, 2017, 02:54:54 pm »
Many thanks for your inputs, mikerj. It certainly helps to know that the chip cannot do this on itsown and certain amount of CPU intervention would be required.

On another note I have connected 10K ohm pots to each of the ADC inputs and I see a certain amount of crosstalk between adjacent channels. That is if I increase the value of one channel by turning the pot I can see a slight increase in value of the next channel.

The ADC clock is set to 21Mhz
Currently my conversion time is 15 ADC clock cycles and sampling time is 3cycles.
 

Offline MT

  • Super Contributor
  • ***
  • Posts: 1616
  • Country: aq
Re: Averaging Multichannel ADC data on STM32F4
« Reply #7 on: October 02, 2017, 08:58:58 pm »
It certainly helps to know that the chip cannot do this on itsown and certain amount of CPU intervention would be required.

On another note I have connected 10K ohm pots to each of the ADC inputs and I see a certain amount of crosstalk between adjacent channels. That is if I increase the value of one channel by turning the pot I can see a slight increase in value of the next channel.

The ADC clock is set to 21Mhz
Currently my conversion time is 15 ADC clock cycles and sampling time is 3cycles.

F4 ADC is famous for its internal noise and other ""things"", there are a noise reduction sugestion paper available from ST. If you are planning to ""try"" to get low noise results you ""must"" read this paper. You cant assume to get god
ADC results from Nucleo borads/Discovery boards, they where not designed with that in mind, particularely not the 64pin Nucleo/Aurdiono compatible crap boards.
 
The following users thanked this post: ZeroResistance

Offline pigrew

  • Frequent Contributor
  • **
  • Posts: 680
  • Country: us
Re: Averaging Multichannel ADC data on STM32F4
« Reply #8 on: October 03, 2017, 03:10:52 pm »
Based on the STM app note AN2834 (How to get the best ADC accuracy in STM32 microcontrollers), their STM32L0 and STM32L4 MCUs support hardware oversampling, so that would be the least software-involvement method, but involve a change in MCU.

With the 'F4, you have to do software averaging after transferring the individual samples with DMA.
 

Offline Jeroen3

  • Super Contributor
  • ***
  • Posts: 4078
  • Country: nl
  • Embedded Engineer
    • jeroen3.nl
Re: Averaging Multichannel ADC data on STM32F4
« Reply #9 on: October 04, 2017, 07:08:19 am »
Just left align the halfword, run the EWMA en you have a q16 to work with.
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf