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.

TM4C ADC for multiple input signals



Hello, this is my first time posting on this forums. I am using a TM4C Micro for acquiring data from a circuit with 3 analog signals. I have worked with this micro for some time now but I can't seem to get this to work properly, and I have browsed through this forum, and all the examples and documentation I could find. My first question is if the 12 shared channels of the ADC module correspond to the 12 analog input channels (PE0,PE1,PE2,PER 3tc..).


This is how I setup my ADC:

void ADCinit(void){
    //Initialize ADC
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE); //Pin for ADC input
    SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0); //ADC peripheral
    //Enable Timer 0
    SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);

    //Pins used for ADC channels (3)
    GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_3 | GPIO_PIN_2 | GPIO_PIN_1); //set GPIO_E3 for channel 1
    //GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_2); //set GPIO_E2 for channel 2
    //GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_1); //set GPIO_E1 for channel 3

    ADCSequenceConfigure(ADC0_BASE, 0, ADC_TRIGGER_TIMER, 0); //sequencer 0
    ADCSequenceConfigure(ADC0_BASE, 1, ADC_TRIGGER_TIMER, 1); //sequencer 1
    ADCSequenceConfigure(ADC0_BASE, 2, ADC_TRIGGER_TIMER, 2); //sequencer 2

    //sequencer 0
    ADCSequenceStepConfigure(ADC0_BASE, 0, 0, ADC_CTL_CH1);
    ADCSequenceStepConfigure(ADC0_BASE, 0, 1, ADC_CTL_CH1);
    ADCSequenceStepConfigure(ADC0_BASE, 0, 2, ADC_CTL_CH1);
    ADCSequenceStepConfigure(ADC0_BASE, 0, 3, ADC_CTL_CH1 | ADC_CTL_END);

    //sequencer 1
    ADCSequenceStepConfigure(ADC0_BASE, 1, 0, ADC_CTL_CH2);
    ADCSequenceStepConfigure(ADC0_BASE, 1, 1, ADC_CTL_CH2);
    ADCSequenceStepConfigure(ADC0_BASE, 1, 2, ADC_CTL_CH2);
    ADCSequenceStepConfigure(ADC0_BASE, 1, 3, ADC_CTL_CH2 | ADC_CTL_END);

    //sequencer 2
    ADCSequenceStepConfigure(ADC0_BASE, 2, 0, ADC_CTL_CH1);
    ADCSequenceStepConfigure(ADC0_BASE, 2, 1, ADC_CTL_CH1);
    ADCSequenceStepConfigure(ADC0_BASE, 2, 2, ADC_CTL_CH1);
    ADCSequenceStepConfigure(ADC0_BASE, 2, 3, ADC_CTL_CH1 | ADC_CTL_IE | ADC_CTL_END);

    //
    //Initialize Timer 0 to trigger an ADC conversion
    //
    TimerConfigure(TIMER0_BASE,TIMER_CFG_PERIODIC);
    TimerLoadSet(TIMER0_BASE,TIMER_A,SysCtlClockGet()/1000); //5k sampling rate
    TimerEnable(TIMER0_BASE, TIMER_A);
    TimerControlTrigger(TIMER0_BASE,TIMER_A,true);


    ADCSequenceEnable(ADC0_BASE,0);
    ADCSequenceEnable(ADC0_BASE, 1);
    ADCSequenceEnable(ADC0_BASE, 2);
    ADCIntEnable(ADC0_BASE,2);

}

And in main()...

ADCinit();
//UARTprintf("ADC Sequence Initiated!\n");

ADCIntClear(ADC0_BASE,2);
ADCIntEnable(ADC0_BASE,2);
IntEnable(INT_ADC0SS2);
IntMasterEnable();

What Seems to happen when i try out the code is that the signal of channel1 follows channel2 (or vice-versa), and even if I don't connect the analog signal to one of the pins, they still give some value different then 0 or near 0. It seems that it is only reading one input signal, anyone of them, but I am not sure since it's pretty random behaviour. I just figure I'm doing somehting wrong, either with the ADC configuration or the interrupt. 

I'm attatching my main.c

Thanks for the help!

EDIT: Added the reviewed code

// Plant Sensor ADC 3 Channels
//
//				Ricardo Cabrita, ISR 2015
//****************************************************************************************************

// Includes ------------------------------------------------------------------------------------------
#include <stdint.h>
#include <stdbool.h>
#include <inttypes.h>

#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
#include "inc/hw_i2c.h"

#include "driverlib/fpu.h"
#include "driverlib/gpio.h"
#include "driverlib/interrupt.h"
#include "driverlib/i2c.h"
#include "driverlib/pin_map.h"
#include "driverlib/rom.h"
#include "driverlib/sysctl.h"
#include "driverlib/uart.h"
#include "driverlib/adc.h"
#include "driverlib/timer.h"

#include "utils/uartstdio.h"

#include "shtLib.h"


// Defines -------------------------------------------------------------------------------------------
#define LED_RED GPIO_PIN_1
#define LED_BLUE GPIO_PIN_2
#define LED_GREEN GPIO_PIN_3
//#define ch1 0001000000000000

