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.

ADC not working

Other Parts Discussed in Thread: CONTROLSUITE

Dear Friends,

I'm a newbie to C2000 MCU's, as I'm trying to run the adc peripheral, I tried to use the sample code on Controlsuit, but when I connect my signal generator (10H sin wave, 1V pk-pk) to either ADCINA4 or ADCINA2, I can not see any change in the watch window, or the Single time graph. I'm using CCS v5. Could you help me on how to solve the problem?

Thank you indeed

//#############################################################################
//
// File: f2802x_examples_ccsv4/adc_soc/Example_F2802xAdcSoc.c
//
// Title: F2802x ADC Start-Of-Conversion (SOC) Example Program.
//
// Group: C2000
// Target Device: TMS320F2802x
//
//! \addtogroup example_list
//! <h1>ADC Start-Of-Conversion (SOC)</h1>
//!
//! Interrupts are enabled and the ePWM1 is setup to generate a periodic
//! ADC SOC - ADCINT1. Two channels are converted, ADCINA4 and ADCINA2.
//!
//! Watch Variables:
//!
//! - Voltage1[10] - Last 10 ADCRESULT0 values
//! - Voltage2[10] - Last 10 ADCRESULT1 values
//! - ConversionCount - Current result number 0-9
//! - LoopCount - Idle loop counter
//
// (C) Copyright 2012, Texas Instruments, Inc.
//#############################################################################
// $TI Release: LaunchPad f2802x Support Library v100 $
// $Release Date: Wed Jul 25 10:45:39 CDT 2012 $
//#############################################################################

#include "DSP28x_Project.h" // Device Headerfile and Examples Include File

#include "f2802x_common/include/adc.h"
#include "f2802x_common/include/clk.h"
#include "f2802x_common/include/flash.h"
#include "f2802x_common/include/gpio.h"
#include "f2802x_common/include/pie.h"
#include "f2802x_common/include/pll.h"
#include "f2802x_common/include/wdog.h"

// Prototype statements for functions found within this file.
interrupt void adc_isr(void);
void Adc_Config(void);

// Global variables used in this example:
uint16_t LoopCount;
uint16_t ConversionCount;
uint16_t Voltage1[10];
uint16_t Voltage2[10];

ADC_Handle myAdc;
CLK_Handle myClk;
FLASH_Handle myFlash;
GPIO_Handle myGpio;
PIE_Handle myPie;
PWM_Handle myPwm;

void main(void)

