ADC not working correctly SAMD20 (No ASF) - Page 1
Forum section: electronics / general

author: matthew_zammit
author_rank: Newbie
timestamp: May 04, 2018, 05:48:16 pm
content: So, I have an ADC which is software triggered every 30ms via the RTC interrupt handler. The problem is that the ADC produces garbage results no matter the voltage applied at the input. Am I setting it up wrongly?Code:void init_ADC(){//ADC INPUT PIN INITPORT->Group.PINCFG.reg = PORT_PINCFG_INEN | PORT_PINCFG_PMUXEN; // INPUT ENABLE AND PERIPHERAL MULTIPLEXING FOR ADC_INPUTPORT->Group.PMUX.reg = PORT_PMUX_PMUXE_B; // ENABLE ANLOUGE INPUT FOR ADC_INPUT//Clock ADC by GCLK0REG_GCLK_CLKCTRL = GCLK_CLKCTRL_WRTLOCK |GCLK_CLKCTRL_CLKEN |GCLK_CLKCTRL_ID_ADC |GCLK_CLKCTRL_GEN_GCLK0;REG_PM_APBCMASK |= PM_APBCMASK_ADC;// enable ADC APB clock BUSNVIC_SetPriority(ADC_IRQn,0); // SET TO HIGHEST PRIORITY INTERRUPTNVIC_EnableIRQ( ADC_IRQn );// enable interrupts for ADC// 1.65V reference Voltage and (Reference buffer gain compensator -- REMOVE COMMENTS TO ENABLE)REG_ADC_REFCTRL |= ADC_REFCTRL_REFSEL_INTVCC1;// | ADC_REFCTRL_REFCOMP;while(ADC->STATUS.bit.SYNCBUSY); //wait for synchronizationREG_ADC_CTRLB |= ADC_CTRLB_PRESCALER_DIV4 | ADC_CTRLB_RESSEL_10BIT | ADC_CTRLB_LEFTADJ; //| ADC_CTRLB_CORREN;while(ADC->STATUS.bit.SYNCBUSY); //wait for synchronization//INTERRUPT SET FOR WINDOW MONITOR or result is readyREG_ADC_INTENSET |= ADC_INTFLAG_RESRDY;while(ADC->STATUS.bit.SYNCBUSY); //wait for synchronizationREG_ADC_INPUTCTRL |= ADC_INPUTCTRL_MUXPOS_PIN12 | ADC_INPUTCTRL_GAIN_DIV2 | ADC_INPUTCTRL_MUXNEG_GND; //PIN MULTIPLEXING FOR ADC INPUTwhile(ADC->STATUS.bit.SYNCBUSY); //wait for synchronization//Use this to calibrate Adc --- REG_ADC_CALIB = ADC_CALIB_BIAS_CAL() | ADC_CALIB_LINEARITY_CAL();//This can be adjusted post testing -- REG_ADC_SAMPCTRL = ADC_SAMPCTRL_SAMPLEN(SOME SAMPLE LENGTH);REG_ADC_CTRLA |= ADC_CTRLA_ENABLE; //ENABLE ADCwhile(ADC->STATUS.bit.SYNCBUSY); //wait for synchronization}The Result register is read in the ADC interrupt handler. I've also tried enabling an LED at different Voltage thresholds but still no luck.

author: ajb
author_rank: Super Contributor
timestamp: May 04, 2018, 08:35:26 pm
content: IIRC, you have to provide some value for the offset and bias cal, I think the reset values will not give correct results. Anyway, you want to at least load the factory cal values if you're not doing your own calibration. Forum member ataradov has some example ADC startup code here:https://github.com/ataradov/dgw/blob/master/embedded/adc.cAlso check that your sampling times are reasonable. For testing purposes, just set the sampling time to maximum to avoid any issues with miscalculated clocks--without knowing what the GCLK source is it's hard to say if the ADC is running at a reasonable rate.

author: ataradov
author_rank: Super Contributor
timestamp: May 04, 2018, 08:39:31 pm
content: What is your frequency on GCLK0? If it is higher than 8 MHz, then you are overclocking the ADC. You need to use the divider to slow down the clock.The code looks reasonable otherwise.And yes, calibration data will help, but without it you would be getting just 0, not random values.

author: matthew_zammit
author_rank: Newbie
timestamp: May 05, 2018, 09:11:04 am
content: Yes, using 8-bit mode made it work correctly. I ended up increasing the prescaler to 16 for it to work in 12-bit. Thanks a lot

author: ataradov
author_rank: Super Contributor
timestamp: May 05, 2018, 09:13:28 am
content: Sample size should not matter. What matters is the input clock frequency. Maximum clock frequency after the prescaler is 2 MHz.