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.

Having trouble with ADC on CC3200

Other Parts Discussed in Thread: CC3200

So I've been having trouble getting the ADC to work. I have a light sensor which is giving an analog value from 0 to 3.3V connected to Pin 59 (which is ADC_CH_2).

Here is my code so far:

In PinMux() - 

// not sure if these are needed, or even correct
HWREG(GPRCM_BASE + GPRCM_O_ADC_CLK_CONFIG) = 0x00000043;
HWREG(ADC_BASE + ADC_O_ADC_CTRL) = 0x00000004;
HWREG(ADC_BASE + ADC_O_ADC_SPARE0) = 0x00000100;
HWREG(ADC_BASE + ADC_O_ADC_SPARE1) = 0x0355AA00;

//PRCMPeripheralClkEnable(PRCM_ADC, (PRCM_RUN_MODE_CLK|PRCM_SLP_MODE_CLK)); // enable ADC clock

//
// Configure PIN_59 for ADC_CH_2
//
PinTypeADC(PIN_59, 0xFF);

In my separate ADCfunctions.c -

void adcGetValue(char *pADCsample) {

	char ucSample;
	char ucIndex = 0;

	 while(ucIndex < 8) {

		 if(ADCFIFOLvlGet(ADC_BASE, ADC_CH_2))
	     {
			 ucSample = ADCFIFORead(ADC_BASE, ADC_CH_2);
	         *pADCsample = ucSample;
	         pADCsample++;
	      }
		 ucIndex++;
	 }



}

void adcInitialize(void) {

	//void *adcint = &adcGetValue();
	// ADC_CH_2 is Pin 59
	ADCChannelEnable(ADC_BASE, ADC_CH_2);

	// interrupts disabled for now
	//ADCIntEnable(ADC_BASE, ADC_CH_2, ADC_FIFO_FULL);
	//ADCIntRegister(ADC_BASE, ADC_CH_2, adcint);

	ADCEnable(ADC_BASE);

}

As you can see I have a lot of debug code going on. The HWREG lines in the PinMux function is pulled directly from the adc.c sample code which is in the CC3200 SDK. Besides that code, which seems to show more about the UART than the ADC, there isn't much else in the way of resources yet (which is understandable at this stage).

However, when I run my above code, all I get is random results which clearly do not correlate to the analog values that I measure with my oscilloscope. I've tried using just the first HWREG line, I've tried leaving them out entirely, nothing seems to change. 

Also -- if I add the name of a function directly to statup_ccs.c, can I skip the ADCIntRegister line? Or is it doing something else? The problem I'm having here is that I can't seem to figure out what variables it requires. Or rather, I know that it wants the ADC_base, the channel, and then a pointer to the function, but I'm still learning about pointers (and as you can see in my above code, I'm clearly doing it wrong -- I haven't worked with pointers to functions yet). In the adc.h it is declared as 

extern void ADCIntRegister(unsigned long ulBase, unsigned long ulChannel, void (*pfnHandler)(void));

I'm guessing it needs a void type pointer, which points to a function that has no arguments (hence the second (void)), which makes sense as most interrupt functions can't have values passed directly to them, they need to be passed through pointers. But no matter how I try to create a pointer to the adcGetValue() function, it never works. I know this is more of a C question, but I really need to get this ADC working! Again, if the ADCIntRegister function is not required if you put the function directly into startup_ccs.c then the point is moot.

Even if someone can write a very simple function that correctly sets up the ADC and does a single sample, I would be greatly, greatly appreciative!

