cancel
Showing results for 
Search instead for 
Did you mean: 

ADC reading 15% low on one channel

roberta.strauss9
Associate II
Posted on March 03, 2015 at 21:57

I am using the STM32F429IIH6 for a project.

I have 3 ADC channels.  Two are working properly, but one is consistently reading 15% low (compared to a DMM).  PC2 is the pin not working properly.

e.g., when I read the ADC I might get 555. So 555counts*3.3v/1024counts = 1.7886, but my DMM reads 2.1042.  If I do a similar test on either of the other two working channels, I calculate the value I see on the DMM.

The ADC init code is standard stuff:

 /* Configure PC2, ADC3 Channel12 pin as analog input  

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;

  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;

  GPIO_Init(GPIOC, &GPIO_InitStructure);

and looks exactly like the other channels.  PC2 is reading across a 5k resistor, one channel is reading across a 1M resistor, and the other is reading across a 180 ohm resistor, so the impedance of the channel that isn't working is between the impedances of the two working channels.

Does anyone have any ideas why this channel would be off?  Maybe an initialization conflict that's buried somewhere?

#adc
6 REPLIES 6
Posted on March 04, 2015 at 01:17

You don't specify, but presuming a custom board. Is the issue reproducible over more than one board? Is the issue reproducible on a different board design?

If it is reproducible does changing the other pins alter the behaviour, and if so how?

No data on the other pins, adc configuration, or sample time.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
AvaTar
Lead
Posted on March 04, 2015 at 10:27

and looks exactly like the other channels.  PC2 is reading across a 5k resistor, one channel is reading across a 1M resistor, and the other is reading across a 180 ohm resistor, so the impedance of the channel that isn't working is between the impedances of the two working channels.

 

That's not correct.

Input impedance of a channel is the value of your resistor PLUS output impedance of the source (plus input impedance of the ADC S&H ...).

What is the ADC reading if you attach a low-impedance source, e.g. a 1.5V dry cell ?

BTW, a 1M resistance is far too high for that kind of SAR ADC, I can't imagine you get proper readings. If my memory serves well, ST suggests 50k or less.

roberta.strauss9
Associate II
Posted on March 04, 2015 at 14:20

This is a custom board.  It is reproducible across boards of the same product, with exactly the same result: .85 of the expected reading, with other channels matching my DMM.  I don't have a different board design to test the same pin against; I am assuming it is something in the initialization code, maybe some module that is affecting pin PC2, but having looked through the code and the data sheets, nothing revealed itself.  I don't know what else it could be, since all other ADC modules are working properly, but figured the pool of talent on this site may have some ideas.

The code where I took the ADC raw reading looks like this:

    for(ad_index = 0; ad_index < NUM_ADC_INPUTS; ad_index++)

    {

...

        if (ad_index == GLOBAL_VALUE_INDEX)

         A_Global_Value = uhADC3ConvertedValue[ad_index];

...

      ADC_SoftwareStartConv(ADC3);

      OS_Yield();       // We're done, so give up the CPU

    }

(the name of the global variable has been changed) where the values from the ADC are fed into the array uhADC3ConvertedValue[] via DMA and an OS task (Segger's OS) loops through and assigns the ADC values to their respective global variables.

The DMA and ADC are initialized thusly:

  /* DMA2 Stream0 channel2 configuration **************************************/

  DMA_InitStructure.DMA_Channel = DMA_Channel_2;  

  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)ADC3_DR_ADDRESS;

  DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&uhADC3ConvertedValue;

  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;

  DMA_InitStructure.DMA_BufferSize = NUM_ADC_INPUTS;  // for multiple channels. 

  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;

  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; // for multiple channels

  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;

  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;

  DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;

  DMA_InitStructure.DMA_Priority = DMA_Priority_High;

  DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;         

  DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;

  DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;

  DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;

  DMA_Init(DMA2_Stream0, &DMA_InitStructure);

  DMA_Cmd(DMA2_Stream0, ENABLE);

/*************************** GPIO initialization*****************************/

  

  /* Configure PA1, ADC3 Channel1 pin */

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;

  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;

  GPIO_Init(GPIOA, &GPIO_InitStructure);

 /* Configure PA2, ADC3 Channel2******************/

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;

  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;

  GPIO_Init(GPIOA, &GPIO_InitStructure);

  /* Configure PF7, ADC3 Channel5, NOTE:TESTED AGAINST DMM*****************/

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;

  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;

  GPIO_Init(GPIOF, &GPIO_InitStructure);

  /* Configure PF8, ADC3 Channel6 pin UNTESTED******************/

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;

  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;

  GPIO_Init(GPIOF, &GPIO_InitStructure);

  /* Configure PC1, ADC3 Channel11 NOTE: TESTED AGAINST DMM************/

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;

  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;

  GPIO_Init(GPIOC, &GPIO_InitStructure);

 /* Configure PC2, ADC3 Channel12 pin NOTE: TESTED AGAINST DMM, THIS PIN IS READING .85 WHAT IT SHOULD COMPARED TO DMM*************/

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;

  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;

  GPIO_Init(GPIOC, &GPIO_InitStructure);

