I am working with an NXP MCXA185 and using the LPADC to read a potentiometer connected to P2_0 / ADC0_A0.
My current implementation uses:
ADC0 / ADC0_A0
High-resolution conversion mode
LPADC hardware averaging of 128 samples
Long ADC sample time (kLPADC_SampleTimeADCK19)
One ADC reading every 1 ms (1000 Hz)
Software-triggered conversions
A block average of 100 samples
The resulting average is updated every 100 ms
So effectively, each value used in the block average has already been averaged by the ADC hardware over 128 conversions.
cmdConfig.conversionResolutionMode = kLPADC_ConversionResolutionHigh; cmdConfig.hardwareAverageMode = kLPADC_HardwareAverageCount128; cmdConfig.sampleChannelMode = kLPADC_SampleChannelSingleEndSideA; cmdConfig.sampleTimeMode = kLPADC_SampleTimeADCK19;
Then every 1 ms:
LPADC_DoSoftwareTrigger(POT_LPADC_BASE,
(1U << POT_LPADC_TRIGGER_ID));
while (!LPADC_GetConvResult(POT_LPADC_BASE, &result))
{
/* Wait for conversion */
}
s_blockSum += result.convValue;
s_sampleCount++;
if (s_sampleCount >= 100U)
{
s_lastAverage =
(uint16_t)(s_blockSum / 100U);
s_blockSum = 0U;
s_sampleCount = 0U;
}Is this a good approach for getting a stable potentiometer value, or is there a better ADC filtering/averaging strategy?
In particular, I am wondering about:
Is using 128-count hardware averaging + 100-sample software averaging excessive for a potentiometer?
Does this actually provide useful additional noise reduction, or am I just increasing the response latency?
Would it be better to use a smaller hardware average, such as 16 or 32 samples, and then use a software filter?
Would an IIR/exponential moving average be better than a 100-sample block average for a potentiometer because it provides a smoother value while responding faster to knob movement?
Is kLPADC_SampleTimeADCK19 appropriate for a typical potentiometer, or should I use a different sample time?
Are there any MCXA185-specific LPADC settings that I should enable for better stability?
Is polling the ADC result inside a 1 ms function a reasonable implementation, or would a hardware timer trigger + ADC FIFO/interrupt approach be preferable?
I am currently using:
cfg.pullSelect = kPORT_PullDisable; cfg.driveStrength = kPORT_LowDriveStrength; cfg.passiveFilterEnable = true; cfg.inputBuffer = kPORT_InputBufferDisable;
The potentiometer is connected as a voltage divider, with the wiper connected to P2_0 / ADC0_A0.
I am mainly interested in getting a value that is:
Stable when the potentiometer is not moving
Responsive when the potentiometer is turned
Not unnecessarily delayed by excessive averaging
Resistant to small ADC/wiper noise
I would appreciate feedback on whether my current 128 hardware average + 100-sample block average approach is appropriate, and what filtering strategy you would recommend for this application.