{

CPU_Handle myCpu;
PLL_Handle myPll;
WDOG_Handle myWDog;

// Initialize all the handles needed for this application
myAdc = ADC_init((void *)ADC_BASE_ADDR, sizeof(ADC_Obj));
myClk = CLK_init((void *)CLK_BASE_ADDR, sizeof(CLK_Obj));
myCpu = CPU_init((void *)NULL, sizeof(CPU_Obj));
myFlash = FLASH_init((void *)FLASH_BASE_ADDR, sizeof(FLASH_Obj));
myGpio = GPIO_init((void *)GPIO_BASE_ADDR, sizeof(GPIO_Obj));
myPie = PIE_init((void *)PIE_BASE_ADDR, sizeof(PIE_Obj));
myPll = PLL_init((void *)PLL_BASE_ADDR, sizeof(PLL_Obj));
myPwm = PWM_init((void *)PWM_ePWM1_BASE_ADDR, sizeof(PWM_Obj));
myWDog = WDOG_init((void *)WDOG_BASE_ADDR, sizeof(WDOG_Obj));

// Perform basic system initialization
WDOG_disable(myWDog);
CLK_enableAdcClock(myClk);
(*Device_cal)();

//Select the internal oscillator 1 as the clock source
CLK_setOscSrc(myClk, CLK_OscSrc_Internal);

// Setup the PLL for x10 /2 which will yield 50Mhz = 10Mhz * 10 / 2
PLL_setup(myPll, PLL_Multiplier_10, PLL_DivideSelect_ClkIn_by_2);

// Disable the PIE and all interrupts
PIE_disable(myPie);
PIE_disableAllInts(myPie);
CPU_disableGlobalInts(myCpu);
CPU_clearIntFlags(myCpu);

// If running from flash copy RAM only functions to RAM
#ifdef _FLASH
memcpy(&RamfuncsRunStart, &RamfuncsLoadStart, (size_t)&RamfuncsLoadSize);
#endif

// Setup a debug vector table and enable the PIE
//PIE_setDebugIntVectorTable(myPie);
PIE_enable(myPie);

// Register interrupt handlers in the PIE vector table
PIE_registerPieIntHandler(myPie, PIE_GroupNumber_10, PIE_SubGroupNumber_1, (intVec_t)&adc_isr);

// Initialize the ADC
ADC_enableBandGap(myAdc);
ADC_enableRefBuffers(myAdc);
ADC_powerUp(myAdc);
ADC_enable(myAdc);
ADC_setVoltRefSrc(myAdc, ADC_VoltageRefSrc_Int);

// Enable ADCINT1 in PIE
PIE_enableAdcInt(myPie, ADC_IntNumber_1);
// Enable CPU Interrupt 1
CPU_enableInt(myCpu, CPU_IntNumber_10);
// Enable Global interrupt INTM
CPU_enableGlobalInts(myCpu);
// Enable Global realtime interrupt DBGM
CPU_enableDebugInt(myCpu);

LoopCount = 0;
ConversionCount = 0;

// Configure ADC
//Note: Channel ADCINA4 will be double sampled to workaround the ADC 1st sample issue for rev0 silicon errata
ADC_setIntPulseGenMode(myAdc, ADC_IntPulseGenMode_Prior); //ADCINT1 trips after AdcResults latch
ADC_enableInt(myAdc, ADC_IntNumber_1); //Enabled ADCINT1
ADC_setIntMode(myAdc, ADC_IntNumber_1, ADC_IntMode_ClearFlag); //Disable ADCINT1 Continuous mode
ADC_setIntSrc(myAdc, ADC_IntNumber_1, ADC_IntSrc_EOC2); //setup EOC2 to trigger ADCINT1 to fire
ADC_setSocChanNumber (myAdc, ADC_SocNumber_0, ADC_SocChanNumber_A4); //set SOC0 channel select to ADCINA4
ADC_setSocChanNumber (myAdc, ADC_SocNumber_1, ADC_SocChanNumber_A4); //set SOC1 channel select to ADCINA4
ADC_setSocChanNumber (myAdc, ADC_SocNumber_2, ADC_SocChanNumber_A2); //set SOC2 channel select to ADCINA2
ADC_setSocTrigSrc(myAdc, ADC_SocNumber_0, ADC_SocTrigSrc_EPWM1_ADCSOCA); //set SOC0 start trigger on EPWM1A, due to round-robin SOC0 converts first then SOC1
ADC_setSocTrigSrc(myAdc, ADC_SocNumber_1, ADC_SocTrigSrc_EPWM1_ADCSOCA); //set SOC1 start trigger on EPWM1A, due to round-robin SOC0 converts first then SOC1
ADC_setSocTrigSrc(myAdc, ADC_SocNumber_2, ADC_SocTrigSrc_EPWM1_ADCSOCA); //set SOC2 start trigger on EPWM1A, due to round-robin SOC0 converts first then SOC1, then SOC2
ADC_setSocSampleWindow(myAdc, ADC_SocNumber_0, ADC_SocSampleWindow_7_cycles); //set SOC0 S/H Window to 7 ADC Clock Cycles, (6 ACQPS plus 1)
ADC_setSocSampleWindow(myAdc, ADC_SocNumber_1, ADC_SocSampleWindow_7_cycles); //set SOC1 S/H Window to 7 ADC Clock Cycles, (6 ACQPS plus 1)
ADC_setSocSampleWindow(myAdc, ADC_SocNumber_2, ADC_SocSampleWindow_7_cycles); //set SOC2 S/H Window to 7 ADC Clock Cycles, (6 ACQPS plus 1)

// Enable PWM clock
CLK_enablePwmClock(myClk, PWM_Number_1);

// Setup PWM
PWM_enableSocAPulse(myPwm); // Enable SOC on A group
PWM_setSocAPulseSrc(myPwm, PWM_SocPulseSrc_CounterEqualCmpAIncr); // Select SOC from from CPMA on upcount
PWM_setSocAPeriod(myPwm, PWM_SocPeriod_FirstEvent); // Generate pulse on 1st event
PWM_setCmpA(myPwm, 0x0080); // Set compare A value
PWM_setPeriod(myPwm, 0xFFFF); // Set period for ePWM1
PWM_setCounterMode(myPwm, PWM_CounterMode_Up); // count up and start

// Wait for ADC interrupt
for(;;)
{
LoopCount++;
}

}


