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.

TMS320F28379D: ADC Error

Part Number: TMS320F28379D
Other Parts Discussed in Thread: SYSCONFIG,

HI 

I am currently using a 1.5V battery to test the ADC error of the F28379D EVM board, but the current test results are shown in the figure below. Both the maximum and minimum values of the ADC exceed the ADC error 7 LSB written on the datasheet. How can I set it to achieve the ADC error 7 LSB?

The following program I wrote first discards the first 9000 data of the ADC value, and calculates the maximum and minimum values and the average ADC value of the 3000 ADC values after the ADC module is stable.

//#############################################################################
//
// FILE:   adc_ex2_soc_epwm.c
//
// TITLE:  ADC ePWM Triggering
//
//! \addtogroup driver_example_list
//! <h1>ADC ePWM Triggering</h1>
//!
//! This example sets up ePWM1 to periodically trigger a conversion on ADCA.
//!
//! \b External \b Connections \n
//!  - A0 should be connected to a signal to convert
//!
//! \b Watch \b Variables \n
//! - \b adcAResults - A sequence of analog-to-digital conversion samples from
//!   pin A0. The time between samples is determined based on the period
//!   of the ePWM timer.
//!
//
//#############################################################################
//
// $Release Date: $
// $Copyright:
// Copyright (C) 2013-2022 Texas Instruments Incorporated - http://www.ti.com/
//
// Redistribution and use in source and binary forms, with or without 
// modification, are permitted provided that the following conditions 
// are met:
// 
//   Redistributions of source code must retain the above copyright 
//   notice, this list of conditions and the following disclaimer.
// 
//   Redistributions in binary form must reproduce the above copyright
//   notice, this list of conditions and the following disclaimer in the 
//   documentation and/or other materials provided with the   
//   distribution.
// 
//   Neither the name of Texas Instruments Incorporated nor the names of
//   its contributors may be used to endorse or promote products derived
//   from this software without specific prior written permission.
// 
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// $
//#############################################################################
//

//
// Included Files
//
#include "driverlib.h"
#include "device.h"

//
// Defines
//
#define RESULTS_BUFFER_SIZE     3000
#define EX_ADC_RESOLUTION       12
// 12 for 12-bit conversion resolution, which supports (ADC_MODE_SINGLE_ENDED)
// Sample on single pin (VREFLO is the low reference)
// Or 16 for 16-bit conversion resolution, which supports (ADC_MODE_DIFFERENTIAL)
// Sample on pair of pins (difference between pins is converted, subject to
// common mode voltage requirements; see the device data manual)

//
// Globals
//
volatile uint16_t adcAResults[RESULTS_BUFFER_SIZE];   // Buffer for results
uint16_t index;                              // Index into result buffer
uint16_t i;
volatile uint32_t sum_of_adc_data;
volatile uint32_t avg_adc_value, diff_value;
volatile uint16_t bufferFull;                // Flag to indicate buffer is full
volatile uint32_t Max_adc_value = 0x00000000;
volatile uint32_t Min_adc_value = 0xFFFFFFFF;
//
// Function Prototypes
//
void initADC(void);
void initEPWM(void);
void initADCSOC(void);
__interrupt void adcA1ISR(void);

//
// Main
//
void main(void)
{
    //
    // Initialize device clock and peripherals
    //
    Device_init();

    //
    // Disable pin locks and enable internal pullups.
    //
    Device_initGPIO();

    //
    // Initialize PIE and clear PIE registers. Disables CPU interrupts.
    //
    Interrupt_initModule();

    //
    // Initialize the PIE vector table with pointers to the shell Interrupt
    // Service Routines (ISR).
    //
    Interrupt_initVectorTable();

    //
    // Interrupts that are used in this example are re-mapped to ISR functions
    // found within this file.
    //
    Interrupt_register(INT_ADCA1, &adcA1ISR);

    //
    // Set up the ADC and the ePWM and initialize the SOC
    //
    initADC();
    initEPWM();
    initADCSOC();

    //
    // Initialize results buffer
    //
    for(index = 0; index < RESULTS_BUFFER_SIZE; index++)
    {
        adcAResults[index] = 0;
    }

    index = 0;
    bufferFull = 0;

    //
    // Enable ADC interrupt
    //
    Interrupt_enable(INT_ADCA1);

    //
    // Enable Global Interrupt (INTM) and realtime interrupt (DBGM)
    //
    EINT;
    ERTM;

    //
    // Loop indefinitely
    //
    while(1)
    {
        //
        // Start ePWM1, enabling SOCA and putting the counter in up-count mode
        //


        EPWM_enableADCTrigger(EPWM1_BASE, EPWM_SOC_A);
        EPWM_setTimeBaseCounterMode(EPWM1_BASE, EPWM_COUNTER_MODE_UP);

        //
        // Wait while ePWM1 causes ADC conversions which then cause interrupts.
        // When the results buffer is filled, the bufferFull flag will be set.
        //
        if(bufferFull == 3){
            EPWM_disableADCTrigger(EPWM1_BASE, EPWM_SOC_A);
            EPWM_setTimeBaseCounterMode(EPWM1_BASE, EPWM_COUNTER_MODE_STOP_FREEZE);

            for(i = 0; i < RESULTS_BUFFER_SIZE; i++){
                if(adcAResults[i] > Max_adc_value){
                    Max_adc_value = adcAResults[i];
                }
                if(adcAResults[i] < Min_adc_value){
                    Min_adc_value = adcAResults[i];
                }
                sum_of_adc_data += adcAResults[i];
            }
            avg_adc_value = sum_of_adc_data / RESULTS_BUFFER_SIZE;
            diff_value = 2121 - avg_adc_value;

            ESTOP0;
        }
//        while(bufferFull == 0)
//        {
//        }
//        bufferFull = 0;     // Clear the buffer full flag
//
//        //
//        // Stop ePWM1, disabling SOCA and freezing the counter
//        //
//        EPWM_disableADCTrigger(EPWM1_BASE, EPWM_SOC_A);
//        EPWM_setTimeBaseCounterMode(EPWM1_BASE, EPWM_COUNTER_MODE_STOP_FREEZE);

        //
        // Software breakpoint. At this point, conversion results are stored in
        // adcAResults.
        //
        // Hit run again to get updated conversions.
        //
        //ESTOP0;
    }
}

