Post Go back to editing

ADuC7061. ADC Offset Calibration Register (ADC0OF, ADC1OF)

Thread Summary

The user is experiencing issues with the ADC offset calibration on the ADuC7060, where the offset calibration registers (ADC0OF, ADC1OF) read 0 after calibration, and the offset error for the auxiliary channels (ADC2/ADC3) remains high (1500-3500) despite enabling chopping and performing self-offset calibration. The final answer suggests that chopping should correct the offset error, but the user's setup shows no improvement. The user also notes a significant difference in offset errors between chips from different distributors, suggesting a potential issue with the chip or external circuitry.
AI Generated Content

After calibration Primary / Auxiliary Channel ADC Offset Calibration Register (ADC0OF, ADC1OF) always are read = 0. Both self-offset and zero-scale calibration mode. It is unclear how to correct the values for negative/positive offsets.

  • Hi,

    I saw that you attached an image, but it's not loading on my end.

    Have you checked the offset calibration register before initiating the calibration? Is the reading 0 as well?

    The ADC offset calibration register is automatically applied to the ADC reading to compensate for the offset error.

    Regards,

    Karl

  • Before initiating the calibration value of registers ADC0OF, ADC1OF is about 2..8.

  • What is the configuration for the ADCFLT register? Is chopping enabled?

  • Yes, of course:

    ADCFLT_CHOP_ENABLE | ADCFLT_RUNNING_AVERAGE | ADCFLT_NOTCH2
    +
     SF=9, AF=63 (Data_Rate=12.12Hz, Settling_Time=165ms, 50Hz --> -329dB)

  • Chopping already corrects the offset error. That is why the offset calibration register (ADC0OF, ADC1OF) reads as 0 after initiating the calibration since the chopping is enabled.

  • Primary (ADC0/ADC1)/ Auxiliary (ADC2/ADC3) channels are in differential mode, enable, external reference inputs (VREF+, VREF−).

    All the iput pins are short-circuited. (ADC0=ADC1=ADC2=ADC3).

    "Chop Enable = 1" does not correct the offset error Auxiliary (ADC2/ADC3) channel.

    Command ADC self-offset calibration: "ADCMDE  = ADCMDE_OFFSET_CAL | ADCCLKSEL_131KHZ;" does not correct the offset error Auxiliary (ADC2/ADC3) channel too.

    The value of offset error Auxiliary (ADC2/ADC3) channel = 1500 ... 3500.

    When using an internal reference, self-offset calibration works well. The value of offset error = 0..3.

  • Is there no difference in ADC output before and after enabling chop or performing ADC self-offset calibration?

    Are you using an ADuC7060 evaluation board or your board in testing the ADC?

    Can you show the register values and sequence used in configuring both?


  •    The board is its own. The board does not affect, because the inputs are short-circuited.

    Uref = 300 Ohm * 600 uA = 180 mV. Increasing the current to 1000uA (300 mV) has no effect.

        // Excitation Current Sources = 600 uA

        IEXCON  = BIT7 | BIT2 | BIT1; // IEXC1=1, 600uA
        DelayMS(2000);          // Delay 2000 mS



        // ADC0 = (ADC0/ADC1) pins
        // ADC1 = (ADC2/ADC3) pins

        ADCMDE  = ADC_IDLE_MODE;    // ADC idle mode
        // SF=7, AF=59 (Data_Rate=16.128Hz, Settling_Time=124ms, 50Hz --> -329dB)
        ADCFLT  = (ADCFLT_CHOP_ENABLE | (0x07 << 0) | (0x3B << 8));
        // ADC0 Gain=1, ext.ref (VREF+,VREF-), ADC0/ADC1
        ADC0CON = (ADC0CON_REF_EXT | ADC0CON_ADC0EN | ADC0CON_CHANNEL_DIFF_0_1);
        // ADC1 Gain=1, ext.ref (VREF+,VREF-), ADC2/ADC3
        ADC1CON = (ADC1CON_REF_EXT | ADC1CON_ADC0EN | ADC1CON_CHANNEL_2_3_DIFF);
        DelayMS(250);               // Delay 250 mS


        // Get Data ADC
        ADCMDE  = ADCMDE_VALUE;     // Continuous mode, ADCCLK = 512 kHz  
        while (!(ADCSTA & (ADC0RDY | ADC1RDY))) {}  // Wait new data
        while (!(ADCSTA & (ADC0RDY | ADC1RDY))) {}  // Wait new data
        while (!(ADCSTA & (ADC0RDY | ADC1RDY))) {}  // Wait new data
        ADC1_Dat = ADC1DAT;        // Auxiliary ADC  =  107
        ADC0_Dat = ADC0DAT;        // Primary ADC    =  2564

        // ADC self-gain calibration
        ADCMDE  = ADCMDE_OFFSET_CAL | ADCCLKSEL_131KHZ;
        while(!(ADCSTA & ADCCALSTA)) {} // Wait ADC calibration status

        // Get Data ADC
        ADCMDE  = ADCMDE_VALUE;     // Continuous mode, ADCCLK = 512 kHz  
        while (!(ADCSTA & (ADC0RDY | ADC1RDY))) {}  // Wait new data
        while (!(ADCSTA & (ADC0RDY | ADC1RDY))) {}  // Wait new data
        while (!(ADCSTA & (ADC0RDY | ADC1RDY))) {}  // Wait new data
        ADC1_Dat = ADC1DAT;        // Auxiliary ADC  =  -27
        ADC0_Dat = ADC0DAT;        // Primary ADC    =  2417









        // ADC0 = ADC1 = (ADC2/ADC3) pins


        ADCMDE  = ADC_IDLE_MODE;    // ADC idle mode
        // SF=7, AF=59 (Data_Rate=16.128Hz, Settling_Time=124ms, 50Hz --> -329dB)
        ADCFLT  = (ADCFLT_CHOP_ENABLE | (0x07 << 0) | (0x3B << 8));
        // ADC0 Gain=1, ext.ref (VREF+,VREF-), ADC2/ADC3
        ADC0CON = (ADC0CON_REF_EXT | ADC0CON_ADC0EN | ADC0CON_CHANNEL_DIFF_2_3);
        // ADC1 Gain=1, ext.ref (VREF+,VREF-), ADC2/ADC3
        ADC1CON = (ADC1CON_REF_EXT | ADC1CON_ADC0EN | ADC1CON_CHANNEL_2_3_DIFF);
        DelayMS(250);               // Delay 250 mS


        // Get Data ADC
        ADCMDE  = ADCMDE_VALUE;     // Continuous mode, ADCCLK = 512 kHz  
        while (!(ADCSTA & (ADC0RDY | ADC1RDY))) {}  // Wait new data
        while (!(ADCSTA & (ADC0RDY | ADC1RDY))) {}  // Wait new data
        while (!(ADCSTA & (ADC0RDY | ADC1RDY))) {}  // Wait new data
        ADC1_Dat = ADC1DAT;        // Auxiliary ADC  =  2480
        ADC0_Dat = ADC0DAT;        // Primary ADC    =  2488

        // ADC self-gain calibration
        ADCMDE  = ADCMDE_OFFSET_CAL | ADCCLKSEL_131KHZ;
        while(!(ADCSTA & ADCCALSTA)) {} // Wait ADC calibration status

        // Get Data ADC
        ADCMDE  = ADCMDE_VALUE;     // Continuous mode, ADCCLK = 512 kHz  
        while (!(ADCSTA & (ADC0RDY | ADC1RDY))) {}  // Wait new data
        while (!(ADCSTA & (ADC0RDY | ADC1RDY))) {}  // Wait new data
        while (!(ADCSTA & (ADC0RDY | ADC1RDY))) {}  // Wait new data
        ADC1_Dat = ADC1DAT;        // Auxiliary ADC  =  2447
        ADC0_Dat = ADC0DAT;        // Primary ADC    =  2478



  • Can you check the ADC reading before and after calibration if the primary and auxiliary ADC configuration uses the internal reference?

    Can you also try performing a system zero-scale calibration using your ADC configurations?

  • Internal reference, before calibration:  ADC0 = 2730;  ADC1 = 4772

    Internal reference, after calibration:  ADC0 = 1;   ADC1 = -3

    As an experiment, I tried to use zero-scale calibration. Works well. But to do this,have to short the channel externally. In work it is impossible.