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 Demo not reading correct values even after fix

Other Parts Discussed in Thread: LM35, CC3200

Hi everyone,

I am using the ADC demo out of the box and I am not getting expected results.  Also I have nothing connected to any of the pins.

After converting the hex value to binary shouldn't I see all 0's for bits [13:2]?

And if not all zeros, it should be pretty close ( taking noise into consideration ).

I posted an example of my output when running the demo and am only showing 25 samples to reduce spam.

Command Usage
--------------
adcdemo <adc_inputpin>

Parameters
--------------
adc_inputpin - Pin to which Analog signal is connected  [58|59|60]
-------------------------------------------------------------------------

cmd# adcdemo 58

Total no of 32 bit ADC data printed :4096

ADC data format:

bits[13:2] : ADC sample

bits[31:14]: Time stamp of ADC sample

0x25ee52fc

0x268e536c

0x272e53fc

0x27ce5360

0x286e53c4

0x290e538c

0x29ae533a

0x2a4e53d6

0x2aee5388

0x2b8e536a

0x2c2e5360

0x2cce5338

0x2d6e5342

0x2e0e5384

0x2eae533c

0x2f4e5346

0x2fee536c

0x308e533a

0x312e5374

0x31ce537e

Even though there was a fix : http://e2e.ti.com/support/wireless_connectivity/f/968/p/354092/1243186.aspx#1243186

