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.

TM4C129XNCZAD: Trouble setting up and reading ADC

Part Number: TM4C129XNCZAD

Hi,

I have inherited a project and I need to add two new ADC inputs on Port E, pins 0 (Cartridge) and 2 (door).   I thought I had configured correctly but apparently not.  I do not see any changes in the ADC reading but I have verified that the voltage to the pin is changing. Code snippets below.  I appreciate any help!

typedef enum
{
  ADC_CHANNEL_0,
  ADC_CHANNEL_WARMER_I = ADC_CHANNEL_0,  
  ADC_CHANNEL_RTD1,
  ADC_CHANNEL_WARMER_ID, 
  ADC_CHANNEL_MOTOR_I, 
  ADC_CHANNEL_SUPPLY_V,
  ADC_CHANNEL_CARTRIDGE, // BAH new design
  ADC_CHANNEL_DOOR, // BAH new design
  ADC_CHANNEL_COUNT,
} ADC_CHANNEL_t;

#define WARMER_I_CHANNEL              (ADC_CTL_CH0)
#define RTD1_CHANNEL                        (ADC_CTL_CH17)
#define WARMER_ID_CHANNEL           (ADC_CTL_CH18)
#define MTR_I_CHANNEL                      (ADC_CTL_CH2)
#define SUPPLY_CHANNEL                   (ADC_CTL_CH19)
#define CARTRIDGE_CHANNEL            (ADC_CTL_CH3 )
#define DOOR_CHANNEL                      (ADC_CTL_CH1)

void adc_Initialize( void )
{
  SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
  SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOK);

  /* Enable the ADC1 Peripheral*/ 
  SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC1);
  GPIOPinTypeADC(GPIO_PORTE_BASE,
  GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3);
  GPIOPinTypeADC(GPIO_PORTK_BASE,
  GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3);

  ADCSequenceDisable( ADC1_BASE, MAIN_SEQUENCE );
  ADCHardwareOversampleConfigure( ADC1_BASE, SAMPLES_TO_AVERAGE );
  ADCReferenceSet( ADC1_BASE, ADC_REF_INT );
  ADCSequenceConfigure( ADC1_BASE, MAIN_SEQUENCE, ADC_TRIGGER_PROCESSOR, MAIN_SEQUENCE_PRIORITY );

  ADCSequenceStepConfigure(ADC1_BASE, MAIN_SEQUENCE, ADC_CHANNEL_WARMER_I, WARMER_I_CHANNEL);
  ADCSequenceStepConfigure(ADC1_BASE, MAIN_SEQUENCE, ADC_CHANNEL_RTD1, RTD1_CHANNEL);
  ADCSequenceStepConfigure(ADC1_BASE, MAIN_SEQUENCE, ADC_CHANNEL_WARMER_ID, WARMER_ID_CHANNEL);
  ADCSequenceStepConfigure(ADC1_BASE, MAIN_SEQUENCE, ADC_CHANNEL_MOTOR_I, MTR_I_CHANNEL);
  ADCSequenceStepConfigure(ADC1_BASE, MAIN_SEQUENCE, ADC_CHANNEL_CARTRIDGE, CARTRIDGE_CHANNEL );
  ADCSequenceStepConfigure(ADC1_BASE, MAIN_SEQUENCE, ADC_CHANNEL_DOOR, DOOR_CHANNEL );
  ADCSequenceStepConfigure(ADC1_BASE, MAIN_SEQUENCE, ADC_CHANNEL_SUPPLY_V,
  SUPPLY_CHANNEL | ADC_CTL_IE | ADC_CTL_END);

  ADCSequenceEnable(ADC1_BASE, MAIN_SEQUENCE);
  ADCIntClear(ADC1_BASE, MAIN_SEQUENCE);
}

void adc_StartScan( void )
{
  /* Trigger the next ADC conversion. */
  ADCProcessorTrigger( ADC1_BASE, MAIN_SEQUENCE );
}