// Variables -----------------------------------------------------------------------------------------
//uint16_t ui16ADC0Value[8] = {0,0,0,0,0,0,0,0};
uint16_t ui16Seq0Value[4] = {0,0,0,0},ui16Seq1Value[4] = {0,0,0,0}, ui16Seq2Value[4] = {0,0,0,0};
uint32_t averagedADC1,averagedADC2,averagedADC3;
uint32_t ui32Baud = 460800;
// Functions -----------------------------------------------------------------------------------------
void ADCinit(void){
	//Initialize ADC
	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE); //Pin for ADC input
	SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0); //ADC peripheral
	//Enable Timer 0
	SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);

	//Pins used for ADC channels (3)
	GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_3 | GPIO_PIN_2 | GPIO_PIN_1); //set GPIO_E3 for channel 1
	//GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_2); //set GPIO_E2 for channel 2
	//GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_1); //set GPIO_E1 for channel 3

	ADCSequenceConfigure(ADC0_BASE, 0, ADC_TRIGGER_TIMER, 0); //sequencer 0
	ADCSequenceConfigure(ADC0_BASE, 1, ADC_TRIGGER_TIMER, 1); //sequencer 1
	ADCSequenceConfigure(ADC0_BASE, 2, ADC_TRIGGER_TIMER, 2); //sequencer 2

	//sequencer 0
	ADCSequenceStepConfigure(ADC0_BASE, 0, 0, ADC_CTL_CH0);
	ADCSequenceStepConfigure(ADC0_BASE, 0, 1, ADC_CTL_CH0);
	ADCSequenceStepConfigure(ADC0_BASE, 0, 2, ADC_CTL_CH0);
	ADCSequenceStepConfigure(ADC0_BASE, 0, 3, ADC_CTL_CH0 | ADC_CTL_END);

	//sequencer 1
	ADCSequenceStepConfigure(ADC0_BASE, 1, 0, ADC_CTL_CH1);
	ADCSequenceStepConfigure(ADC0_BASE, 1, 1, ADC_CTL_CH1);
	ADCSequenceStepConfigure(ADC0_BASE, 1, 2, ADC_CTL_CH1);
	ADCSequenceStepConfigure(ADC0_BASE, 1, 3, ADC_CTL_CH1 | ADC_CTL_END);

	//sequencer 2
	ADCSequenceStepConfigure(ADC0_BASE, 2, 0, ADC_CTL_CH2);
	ADCSequenceStepConfigure(ADC0_BASE, 2, 1, ADC_CTL_CH2);
	ADCSequenceStepConfigure(ADC0_BASE, 2, 2, ADC_CTL_CH2);
	ADCSequenceStepConfigure(ADC0_BASE, 2, 3, ADC_CTL_CH2 | ADC_CTL_IE | ADC_CTL_END);

	//
	//Initialize Timer 0 to trigger an ADC conversion
	//
	TimerConfigure(TIMER0_BASE,TIMER_CFG_PERIODIC);
	TimerLoadSet(TIMER0_BASE,TIMER_A,SysCtlClockGet()/100000); // sampling rate
	TimerEnable(TIMER0_BASE, TIMER_A);
	TimerControlTrigger(TIMER0_BASE,TIMER_A,true);


	ADCSequenceEnable(ADC0_BASE,0);
	ADCSequenceEnable(ADC0_BASE, 1);
	ADCSequenceEnable(ADC0_BASE, 2);
	//ADCIntEnable(ADC0_BASE,0);
	ADCIntEnable(ADC0_BASE,2);
	//IntEnable(INT_ADC0SS1);

}

void ConfigureUART1(void){

	// Enable the peripherals used by UART
	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
	SysCtlPeripheralEnable(SYSCTL_PERIPH_UART1);

	// Set GPIO A0 and A1 as UART pins.
	GPIOPinConfigure(GPIO_PB0_U1RX);
	GPIOPinConfigure(GPIO_PB1_U1TX);
	GPIOPinTypeUART(GPIO_PORTB_BASE, GPIO_PIN_0 | GPIO_PIN_1);

    // Configure UART clock using UART utils
    UARTClockSourceSet(UART1_BASE, UART_CLOCK_PIOSC);
    UARTStdioConfig(1, ui32Baud, 16000000);
}