Thanks!

  • So I've managed to get some different results (still getting random data, but I seem to be a step in the right direction) by changing all the variables related to the ADC sampling and UART sending of the data to unsigned long instead of char. Before, all I was getting on the serial port was

    00 FE 00 FE 00 FE 00 FE ... etc

    Now, I'm still getting seemingly random data, but it looks like this:

    1E 48 68 D3 6C 84 6C 74 22 34 21 6A 20 74 1E C2 1E 48 68 D3 6C 84 6C 74
    21 F0 21 70 22 BE 1E FC 21 38 68 D3 6C 84 6C 74 1F F0 1F 7A 21 F8 1F 0E
    21 38 68 D3 6C 84 6C 74 21 DE 1F C8 22 7C 22 06 20 BC 68 D3 6C 84 6C 74

    Each two bytes should be one sample, at least from what I can tell of the ADC. As you can see, there does seem to be some (sort of) pattern to the data, however it's still not correlating to my data at all...

    At least it's not just the same numbers over and over!

  • Hi Alexander,

    Thanks for your inputs. Please find below some info which might help you.

    #1 ADC demo :

    There is an adc example(http://processors.wiki.ti.com/index.php/CC32xx_ADC) which you can use as it is so as to get started. After adc example is run, example usage would be displayed on the terminal. Then type adcdemo 59. Example code will now print out 4096 ADC samples. Refer the wiki page for details about characteristics of the input being fed on ADC pin and to interpret the ADC sample data being printed. I would suggest you to first try with a Analog signal generated from a signal generator and then switch to the actual light sensor.

    #2 In PinMux() :

    If you are using CC3200 LAUNCH XL Rev 3.2 You would need only the below line

    PinTypeADC(PIN_59, 0xFF);

    #3 adcInitialize and adcGetValue:

    This looks correct.

    I would suggest you to first try with a signal generated using signal generator and then switch to the actual light sensor. Please find below details of the input signal to be fed. This info is also present in the wiki page.

    Setup of signal genearator for generating analog signal:

    • Waveform - Select any suitable waveform - Sine,square,Ramp
    • Input Frequency - As ADC reaches nyquist rate at 31250 Hz, Input frequency should be between 50 Hz-30 KHz.
    • Input Amplitude - Low Level should be greater than 5 mV and high level should be less than 1.45 V.
    • Note - If there is a setting in the signal/function generator the change the output termination impedance of signal/Function generator to Infinite/High Z

    Thanks and Regards,

    Siddaram

  • Thanks Siddaram

    I've tried running the adc demo program. It works as intended but the last 4 digits of each sample remains the same, no matter what the analog level on the pin is.

    I know the pins are all 3.3V, but the ADC is only 1.4V? Will higher voltages than that damage the ADC? It seems strange to me that the reference voltage is 1.4V yet there's no output for this voltage, so powering a sensor from that voltage is very difficult.

    So far, the sensors I have connected are running off of 3.3V but their output hasn't come close to 1.4V as there is no op-amp (yet).

  • Thanks Alexander,

    Good to know the adcdemo works at your end with one observation about "last 4 digits". Please find below responses to your further queries.

    #1) 4 digits of each sample remain the same :

    I did some measurements using 0, 0.7, and 1.4 Volts as input and the results are as below. The 12 bits highlighted in yellow is ADC sample data. The results are as expected and I can see the upper 4 bits also changing. However there is a known issue in the demo that data printed out is stale if it is executed multiple times. Please see #3) below.

    Input in Volts 32 bit data printed in binary 32 bit data printed in hex
     1.4 1010010100110010111110100101100 0x52997d2c
     0.7 0010000100111110101111001110100 0x109f5e74
     0.0 0100101101110000100000000000000 0x25b84000

    #2) ADC input higher than 1.4 V :

    Yes inputs higher than 1.4 V can damage the ADC. Yes there is no 1.4 V output, I can understand the problem so to power a sensor you need to do some scaling. 

    #3) Known issue in the demo for multiple execution:

    After printing 4096 ADC samples demo again provides a prompt for further requests. If we provide a request again then the data printed is stale. In order to work around this issue one option is to do a reset. To fix this issue please make the following change in the main() routine which is in main.c file. Inside "while(FOREVER)" loop add "uiIndex=0;" as the first statement. We will fix this in the new release.
    while(FOREVER)
    {
    uiIndex=0;

    ................................................................

    }

    Thanks and Regards,

    Siddaram

  • Hi,

    I have a question about #1):

    ---what is meaning of two lowest bits??

    ---what is meaning of bits higher of 14bit???

    I' m reading a Technical Reference Manuel and there are written different. In description of register CHANNEL0FIFODATA they say that bits [13:0] are ADC sample and bits [31:14] are time stamp per ADC sample.

  • Hi,

    It is a 12 bit ADC. Please see below the meaning of the 32 bits in CHANNEL0FIFODATA. There are inconsistencies in the TRM and we will correct it. Thanks for pointing out.

    [1:0] : Reserved

    [13:2] : ADC sample Bits

    [30:14]:  time stamp per ADC sample

    [31] : Reserved

    Bits [30:14] correspond to the ADC sample time stamp based on a 17 bit time stamp counter

    Thanks and Regards,

    Siddaram

  • Hi,

    I can't fully understand meaning of ADC timer. TRM says that sampling is fixed on 16us per channel. What have I achieved with writtng value in ADCTimerConfig()???

    I want to read adc samples every 1ms, that is my goal.

    Thanks again,

    Srdjan

  • Hi Srdjan,

    ADC time stamping counter and sampling rate of 16 us are two different things. By using ADCTimerConfig you have set the wrap around value of the time stamping counter. This time that you set using ADCTimerConfig has no bearing on the sampling rate. Sampling rate is always fixed at 16 us.

    If you need to read ADC samples every ms, you should perhaps setup a GP timer with 1 ms periodicity and then read the sample. You could use the 17 bit time stamp value associated with sample to cross check if the time delta between two samples is indeed 1 ms.

    Please see if this helps.

    Thanks and Regards,

    Siddaram

  • Hi CC3200 champions,

     When use ADC (pin #60, GPIO5), should I config it to be high-Z input and set as ADC by using the "pin.c" reference code in SDK 0.52 driverlib folder (please see below, the portion of the pin.c code)?

     After I setting it, I can measure 0.608V on this pin #60 (floating, and measured by voltage meter). Is this correct?

     By the way, what does "See" mean in the Pin Multiplexing Table of CC3200 Technical Reference Manual?

     

     

    ======================

    void PinConfigSet(unsigned long ulPin,unsigned long  ulPinStrength,
          unsigned long ulPinType)
    {

      unsigned long ulPad;

      //
      // Get the corresponding Pad
      //
      ulPad = g_ulPinToPadMap[ulPin & 0x3F];

      //
      // Write the register
      //
      if(ulPinType == PIN_TYPE_ANALOG)
      {
        //
        // Isolate the input
        //
        HWREG(0x4402E144) |= ((0x80 << ulPad) & (0x1E << 8));

        //
        // Calculate the register address
        //
        ulPad = ((ulPad << 2) + PAD_CONFIG_BASE);

        //
        // Isolate the output
        //
        HWREG(ulPad) |= 0xC00;

    ====================================

  • Hi Jesse,

    There is an example "adc" in SDK which demonstrates the usage of ADC pin# 60 also. The below line of code in main.c will do all the necessary pinmuxing for ADC usage. 

            MAP_PinTypeADC(uiAdcInputPin,0xFF);

    The link location after "See" in the Pin Multiplexing Table of CC3200 Technical Reference Manual" is missing, These links are working fine in the Pin mux table present in datasheet. Please refer that till we fix this in the TRM.

    Thanks and Regards,

    Siddaram

  • Hi,

     After following the sample code of "ADC", I can read the data back from pin 58, or pin 60 without issue.

     But there are DC bias on these pins when I use voltage meter to measure (it will have different voltage bias depending on different external resistor value shunt to ground). Is this normal? I think our code already set this pin as high-Z already. 

  • I am running the ADC demo and noticed that the timestamp value does not change from zero. Shouldn't it be incremented at 40MHz? I am using the CC3200 Launchpad with preproduction silicon.

  • I was about to start my own thread on this, but Jim seems to be seeing the same thing I am. The timer doesn't work. It runs fine, and stamps each sample fine, unless you write to the timer config register. As soon as you set the timer overflow value, the timer stops running, and every timestamp from that point forwards is zero. The issue survives program cycles - you have to cut power to get it running again, even if you remove the timer config write when you reprogram. I tried different sequences of setting the value, resetting the timer, enabling the ADC, same result each time.

    I was planning on using the timer to control sampling frequency, but if you can't set the rollover value it's almost useless (at least without code a lot more complex than just writing a GPT). I had hoped for an interrupt on the timer overflow, but it doesn't have that either. GPT will work better, as I was having to inspect the timestamp of every single sample, but it's frustrating that there's a timer there for this purpose that we can't use.

  • Hello,
    At first, sorry for my very bad english.

    If I convert the yellow bits to decimal , I do not get 1.4, 0.7 and 0 but 3.9, 1.9 and 0.
    Why?

    How can I extract the 12 bits of the ADC (yellow ) from the data output ?

    I hope you can help me .
    Thank you

    Siddaram Mathapathi wrote:

    Input in Volts 32 bit data printed in binary 32 bit data printed in hex
     1.4 1010010100110010111110100101100 0x52997d2c
     0.7 0010000100111110101111001110100 0x109f5e74
     0.0 0100101101110000100000000000000 0x25b84000
  • Hello!

    I've been following this topic for a long time, I feel great by contribute.

    There are instructions at the "CC3200 SimpleLink Wi-Fi and Internet-of-
    Things Solution, a Single Chip Wireless MCU
    Technical Reference Manual".


    float see;
    //
    // ADC Config
    //
    /* 1. Set the pin type as ADC for required pin */
    PinTypeADC(PIN_58, 0xFF);
    /* 2. Enable the ADC channel ADCChannel */
    ADCChannelEnable(ADC_BASE, ADC_CH_2);
    /* 3. Optionally configure internal timer for time stamping */
    ADCTimerConfig(ADC_BASE, 80000);
    ADCTimerEnable(ADC_BASE);
    /* 4. Enable the ADC module */
    ADCEnable(ADC_BASE);

    // GET VALUE
    5. Read out the ADC samples using following code
    if( ADCFIFOLvlGet(ADC_BASE, ADC_CH_2) )
    {
    unsigned long ulSample = ADCFIFORead(ADC_BASE, ADC_CH_2);

    ulSample = (ulSample & 0x3ffc)>>2; // HERE WE EXTRACT THE YELLOW PART!

    see = (float)ulSample;
    }
  • If you want any example of simple interrupt timer, he are here.

    But you have to add the library: #include "gpio_if.c" and "timer_if.c"

    IntPrioritySet(INT_TIMERA0A, INT_PRIORITY_LVL_6); // IF you are using FreeRTOS, else exclude this line

        // Interrupt Config //

       Timer_IF_Init(PRCM_TIMERA0, TIMERA0_BASE, TIMER_CFG_PERIODIC, TIMER_A, 0);

        // Set up the interrupts for the timer timeouts //

       /* BASE ADDRESS , TIMER _A OR _B

       OR _BOTH, TIME TO INTERRUPT (80MHZ => 1 CLOCK = 1HZ)   */

       Timer_IF_Start(TIMERA0_BASE, TIMER_A, 80000000 / 1000); // 80000000 / 1000 = 1KHZ

        // Turn on Interrupt //

       Timer_IF_IntSetup(TIMERA0_BASE, TIMER_A, THE NAME OF YOUR FUNCTION HANDLER (e.g. GetValue));

  • did you see periodic timer does not working properly? I try to use periodic timer but saw unexpect result, would you please help have a look at my problem in below link, Thank you very much.
    e2e.ti.com/.../469174