void adc_ReadScan( void )
{
  int i;
  uint32_t *raw;
  ADCScale_t *scale;
  uint32_t rid;
  uint32_t *converted;
  int32_t temp;

  if ( ADCIntStatus( ADC1_BASE, MAIN_SEQUENCE, false ) )
  {
    /* Clear Interrupt Flag and Read Data */ 
    ADCIntClear( ADC1_BASE, MAIN_SEQUENCE );
    ADCSequenceDataGet( ADC1_BASE, MAIN_SEQUENCE, rawADC );

    raw = rawADC;

    converted = convertedADC;
    scale = ADCScale;

    rid = FULL_SCALE - rawADC[ADC_CHANNEL_WARMER_ID];
    for ( i = 0 ; i < sizearray(rawADC) ; ++i )
   {
      // Offset is applied before the shift to get extra precision
      // Adding 1 << (shift - 1) rounds the result.
      temp = *raw * scale->gain;
      if ( temp >= scale->offset )
     {
        *converted = (temp - scale->offset + (1 << (scale->shift - 1))) >> scale->shift;
     }
    else
    {
       *converted = 0;
    }
   ++raw;
   ++converted;
   ++scale;
 }
// Finish up the warmer RID calculation with rounding.
convertedADC[ADC_CHANNEL_WARMER_ID] =
(((convertedADC[ADC_CHANNEL_WARMER_ID] + rid / 2) / rid) + (1 << (RID_LOG_PRESCALE - 1))) >> RID_LOG_PRESCALE;
}
}

  • Hello Brad,

    A bit hard to tell what is going on here, but I'm gonna take a stab at a suggestion... maybe instead of this:

      ADCSequenceStepConfigure(ADC1_BASE, MAIN_SEQUENCE, ADC_CHANNEL_CARTRIDGE, CARTRIDGE_CHANNEL );
      ADCSequenceStepConfigure(ADC1_BASE, MAIN_SEQUENCE, ADC_CHANNEL_DOOR, DOOR_CHANNEL );
      ADCSequenceStepConfigure(ADC1_BASE, MAIN_SEQUENCE, ADC_CHANNEL_SUPPLY_V,
      SUPPLY_CHANNEL | ADC_CTL_IE | ADC_CTL_END);

    Try this:

      ADCSequenceStepConfigure(ADC1_BASE, MAIN_SEQUENCE, ADC_CHANNEL_SUPPLY_V, SUPPLY_CHANNEL );
      ADCSequenceStepConfigure(ADC1_BASE, MAIN_SEQUENCE, ADC_CHANNEL_CARTRIDGE, CARTRIDGE_CHANNEL );
      ADCSequenceStepConfigure(ADC1_BASE, MAIN_SEQUENCE, ADC_CHANNEL_DOOR,
      DOOR_CHANNEL | ADC_CTL_IE | ADC_CTL_END);

    If that doesn't work, can you check if you are still getting ADC results from your other channels which had been working before?

  • Hi Ralph,

    Thank you.  I tried your suggestion and I am still not getting anything on the new ADC channels.  The other ADC channels are working as desired.  The two new channels are inputs from optical sensors.

    Best regards,

    Brad Haber

  • Brad Haber said:
      /* Enable the ADC1 Peripheral*/ 
      SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC1);
      GPIOPinTypeADC(GPIO_PORTE_BASE,
      GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3);
      GPIOPinTypeADC(GPIO_PORTK_BASE,
      GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3);

    Perhaps try separate input pin types rather than OR all together.  

  • Hello Brad,

    Okay, can you provide the details for the #define's for other settings?

    MAIN_SEQUENCE

    SAMPLES_TO_AVERAGE 

    MAIN_SEQUENCE_PRIORITY 

    With that I think I can try a bit of testing on my end too.

    Also you mentioned verifying the voltage to the pins is changing, what is the range of voltages you are seeing at the MCU GPIO?

    And just for a sanity check, can you make sure those GPIO were not possible unconfigured at any other part of your program? I highly doubt this would be the case of course but can't hurt to verify that there isn't code that sets all unused GPIO to another state which would need to be updated.

  • Hello,

    Here's a 'Quick/Dirty' suggestion which should prove highly useful: "Simply route one of your known good channel input signals to one of those (added) channels - which are failing."     (this insures that your input signal is 'proper' - which is currently, 'Up for some debate.')

    As you've 'inherited' this project - have you (really) confirmed that the Added Channels appear upon: 'official, ADC capable pins?'     (only those pins noted as having ADC capability - may serve that role...)

    Unless the ADC pins mandate 'different treatment' - it is normal/customary that, "GPIOPinType()" accommodates the OR'ing of several pins.   (just as you've done!)    And - even more substantial - "ALL of your past channel coding - employing OR'ing - succeeded!"    (somehow - that was missed!)   Instead it is "GPIOPinConfigure()" which demands 'single entry.'

    As always - if you've not already done so - test for the presence of the analog signal, "At the actual MCU's pin!"     (provided it is possible to do so - BGA devices, "Try one's soul.")     Inherited projects too often may contain (little or undocumented) pcb updates/routings - it may be that "unwanted, foreign connections" exist upon you 'new channels.'    Careful probing - while the board is 'Live' - will confirm the safe/unloaded arrival of your desired analog signals...   (or the presence of a competing (illegal) load or signal...)

  • Hi,

    Thank you but that made no difference.

    Best regards,

    Brad

  • Hi Ralph,

    #define MAIN_SEQUENCE (0)
    #define MAIN_SEQUENCE_PRIORITY (0) // Highest

    #define SAMPLES_TO_AVERAGE  64

    The voltage range is from .2mV to 1V

    I will check the on your suggestion about changing unused pins code.

    Thank you, I appreciate the help!

    Best regards,

    Brad

  • Hi ,

    Yet Tivaware makes no such claim PinTypeADC() can OR multiple pins. Also PinMux tool output produces single GPIO pin ever to any analog pin type statement. Typically Tivaware text will state when OR multiple pins is allowed.

  • Hello Gl,

    Any of the GPIOPinType___ API's can be used with multiple pins. That is not causing this problem. Also only two pins were added which means that the prior API with 3 pins each worked fine.

  • Hello (2),

    We don't know if you've seen staff's/my earlier suggestion.     (on/about 10:55 CST, earlier today)

    You note that both new channels emanate from "optical sensors."    Certain optical sensors have (very high impedance - i.e. those from photo-detectors) and as such may 'badly' match the ADC's (suggested) much lower input impedance.

    By following our earlier suggestion, "Swap one of the known good input signals w/your (failing) optical signal" - you should be able to recognize & identify a, "Failed Input vs. an ADC (pin or code) issue."     

    Follows a "Guaranteed Method" to reduce the, "Number of Unknowns" in your ADC's Technical Challenge:

    • Break the outside-world connection from one of the 'successfully working' ADC Channels - route that connection to one of your (new) 'Failing Channels?'    As it is known that that outside-world signal converts nicely - it shifts the 'unknown' away from, 'Failed/Flawed signal input.'    Should incorrect (or no) readings (now) result - that particular ADC channel and/or your ADC Code for that channel are suspect.
    • Break one of your new (optical) connections - made to the ADC (to one of the 'new' pins) and instead route that signal to the (earlier, working) ADC channel.    (from which you just removed & rerouted its earlier (proven) input signal.    In this manner - you are presenting a 'suspect' (not yet confirmed good) input signal to one of the 'known good' ADC pins.'    Again - should incorrect (or no) readings result - that 'new' input signal is 'highly suspect!'

    Thinking further - by breaking (both) existing 'new' (optical connections) and presenting them to any two of the prior 'working ADC channels' (after first removing the existing 'known good signals') you are isolating your 'hunt' to the 'Correctness of the new/optical signal source.'    Should either channel 'Not properly convert' - as no change beyond 'Signal Source' was instituted - it is the 'Signal Source' (and/or its presentation to the ADC) which is flawed!      NO software changes are required - which 'Speeds, Eases & Enhances' this (much preferred) method!    

    As with most 'Troubleshooting' - reducing the number of 'unknowns in play' leads to improved & faster diagnosis & correction.

  • Hello Brad,

    Just want to second cb1's suggestions here, look forward to hearing about your test results trying his methods. I haven't had a chance to run the ADC code yet and I am not 100% sure I will be able to on Monday, but I think cb1 is onto something because I really don't see anything wrong with your code setup still.

  • Thank you Ralph - the systematic methods my group has suggested are 'Classic' -  reduce the number of 'unknowns' -  & are (near) effortless to implement.    (i.e. enables unchanged poster software - by exercising those ADC Channels which poster has reported as 'well working.'    Such brutally 'focuses/exposes' poster's introduction of those, 'new, optical sensors' -  and will clearly, "Accept or Reject" their implementation!)

    All (other) suggestions have been acknowledged - yet those "most methodical, detailed & justified" - bask in (strange) silence...   (which proves beyond my young/gifted team's control...)

    Should poster at some point choose to, "Adopt my team's guide" -  the odds are high that the, "Imposition of an op-amp between optical sensor's output and ADC's input" (far better 'matching' the ADC's input requirement) will yield success...    (i.e. far more stable/secure (and unloaded) sensor output which (only then) enables proper ADC measures.)

  • Hi CB and Ralph,

    No silence intended!  The EE is setting up the test that you suggested and hopefully he will be ready on Monday.  The pins being used do have ADC as their alternate function. 

    Best regards,

    Brad Haber

  • Update.  I had a unit at home over the weekend and left the unit powered on continuously from Saturday morning.  At around 6:30 PM Sunday evening the sensor reading started to work.  No changes were made to the ADC code.  Cold solder joint?

  • Greetings,

    My group would not present such finding to a client - it is not conclusive.      Further - you past noted 'TWO Failed Channels' (both of your new ones) - are you thus suggesting TWO FAILED Solder Joints?    

    We stand by the methodical trouble-shooting method - rather clearly presented.    

    This report does not indicate the operating conditions under which, "Started to work" was noted.    (and if/how you had you implemented (any) of those earlier listed, systematic suggestions?)   

    Note too, "Started to Work" (somehow) is not especially detailed and/or inspiring.      (only you know the parameters of 'working' - as these have never been disclosed...)

  • Greetings,

    I was excited to post a new development. 

    By working I mean that the sensor input to the ADC pin was no longer static and that the software displayed the correct screen and sounded an alert based on the sensor reading.   

    However, the device again stopped working as intended.  Our new discovery is that the stack tolerance was off which was pushing the touchscreen against its enclosure.   When the touchscreen attachment screws were loosened the device behaved again. 

    I don't fully understand yet but it appears possible that the device working, screen changing and alert sounding based on sensor input, last night is more likely attributed to movement that temporarily relieved the touchscreen from pushing to tightly against its enclosure.

    I have again given your suggested steps.  

    The second new channel is not yet working but our EE and ME believe it is due to the position of the sensor.

  • Thank you - that's much needed new data.

    It would appear that yours is a, "4-wire, Analog-Resistive, Touch Screen" - and "Unwanted Perimeter contact" is a 'known cause of difficulty.'     That said - the description of, "Two touch-screen analog inputs as, 'Optical Sensors' proves unlikely!    (unless the touch-screen in question is a 1980's era 'IR' (infrared) version!)     Accurate & efficient Diagnosis demands (proper) descriptive data...   (that touch-screen was more likely: Analog Resistive or Capacitive (i.e. multi-touch capable.)

    There exist specialized, "Touch-Screen Control ICs" - which speed, ease & enhance the interface to such screens.    It is also possible to employ the MCU to drive - and then resolve - touch inputs to such screens.    (This to follow your, "Correction of the illegal activation of the touch screen" due to mounting insufficiency.) 

    In the case of "4-wire, Resistive" - there are two orthogonal, touch planes.    These planes must be (both) actively (sequentially) driven & then 'read' - which requires (some) indirection & coordination of MCU operations.   It appears that you have now succeeded  (or are close to) - and that the MCU's ADC was 'blameless' - and that the, 'Integrity of the New ADC Channels introduction to the MCU' (as predicted) proved suspect.

  • Thank you cb1_mobile and Ralph!  The birds are singing and the sun is shining!  I learned to provide a better description of the problem that I am dealing with.