AnsweredAssumed Answered

Inconsistency of ADC Conversion value

Question asked by Gaurav Banyal on Sep 20, 2017
Latest reply on Sep 21, 2017 by Jing Pan

Hello,

I am using MKL03Z32VFG4 and using the ADC0 peripheral for measuring voltage.

I am using the internal voltage reference. I have seen that when I have under 1.0 volts on the analog pin, I have a certain value the ADC returns. Then if I increase to 1.1volts, the value is smaller than at 1.0 volts. And subsequently, as I go on increasing voltage on the analog pin, the values that the ADC returns are incrementing / decrementing together with the increment/decrement of the voltage. 

 

Please let me know how can I get rid of that value going low even though the voltage level on the pin is higher.

 

My code is as follows:

================================

#define BATT_ADC16_BASE ADC0
#define BATT_ADC16_CHANNEL_GROUP 0U
#define BATT_ADC16_USER_CHANNEL 15U /* PTA0, ADC0_SE15 */

#define BATT_ADC16_IRQn ADC0_IRQn

#define BATT_VOLTAGE_READING_AVAILABLE ADC0_IRQHandler

 

void batt_mon_init(){

EnableIRQ(BATT_ADC16_IRQn);
ADC16_GetDefaultConfig(&adc16ConfigStruct);
adc16ConfigStruct.clockDivider = kADC16_ClockDivider1;
adc16ConfigStruct.referenceVoltageSource = kADC16_ReferenceVoltageSourceValt;
adc16ConfigStruct.enableHighSpeed = true;
ADC16_Init(BATT_ADC16_BASE, &adc16ConfigStruct);
ADC16_EnableHardwareTrigger(BATT_ADC16_BASE, false); /* Make sure the software trigger is used. */
#if defined(FSL_FEATURE_ADC16_HAS_CALIBRATION) && FSL_FEATURE_ADC16_HAS_CALIBRATION
if (kStatus_Success != ADC16_DoAutoCalibration(BATT_ADC16_BASE))
{
LOG_E("ADC16_DoAutoCalibration() Failed.\r\n");
}
#endif /* FSL_FEATURE_ADC16_HAS_CALIBRATION */

adc16ChannelConfigStruct.channelNumber = BATT_ADC16_USER_CHANNEL;
adc16ChannelConfigStruct.enableInterruptOnConversionCompleted = true; /* Enable the interrupt. */
#if defined(FSL_FEATURE_ADC16_HAS_DIFF_MODE) && FSL_FEATURE_ADC16_HAS_DIFF_MODE
adc16ChannelConfigStruct.enableDifferentialConversion = false;
#endif /* FSL_FEATURE_ADC16_HAS_DIFF_MODE */
}

 

 

void read_battery_level(){

g_Adc16ConversionDoneFlag = false;
/*
When in software trigger mode, each conversion would be launched once calling the "ADC16_ChannelConfigure()"
function, which works like writing a conversion command and executing it. For another channel's conversion,
just to change the "channelNumber" field in channel configuration structure, and call the function
"ADC16_ChannelConfigure()"" again.
Also, the "enableInterruptOnConversionCompleted" inside the channel configuration structure is a parameter for
the conversion command. It takes affect just for the current conversion. If the interrupt is still required
for the following conversion, it is necessary to assert the "enableInterruptOnConversionCompleted" every time
for each command.
*/
ADC16_SetChannelConfig(BATT_ADC16_BASE, BATT_ADC16_CHANNEL_GROUP, &adc16ChannelConfigStruct);
}

 

void BATT_VOLTAGE_READING_AVAILABLE(void)
{
g_Adc16ConversionDoneFlag = true;
static volatile uint32_t avgAdc16ConvValue = 0;
static volatile int i=0;
/* Read conversion result to clear the conversion completed flag. */
volatile uint32_t adc16ConversionValue = ADC16_GetChannelConversionValue(BATT_ADC16_BASE, BATT_ADC16_CHANNEL_GROUP);

if(i<200){
if (i==0) avgAdc16ConvValue = adc16ConversionValue;
uint32_t quotient = (avgAdc16ConvValue+adc16ConversionValue)/2;
uint32_t remainder = (avgAdc16ConvValue+adc16ConversionValue)%2;
avgAdc16ConvValue = quotient+remainder;
}
i++;

if (i == 200){
i=0;
(void) enqueueEvent( mainEventQueue, ADC_MEASUREMENT_AVAILABLE, (invisible_event_params_t) { .uIntVal = avgAdc16ConvValue }, event_batt_measurement_available );
}
else{
read_battery_level();
}
}

=====================

 

Best regards,

Gaurav.

Outcomes