//
// Function to configure and power up ADCA.
//
void initADC(void)
{
    
    //
    // Set ADCDLK divider to /4
    //
    ADC_setPrescaler(ADCA_BASE, ADC_CLK_DIV_2_0);

    //
    // Set resolution and signal mode (see #defines above) and load
    // corresponding trims.
    //
#if(EX_ADC_RESOLUTION == 12)
    ADC_setMode(ADCA_BASE, ADC_RESOLUTION_12BIT, ADC_MODE_SINGLE_ENDED);
#elif(EX_ADC_RESOLUTION == 16)
    ADC_setMode(ADCA_BASE, ADC_RESOLUTION_16BIT, ADC_MODE_DIFFERENTIAL);
#endif

    //
    // Set pulse positions to late
    //
    ADC_setInterruptPulseMode(ADCA_BASE, ADC_PULSE_END_OF_CONV);

    //
    // Power up the ADC and then delay for 1 ms
    //
    ADC_enableConverter(ADCA_BASE);
    DEVICE_DELAY_US(1000);
}

//
// Function to configure ePWM1 to generate the SOC.
//
void initEPWM(void)
{
    //
    // Disable SOCA
    //
    EPWM_disableADCTrigger(EPWM1_BASE, EPWM_SOC_A);

    //
    // Configure the SOC to occur on the first up-count event
    //
    EPWM_setADCTriggerSource(EPWM1_BASE, EPWM_SOC_A, EPWM_SOC_TBCTR_U_CMPA);
    EPWM_setADCTriggerEventPrescale(EPWM1_BASE, EPWM_SOC_A, 1);

    //
    // Set the compare A value to 1000 and the period to 1999
    // Assuming ePWM clock is 100MHz, this would give 50kHz sampling
    // 50MHz ePWM clock would give 25kHz sampling, etc. 
    // The sample rate can also be modulated by changing the ePWM period
    // directly (ensure that the compare A value is less than the period). 
    //
    EPWM_setCounterCompareValue(EPWM1_BASE, EPWM_COUNTER_COMPARE_A, 1000);
    EPWM_setTimeBasePeriod(EPWM1_BASE, 1999);

    //
    // Set the local ePWM module clock divider to /1
    //
    EPWM_setClockPrescaler(EPWM1_BASE,
                           EPWM_CLOCK_DIVIDER_1,
                           EPWM_HSCLOCK_DIVIDER_1);

    //
    // Freeze the counter
    //
   // EPWM_setTimeBaseCounterMode(EPWM1_BASE, EPWM_COUNTER_MODE_STOP_FREEZE);
}

