How to use ADC in Differential Mode

This is the Tenth 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 ADC in Differential Mode to measure the voltage difference between the input pins.

Differential ADCs are generally used in applications requiring high precision, noise reduction, and increased dynamic range. In this tutorial we will specifically focus on just measuring the voltage difference between the two differential inputs. The ADC data will be based on this differential voltage, which we will later convert into the voltage.

Not all the STM32 devices support differential ADC. I am going to use the STM32H7 based custom development board.

There are some important things we need to take care while setting up the differential ADC.

Some important tips

As mentioned in the reference manual both the differential inputs should be biased at Vref/2. The Vref is a custom reference voltage which can be provided externally, but the hardware on the board should be configured accordingly. By default the Vref is connected to the VDDA (& VCC), therefore the Vref is 3.3V.

Biasing means that instead of fluctuating around 0V, the signals should be centred around 1.65V.


We should also take care of the Common mode voltage (CMV). This Common-mode voltage is the average voltage of two input signals in a differential system. This voltage only has a small range in STM32. You can see it in the image from datasheet of the device.

You can see the common mode voltage varies by only 10% from Vref/2 voltage. So if the Vref is at 3.3V, the common mode voltage can vary from around 1.48 V to 1.82V.

When choosing the input voltages on both the differential pairs make sure the average of both voltages lies within this range. It does not mean that it will not work outside this range rather the result outside this range is unpredictable. In certain cases it might work while in other cases it won’t.


The ADC will convert the voltage difference between both the input pins as per the formula shown below.

  • If the VINN = 0 and VINP = VREF, the ADC value will be equal to the MAXIMUM.
  • Whereas when VINN = VREF and VINP = 0, the ADC value will be equal to the 0.
  • When VINN = VINP, the ADC value will be exactly HALF the MAXIMUM.

Below is the image showing the range of ADC value based on the differential inputs. The VDIFF is the voltage difference between the input signals.

We will write our code in such a way that the ADC MAXIMUM (65535) indicates a +3.3V while the ADC MINIMUM (0) indicates a -3.3V. Also the ADC MAX/2 (32768) will indicate 0V.



CubeMX Configuration

Below is the image showing the ADC configuration.

I have enabled ADC Channel 3 in the differential Mode. You can see the pin PA6 is configured as the INP (+ve Input) pin whereas the pin PA7 is configured as the INN (-ve Input) pin.

The ADC is configured with continuous conversion mode enabled, so that the next conversion can start automatically as soon as the previous one is finished. I have also enabled the interrupt for ADC.


The Connection for this project is shown in the image below.

I am using Active Pro Debugger to provide variable voltages to the ADC input. The A1 pin is connected to the PA6 (+ve Input) whereas the A0 pin is connected to the PA7 (-ve Input).



The Code

uint16_t ADC_VAL;
int voltage;

The variable ADC_VAL will be used to store the Raw ADC value. This value is generated by the ADC based on the difference in voltage between the inputs. The variable voltage will store the voltage data based on the Raw value.

Inside the main function we will start the ADC in interrupt mode. Once the conversion is finished, an interrupt will trigger and the ConvCpltCallback will be called. Inside this callback we will simply set the variable isDone. The data will be processed in the while loop.

int isDone =0;
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)
{
	isDone = 1;
}

Below is the main function.

int main ()
{
  ....
  ....
  HAL_ADC_Start_IT(&hadc1);
  while (1)
  {
    if (isDone)
    {
	  ADC_VAL = HAL_ADC_GetValue(&hadc1);
	  voltage = (3300*2*ADC_VAL/65535)-3300;
	  isDone = 0;
    }
    HAL_Delay(250);
  }
}   

Inside the while loop we will check if the variable isDone is set. If it is, we will read the Raw ADC value.

Then convert this Raw value to the voltage. By default the Vref is connected to VDDA (&VCC), therefore the Vref = 3.3V. Hence the value 3300 is used here. We want to convert the RAW ADC value to the voltage ranging from +Vref to -Vref, hence this formula is used baed on the examples provided by ST.



Result

Below are the images showing the output of the above code. When the +ve Input is at 0V and -ve Input is at 3.3V, the average input voltage is 1.5V, which is within the Common Mode Voltage (CMV ) range. The Raw ADC value is near 0 and the converted voltage (Difference between INP and INN) is -3.3V.

When the +ve Input is at 3.3V and -ve Input is at 0V, the average input voltage is 1.5V, which is within the Common Mode Voltage (CMV ) range. The Raw ADC value is 65535 and the converted voltage (Difference between INP and INN) is 3.3V.

When both the +ve Input and -ve Input are equal at 1.6V, the average input voltage is 1.6V, which is within the Common Mode Voltage (CMV ) range. The Raw ADC value is near Half the MAX and the converted voltage (Difference between INP and INN) is 0V.

When the +ve Input is at 3V and -ve Input is at 1V, the average input voltage is 2.5V, which is far outside the Common Mode Voltage (CMV) range. The ADC behaviour is unpredictable at this point. You can see in the image below the converted voltage is wrong.

Hence while designing the differential ADC, we must take care that the average input voltage of the two inputs must lie within the CMV range.

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