void ADC0IntHandler(void){

	//short a,b;
	uint32_t send1,send2;
	uint32_t start = 122, checksum; // 0x00FF start byte

	//Clear ADC interrupt  here if interrupt is Light Cycle and small nr of instructions
	//ADCIntClear(ADC0_BASE,1);

	//get averaged data from the ADC
	ADCSequenceDataGet(ADC0_BASE,0,ui16Seq0Value);
	ADCSequenceDataGet(ADC0_BASE,1,ui16Seq1Value);
	ADCSequenceDataGet(ADC0_BASE,2,ui16Seq2Value);

	//Chan1 value
	averagedADC1 = (ui16Seq0Value[0] + ui16Seq0Value[1] + ui16Seq0Value[2] + ui16Seq0Value[3])/4;
	//Chan2 value
	averagedADC2 = (ui16Seq1Value[0] + ui16Seq1Value[1] + ui16Seq1Value[2] + ui16Seq1Value[3])/4;
	//Chan3 value
	averagedADC3 = (ui16Seq2Value[0] + ui16Seq2Value[1] + ui16Seq2Value[2] + ui16Seq2Value[3])/4;

	//Debugging sequence
	/*averagedADC1 = 1122;
	averagedADC2 = 1123;
	averagedADC3 = 1124; //Ab4FdTF
	//start = 65;
	//end of Debugging sequence */

	UARTprintf("0 - Chan0: %d | Chan1: %d | Chan2: %d\n", ui16Seq0Value[0], ui16Seq1Value[0],ui16Seq2Value[0]); //for debugg
	UARTprintf("1 - Chan0: %d | Chan1: %d | Chan2: %d\n", ui16Seq0Value[1], ui16Seq1Value[1],ui16Seq2Value[1]);
	UARTprintf("2 - Chan0: %d | Chan1: %d | Chan2: %d\n", ui16Seq0Value[2], ui16Seq1Value[2],ui16Seq2Value[2]);
	UARTprintf("3 - Chan0: %d | Chan1: %d | Chan2: %d\n", ui16Seq0Value[3], ui16Seq1Value[3],ui16Seq2Value[3]);

	//check sum
	checksum = averagedADC1 ^ averagedADC2 ^ averagedADC3;

	//prepare stream to send, 7 bytes in send1 and send2
	// start byte + chan1 + chan2 + chan3 + checksum:

	send1 = averagedADC2 << 20; //put chan2 in the enf of send1
	send1 = send1 + (averagedADC1<<8);//add chan1 and leave room for start byte
	send1 = send1 + start; //add start byte to stream
	send2 = checksum << 12; //put checksum and leave space for chan3
	send2 = send2 + averagedADC3; //add chan3

	//UARTprintf("AV1: %d | AV2: %d | AV3: %d\n",averagedADC1,averagedADC2,averagedADC3);
	//send...
	/*UARTCharPut(UART1_BASE,send1); //start byte
	UARTCharPut(UART1_BASE,send1 >> 8); //least sig byte of chan1
	UARTCharPut(UART1_BASE,send1 >> 16); //4 most sig bits of chan1 and least sig 4 bits of chan2
	UARTCharPut(UART1_BASE,send1 >> 24); //most sig byte of chan2
	UARTCharPut(UART1_BASE,send2); // least sig byte of chan3
	UARTCharPut(UART1_BASE,send2 >> 8); //4 most sig bits of chan3 and least sig 4 bits of checksum
	UARTCharPut(UART1_BASE,send2 >> 16); //most sig byte of checksum
	//UARTCharPut(UART1_BASE,10); // \n for DEBUGGG */

	//otherwise clear here (might loose some data points)
	//ADCIntClear(ADC0_BASE,0);
	ADCIntClear(ADC0_BASE,2);
}