interrupt void adc_isr(void)
{

//discard ADCRESULT0 as part of the workaround to the 1st sample errata for rev0
Voltage1[ConversionCount] = ADC_readResult(myAdc, ADC_ResultNumber_1);
Voltage2[ConversionCount] = ADC_readResult(myAdc, ADC_ResultNumber_2);

// If 10 conversions have been logged, start over
if(ConversionCount == 9)
{
ConversionCount = 0;
}
else ConversionCount++;

// Clear ADCINT1 flag reinitialize for next SOC
ADC_clearIntFlag(myAdc, ADC_IntNumber_1);
// Acknowledge interrupt to PIE
PIE_clearInt(myPie, PIE_GroupNumber_10);

return;
}

  • Hi Tafvizi,

    Have you clicked on the continous refresh button in the watch window? If that is not the issue, what device are you using?

    Regards,

    Frank

  • Hi Frank,

    Thank you for the response. Yeah I have done it and it never changes. I'm using C200 Launchpad which has a F28027 in its core.

  • Hi Tafvizi,

    There are two sets of example code for the f2802x. Try the adc_soc example in controlSUITE/device_support/v220 instead of the one in development_kits/C2000_LaunchPad. That one should work. Essentially one uses driverlib and the other uses structs and bitfields. I'm looking into why the driverlib version is not working.

    Regards,

    Frank

  • Hi Frank,

    I used the adc_soc in v220 and it works fine now, but the problem is the sampling rate is too low, I mean only sine waves until 10Hz are shown fine on this, I tried to change the PWM settings (like shortening the period or reducing CmpA value, but it did not help. Could you give me a hint on how to effectively increase the sampling rate?

    Thank you.

  • Tafvizi,

    The sampling rate is a function of the ADC clock, sampling window and trigger rate. The Adc_soc example is configured to run the ADC at 60MHz. The ADC conversion time is fixed at 13 ADC clocks. The sampling window can be adjusted with the ACQPS field. The ADC requires a minimum sampling window of 7 ADC clocks which is what the Adc_soc example is configured as. So those two parameters are maxed out.The ePWM is setup to run at 30MHz and triggering the ADC every 0xFFFF (0xFF7F+0x80) ePWM clocks. To increase the sampling rate, you could decrease the TBPRD from 0xFFFF to something lower. You could also increase the ePWM frequency from 30MHz to 60MHz. Just keep in mind that the trigger time you choose has to be greater than (Adc sampling duration + Adc Conversion time). With these settings, the ADC is sampling at 457Hz so you should be able to sample signals upto about 228 without aliasing.   

    Regards,

    Frank

  • Hi Franck,

    Thank you indeed for your response. As you said, I tried to reduce period of the epwm by changing   PWM_setPeriod(myPwm, 0x0FFFF)

    to  

    PWM_setPeriod(myPwm, 0x0AFF);

    and then in another attemp change

    PWM_setCmpA(myPwm, 0x0080);

    to 

    PWM_setCmpA(myPwm, 0x0050) (without changing pwm period this time),

    but when I increase my sinewave input to 5Khz, it again shows nonsense. Theoretically it should be fine but I dunno whats the problem. Could you help me with that? Actually what I'm trying to do finally is sampling a 100Khz saw tooth waveform. Do you think this device could be a good fit for this task?

    Kind regards,

    Soroush 

  • Soroush,

    I am having the same problem you had with the interrupt not triggering.  However, the code in my C:\ti\controlSUITE\device_support\f2802x\v200\f2802x_examples looks exactly the same as the code you first posted.  Could you let me know what code ended up working for you?  If I get mine to the same place as yours, maybe I can help you with the sample rate problem.

    Thanks,

    Edward

  • Hi Edward,

    I used the code in the v220 folder. Bote that I created a new project myself and then only copied the code from the example project to my main.c file. Don't forget to include needed folders. Also don't forget

    in project -> properties -> CCS Build -> C2000 Linker -> File Search Path -> Include library : "C:\ti\controlSUITE\development_kits\C2000_LaunchPad\f2802x_common\lib\driverlib.lib"

    and it should work fine, if you graph the Voltage1[n] value in debug mode. If you have any idea for sampling rate please let me know.

    Soroush

  • Thanks!  I started what you were saying but after further research, I found on this page ( http://www.forum.c2kcentral.com/topic/90-launchpad-unable-to-get-adc-examples-to-work/ ) that in the examples the develper forgot to enable the PWM clock!  So I replaced 

    // Perform basic system initialization
    WDOG_disable(myWDog);
    CLK_enableAdcClock(myClk);

    with

    // Perform basic system initialization
    WDOG_disable(myWDog);
    CLK_enableAdcClock(myClk);
    CLK_enableTbClockSync(myClk);
    CLK_enablePwmClock(myClk, PWM_Number_1);


    Now the interrupt is triggered!

    Now I will keep you updated on the sampling rate - I'll first be trying to get handy with the graphing feature which I didn't know existed!

  • Hi Ed,

    I checked my code ( you can see it in the first post) and the lines you mentioned where there (a couple of lines beneath where u replaced them), so that could not be the problem. Anyway I used your codes and replaced them but again it did not help. Do you have any update? could you make your adc work?

    Thank you,

    Soroush

  • Soroush,

    I had to come up with my own graphing scheme because in Code Composer when I click View, Other and then open discrete graph it briefly shows and then instantly disappears.  So I outputted samples to the console and then used Mathematica's ListLinePlot function to graph it.  This does limit me to about 1000 samples because of the size of RAM and the nature of printf when inside an interrupt.  Anyways, I am aiming for a sample rate of 44.1 kHz so I calculated that I would need to set it to trigger after 680 PWMs.  At first the graphs did look like garbage.  But then I remembered that the C2000 only takes positive samples, not negative, so I gave the sin wave input a DC bias, which helped.  Then for the ADC_ReadResult functions, I started taking the average of the sample and the "hold" like this:

    int a = ADC_readResult(myAdc, ADC_ResultNumber_1);
    int b = ADC_readResult(myAdc, ADC_ResultNumber_2);
    voltage[ConversionCount] = (a+b)/2;

    This seemed to help a little bit and make it a little less jumpy.  The signals I tested were in the range of about 1kHz to 1.7 kHz.  Here is an example graph I got. Hoping to make it clearer but you can see the general shape. I hope that anything I said may have helped.

  • I am also now noticing that I don't see the pin VSSA in the C2000 Launchpad user guide as one of the pin headers.  Which makes me wonder where it is and which pin I should have connected to ground from my function generator.  Hmm...

  • Hi Ed,

    You made a very interesting point about ground, when I disconnect my input signal (from a signal generator) ground from the GRND of launchpad, nothing changes, it shows the same crap! so I believe maybe the ground for ADC might be different from GND pin!

    Keep in touch with you updates. Thanks,

    Soroush 

  • Here's an update for you.  I found on page 10 of the "LAUNCHXL-F28027 C2000 Piccolo LaunchPad Experimenter Kit User's Guide" that analog ground, VSSA, is in fact connected to to GND as shown below.  Maybe not so exciting for us, but for me at least since it was late when I was testing, it is entirely possible that my wire to ground got disconnected at some point without me noticing.

     

  • My ground wire definitely fell off because I did the same tests again with it securely attached and got much cleaner results!  I hope things worked out on your end.

  • Hi Ed,

    Could you send my a copy of your complete code? I'm trying again, tightening my ground but still the same results!

    Best,

    Soroush

  • Sure thing - here is the commit at the time that everything started working: https://github.com/VoiceOvers/VoiceModule/blob/e14dbfebb377dab538f819970887224e61f1dbde/VoiceModule.c  Maybe you could look into the graphing technique that I described, in case it is a CCS issue, and once again make sure that the input signal has a DC offset, placing it between 0 and 3.3 V.  I think at the time of that commit, there are a few comments that are off, particularly lines 356 and at 419, I know another poster on this issue was saying the example set the PWM clock at 30MHz, even though I hadn't seen in code where that could happen, so that line could be wrong.  You can also go to the lastest commit to see the most up to date version, but it is evolving with more features beyond the ADC.

  • Thank you for your response. I checked that coud and main parts look the same as mine. Maybe the problem is with my sketching scheme. I had a question: to which of the grounds on launchpad you connect ground of your input signal?

  • I believe I used the one that was farther from the bottom edge of the board/is closer to the middle.  That was a good question and got me wondering if there was a difference but as you can see from the schematic on page 10 of the Launchpad User Guide, the two GND pins on J3 are both tied together, and to ground.  So it shouldn't make a difference.

  • Hi Ed,

    I found something (surprising!) by chance. I was watching the graph window with the old code and changing the frequency of waveform generator. Suddenly I noticed that on some certain frequencies, ADC work just correct [ or at least i could see the result fine on single time graph] (I have not found any logical connection between those freqs).

    I increased my wave form to 100khz (what I'm supposed to sample) and with playing a lil bit with them triggering epwm values, I could find these two numbers:

    PWM_setCmpA(myPwm, 0x03F0); // Set compare A value
    PWM_setPeriod(myPwm, 0x0FEFF); // Set period for ePWM1

    Also I rised to increase the buffer size to 200 instead of 10, and it helped a lot.

    to be proper for sampling a 100khz sinewave. I know it looks a weird but that really happened. Could you also try it and let me know about your idea on this?

    Thank you!

  • Hi Soroush,

    I'm guessing that buffer size you're talking about is something inside of CCS for the graphing feature.  With that increase it makes me think that maybe the graphing feature might truly be the problem.  The reason I say that is because I have been told here on the forums that the printf() function takes a lot of time and thus should not be used much in interrupts if you can help it.  Therefore, when I print all my number to the console, I only do it during my final sample, and its from a stored array, and then I stop sampling.  It makes me wonder if there is some sort of latency with the graphing feature to where it can't catch all the interrupts.  And according the Nyquist Theorem, you have to keep a sample rate of at least double your highest frequency in order to capture the waveform.  If the graphing can't keep up with that high of a sample rate, maybe it skips some of the values?

    If that doesn't help, then maybe I can try those values sometime - I just have been very busy with my classes though.

  • Hi Ed,

     I definitely agree with you and I'm now almost sure that it is the graphical problem this CCS has, and there was actually no problem from the beginning.

    The reason is as I moved on with my project, I tried to generate a ramp using a PWM counter, and as I increase the frequency of the ramp, the CCS graph window shows garbage. actually it can work at most till frequency of 5,6 Hz!

    Best,

    Soroush