cancel
Showing results for 
Search instead for 
Did you mean: 

Non linearity in ADC Measurement using STM32F051R4T6TR IC

Amal Babu
Associate III

Hai,

i have been into designing a solar inverter using STMF051R4 series IC for past few years. Presently we are working

on ADC Measurement with DC voltage.The problem we are facing now is we not able to get a linearity in measurement of the dc voltage at the adc pins of the STM32 ic.We are getting different ratio for the different voltage ranges when we linearly increase the voltage with a constant difference .Can you please suggest me what kind of problem am i facing with the measurement of the voltages.Specifically can someone help me with the error i am facing right now.

I have also tried using low pass filter but couldnt find much difference in reading the values at the adc pins of the ic.

28 REPLIES 28
T J
Lead

Is that a battery ?

remove C9 from the battery..

it looks a very simple circuit.

the OPAMP wont like going anywhere near the rails. @Avatar has eluded to this.

you will find that different opamps will give you different results at the rails.

if you could use a +/- 5v supply, then the opamp will be ok,

then you need input protection diodes.. to stop the -5V blowing up the processor...

otherwise choose a Rail to Rail opamp from Analog Devices.. and pay for the good one...

Amal Babu
Associate III

Hai,

guys did you find any mistake in my code configuration.

Amal Babu
Associate III

I have a doubt regarding DMA.

I read a single channel adc using dma initially, later on read two channels using DMA and found significant decrease in ADC reading.What could be the possible reason behind that.

Amal Babu
Associate III

For example if i read channel 2 initially using DMA and got a ADC reading of 1011.Later on when i read two different channels, channel 2 and 4 together with DMA,

i found significant decrease in first channel adc value (channel 2) showed up just 1002.Why am i getting such a result in my adc measurement?Is it due to the error in my code?

T J
Lead

if you set the clocks too high, you get different readings.

did you calibrate the ADC ?

you have to check the Vdda reading and calculation to know if your readings are good.

without calibration the difference is not good.

with calibration I get within 1-2mV on the good quality meter.

but I think your non-linearity question was answered due to the rail to rail opamp.

I think you need to use a TVS diode on the ADC input

that chip may already be damaged.

Does C31 and C33 say pF ? its not a good image.

Yes I agree the 4.7uF is a bit over the top. please try a 0.22uF low ESR for better results.

Amal Babu
Associate III

I have one more doubt regarding the ADC measurement.I am presently using circular DMA (conversion in circular mode).Here what i did is that...suppose i have configured three different channels...for example Channel 2,4 and 6.I have written the code in such a way that in ADC measurement , the values would be read in a sequence from channel 2 ,4 and 6 sequencing and would be stored in an array declared.Usually the channel 2 reading should be stored at zeroth location of array,channel 4 on first location sequentially channel 6 on the 3rd location of the array. Normally we can configure it in two ways either UP mode or down mode.Suppose as i said above conversion result of channel 2 is getting loaded in first location instead of the zeroth location and conversion result of channel 4 is getting loaded in the 0th or 3rd location . And the next channel reading on a different location of the array which is not expected.This happens in both up and down mode.Please share your suggestions regarding this issue.

Amal Babu
Associate III

Hai,

i am using system clock as 48MHZ.For adc its PCLK/2.

The ADC configuration code is being shown below:

void adc_configuration()

{

   GPIOC->MODER |= BIT(9) | BIT(8);                                                    

   GPIOA->MODER |= BIT(7)| BIT(6);

      ADC1->CR &= ~ADC_CR_ADEN;

   RCC->APB2ENR |= RCC_APB2ENR_ADCEN;                                                              

   ADC1->CFGR2 |= ADC_CFGR2_CKMODE_0;    

   ADC1->SMPR |= 0X00000007;

   ADC1->CFGR1 |= ADC_CFGR1_CONT | ADC_CFGR1_DMACFG | ADC_CFGR1_DMAEN | ADC_CFGR1_RES_0| ADC_CFGR1_SCANDIR;

   ADC1->CFGR1 &= ~(ADC_CFGR1_ALIGN | ADC_CFGR1_SCANDIR);                                

 ADC1->SMPR   &= ~ADC_SMPR_SMP;                                                        

   ADC1->CHSELR |= ADC_CHSELR_CHSEL4 ;                  

   //ADC Enable

   ADC1->CR |= ADC_CR_ADEN;

   while(!(ADC1->ISR & ADC_ISR_ADRDY));

   ADC1->CR |= ADC_CR_ADSTART;

}

AvaTar
Lead

This sounds like your DMA configuration, i.e. number of elements, is not right.

DMA is a "dumb" unit that transfers the configured number of elements of configured size.

You can verify the channel setup easily by connecting all except one channel to ground, and check the values in memory. The continue with the next.

And to a former remark:

> For example if i read channel 2 initially using DMA and got a ADC reading of 1011.Later on when i read two different channels, channel 2 and 4 together with DMA, i found significant decrease in first channel adc value (channel 2) showed up just 1002.Why am i getting such a result in my adc measurement?

This usually happens if the sampling time is too short, and the S&H capacitor "bleeds" over to consecutive channels. But you have added a huge capacitor (4.7uF) at the inputs externally, which can cause the same.

T J
Lead

I do exactly the same thing.

at startup I initialise the ADC and DMA once.

The DMA results are always in the correct spot...

underDMA interrupt, I pull the data from the DMA buffer to the ADCRow buffer, I have 16 rows

every interrupt we update this Row, and recalculatew the last 16 readings for every channel and save the AverageChReadings[2,4,6];

then in any process, they can just go and check the average readings without fear of corruption.

Amal Babu
Associate III

I had mentioned regarding this problem before.Actually to explain more about my problem when i read a single channel adc using DMA ,for a voltage of 3.3 i got the maximum value of 1023.When i read two different adc channels at a time using DMA, The adc reading of the first channel read 1013 instead of 1023.I cross checked the same by reading a single channel adc again and got the adc reading as 1023.I am not having this variation in the result if i read the adc directly without DMA.I found the issue only when i read multiple channels using DMA. Actually i cannot move forward without using DMA in my code.