I did not need to do it since my version is new.

  • Jon Torrey said:
     Also I have nothing connected to any of the pins.

    Try connecting the ADC pin to GND, and see if you still get the same results.

    - kel

  • Alright, I did hook it to ground and am now getting expected results. Great!

    But why? 

    I have the output voltage of a LM35 temperature sensor hooked to the ADC and want to monitor temperature.  Is there a way so that the ADC reference voltage is 0V.  I have my sensor hooked to a multimeter to monitor the output voltage and was going to use that voltage for verification along with a stand-alone thermometer.

  • Hi Jon,

         Supposedly most LM35 circuitry is already referenced to 0V as it is connected to GND. 

         To convert the 12 bit ADC value to Celsius or Farenheight, you need to convert it, with known formulas.

         Here is one below, from Tiva forum. This one averages 4 LM35 ADC values from 1 ADC input. Conversion formula is also shown in the code.

         lm35 and tiva c launchpad issue

    - kel

  • Thanks for the info!

    But why does the C3200 ADC input not read 0 when not grounded or in my case, when nothing is hooked up to it? 

  • Jon Torrey said:
    But why does the C3200 ADC input not read 0 when not grounded or in my case, when nothing is hooked up to it? 

    I am unable to find the specific answer right now at the CC3200 documentations.

    But, usually when you read a ADC pin that has no connected input, the ADC pin reading will fluctuate base from other factors like ADC reading from other ADC pins or environmental factors.

    - kel

  • Jon Torrey said:
    But why does the C3200 ADC input not read 0 when not grounded or in my case, when nothing is hooked up to it? 

    This is because the ADC is a "floating input" till you pull it up or more commonly down using a resistor. You can perform this pull by using an external resistor or you should also be able to perform it with an internal pull.

    Check out this post for details on using an internal pulls with the CC3200 - http://e2e.ti.com/support/wireless_connectivity/f/968/t/354122.aspx

    The reason you get this fluctuations is due to random electrons from the environment and electro-magnetic interference.

    Glenn.

  • @Jon,

    About LM35: since it is a centigrade temperature sensor, at normal ambient temperature its output should be around 3V ( 273.5+23) x10 mV - so you need some special measures to make it work:

    a) first, if you need to measure up to 125 degC, a separate power supply is needed ( don't know what you used up to now). When taking this into account, add 2-3V for internal LM circuitry to work;

    b) the CC32xx ADC is rated to maximum 1.4V, so you really need a voltage divider to reduce the LM output to ADC maximum input.

    c) when tying an ADC input to ground, every parasitic voltage counts so does matter where you make the connection to ground - you really need to avoid the inclusion of digital ground traces between the ADCinput pin and the connection to ground location - just to make an approximate test would be OK,  but on a pre-defined board, do not expect too much.

    Petrei

  • @Glenn - 

    This is what I assumed, thank you for the confirmation.  More than anything, I probably should have looked at the schematic and I apologize.

    @Petrei

    I have been testing the LM35 using the 5V pin from the board along with the ground and having Vout hooked to a multimeter.  LM35 datasheet specifies 4V to 20V for it's input so I think I'm okay?

    The highest temperature that this sensor is going to experience shouldn't be anything greater than 200F/93C or in this case, 1V for Vout.  My specific purpose is to measure the internal temperature of meat during the smoking process.  Right now I just some 3 foot 22 gauge wire wrapped in heat shrink that is connected to the terminals of the LM35.  In the future, my goal is to find some 5mm inner diameter metal tube to fish the sensor into then re-test it.

    Do you think manually disabling the pins surrounding the ADC pin would help prevent noise and other signals from giving me incorrect data?

  • Hi,

    OK, as the data sheet say, 5V would be enough.

    As for connecting to the board - use a shielded cable and follow the principle from fig.14 in the data sheet to realise a voltage divider. Place the ground connection as near as possible to micro controller, to avoid digital ground lines common with this analog line. The noise level should be below 1.4V/4094, which is very small and hard to realise, but at least minimise the effects, otherwise the measurement can be erroneous one. Further you may acquire several samples and average them (the amount of reduction is the square root of number of samples).

    The other pins around the analog input may remain as they are.

    Petrei

  • Will do, thank you.

    I have another question, if you would? I am a bit rusty - 

    I've been able to successfully read ADC samples from the demo and extract bits [13:2] for the raw data that I need to do calculations with.

    My data is an unsigned long and gets printed to TeraTerm in hexadecimal format. How would I able to verify the ADC sample with the value on my multimeter? 

  • Hi,

    You may write some calculations: if y is your sample value, then the decimal equivalent will be ((y*1400)/4096)* divider factor and will give you the result in mV. The 1400 is the maximum(reference) value of your ADC. 

    Then expressing it in 10 mV units is easy. Do not forget to remove the absolute value 2735 from result.

    Petrei

  • What is the divider factor?

    My current formula is : 

    voltageResult = ( (1400.0f/4096.0f) * samplesAveraged );

    And what do you mean by removing the absolute value 2735 from my result? Why? 

  • Hi,

    OK, that's it is - I make an assumption your device is also calibrated in degK (mine is that). That formula is OK.

    Regards,

    Petrei

  • I don't know if the formula is correct.  When stepping through the code in the debugger, my voltageResult does not match my reading off the multi-meter.  For example, right now my multimeter reads 199 and voltageResult reads 246. 

    I posted my code below if you could double check?

    void main()
    {
        unsigned long pulAdcSamples[4096];
    
        unsigned long uiAdcInputPin;
        unsigned int  uiChannel;
        unsigned long ulSample;
    
        float samplesAveraged;
        float voltageResult;
    
        float celsiusTemp;
        float fahrenheitTemp;
    
        //celsiusTemp = 0.0;
        fahrenheitTemp = 0.0; //compilier complains
    
        uiAdcInputPin = PIN_59;
        unsigned int  uiIndex=0;
        BoardInit();
        PinMuxConfig();
        InitTerm();
    
            //
            // Initialize Array index for multiple execution
            //
            uiIndex=0;
    
            //
            // Pinmux for the selected ADC input pin
            //
            MAP_PinTypeADC(uiAdcInputPin,PIN_MODE_255);
    
            //
            // Convert pin number to channel number
            //
            switch(uiAdcInputPin)
            {
                case PIN_58: {uiChannel = ADC_CH_1;}break;
                case PIN_59: {uiChannel = ADC_CH_2;}break;
                case PIN_60: {uiChannel = ADC_CH_3;}break;
                default: break;
            }
    
            //
            // Enable ADC channel
            //
            MAP_ADCChannelEnable(ADC_BASE, uiChannel);
    
            //
            // Configure ADC timer which is used to timestamp the ADC data samples
            //
            MAP_ADCTimerConfig(ADC_BASE,2^17);
    
            //
            // Enable ADC timer which is used to timestamp the ADC data samples
            //
            MAP_ADCTimerEnable(ADC_BASE);
    
            //
            // Enable ADC module
            //
            MAP_ADCEnable(ADC_BASE);
    
            while(uiIndex < 4096)
            {
                if(MAP_ADCFIFOLvlGet(ADC_BASE, uiChannel))
                {
                    ulSample = MAP_ADCFIFORead(ADC_BASE, uiChannel);
                    ulSample = (ulSample & 0x3ffc)>>2; //get bits [13:2]
                    pulAdcSamples[uiIndex++] = ulSample; //store
    
                    samplesAveraged += (float)ulSample; //sum up all of the reading
                    Report("%");
                }
            }
            samplesAveraged = ( samplesAveraged/4096.0f ); //get average
    
            voltageResult = ( (1400.0f/4095.0f) * samplesAveraged ); //calculate mV
    
            //UART_PRINT("\n\r voltageResult = %d \n\r", voltageResult);
    
            celsiusTemp = (voltageResult / 10.0f); //calculate celsius temp
    
            fahrenheitTemp = (1.8f * celsiusTemp) + 32.0f;
    
    
    } //end of main

  • Hi,

    A small problem with the code: either at the beginning, where is declared either before the expression:  while(uiIndex < 4096) 

    write/insert this: samplesAveraged = 0.0f;

    Next - what is the room temperature at your location? 19.9 or 24.5 degC? your voltmeter is a good one? (Rin>=1Mohm?)

    I do not have your device now, and mine is far away at the office...sorry, just now i can't help (and is snowing already...).

    Petrei

  • I have a thermometer in the room to get a good idea of the temperature and the LM35 to the multimeter. It says 190mV - 200mV depending on the day so the multimeter output divided by 10 should give me degrees Celsius. 

    I will try your advice on setting samplesAveraged = 0.0f when I get back home and let you know. 

  • I have a thermometer in the room to get a good idea of the temperature and the LM35 to the multimeter. It says 190mV - 200mV depending on the day so the multimeter output divided by 10 should give me degrees Celsius. 

    I tried initializing samplesAveraged = 0.0f prior to adding any data to it.

    My mV reading is still incorrect :(

  • Hi,

    OK, should be some offset or common traces between analog and digital paths on board. Do the following: remove the connection from the output of LM and the board. Place a connection from on-board input to the ground connection where you connect the LM. Start again and determine this voltage, small - you already said you do not get zero - should be around 50 mV, an inherent offset which must be removed by subtraction from every result. Sometimes this kind of things are usual and this is the usual practice. I had such thing checked periodically by connecting the input to ground and saving the result and removing from every measurement. (Even more, making a calibration of the whole conversion chain, with awesome results can be done, but let's limit to this offset now).

    You are very close to a good result. 

    Petrei

  • If I connect the board's ground to the board's ADC input, I get samples of 0. 

    Are you talking about running my program with nothing connected and subtract that result from the result with the sensor hooked up?

  • Jon Torrey said:
    If I connect the board's ground to the board's ADC input, I get samples of 0. 

    Just in case this wasn't clear. Do you have a resistor between the ground and the ADC input? You need to create a weak pull, through the use of a resistor, try a 10,000k resistor, or use the internal pulls as I have detailed previously.

    Glenn.

  • Hi Glenn,

    I do not have a pull-down resistor anywhere.  I will pick one up from my lab tomorrow.

    I've read through the post along with the replies.  You mentioned that the CC3200 may require an external pull?

    I tried the following piece of code prior to enabling the ADC  

    PinConfigSet(PIN_59, PIN_STRENGTH_4MA, PIN_TYPE_STD_PD);

    Still no good :(

  • Glenn, Petrei, and Kel :

    Thank you for your strong efforts in getting me up to speed in finishing the first part of my project, I greatly appreciate it.  

    The 10k resistor was what I needed!  Right now I am getting in range of about +/- 10mV of my multimeter reading.  I am going to find the exact value tomorrow so it can be super fine tuned.

    Thank you guys,

    JT