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 pin not set properly

Other Parts Discussed in Thread: EK-TM4C1294XL

Hello, I'm trying to interface the SEN0193 moisture sensor with the EK-TM4C1294XL launchpad. I've checked the hardware and made sure that the sensor is indeed receiving power, and it is indeed reading in data (voltage changes when I touch the moisture sensor). The problem I'm having is that it is not showing this value onto the screen. I tried following an example of setting up the ADC pin, but I guess I'm doing it wrong somehow. Here is the code where I'm configuring the ADC:

	//
	// Enable the peripherals to be used.
	//
	MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);
	MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);

	//
	// Delay 6 clock cycles.
	//
	MAP_SysCtlDelay(2);

	//
	// Configure PE3 as analog.
	//
	MAP_GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_3);

	//
	// Configure sample sequencer 3.
	//
	MAP_ADCSequenceConfigure(ADC0_BASE, 3, ADC_TRIGGER_PROCESSOR, 0);

    //
    // Configure step 0 on sequence 3.  Sample channel 0 (ADC_CTL_CH0) in
    // single-ended mode (default) and configure the interrupt flag
    // (ADC_CTL_IE) to be set when the sample is done.  Tell the ADC logic
    // that this is the last conversion on sequence 3 (ADC_CTL_END).  Sequence
    // 3 has only one programmable step.  Sequence 1 and 2 have 4 steps, and
    // sequence 0 has 8 programmable steps.  Since we are only doing a single
    // conversion using sequence 3 we will only configure step 0.  For more
    // information on the ADC sequences and steps, reference the datasheet.
    //
    MAP_ADCSequenceStepConfigure(ADC0_BASE, 3, 0, ADC_CTL_CH0 |
    		ADC_CTL_IE | ADC_CTL_END);

    //
    // Enable sample sequencer 3.
    //
    MAP_ADCSequenceEnable(ADC0_BASE, 3);

    //
    // Clear the interrupt status flag.  This is done to make sure the
    // interrupt flag is cleared before sampling.
    //
    MAP_ADCIntClear(ADC0_BASE, 3);

And here is where I'm reading the data from the buffer:

	uint32_t AIN0Buffer[1] = {};

	const uint32_t AirValue = 520; 
	const uint32_t WaterValue = 260;
	uint32_t intervals = (AirValue - WaterValue) / 3;

	//
	// Read the analog voltage measurement.
	//
	MAP_ADCSequenceDataGet(ADC0_BASE, 3, AIN0Buffer);

	//
	// Display messages based on the AIN0 analog value.
	//
	if(AIN0Buffer[0] > WaterValue && AIN0Buffer[0] < (WaterValue + intervals))
	{
		UARTprintf("AIN0 = %u | Very Wet\n", AIN0Buffer[0]);
	}
	else if(AIN0Buffer[0] > (WaterValue + intervals) &&
			AIN0Buffer[0] < (AirValue - intervals))
	{
		UARTprintf("AIN0 = %u | Wet\n", AIN0Buffer[0]);
	}
	else if(AIN0Buffer[0] < AirValue && AIN0Buffer[0] > (AirValue - intervals))
	{
		UARTprintf("AIN0 = %u | Dry\n", AIN0Buffer[0]);
	}

	UARTprintf("**** this ****, %u\n", AIN0Buffer[0]);

As you can guess, the code runs straight through the if conditions and get to the last printf, which prints out the subtle message and the value of 0 for the buffer.

  • Hello Thomas,

    Certainly, this is something that is normal to do especially in a university/lab environment. However, I would be certain to check the connections to make sure they have the correct continuity from end to end. I would also double check to make sure each wire is connected to the right pin and that the voltage levels on each signal wire are at expected/specified values ( supply, gnd, and sense signal line). Once you have verifed all the hardware is hooked up as intended, we can have a look at the software assuming this is a straight forward ADIN program.
  • Hi Chuck,

    I've changed the question and the content to reflect my current problem.

    Thomas
  • I'm away from my references but I'm not sure you ever start a conversion.

    More to the point perhaps, you also don't check that the conversion completes.

    Robert
  • Also do search the bookshelf tag for course notes from TI on the care and feeding of A/Ds

    Robert
  • Hi Robert,

    Sorry, I'm not sure what you mean by not starting a conversation?

    Also, how can you check if a conversion completes if not by printing out the result? I don't see any function from the TI library to do so.

    Thomas
  • Thomas,

    Why would you edit your post to completely change the context of the thread and not simply open a new thread??? This makes my initial reply completely out of context with your first post......

    With that said, Robert said he doesn't see where you start a conversion. He doesn't mention anything about a conversation.

    The general flow for doing an ADC conversion is:

    (A) Configure ADC (clocks, sample times, channels, etc)--> (B) Kick off conversion --> (C) Wait for conversion to complete --> (D) Read ADC count --> (E) process read count

    Robert is stating that you have skipped steps B and C based on the code shown above. Perhaps this is simply not posted as you jump from the configuration code (A) to the read code (D) with code posted.

    Have a look at the example in TivaWare at C:\ti\TivaWare_C_Series-2.1.2.111\examples\peripherals\adc to get a general idea of the framework necessary for performing a conversion.

  • Separate from your problem.

    This:

    Thomas Phan said:

    Here is the code where I'm configuring the ADC:

    	//
    	// Enable the peripherals to be used.
    	//
    	MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);
    	MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
    
    	//
    	// Delay 6 clock cycles.
    	//
    	MAP_SysCtlDelay(2);

    is a dangerous construct. If ever the delay changes for whatever reason it will fail.

    Instead use something like

             SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI0);
             SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
             
        		/* Make sure peripherals are turned on before proceeding further */
             while(!(SysCtlPeripheralReady(SYSCTL_PERIPH_SSI0) &&
        		SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOA))){
                  }
    

    This is independent of the delay

    Robert

    I have my doubts that there is ever a situation that really justifies the use of SysCtlDelay but that's beyond this discussion.

  • Chuck,

    Ah I feel quite dumb. I thought it was a problem with how I was configuring the ADC, which I did get that part of the code from the example that you listed. I also thought that I would only need to do a get on the sequence data, so I never noticed that I also needed to trigger the conversion, wait for it, and THEN get the data. Thank you for pointing that out.

  • Robert,

    Thanks for the clarification. I will change my code to not make use of SysCtlDelay anymore but to go with your method.

  • Thomas,

    I'm glad you were able to see the full process now; however, I can't take credit for the observation that this missing. Robert was the one that pointed this out. I simply clarified when his statement was misunderstood and added the references since I had them handy. So many thanks to Robert for spotting the issue!!