This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TM4C129ENCPDT: ADC Reading not correct

Part Number: TM4C129ENCPDT

Hi,

I have configured the Internal ADC of the microcontroller. I am receiving correct values for AIN0, AIN1, AIN2, AIN3, however for AIN8 and AIN9 it would be spitting wrong values. I am guessing, if it has something to do with the order of the channels since there is missing ADC channels between AIN3 and AIN8.

I have configured Port E of the controller for the above signals.

Here is my code;

The port pin definitions are below;

uint32_t IntADCRawData0[8]; //Buffer array that holds ADC samples

//On Board ADC Signals Pins map connected to microcontroller internal ADC
#define ADC_PIN_33Volt GPIO_PIN_0
#define ADC_PIN_5Volt GPIO_PIN_1
#define ADC_PIN_15NegVolt GPIO_PIN_2
#define ADC_PIN_15PosVolt GPIO_PIN_3
#define ADC_PIN_VCF GPIO_PIN_4
#define ADC_PIN_VC2 GPIO_PIN_5


#define ADC_CH_33Volt           ADC_CTL_CH3 //PE0 = AIN3
#define ADC_CH_5Volt            ADC_CTL_CH2 //PE1 = AIN2
#define ADC_CH_15NegVolt        ADC_CTL_CH1 //PE2 = AIN1
#define ADC_CH_15PosVolt        ADC_CTL_CH0 //PE3 = AIN0
#define ADC_CH_VCFVolt          ADC_CTL_CH9 //PE4 = AIN9
#define ADC_CH_VC2Volt          ADC_CTL_CH8 //PE5 = AIN8

The ADC init function is here;

void Internal_ADC0_Init(void)
{
    //First configure common ADC Ports and Pins
    // *** Peripheral Enable
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);
    ROM_SysCtlPeripheralReset(SYSCTL_PERIPH_GPIOE);
    SysCtlDelay(100);
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
    SysCtlDelay(100);

    //Configure the individual pins being used as ADC input pins
    ROM_GPIOPinTypeADC(GPIO_PORTE_BASE, ADC_PIN_VC2 | ADC_PIN_VCF | ADC_PIN_15PosVolt | ADC_PIN_15NegVolt | ADC_PIN_5Volt | ADC_PIN_33Volt);

    ROM_ADCReferenceSet(ADC0_BASE,ADC_REF_INT);

    ROM_ADCSequenceDisable(ADC0_BASE, 0);  //Disable sequence before we change it

    ROM_ADCSequenceConfigure(ADC0_BASE,0,ADC_TRIGGER_PROCESSOR,0); //ADC Trigger by Processor

    ROM_ADCSequenceStepConfigure(ADC0_BASE,0,0,ADC_CH_15PosVolt); //To sample Channel 0
    ROM_ADCSequenceStepConfigure(ADC0_BASE,0,1,ADC_CH_15NegVolt); //To sample Channel 1
    ROM_ADCSequenceStepConfigure(ADC0_BASE,0,2,ADC_CH_5Volt); //To sample Channel 2
    ROM_ADCSequenceStepConfigure(ADC0_BASE,0,3,ADC_CH_33Volt); //To sample Channel 3
    ROM_ADCSequenceStepConfigure(ADC0_BASE,0,4,ADC_CH_VC2Volt); //To sample Channel 8
    ROM_ADCSequenceStepConfigure(ADC0_BASE,0,5,ADC_CH_VCFVolt); //To sample Channel 9


    ROM_ADCHardwareOversampleConfigure(ADC0_BASE, 64); //Configure the hardware Averager module to average out 64 samples for each channel.

    ROM_ADCSequenceStepConfigure(ADC0_BASE,0,6,ADC_CTL_TS|ADC_CTL_IE|ADC_CTL_END);

    ROM_ADCSequenceEnable(ADC0_BASE,0);
}

After initialization, I call the following function to collect data and save in different variables.