// Main ----------------------------------------------------------------------------------------------
int main(void){

	// Enable lazy stacking
	FPULazyStackingEnable();

	// Set the system clock to run at 20Mhz off PLL with external crystal as reference.
	SysCtlClockSet(SYSCTL_SYSDIV_10 | SYSCTL_USE_PLL | SYSCTL_XTAL_16MHZ | SYSCTL_OSC_MAIN);

	// Initialize the UART and write status.
	ConfigureUART1();
	//UARTprintf("ADC CRASH OVERRIDE!! Using clock %d\n",  SysCtlClockGet());

	// Enable LEDs
	//SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
	//GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, LED_RED|LED_BLUE|LED_GREEN);

	//Initialize ADC
	ADCinit();
	//UARTprintf("ADC Sequence Initiated!\n");


	ADCIntClear(ADC0_BASE,2);
	ADCIntEnable(ADC0_BASE,2);
	IntEnable(INT_ADC0SS2);
	IntMasterEnable();
	// Create print variables

	while(1){
				//forever!
	}

}

  • Hello Ricardo

    The channel number corresponding to the GPIO Pins is mentioned in the data sheet chapter under section for Signal Description.

    If you connect the input signal to 3.3V then does the conversion follow suite?

    E.g. is AIN1 is connected to 3.3V and AIN2 is connected to 0V then do the conversions happen correctly?

    Regards
    Amit
  • // Plant Sensor ADC 3 Channels
    //
    //				Ricardo Cabrita, ISR 2015
    //****************************************************************************************************
    
    // Includes ------------------------------------------------------------------------------------------
    #include <stdint.h>
    #include <stdbool.h>
    #include <inttypes.h>
    
    #include "inc/hw_ints.h"
    #include "inc/hw_memmap.h"
    #include "inc/hw_i2c.h"
    
    #include "driverlib/fpu.h"
    #include "driverlib/gpio.h"
    #include "driverlib/interrupt.h"
    #include "driverlib/i2c.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/rom.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/uart.h"
    #include "driverlib/adc.h"
    #include "driverlib/timer.h"
    
    #include "utils/uartstdio.h"
    
    #include "shtLib.h"
    
    
    // Defines -------------------------------------------------------------------------------------------
    #define LED_RED GPIO_PIN_1
    #define LED_BLUE GPIO_PIN_2
    #define LED_GREEN GPIO_PIN_3
    //#define ch1 0001000000000000
    
    // Variables -----------------------------------------------------------------------------------------
    //uint16_t ui16ADC0Value[8] = {0,0,0,0,0,0,0,0};
    uint16_t ui16Seq0Value[4] = {0,0,0,0},ui16Seq1Value[4] = {0,0,0,0}, ui16Seq2Value[4] = {0,0,0,0};
    uint32_t averagedADC1,averagedADC2,averagedADC3;
    uint32_t ui32Baud = 460800;
    // Functions -----------------------------------------------------------------------------------------
    void ADCinit(void){
    	//Initialize ADC
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE); //Pin for ADC input
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0); //ADC peripheral
    	//Enable Timer 0
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);
    
    	//Pins used for ADC channels (3)
    	GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_3 | GPIO_PIN_2 | GPIO_PIN_1); //set GPIO_E3 for channel 1
    	//GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_2); //set GPIO_E2 for channel 2
    	//GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_1); //set GPIO_E1 for channel 3
    
    	ADCSequenceConfigure(ADC0_BASE, 0, ADC_TRIGGER_TIMER, 0); //sequencer 0
    	ADCSequenceConfigure(ADC0_BASE, 1, ADC_TRIGGER_TIMER, 1); //sequencer 1
    	ADCSequenceConfigure(ADC0_BASE, 2, ADC_TRIGGER_TIMER, 2); //sequencer 2
    
    	//sequencer 0
    	ADCSequenceStepConfigure(ADC0_BASE, 0, 0, ADC_CTL_CH1);
    	ADCSequenceStepConfigure(ADC0_BASE, 0, 1, ADC_CTL_CH1);
    	ADCSequenceStepConfigure(ADC0_BASE, 0, 2, ADC_CTL_CH1);
    	ADCSequenceStepConfigure(ADC0_BASE, 0, 3, ADC_CTL_CH1 | ADC_CTL_END);
    
    	//sequencer 1
    	ADCSequenceStepConfigure(ADC0_BASE, 1, 0, ADC_CTL_CH2);
    	ADCSequenceStepConfigure(ADC0_BASE, 1, 1, ADC_CTL_CH2);
    	ADCSequenceStepConfigure(ADC0_BASE, 1, 2, ADC_CTL_CH2);
    	ADCSequenceStepConfigure(ADC0_BASE, 1, 3, ADC_CTL_CH2 | ADC_CTL_END);
    
    	//sequencer 2
    	ADCSequenceStepConfigure(ADC0_BASE, 2, 0, ADC_CTL_CH1);
    	ADCSequenceStepConfigure(ADC0_BASE, 2, 1, ADC_CTL_CH1);
    	ADCSequenceStepConfigure(ADC0_BASE, 2, 2, ADC_CTL_CH1);
    	ADCSequenceStepConfigure(ADC0_BASE, 2, 3, ADC_CTL_CH1 | ADC_CTL_IE | ADC_CTL_END);
    
    	//
    	//Initialize Timer 0 to trigger an ADC conversion
    	//
    	TimerConfigure(TIMER0_BASE,TIMER_CFG_PERIODIC);
    	TimerLoadSet(TIMER0_BASE,TIMER_A,SysCtlClockGet()/1000); //5k sampling rate
    	TimerEnable(TIMER0_BASE, TIMER_A);
    	TimerControlTrigger(TIMER0_BASE,TIMER_A,true);
    
    
    	ADCSequenceEnable(ADC0_BASE,0);
    	ADCSequenceEnable(ADC0_BASE, 1);
    	ADCSequenceEnable(ADC0_BASE, 2);
    	//ADCIntEnable(ADC0_BASE,0);
    	ADCIntEnable(ADC0_BASE,2);
    	//IntEnable(INT_ADC0SS1);
    
    }
    
    void ConfigureUART1(void){
    
    	// Enable the peripherals used by UART
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_UART1);
    
    	// Set GPIO A0 and A1 as UART pins.
    	GPIOPinConfigure(GPIO_PB0_U1RX);
    	GPIOPinConfigure(GPIO_PB1_U1TX);
    	GPIOPinTypeUART(GPIO_PORTB_BASE, GPIO_PIN_0 | GPIO_PIN_1);
    
        // Configure UART clock using UART utils
        UARTClockSourceSet(UART1_BASE, UART_CLOCK_PIOSC);
        UARTStdioConfig(1, ui32Baud, 16000000);
    }
    
    void ADC0IntHandler(void){
    
    	//short a,b;
    	uint32_t send1,send2;
    	uint32_t start = 122, checksum; // 0x00FF start byte
    
    	//Clear ADC interrupt  here if interrupt is Light Cycle and small nr of instructions
    	//ADCIntClear(ADC0_BASE,1);
    
    	//get averaged data from the ADC
    	ADCSequenceDataGet(ADC0_BASE,0,ui16Seq0Value);
    	ADCSequenceDataGet(ADC0_BASE,1,ui16Seq1Value);
    	ADCSequenceDataGet(ADC0_BASE,2,ui16Seq2Value);
    
    	//Chan1 value
    	averagedADC1 = (ui16Seq0Value[0] + ui16Seq0Value[1] + ui16Seq0Value[2] + ui16Seq0Value[3])/4;
    	//Chan2 value
    	averagedADC2 = (ui16Seq1Value[0] + ui16Seq1Value[1] + ui16Seq1Value[2] + ui16Seq1Value[3])/4;
    	//Chan3 value
    	averagedADC3 = (ui16Seq2Value[0] + ui16Seq2Value[1] + ui16Seq2Value[2] + ui16Seq2Value[3])/4;
    
    	//Debugging sequence
    	/*averagedADC1 = 1122;
    	averagedADC2 = 1123;
    	averagedADC3 = 1124; //Ab4FdTF
    	//start = 65;
    	//end of Debugging sequence */
    
    	UARTprintf("Chan1: %d | Chan2: %d | Chan3: %d\n", averagedADC1, averagedADC2,averagedADC3); //for debugg
    
    	//check sum
    	checksum = averagedADC1 ^ averagedADC2 ^ averagedADC3;
    
    	//prepare stream to send, 7 bytes in send1 and send2
    	// start byte + chan1 + chan2 + chan3 + checksum:
    
    	send1 = averagedADC2 << 20; //put chan2 in the enf of send1
    	send1 = send1 + (averagedADC1<<8);//add chan1 and leave room for start byte
    	send1 = send1 + start; //add start byte to stream
    	send2 = checksum << 12; //put checksum and leave space for chan3
    	send2 = send2 + averagedADC3; //add chan3
    
    	//UARTprintf("AV1: %d | AV2: %d | AV3: %d\n",averagedADC1,averagedADC2,averagedADC3);
    	//send...
    	/*UARTCharPut(UART1_BASE,send1); //start byte
    	UARTCharPut(UART1_BASE,send1 >> 8); //least sig byte of chan1
    	UARTCharPut(UART1_BASE,send1 >> 16); //4 most sig bits of chan1 and least sig 4 bits of chan2
    	UARTCharPut(UART1_BASE,send1 >> 24); //most sig byte of chan2
    	UARTCharPut(UART1_BASE,send2); // least sig byte of chan3
    	UARTCharPut(UART1_BASE,send2 >> 8); //4 most sig bits of chan3 and least sig 4 bits of checksum
    	UARTCharPut(UART1_BASE,send2 >> 16); //most sig byte of checksum
    	//UARTCharPut(UART1_BASE,10); // \n for DEBUGGG */
    
    	//otherwise clear here (might loose some data points)
    	//ADCIntClear(ADC0_BASE,0);
    	ADCIntClear(ADC0_BASE,2);
    }
    
    
    // Main ----------------------------------------------------------------------------------------------
    int main(void){
    
    	// Enable lazy stacking
    	FPULazyStackingEnable();
    
    	// Set the system clock to run at 20Mhz off PLL with external crystal as reference.
    	SysCtlClockSet(SYSCTL_SYSDIV_10 | SYSCTL_USE_PLL | SYSCTL_XTAL_16MHZ | SYSCTL_OSC_MAIN);
    
    	// Initialize the UART and write status.
    	ConfigureUART1();
    	//UARTprintf("ADC CRASH OVERRIDE!! Using clock %d\n",  SysCtlClockGet());
    
    	// Enable LEDs
    	//SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
    	//GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, LED_RED|LED_BLUE|LED_GREEN);
    
    	//Initialize ADC
    	ADCinit();
    	//UARTprintf("ADC Sequence Initiated!\n");
    
    
    	ADCIntClear(ADC0_BASE,2);
    	ADCIntEnable(ADC0_BASE,2);
    	IntEnable(INT_ADC0SS2);
    	IntMasterEnable();
    	// Create print variables
    
    	while(1){
    				//forever!
    	}
    
    }
    
    Thank you for your reply

    So when i started doing the tests you suggested I noticed i had a lot of mistakes in my code, because at first I was using Sequencer 0 for both Chan0 and Chan1 and when I changed to Sequencer 0 for Chan0 and Seq1 for Chan1 I forgot to change some stuff. I attached the reviewed code.

    After fixing that what I did was connect AIN0 to 3.3V and AIN1 to gnd, and AIN0 to nothing. I checked with multimeter and values were 3.3V, 0V and something like 0.2V respectively. When I sent values to UART I noticed Chan0 value was like 1.5V, and since I was showing the averaged result of the 4 samples, I decided seeing all the values, and this is what I got:

    0 - Chan0: 4095 | Chan1: 0 | Chan2: 112
    1 - Chan0: 0 | Chan1: 0 | Chan2: 0
    2 - Chan0: 4095 | Chan1: 3 | Chan2: 123
    3 - Chan0: 0 | Chan1: 0 | Chan2: 0

    It seems only the odd slots of each sequencer's FIFO is being filled with the (right, after all) values from ADC, the even slots are zero'ed I don't know why.

    Regards,
    Ricardo

  • Ricardo,

    There is no reason to expect a floating input to read zero. For that matter you cannot expect a grounded input to read zero although there is at least the possibility that it will.

    There will be cross talk between the channels if the impedance is not sufficiently low. An input capacitor is IMO necessary.

    Check the Bookshelf tag. You will find references to appnotes on the care and feeding of A/D inputs.

    Robert
  • Hello Ricardo

    Your code only uses ADC_CTL_CH1 and ADC_CTL_CH2. This is AIN1 and AIN2 and not AIN0 and AIN1

    Regards
    Amit
  • // Plant Sensor ADC 3 Channels
    //
    //				Ricardo Cabrita, ISR 2015
    //****************************************************************************************************
    
    // Includes ------------------------------------------------------------------------------------------
    #include <stdint.h>
    #include <stdbool.h>
    #include <inttypes.h>
    
    #include "inc/hw_ints.h"
    #include "inc/hw_memmap.h"
    #include "inc/hw_i2c.h"
    
    #include "driverlib/fpu.h"
    #include "driverlib/gpio.h"
    #include "driverlib/interrupt.h"
    #include "driverlib/i2c.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/rom.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/uart.h"
    #include "driverlib/adc.h"
    #include "driverlib/timer.h"
    
    #include "utils/uartstdio.h"
    
    #include "shtLib.h"
    
    
    // Defines -------------------------------------------------------------------------------------------
    #define LED_RED GPIO_PIN_1
    #define LED_BLUE GPIO_PIN_2
    #define LED_GREEN GPIO_PIN_3
    //#define ch1 0001000000000000
    
    // Variables -----------------------------------------------------------------------------------------
    //uint16_t ui16ADC0Value[8] = {0,0,0,0,0,0,0,0};
    uint16_t ui16Seq0Value[4] = {0,0,0,0},ui16Seq1Value[4] = {0,0,0,0}, ui16Seq2Value[4] = {0,0,0,0};
    uint32_t averagedADC1,averagedADC2,averagedADC3;
    uint32_t ui32Baud = 460800;
    // Functions -----------------------------------------------------------------------------------------
    void ADCinit(void){
    	//Initialize ADC
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE); //Pin for ADC input
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0); //ADC peripheral
    	//Enable Timer 0
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);
    
    	//Pins used for ADC channels (3)
    	GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_3 | GPIO_PIN_2 | GPIO_PIN_1); //set GPIO_E3 for channel 1
    	//GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_2); //set GPIO_E2 for channel 2
    	//GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_1); //set GPIO_E1 for channel 3
    
    	ADCSequenceConfigure(ADC0_BASE, 0, ADC_TRIGGER_TIMER, 0); //sequencer 0
    	ADCSequenceConfigure(ADC0_BASE, 1, ADC_TRIGGER_TIMER, 1); //sequencer 1
    	ADCSequenceConfigure(ADC0_BASE, 2, ADC_TRIGGER_TIMER, 2); //sequencer 2
    
    	//sequencer 0
    	ADCSequenceStepConfigure(ADC0_BASE, 0, 0, ADC_CTL_CH0);
    	ADCSequenceStepConfigure(ADC0_BASE, 0, 1, ADC_CTL_CH0);
    	ADCSequenceStepConfigure(ADC0_BASE, 0, 2, ADC_CTL_CH0);
    	ADCSequenceStepConfigure(ADC0_BASE, 0, 3, ADC_CTL_CH0 | ADC_CTL_END);
    
    	//sequencer 1
    	ADCSequenceStepConfigure(ADC0_BASE, 1, 0, ADC_CTL_CH1);
    	ADCSequenceStepConfigure(ADC0_BASE, 1, 1, ADC_CTL_CH1);
    	ADCSequenceStepConfigure(ADC0_BASE, 1, 2, ADC_CTL_CH1);
    	ADCSequenceStepConfigure(ADC0_BASE, 1, 3, ADC_CTL_CH1 | ADC_CTL_END);
    
    	//sequencer 2
    	ADCSequenceStepConfigure(ADC0_BASE, 2, 0, ADC_CTL_CH2);
    	ADCSequenceStepConfigure(ADC0_BASE, 2, 1, ADC_CTL_CH2);
    	ADCSequenceStepConfigure(ADC0_BASE, 2, 2, ADC_CTL_CH2);
    	ADCSequenceStepConfigure(ADC0_BASE, 2, 3, ADC_CTL_CH2 | ADC_CTL_IE | ADC_CTL_END);
    
    	//
    	//Initialize Timer 0 to trigger an ADC conversion
    	//
    	TimerConfigure(TIMER0_BASE,TIMER_CFG_PERIODIC);
    	TimerLoadSet(TIMER0_BASE,TIMER_A,SysCtlClockGet()/1000); //5k sampling rate
    	TimerEnable(TIMER0_BASE, TIMER_A);
    	TimerControlTrigger(TIMER0_BASE,TIMER_A,true);
    
    
    	ADCSequenceEnable(ADC0_BASE,0);
    	ADCSequenceEnable(ADC0_BASE, 1);
    	ADCSequenceEnable(ADC0_BASE, 2);
    	//ADCIntEnable(ADC0_BASE,0);
    	ADCIntEnable(ADC0_BASE,2);
    	//IntEnable(INT_ADC0SS1);
    
    }
    
    void ConfigureUART1(void){
    
    	// Enable the peripherals used by UART
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_UART1);
    
    	// Set GPIO A0 and A1 as UART pins.
    	GPIOPinConfigure(GPIO_PB0_U1RX);
    	GPIOPinConfigure(GPIO_PB1_U1TX);
    	GPIOPinTypeUART(GPIO_PORTB_BASE, GPIO_PIN_0 | GPIO_PIN_1);
    
        // Configure UART clock using UART utils
        UARTClockSourceSet(UART1_BASE, UART_CLOCK_PIOSC);
        UARTStdioConfig(1, ui32Baud, 16000000);
    }
    
    void ADC0IntHandler(void){
    
    	//short a,b;
    	uint32_t send1,send2;
    	uint32_t start = 122, checksum; // 0x00FF start byte
    
    	//Clear ADC interrupt  here if interrupt is Light Cycle and small nr of instructions
    	//ADCIntClear(ADC0_BASE,1);
    
    	//get averaged data from the ADC
    	ADCSequenceDataGet(ADC0_BASE,0,ui16Seq0Value);
    	ADCSequenceDataGet(ADC0_BASE,1,ui16Seq1Value);
    	ADCSequenceDataGet(ADC0_BASE,2,ui16Seq2Value);
    
    	//Chan1 value
    	averagedADC1 = (ui16Seq0Value[0] + ui16Seq0Value[1] + ui16Seq0Value[2] + ui16Seq0Value[3])/4;
    	//Chan2 value
    	averagedADC2 = (ui16Seq1Value[0] + ui16Seq1Value[1] + ui16Seq1Value[2] + ui16Seq1Value[3])/4;
    	//Chan3 value
    	averagedADC3 = (ui16Seq2Value[0] + ui16Seq2Value[1] + ui16Seq2Value[2] + ui16Seq2Value[3])/4;
    
    	//Debugging sequence
    	/*averagedADC1 = 1122;
    	averagedADC2 = 1123;
    	averagedADC3 = 1124; //Ab4FdTF
    	//start = 65;
    	//end of Debugging sequence */
    
    	UARTprintf("0 - Chan0: %d | Chan1: %d | Chan2: %d\n", ui16Seq0Value[0], ui16Seq1Value[0],ui16Seq2Value[0]); //for debugg
    	UARTprintf("1 - Chan0: %d | Chan1: %d | Chan2: %d\n", ui16Seq0Value[1], ui16Seq1Value[1],ui16Seq2Value[1]);
    	UARTprintf("2 - Chan0: %d | Chan1: %d | Chan2: %d\n", ui16Seq0Value[2], ui16Seq1Value[2],ui16Seq2Value[2]);
    	UARTprintf("3 - Chan0: %d | Chan1: %d | Chan2: %d\n", ui16Seq0Value[3], ui16Seq1Value[3],ui16Seq2Value[3]);
    
    	//check sum
    	checksum = averagedADC1 ^ averagedADC2 ^ averagedADC3;
    
    	//prepare stream to send, 7 bytes in send1 and send2
    	// start byte + chan1 + chan2 + chan3 + checksum:
    
    	send1 = averagedADC2 << 20; //put chan2 in the enf of send1
    	send1 = send1 + (averagedADC1<<8);//add chan1 and leave room for start byte
    	send1 = send1 + start; //add start byte to stream
    	send2 = checksum << 12; //put checksum and leave space for chan3
    	send2 = send2 + averagedADC3; //add chan3
    
    	//UARTprintf("AV1: %d | AV2: %d | AV3: %d\n",averagedADC1,averagedADC2,averagedADC3);
    	//send...
    	/*UARTCharPut(UART1_BASE,send1); //start byte
    	UARTCharPut(UART1_BASE,send1 >> 8); //least sig byte of chan1
    	UARTCharPut(UART1_BASE,send1 >> 16); //4 most sig bits of chan1 and least sig 4 bits of chan2
    	UARTCharPut(UART1_BASE,send1 >> 24); //most sig byte of chan2
    	UARTCharPut(UART1_BASE,send2); // least sig byte of chan3
    	UARTCharPut(UART1_BASE,send2 >> 8); //4 most sig bits of chan3 and least sig 4 bits of checksum
    	UARTCharPut(UART1_BASE,send2 >> 16); //most sig byte of checksum
    	//UARTCharPut(UART1_BASE,10); // \n for DEBUGGG */
    
    	//otherwise clear here (might loose some data points)
    	//ADCIntClear(ADC0_BASE,0);
    	ADCIntClear(ADC0_BASE,2);
    }
    
    
    // Main ----------------------------------------------------------------------------------------------
    int main(void){
    
    	// Enable lazy stacking
    	FPULazyStackingEnable();
    
    	// Set the system clock to run at 20Mhz off PLL with external crystal as reference.
    	SysCtlClockSet(SYSCTL_SYSDIV_10 | SYSCTL_USE_PLL | SYSCTL_XTAL_16MHZ | SYSCTL_OSC_MAIN);
    
    	// Initialize the UART and write status.
    	ConfigureUART1();
    	//UARTprintf("ADC CRASH OVERRIDE!! Using clock %d\n",  SysCtlClockGet());
    
    	// Enable LEDs
    	//SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
    	//GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, LED_RED|LED_BLUE|LED_GREEN);
    
    	//Initialize ADC
    	ADCinit();
    	//UARTprintf("ADC Sequence Initiated!\n");
    
    
    	ADCIntClear(ADC0_BASE,2);
    	ADCIntEnable(ADC0_BASE,2);
    	IntEnable(INT_ADC0SS2);
    	IntMasterEnable();
    	// Create print variables
    
    	while(1){
    				//forever!
    	}
    
    }
    
    Hello Amit,

    Sorry, i had already changed that when i did the tests I mentioned, but I added the wrong version of code it seems.
    I am reading the right values now as I said, but only in half the values of sequencer's FIFO. For example, AIN0 is using Sequencer0 and it reads:
    ui16Seq0Value[0] = 4095 (3.3v)
    ui16Seq0Value[1] = 0
    ui16Seq0Value[2] = 4095 (3.3v)
    ui16Seq0Value[3] = 0

    My question is why is this happening ? Why are half the values of the FIFO coming as zero.

    thank you for your attention,
    Ricardo

  • Hello Robert,

    Thank you for your reply. Yes of course I wasn't expecting the grounded value to be exactly zero. At first i was reading the wrong channels and reading from the wrong variable, after fixing that it seems to be reading correctly. My problem now is with the sequencer's FIFO, because it seems only half the values are being written to.

    ADCSequenceDataGet(ADC0_BASE,0,ui16Seq0Value);

    For example, for squencer 0, i'm getting:
    ui16Seq0Value[0] = 4095 (3.3v)
    ui16Seq0Value[1] = 0
    ui16Seq0Value[2] = 4095 (3.3v)
    ui16Seq0Value[3] = 0

    And this happens for all 3 sequencers I'm using.

    Nonetheless I will check those appnotes since it will be important for the development of this project, thank you very much.

    Regards,

    Ricardo

  • Hello Ricardo,

    I think the issue is perhaps becuase of the UARTprintf in the Interrupt handler.

    The conversion frequency is 20KHz or 50us. Out of which 12us is taken by the conversion of the ADC. Now there is a UARTprintf that prints at minimum 30 characters @ 115200 bps. That becomes 30*10 (8N1 format) @ 115200 bps = 2.604 ms. So what is happening is that the FIFO pointers are now getting mismanaged.

    To test the theory:

    Change the sampling rate from 20KHz to 20Hz to give enough time for the ADC to convert and display.

    Regards
    Amit
  • Hello Robert,

    Thank you for your reply. Yes, I wasn't expecting the grounded input to be necessarily zero. I think I am now reading correctly the values as I said in my response to Amir. My problem now is with the FIFO I think.
    Nonetheless I will look into the appnotes you talked about since they might come in handy in the development of this project.

    thank you,
    Ricardo
  • Hello Amit,

    //Initialize Timer 0 to trigger an ADC conversion
    //
    TimerConfigure(TIMER0_BASE,TIMER_CFG_PERIODIC);
    TimerLoadSet(TIMER0_BASE,TIMER_A,SysCtlClockGet()/1000); // sampling rate
    TimerEnable(TIMER0_BASE, TIMER_A);
    TimerControlTrigger(TIMER0_BASE,TIMER_A,true);

    (and Timer is running from PLL with 20MHz)

    This is where I should change the sampling rate of the ADC conversion right ? So 20Hz would be SysCtlClockGet()/1000000 ? I am asking because I never understood this quite well.

    I ran it with SysCtlClockGet()/1000000 and nothing even appeared on UART. I also tried with SysCtlClockGet()/100000 (which would be 200Hz if I got it right) and UART works well but same problem, with values [1] and [3] of FIFO zero'ed.

    I should add that I am using UART1 with an FTDI and a baudrate of 460800.

    regards,
    Ricardo
  • Hello Ricardo

    Even with 460K Baud Rate the time for the UARTprintf would be reduced by 1/4 from 2.604ms to ~0.651ms which would not be sufficient.

    Let me see if your code shows the same behavior on my TM4C123 LaunchPad.

    Regards
    Amit
  • Hello Amit,

    I tried witth a 20Hz timer triggering ADC Conversion (I was doing it wrong before) and still the odd values of the squencer's FIFO como zero'ed.

    uint32_t ui32period = SysCtlClockGet()/20;

    TimerConfigure(TIMER0_BASE,TIMER_CFG_PERIODIC);
    TimerLoadSet(TIMER0_BASE,TIMER_A,ui32period-1); // sampling rate
    TimerEnable(TIMER0_BASE, TIMER_A);
    TimerControlTrigger(TIMER0_BASE,TIMER_A,true);

    Did you get anything different ?

    Regards
    Ricardo
  • Hello Ricardo,

    The issue was in the variable for reading the data. The data returned from the ADC register is in 32 bit format

    However the variables are declared as uint16_t
    uint16_t ui16Seq0Value[4] = {0,0,0,0},ui16Seq1Value[4] = {0,0,0,0}, ui16Seq2Value[4] = {0,0,0,0};

    Changing it to uint32_t corrected the issue.

    Regards,
    Amit
  • Hello Amit,

    Thank you so much! Inded I used 16bits because since the data from the ADC was 12 bits I figures there was no point in using 32 bits and I never thought about it again... guess i should have payed more attention to the warnings.

    thank you once again,
    regards
    Ricardo