/* Configure PC3, ADC3 Channel13 pin UNTESTED *****************/

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;

  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;

  GPIO_Init(GPIOC, &GPIO_InitStructure);

/************************ADC Configuration************************************/

  

  /* ADC Common Configuration *************************************************/

  ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;

  ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2;

  ADC_CommonInitStructure.ADC_DMAAccessMode =  ADC_DMAAccessMode_Disabled;

  ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;

  ADC_CommonInit(&ADC_CommonInitStructure);

  /* ADC3 Configuration *******************************************************/

  ADC_InitStructure.ADC_Resolution = ADC_Resolution_10b;

  ADC_InitStructure.ADC_ScanConvMode = ENABLE;  // for mutlitple channels

  ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; 

  ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;

  ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1;

  ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;

  ADC_InitStructure.ADC_NbrOfConversion = NUM_ADC_INPUTS;  //For multiple inputs. 

  ADC_Init(ADC3, &ADC_InitStructure);

  /* ADC3 regular channel13 configuration *************************************/

  ADC_RegularChannelConfig(ADC3, ADC_Channel_1, 1, ADC_SampleTime_3Cycles);   //GND (Untested)

  ADC_RegularChannelConfig(ADC3, ADC_Channel_2, 2, ADC_SampleTime_3Cycles);   //VOUT

  ADC_RegularChannelConfig(ADC3, ADC_Channel_5, 3, ADC_SampleTime_3Cycles);  //3 Volt Ref NOTE: This channel is working correctly against DMM

  ADC_RegularChannelConfig(ADC3, ADC_Channel_11,4, ADC_SampleTime_3Cycles);  //NOTE: This channel is working correctly against DMM

  ADC_RegularChannelConfig(ADC3, ADC_Channel_12,5, ADC_SampleTime_3Cycles);  //NOTE: This channel is NOT working correctly against DMM

  ADC_RegularChannelConfig(ADC3, ADC_Channel_13,6, ADC_SampleTime_3Cycles);  //Untested

  ADC_RegularChannelConfig(ADC3, ADC_Channel_6, 7, ADC_SampleTime_3Cycles);  //Untested 

 /* Enable DMA request after last transfer (Single-ADC mode) */

  ADC_DMARequestAfterLastTransferCmd(ADC3, ENABLE);

  /* Enable ADC3 DMA */

  ADC_DMACmd(ADC3, ENABLE);

  /* Enable ADC3 */

  ADC_Cmd(ADC3, ENABLE);

  

   /* Start ADC3 Software Conversion */ 

  ADC_SoftwareStartConv(ADC3);

/*********************/

The comments have been altered to reflect the tested vs untested channels, and which channel is NOT working correctly against the DMM.  There are, in fact, more than 3 ADC channels; the untested channels have been reporting good data, but have not been tested against the DMM, and I didn't want to complicate the matter in my first post.

So, does anyone have any ideas why one channel might read .85 the expected reading?

I can reply with more code if I missed something.

From clive1:

''If it is reproducible does changing the other pins alter the behaviour, and if so how?''

I'm not sure what you're asking here.

roberta.strauss9
Associate II
Posted on March 04, 2015 at 14:35

That's not correct.

 

Input impedance of a channel is the value of your resistor PLUS output impedance of the source (plus input impedance of the ADC S&H ...).

 

 

What is the ADC reading if you attach a low-impedance source, e.g. a 1.5V dry cell ?

 

 

BTW, a 1M resistance is far too high for that kind of SAR ADC, I can't imagine you get proper readings. If my memory serves well, ST suggests 50k or less.

 

 

 

I didn't design the board, and agree 1M is a strange resistance to pick, but it is reading correctly (it's a 100k over 1M voltage divider on a 3.3V line to give a 3V source, and the reading is something like 2.998V; I don't know why it was designed into the board, but it is working properly; I don't know why it is working properly).

The STM32F429IIH6 doesn't have any exposed pins, and I can't attach a dry cell to it, or anything else for that matter.  I can, however, test it with a DMM, and it is reading correctly on the other two channels but reading at .85 the correct value on PC2.  I have looked at it with a scope, and there isn't significant noise.  The .85 was found from many samples at many set points on several of different samples of this custom device and was perfectly repeatable.

The source for PC2, the channel that is causing problems, is an op amp.  The output of the op amp is an 18.2k in series with a 5.11k to ground, and the reading I'm taking is on the non-ground leg of the 5.11k resistor.  The op amp's feedback resistor is 18.2k, and it is an LMC7101BIM5. The DMM is a Fluke 117.

Posted on March 04, 2015 at 15:04

''If it is reproducible does changing the other pins alter the behaviour, and if so how?''

 

I'm not sure what you're asking here.

Changing the pins used, the order/rank at which the samples are taken, the voltages on the other pins.

You might want to increase the sample time, 3 is awfully short, if the signals have a significant delta, and your ability to supply current to charge/discharge the capacitor quickly enough.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
roberta.strauss9
Associate II
Posted on March 04, 2015 at 15:28

I increased the sampling time to ADC_SampleTime_15Cycles, and it works.

When my coworkers said ''good job'', I said, ''it wasn't me, it was clive1''.

I see how the order could make one channel off but leave the others reading correctly if the sampling time is too short; I'd never run into this before.  Thanks so much for the help!