//This function collects data from internal ADC and saves at the pointer location.
void IntADC_Collect_Data(void)
{

        // Trigger the sample sequence.
        ADCProcessorTrigger(ADC0_BASE, 0);

        //while(!ADCIntStatus(ADC0_BASE, 0, false)){} //DO NOT use this while loop as it may take forever instead use a delay
        vTaskDelay(10/portTICK_PERIOD_MS); // 10msec delay
        
        ADCSequenceDataGet(ADC0_BASE, 0, IntADCRawData0);

        volt15Pos.data.value16bits              =   0x0000FFFF & IntADCRawData0[0];
        volt15Neg.data.value16bits              =   0x0000FFFF & IntADCRawData0[1];
        volt5.data.value16bits                  =   0x0000FFFF & IntADCRawData0[2];
        volt33.data.value16bits                 =   0x0000FFFF & IntADCRawData0[3];
        VC2DAC_ReadBack.data.value16bits        =   0x0000FFFF & IntADCRawData0[4];
        VCFDAC_ReadBack.data.value16bits        =   0x0000FFFF & IntADCRawData0[5];
        ProcessorTemp.data.value16bits          =   0x0000FFFF & IntADCRawData0[6];
        Kicker_Spare_Temp.data.value16bits      =   0x0000FFFF & IntADCRawData0[7]; //This is just a place holder since in case of Septum Kicker_Spare_Temp doesnt exist

}

As I said earlier, We can read correctly all values for AIN0, AIN1, AIN2, AIN3, however for AIN8 and AIN9 are not reporting correct values.

Any idea / hint ?

Thanks

  • Hi,

      I have a few questions and comments:

      - What do you mean by incorrect values? Do you mean they are totally random values? What if you tie AIN8/AIN9 to either ground or 3.3V. How much are they off?

     - Can you repeat the same problem on a LaunchPad?

     - For experiment, can you move AIN8 and AIN9 before AIN0. In another word, make AIN8 and AIN9 the step 0 and 1. What is the result?

     - For experiment, can you disable hardware average? What is the result?

  • They are not totally random as they would report a change if my actual voltage at the pin changes. But they are not repeatable for example if you set the input to 2V, they might report 2.5V, now if you change the input pin voltage either increase or decrease the ADC will stay. If you repeat after rebooting the board, the ADC and set 2V at the input pin, the ADC may report a completely different value say for example 3.1V and again if you increase or decrease the pin voltage, the ADC will move accordingly. But then some time it would not move and stay at same level.

    I have tried swapping AIN8 with AIN0, and the problem will move with the swap.

    I have tried disabling the hardware average but not effect.

  • In your IntADC_Collect_Data, why are you not using while(!ADCIntStatus(ADC0_BASE, 0, false)){} and instead using TaskDelay? You may have read the ADC FIFO too quickly before they are done especially when you were using Averaging. Why don't you first remove the averaging circuit and use only while(!ADCIntStatus(ADC0_BASE, 0, false)){}. See below TivaWare example. Do you see any difference? You have not told me what is the result with the LaunchPad? Do you see the same?

    //
    // Trigger the ADC conversion.
    //
    ADCProcessorTrigger(ADC0_BASE, 3);

    //
    // Wait for conversion to be completed.
    //
    while(!ADCIntStatus(ADC0_BASE, 3, false))
    {
    }

    //
    // Clear the ADC interrupt flag.
    //
    ADCIntClear(ADC0_BASE, 3);

    //
    // Read ADC Value.
    //
    ADCSequenceDataGet(ADC0_BASE, 3, pui32ADC0Value);

  • I have removed the hardware average. Instead of using the while() loop, I am waiting for 10 msec, which should be more than enough. I can increase that delay. Trying my code on the development board will take a lot of efforts, I may try some other day. But I have something useful to report back. I see AIN9 is reporting correctly but AIN8 is not reporting correctly. That means all channels AIN0, AIN1, AIN2, AIN3, AIN9 are reporting correctly only AIN8 is reporting wrong values. I was able to read the pin voltage so I am sure what is on the PIN but the ADC is reporting wrong values. 

  • Hi,

      What if you swap the order between AIN8 and AIN9? What is the result. I can't find anything in the errata that explains your findings.

  • Hi Charles,

    I found it was a dry-sold on the Pin for AIN8.. It is working now. Thanks for your help and you have a wonderful day.