This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

ADC Single Conversion Sample

Hi

I am currently having a issue about ADC conversion because I always get the first wrong ADC sample but get correct reading after second try. I assume it is reading dummy data.

Now I tried to read three channels starting from channel 0 to channel 2 respectively at first try and second try.

I measured the voltage signal on each channel and know what to expect from ADC channel from zero to two. I obtained incorrect readings.

Here is my extracted code:


// 1st Try
// Channel 0
ADC_vConfConv(ADC_FIXED, ADC_ANA_0);
ADC_vStartConv();
while(ADC_ubBusy());
ReturnedADC = ADC_DAT & 0x0FFC;
adc_result[ADC_ANA_0] = _iror_(ReturnedADC,2);
First_Try_Channel[0]=adc_result[ADC_ANA_0];


// Channel 1
ADC_vConfConv(ADC_FIXED, ADC_ANA_1);
ADC_vStartConv();
while(ADC_ubBusy());
ReturnedADC = ADC_DAT & 0x0FFC;
adc_result[ADC_ANA_1] = _iror_(ReturnedADC,2);
First_Try_Channel[1]=adc_result[ADC_ANA_1];


// Channel 2
ADC_vConfConv(ADC_FIXED, ADC_ANA_2);
ADC_vStartConv();
while(ADC_ubBusy());
ReturnedADC = ADC_DAT & 0x0FFC;
adc_result[ADC_ANA_2] = _iror_(ReturnedADC,2);
First_Try_Channel[2]=adc_result[ADC_ANA_2];



// 2nd Try
// Channel 0
ADC_vConfConv(ADC_FIXED, ADC_ANA_0);
ADC_vStartConv();
while(ADC_ubBusy());
ReturnedADC = ADC_DAT & 0x0FFC;
adc_result[ADC_ANA_0] = _iror_(ReturnedADC,2);
Second_Try_Channel[0]=adc_result[ADC_ANA_0];

// Channel 1
ADC_vConfConv(ADC_FIXED, ADC_ANA_1);
ADC_vStartConv();
while(ADC_ubBusy());
ReturnedADC = ADC_DAT & 0x0FFC;
adc_result[ADC_ANA_1] = _iror_(ReturnedADC,2);
Second_Try_Channel[1]=adc_result[ADC_ANA_1];

// Channel 2
ADC_vConfConv(ADC_FIXED, ADC_ANA_2);
ADC_vStartConv();
while(ADC_ubBusy());
ReturnedADC = ADC_DAT & 0x0FFC;
adc_result[ADC_ANA_2] = _iror_(ReturnedADC,2);
Second_Try_Channel[2]=adc_result[ADC_ANA_2];

Is there summat wrong with my snippet code?

Regards

RC

Parents
  • Hallo!

    What is inside you magic functions and what ADC mode are you using? In some cases there is noting bad to get what you got. Please refer to C167 User Manual, ADC section, to learn more about it. E.g., as I can interpret an illustration in there, in Auto Scan Convertion Mode example, you will have "garbage" for the very first convertion output (there is an effective shift of samples). It is not visible from the snippets how do you program the ADC. E.g., even when I use single channel mode I use "clean-up" code as shown below t obe on safe side.

    static WORD iadc_get_average(int ch, int n, int ms) {
     long s= 0L;
     int i, x;
    
     // clean-it  ;-)
     ADCON= 0xF080 + ch;  // start new conversion on channel 'ch' so it pre-set
     while (ADBSY);       // wait for conversion to finish
     x= ADDAT & 0x3FF;    // sample
    
     for(i= 0; i< n; i++) {
       IAdcDelay(ms);
       ADCON= 0xF080 + ch;
       while (ADBSY);
       x= ADDAT & 0x3FF;    // sample
       s+= x;
     };
    
     return (WORD)((((float)s)/((float)n)) + 0.5);
    }
    

    As I can imagine for auto-scan convertion mode where multiple number of channels participate, this behavior of ADC is OK. It is because when you start internal ADC convertion routine for the very first time you CAN NOT yet communicate to the chip which channel HAD to be set in its pre-history ;-)

    I.e., launching the ADC starting from channel A, you ask ADC to convert previously latched channel X and as soon as initiated conversion done, you will get answer for a previously multiplexed channel X which is a 'garbage'. Correct sequence you expecting for, will appear with one sample shift (at least for scan mode).

    P.S. Can somebody prove this understanding is incorrect, i.e. ADC should yield the first sample correctly under any circumstances?

    Regards,
    Nikolay.

Reply
  • Hallo!

    What is inside you magic functions and what ADC mode are you using? In some cases there is noting bad to get what you got. Please refer to C167 User Manual, ADC section, to learn more about it. E.g., as I can interpret an illustration in there, in Auto Scan Convertion Mode example, you will have "garbage" for the very first convertion output (there is an effective shift of samples). It is not visible from the snippets how do you program the ADC. E.g., even when I use single channel mode I use "clean-up" code as shown below t obe on safe side.

    static WORD iadc_get_average(int ch, int n, int ms) {
     long s= 0L;
     int i, x;
    
     // clean-it  ;-)
     ADCON= 0xF080 + ch;  // start new conversion on channel 'ch' so it pre-set
     while (ADBSY);       // wait for conversion to finish
     x= ADDAT & 0x3FF;    // sample
    
     for(i= 0; i< n; i++) {
       IAdcDelay(ms);
       ADCON= 0xF080 + ch;
       while (ADBSY);
       x= ADDAT & 0x3FF;    // sample
       s+= x;
     };
    
     return (WORD)((((float)s)/((float)n)) + 0.5);
    }
    

    As I can imagine for auto-scan convertion mode where multiple number of channels participate, this behavior of ADC is OK. It is because when you start internal ADC convertion routine for the very first time you CAN NOT yet communicate to the chip which channel HAD to be set in its pre-history ;-)

    I.e., launching the ADC starting from channel A, you ask ADC to convert previously latched channel X and as soon as initiated conversion done, you will get answer for a previously multiplexed channel X which is a 'garbage'. Correct sequence you expecting for, will appear with one sample shift (at least for scan mode).

    P.S. Can somebody prove this understanding is incorrect, i.e. ADC should yield the first sample correctly under any circumstances?

    Regards,
    Nikolay.

Children
  • If you are using an XC16x device then if is recommended not to used the ADBSY bit (Sorry DAvE).

    ADC_X.H1 Polling of Bit ADBSY
    After an A/D conversion is started (standard conversion by setting bit ADST = 1, injected conversion by setting ADCRQ = 1), flag ADBSY is set 5 clock cycles later. When polling for the end of a conversion, it is therefore recommended to check e.g. the interrupt request flags ADC_CIC_IR (for standard conversions) or ADC_EIC_IR (for injected conversions) instead of ADBSY.

    Meaning you read it before it was actually converted.