PIC32MZ - ADC alternate pin
I am working on a PIC32MZ project, and getting a bit stuck on the ADC.
So far, I only worked with PIC32MX device, and my new design with PIC32MZ was mostly based on what I already knew. It's only when I started working on the software that I discovered that the ADC is far different between PIC32MX and MZ.
Anyway, I know have my hardware in front of me, and need to work with it.
I managed to properly setup the ADCs I need (Class1 ADC1 to ADC4, and Class 3 ADC7), and I get the expected ADC results.
I need to make measurement on AN0 and AN45, which are both connected to ADC1. Selection is made using the SH0ALT register.
- AN0 is measuring an image of one of the DC inputs, providing ~2.5V
- AN45 is reading another DC signal, that can be either 0V or 0.25V.
Most of the time, I am getting normal result. However, from time to time, the result on AN45 can vary quite a lot (+/- 25%), while the signal is not moving at all. I haven't check for any error error on AN0, since it's less sensitive in my application, but it's probably similar.
I first suspected an issue with the sampling duration : CHOLD might not have enough time to charge/discharge to the level of AN0/AN45 when changing the input. That's why I have a 1ms delay after setting SH0ALT. Also, the sampling time is ~100µs, which should be more than enough.
I know that the ADC is properly setup, because if I using a secondary DC input, I am never getting false results. In this case, ADC1 is still toggling between AN0 and AN45, but the voltage AN0 is 0V.
I did not find any info concerning the modification of SHxALT during runtime. This register is probably designed to be configured only once at the init ?
Here is a simplified version of my code.
Note that I don't think it's a code problem, as the wrong results only occur from time to time.
// Request conversions for the Class 1 ADC, by setting the trigger
ADCCON3bits.GSWTRG = 1;
// Wait for the results
ADC_State = ADC_WAIT_CLASS1_RESULTS_READY ;
// Wait for all the Class 1 ADC to be done
while(!ADCDSTAT1bits.ARDY0 && !ADCDSTAT1bits.ARDY1 && !ADCDSTAT1bits.ARDY2 && !ADCDSTAT1bits.ARDY3 &&! ADCDSTAT1bits.ARDY4) ;
// Results are ready !
localADCResults = ADCDATA0 ; // Read the results
localADCResults = ADCDATA1 ;
localADCResults = ADCDATA2 ;
localADCResults = ADCDATA3 ;
localADCResults = ADCDATA4 ;
// Toggle ADC0 to sample AN45 instead of AN0,
// and allow a bit of time for the change to be effective
ADCTRGMODEbits.SH0ALT = 1 ;
// AN45 is now connected to ADC0 : force a conversion on ADC0
// Don't use GSWTRG : that would request a conversion on all the ADCs.
// Use the Single Conversion flag (RQCNVRT)
ADCCON3bits.ADINSEL = 0 ;
ADCCON3bits.RQCNVRT = 1 ;
// Wait for completion and get the result
// Result is ready !
localADCResults = ADCDATA0 ;
// Set ADC0 back to AN0, for the next call
ADCTRGMODEbits.SH0ALT = 0 ;
Note that since I am measuring slow DC signal, I have no special needs for very fast or very accurate ADC, as long as I am getting some reliable results (10%).
Any help is welcome !