How to use Oversampling to increase Resolution

This is the Ninth tutorial in the STM32 ADC series. In this series will see how to use the ADC peripheral of the STM32 to read the data from the Analog devices. We will cover how to use the ADC in different modes, that includes polling mode, interrupt mode and the DMA mode. We will also see how to use the multiple channels to read multiple analog devices using the same ADC. Later in the series we will cover more advanced features like differential ADC, combined ADCs, ADC watchdogs, injected channels etc.

This tutorial will cover how to use the oversampling to increase the ADC resolution.

I am going to use the STM32L496ZG microcontroller for this tutorial because it supports the ADC Oversampling. My regular STM32F103C8 and STM32F446RE microcontrollers do not support oversampling. The H750 do support it but things are simpler in it compared to L496. Therefore I have decided to use L496.

What is oversampling

All STMicroelectronics microcontrollers embed an ADC (analog-to-digital converter) with a given resolution (number of bits) and sampling rate. For most applications, this resolution is sufficient, but in some cases where a higher accuracy is required, oversampling, and decimating the input signal can be implemented to avoid the use of an external ADC solution and the associated increase in application power consumption.

The hardware oversampling engine accumulates the results of ADC conversions. The accumulated output data can be right-shifted (and rounded) to provide selected bit-depth in relation to OSR. The output value is not updated every sampling period, but once N samples are accumulated, therefore, the output data rate is decimated by a factor of OSR.

In some of the STM32 MCUs (For eg- STM32L496), the oversampling engine keeps the 16 least significant bits after the shift, and rounds the result to the nearest value according to the bits removed by the shifting. The final result is saved in the ADC_DR data register and because of the 16-bit truncation, it cannot be represented on more than 16 bits. While in other STM32 MCUs (For eg- STM32H750), the bit shifting and truncation is optional. These MCUs has 32-bit wide ADC_DR register, therefore storing higher resolution data in the data Register is possible.

Below is the formula to calculate the bit depth after oversampling.

Here X represents the number of bits on which the samples are accumulated. OSR is the Oversampling ratio and M represents the number of bits to be shifted.

Note:- The output value is not updated every sampling period, but once N samples are accumulated, therefore, the output data rate is decimated by a factor of OSR. Therefore our formula to calculate the sampling frequency / conversion time changes compared to what we discussed in the previous tutorial.



CubeMX Configuration

Clock Config

Below is the image showing the clock configuration for STM32L496ZG.

I have configured the system clock to run at maximum 80MHz. The ADC is also configured to run at 64MHz.


ADC Config

Below is the image showing the ADC configuration.

  • I have configured the ADC1 CH8, which is connected to pin PA3.
  • The clock prescaler is set to 1, so the ADC clock is still at 64MHz (64MHz/PSC).
  • The Resolution is set to 12-bit. The extra samples we take, will be accumulated on 12-bit.
  • The continuous conversion mode is enabled, so the next conversion will automatically start once the previous conversion is over.
  • The DMA continuous request is enabled, so the DMA will fetch the data from the channel continuously.

Oversampling config

Below is the image showing the oversampling and channel configuration of the ADC.

Here we will first enable the oversampling for the Regular channels. As I mentioned, below is the formula to calculate the oversampling bit width.

Here I am choosing the OSR as 64. Therefore 64 samples will be collected for each trigger (software start). The Right shift (M) is set to 2. This will result in the bit width of 16 bits.

As I already mentioned, the STM32L496 has 16-bit ADC Data register, therefore we can not have the bit width higher than this value. Therefore the bit shift (M) and OSR should be selected in a way that the bit width is not higher than 16 bits.

The sampling time for the Channel 8 is set to 47.5 Cycles. With the ADC clock of 64 megahertz, the total time to convert the channel should be as shown below.

  • Here 12.5 is the ADC clock for 12-bit Resolution.
  • 47.5 is the sampling time we selected.
  • 64MHz is the ADC clock.
  • 64 is the OSR we selected.

The total conversion time for channel 8 should be 60uS. We will measure it in the analyzer.


DMA config

Below is the image showing the ADC DMA Configuration.

The DMA is configured in the Circular mode, so that it can work continuously. The data width is set to 16-bit.



Connection

Below is the image showing the connection used in this project.

The potentiometer is connected to 3.3V with the MCU. The output pin of the potentiometer is connected to the pin PA3 (ADC1 CH8). I am going to use the pin PD7 toggle to measure the ADC conversion time, therefore it is connected to the Logic Analyzer.



The code

There is nothing special in the programming section to make the oversampling work. We will simply start the ADC in the DMA mode.

uint16_t ADC_VAL = 0;

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)
{
    HAL_GPIO_TogglePin(GPIOD, GPIO_PIN_7);
}

int main(void)
{
  ....
  ....
  
  HAL_ADC_Start_DMA(&hadc1, &ADC_VAL, 1);
  while (1)
  {
  }
}

Here inside the main function, we will start the ADC in the DMA mode. The converted data will be stored in the ADC_VAL variable.

Once the conversion is finished, an interrupt will trigger and the conversion complete callback is called. Inside the callback we will toggle the pin PD7. This is to measure the conversion time of the ADC.



Result

Below is the gif showing the ADC_VAL in the live expression.

You can see in the gif above, as the potentiometer is rotated, the ADC_VAL is increasing. The interesting thing is that the maximum value of this variable is around 65000.

The STM32L496 supports a maximum of 12-bit ADC resolution. With 12-bit resolution, the maximum value of the variable should have been 4095. But because of oversampling, we are able to increase the resolution to 16-bit and that is why the value is reaching 65000.

Below is the image showing the sampling time as measured by the pin PD7.

As you can see above, the pin toggles every 60us. This is exactly the same time as we calculated using the formula.

The point is, Oversampling increases the number of samples taken per trigger by the factor OSR but it also reduces the overall sampling frequency by same factor. Hence we need to take in consideration the OSR factor while calculating the sampling or conversion frequency.

Check out the Video Below




Info

You can help with the development by DONATING Below.
To download the project, click the DOWNLOAD button.

Subscribe
Notify of

0 Comments
Newest
Oldest Most Voted
Inline Feedbacks
View all comments
keyboard_arrow_up