//
// Function to configure ADCA's SOC0 to be triggered by ePWM1.
//
void initADCSOC(void)
{
    //
    // Configure SOC0 of ADCA to convert pin A0. The EPWM1SOCA signal will be
    // the trigger.
    // - For 12-bit resolution, a sampling window of 15 (75 ns at a 200MHz
    //   SYSCLK rate) will be used.  For 16-bit resolution, a sampling window
    //   of 64 (320 ns at a 200MHz SYSCLK rate) will be used.
    // - NOTE: A longer sampling window will be required if the ADC driving
    //   source is less than ideal (an ideal source would be a high bandwidth
    //   op-amp with a small series resistance). See TI application report
    //   SPRACT6 for guidance on ADC driver design.
    //

#if(EX_ADC_RESOLUTION == 12)
    ADC_setupSOC(ADCA_BASE, ADC_SOC_NUMBER0, ADC_TRIGGER_EPWM1_SOCA,
                 ADC_CH_ADCIN0, 128);
#elif(EX_ADC_RESOLUTION == 16)
    ADC_setupSOC(ADCA_BASE, ADC_SOC_NUMBER0, ADC_TRIGGER_EPWM1_SOCA,
                 ADC_CH_ADCIN0, 64);
#endif

    //
    // Set SOC0 to set the interrupt 1 flag. Enable the interrupt and make
    // sure its flag is cleared.
    //
    ADC_setInterruptSource(ADCA_BASE, ADC_INT_NUMBER1, ADC_SOC_NUMBER0);
    ADC_enableInterrupt(ADCA_BASE, ADC_INT_NUMBER1);
    ADC_clearInterruptStatus(ADCA_BASE, ADC_INT_NUMBER1);
}

//
// ADC A Interrupt 1 ISR
//
__interrupt void adcA1ISR(void)
{

    //
    // Add the latest result to the buffer
    //
    adcAResults[index++] = ADC_readResult(ADCARESULT_BASE, ADC_SOC_NUMBER0);

    //
    // Set the bufferFull flag if the buffer is full
    //

    if(RESULTS_BUFFER_SIZE <= index)
    {
        index = 0;
        bufferFull += 1;
    }

    //
    // Clear the interrupt flag
    //
    ADC_clearInterruptStatus(ADCA_BASE, ADC_INT_NUMBER1);

    //
    // Check if overflow has occurred
    //
    if(true == ADC_getInterruptOverflowStatus(ADCA_BASE, ADC_INT_NUMBER1))
    {
        ADC_clearInterruptOverflowStatus(ADCA_BASE, ADC_INT_NUMBER1);
        ADC_clearInterruptStatus(ADCA_BASE, ADC_INT_NUMBER1);
    }

    //
    // Acknowledge the interrupt
    //
    Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP1);
}

  • Hello Poyi,

    What is the sampling rate that you are using for the ADC (in samples per second)? Also, do you have some sort of capacitor that can filter noise from the ADC input pin?

    Best regards,

    Omer Amir

  • Hi

    SYSCLK = 120MHz(8.33ns)

    ADCCLK = 60MHz(16.6ns)

    ADC sample window =128

    DACB output 2048(1.5V)

    I did another experiment, using DACB output 2048 (1.5V) to ADCA0, adding 0.1uF capacitor to ADC 128 SampleWindow and ADC input to filter the noise, but there is still a lot of noise as shown in the figure below.

  • Hello Poyi,

    What was the original setup when you were measuring the 1.5V battery? It sounds like there wasn't a capacitor on the input, was there anything else different? Next, verify that the battery connection is very secure, any loose connection can create noise.

    As a side question, are you using SysConfig to configure any of the initialization, or is the attached code all that you have configured?

    Best regards,

    Omer Amir

  • hi

    1. In the original experiment, I did not add a capacitor, but in the later experiment I added a 150pF capacitor, as shown in the figure below, there is still a lot of noise.
    2. The code above is my setup, I am not using SYSCONFIG.
    3. In addition, I found that I connected ADCAIN0 to the GND of F28379D. The experimental results are as shown in the figure below and there is a lot of noise. Could you please help me with the experiment, whether the GND of the F28379D controlcard contains noise and cause ADC noise.

  • Hi Poyi,

    Omer is out of office due to Thanksgiving Holiday. He will be back in office next week, please expect response by Monday/Tuesday. Sincere apology for delay.

    Regards, Santosh

  • Hello Poyi,

    I'll look into this a little more and try to do more research regarding noise reduction for this device. I will try to have a response by end of day tomorrow.

    Best regards,

    Omer Amir

  • Hello Poyi,

    A few follow-up questions for you regarding your setup:

    1. What is the EVM you are using? If it's something custom, do you mind providing the schematics?
    2. What sort of supplies are connected to the EVM?
    3. Is there anything in your software that's running besides the ADC conversion? This could be GPIOs toggling, etc.
    4. Are you running your code from Flash or RAM? If you're using RAM, what type of emulator are you using and what's the TCK running at?

    Best regards,

    Omer Amir

  • HI,

    1. Delfino TMS320F28379D controlCARD R1.3,no other custom.
    2. USB HUB to EVM
    3. I use TI provide example  adc_ex2_soc_epwm.c. This example only use ADC & EPWM.
    4. I run my code on Flash.

    The above is the answer to my question, can you help me test the ADC example,if you have the same EVM borad,thank you.

    Best regards,

    Poyi Li

  • Hello Poyi,

    Does the error occur when you choose any ADC channel? If so, does it still occur when you choose another ADC? I'll look into why you may be seeing noise on A0, but for now you can try something like A5 to see if the issue is consistent.

    Best regards,

    Omer Amir