On STM32G473, why would the ADC readings be lower than the calculation says they should be?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2021-09-24 1:33 PM
We are running the STM32G473 micro and are using an ADC channel to read the various bus voltages (3.3v, 5v, and 24v) as well as motor currents. All the ADC readings are lower than they should be, but not by the same percentage.
I am pasting some sample code that reads the 3.3v bus. Based on the circuit we are using, the math says we should be reading 408 counts, but we are reading only 349. Any thoughts on why this is, or how to correct it?
Here is the sample code:
tUINT16 Voltage3_3Reading;
tVOID main(tVOID)
{
HAL_IsrInstallHandler(ADC1_2_IRQn, AdcIrqHandler, ISR_PRIORITY_MEDIUM);
ConfigureAdc();
ConfigureFor3_3vBus();
}
static tVOID ConfigureFor3_3vBus(tVOID)
{
LL_ADC_REG_StopConversion(ADC2);
LL_ADC_Disable(ADC2);
LL_ADC_REG_SetTriggerSource(ADC2, LL_ADC_REG_TRIG_SOFTWARE);
LL_ADC_SetChannelSamplingTime(ADC2, LL_ADC_CHANNEL_12, LL_ADC_SAMPLINGTIME_640CYCLES_5);
LL_ADC_REG_SetSequencerRanks(ADC2, LL_ADC_REG_RANK_1, LL_ADC_CHANNEL_12);
// Start the conversion
LL_ADC_Enable(ADC2);
// Wait for enable to be active
tTIMER enabledTimer;
LIB_TimerStart(&enabledTimer, 3); // Arbitrary enabled timeout value of 3ms
while (!LL_ADC_IsEnabled(ADC2))
{
ASSERT_OR_BREAK(LIB_TimerCheck(&enabledTimer) == TIMER_RUNNING);
}
// Start converting
LL_ADC_REG_StartConversion(ADC2);
}
static tVOID ConfigureAdc(tVOID)
{
// Make sure it is disabled to change ADC settings.
LL_ADC_Disable(ADC2);
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_ADC12);
LL_ADC_DeInit(ADC2);
LL_ADC_CommonInitTypeDef adcCommonInitStruct;
LL_ADC_CommonStructInit(&adcCommonInitStruct);
adcCommonInitStruct.CommonClock = LL_ADC_CLOCK_SYNC_PCLK_DIV4;
adcCommonInitStruct.Multimode = LL_ADC_MULTI_INDEPENDENT;
adcCommonInitStruct.MultiDMATransfer = LL_ADC_MULTI_REG_DMA_EACH_ADC;
adcCommonInitStruct.MultiTwoSamplingDelay = LL_ADC_MULTI_TWOSMP_DELAY_5CYCLES;
LL_ADC_CommonInit(__LL_ADC_COMMON_INSTANCE(ADC2), &adcCommonInitStruct);
// Configure ADC settings.
LL_ADC_InitTypeDef adcInitStructure;
LL_ADC_StructInit(&adcInitStructure);
adcInitStructure.Resolution = LL_ADC_RESOLUTION_12B;
adcInitStructure.DataAlignment = LL_ADC_DATA_ALIGN_RIGHT;
adcInitStructure.LowPowerMode = LL_ADC_LP_MODE_NONE;
LL_ADC_Init(ADC2, &adcInitStructure);
LL_ADC_REG_InitTypeDef adcRegInitStructure;
LL_ADC_REG_StructInit(&adcRegInitStructure);
adcRegInitStructure.SequencerDiscont = LL_ADC_REG_SEQ_DISCONT_DISABLE;
adcRegInitStructure.ContinuousMode = LL_ADC_REG_CONV_SINGLE;
adcRegInitStructure.DMATransfer = LL_ADC_REG_DMA_TRANSFER_NONE;
LL_ADC_REG_Init(ADC2, &adcRegInitStructure);
LL_ADC_DisableDeepPowerDown(ADC2);
LL_ADC_EnableInternalRegulator(ADC2);
LL_ADC_REG_SetOverrun(ADC2, LL_ADC_REG_OVR_DATA_OVERWRITTEN);
// Calibrate ADCs
tTIMER adcCalTimer;
LL_ADC_StartCalibration(ADC2, LL_ADC_SINGLE_ENDED);
LIB_TimerStart(&adcCalTimer, 5); // Arbitrary calibration timeout value of 5ms
while (LL_ADC_IsCalibrationOnGoing(ADC2) == 1)
{
ASSERT_OR_BREAK(LIB_TimerCheck(&adcCalTimer) == TIMER_RUNNING);
}
LL_ADC_EnableIT_EOC(ADC2);
}
static tVOID AdcIrqHandler(tVOID)
{
if (LL_ADC_IsActiveFlag_EOC(ADC2) == TRUE)
{
LL_ADC_REG_StopConversion(ADC2);
LL_ADC_Disable(ADC2);
// Retrieve the data (this also clears EOC flag)
Voltage3_3Reading = LL_ADC_REG_ReadConversionData12(ADC2);
}
}
- Labels:
-
ADC
-
STM32G4 series
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2021-09-24 4:31 PM
Some combination of:
- Wrong reference voltage.
- Unstable reference voltage.
- Voltages aren't actually what you think they are.
- Impedance is too high.
- ADC is damaged.
My first two things to debug would be to ground a pin and verify that it reports 0 counts, then short a pin directly to 3.3V (assuming that's your reference) and see that it reports 4095 counts (or whatever the max is for your conversion resolution).
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2021-09-24 8:10 PM
Also read the 'G4-specific ADC appnote.
JW
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2021-09-28 9:41 AM
Thank you all for the suggestions.
The issue was resolved by adding a 20us delay after LL_ADC_EnableInternalRegulator().
