Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

[SOLVED] [MOVED] ADS1118 interfacing to pic30f by using SPI

Status
Not open for further replies.

Thota Suresh Avionics

Member level 2
Joined
Jul 15, 2013
Messages
45
Helped
2
Reputation
4
Reaction score
2
Trophy points
8
Activity points
345
Hi
i am using pic30f5011 (16 bit) controller and mplabc30 compiler,to observe the output of the program i am using terminal programming....

My task is to read Voltage readings by using , i am new to SPI and ADS1118 ...
while running my code no errors... its showing fixed output as 65536..

Code:
#define SCLK LATGbits.LATG6 //clock line
#define SDI LATGbits.LATG7 //SPI data input
#define SDO LATGbits.LATG8 // SPI data output
#define CS LATGbits.LATG9 // chip select


/// main starts here

int main()
{
        double temp,result; // variable to store output

    ADPCFG = 0; //ALL PINS in ANALOG form

    TRISGbits.TRISG6 = 0; // SCK is an output
    TRISGbits.TRISG7 = 1; // SDI is an input
    TRISGbits.TRISG8 = 0; // SDO is an output
    TRISGbits.TRISG9 = 0; // CHIP SELECT AS O/P

        CS =1;
    uart_init(); //Uart Initialization
    SPI2_Init(); //SPI Initialization

    while (1)
    {
        CS =0;
        WriteSPI2(0x04EB); // Configure ADS1118
        result = ReadSPI2(0x0000); // reading results from ADS1118
        CS =1;

        printf("%f\n",result); 

        Delay();
        Delay();

    }


}



/// SPI initialization
void SPI2_Init(void)
{


    SPI2STATbits.SPIEN = 0; //initially disable pin
    SPI2STATbits.SPISIDL = 0; //opertion mode idle
    SPI2STATbits.SPIROV = 0; // Rx overflow flag
    SPI2STATbits.SPITBF = 0; //Tx buf full status
    SPI2STATbits.SPIRBF = 0; //Rx buf full status
    
    SPI2CONbits.FRMEN = 0; //Framing support diabled
    SPI2CONbits.SPIFSD = 0; //Frame Sync Pulse Direction Control on SSx pin bit 0-master,1-slave
    SPI2CONbits.DISSDO = 0; //Disable SDOx pin bit,0=pin conreolled by module,1=Pin is controlled by associated port register
    SPI2CONbits.MODE16 = 1; //Communication is word-wide (16 bits),0=Communication is word-wide (8 bits)
    SPI2CONbits.SMP = 0; //SPI Data Input Sample Phase bit Master mode:0,1 Slave mode =0; 
    SPI2CONbits.CKE = 0; //
    SPI2CONbits.SSEN = 1; //Slave Select Enable (Slave mode) bit
    SPI2CONbits.CKP = 0; //Clock Polarity Select bit
    SPI2CONbits.MSTEN = 1; //Master mode enabled
    SPI2CONbits.SPRE = 7; //Primary prescalr 1:1
    SPI2CONbits.PPRE = 3; //Secondary Prescalar 1:1
    
// IFS1bits.SPI2IF = 0; // Clear IF bit 
// IPC6bits.SPI2IP = 6; // Assign interrupt priority
// IEC1bits.SPI2IE = 1; // Interrupt En 

    SPI2STATbits.SPIEN = 1;
    printf("SPI2 init done\n");
}


void WriteSPI2(unsigned int data_out)
{ 

   if (SPI2CONbits.MODE16) // word write 
        SPI2BUF = data_out;
    else 
        SPI2BUF = data_out & 0xff; // byte write 

}
unsigned int ReadSPI2()
{ 
    /* Check for Receive buffer full status bit of status register*/
    if (SPI2STATbits.SPIRBF)
    {
        SPI2STATbits.SPIROV = 0;
                
        if (SPI2CONbits.MODE16)
            return ( SPI2BUF ); /* return word read */
        else
            return (SPI2BUF & 0xff); /* return byte read */
    }
    return -1; /* RBF bit is not set return error*/
}




void Delay ( void )
{
    int temp;
    for( temp = 0; temp < 255; temp++ );
}


am i missing something in SPI or ADS1118? plz help me anyone


showing output like this : output.jpg

- - - Updated - - -

ADS1118 vs Microcontroller connection is like this
SCLK--------->SCLK
CS ----------->CS
SDO---------->SDI
SDI----------->SDO


4 Pullup resistors connected to SDO,SDI,SCLK,CS
And Variable pot is connected to ADS1118 analog channel AIN0 (ADS1118 -4th pin) to vary the in put voltage to ADS1118
 

Re: ADS1118 interfacing to pic30f by using SPI

uart_init(); //Uart Initialization
Can you explain why are you using UART also,along with SPI?
 

Re: ADS1118 interfacing to pic30f by using SPI

Seems like you missed lot of things.. You are reading the input value with double format but you are getting only 16 bits??
Did you wait for data ready??
 

Re: ADS1118 interfacing to pic30f by using SPI

Hi udayan92

Uart is to debug the program, i can see the output results of adc on the terminal

- - - Updated - - -

Hi venkadesh_M
thanq for ur reply

Code:
#include"SPI_2.h"
#include"uart.h"

volatile double temp,result;


int main()
{
ADPCFG = 1; //ALL PINS in ANALOG form
TRISGbits.TRISG6 = 0; // SCK is an output
TRISGbits.TRISG7 = 1; // SDI is an input
TRISGbits.TRISG8 = 0; // SDO is an output
TRISGbits.TRISG9 = 0; // CHIP SELECT AS O/P
CS =1;
uart_init(); //Uart Init
SPI2_Init(); //SPI INIT
while (1)
{
CS =0;
 
//Programmable gain amplifier configuration (011) ==> FS is ±1.024 V
//Data rate (111) = 860 Samples Per Second
//Data rate (000) = 8 SPS
 
WriteSPI2(0x0000);
WriteSPI2(0x060B); //06EB working with 0.2 volts difference
 
Delay();
Delay();
 
result = ReadSPI2();
temp = ReadSPI2();
CS =1;

Delay();
Delay();
 
printf("V %.5f\n",(double)result);
}
 
}

}

Above modifications in my code ADC along with SPI working with some issues

Issue 1 :The output voltage readings i am getting is 0.2 volts to 0.4 volts difference with actual ADS1118 input voltage

Issue 2: Input voltage to the ADS1118 is maximum 5 volts and Minimum 0 volts (Variable),

When i am increasing ADC input voltage from 0 to 5 volts at 2.5 volts ADC working fine beyond that voltage levels OUTPUT showing 2.5 volts only (No increment happening)..

When i am decreasing from 5 to 0 volts at 0 volts showing results as 4.9 volts or 5 volts or may some times decreasing...
where i am missing??
 

Re: ADS1118 interfacing to pic30f by using SPI

Hi,


FS is ±1.024 V
&
OUTPUT showing 2.5 v

When input FS range is +/- 1.024V how can it show 2.5V?
There must be something wrong in your calculations.

Klaus
 

Re: ADS1118 interfacing to pic30f by using SPI


Code C - [expand]
1
result = ReadSPI2(0x0000); // reading results from ADS1118


the ReadSPI2(0x0000) function returns unsigned int raw adc value. but you are assigning it to a double variable how can it work?
 

Re: ADS1118 interfacing to pic30f by using SPI

Hi KlausST thanq for reply,

i tested FS(Programmable gain )with all these ranges

000 = FS is ±6.144 V(1)
001 = FS is ±4.096 V(1)
101 = FS is ±0.256 V
010 = FS is ±2.048 V (default)
110 = FS is ±0.256 V
011 = FS is ±1.024 V

and also with Data rates but no use

000 = 8 SPS
100 = 128 SPS (default)
001 = 16 SPS
101 = 250 SPS
010 = 32 SPS
110 = 475 SPS
011 = 64 SPS
111 = 860 SPS

what is the suitable FS(PGA) configuration for my hardware??

- - - Updated - - -

Hi Venkadesh_M


//Mul factor = Operating voltage * 16bit resolution (2^16 =65536 )

digi_result= digi_result +((float)result * Mulfactor);
printf("V %.5f\n",(double)digi_result);
i used multiplication factor to calculate voltage
 

Re: ADS1118 interfacing to pic30f by using SPI

Hi,

what is the suitable FS(PGA) configuration for my hardware??
We can not know what input voltages you connect to your ADC.

//Mul factor = Operating voltage * 16bit resolution (2^16 =65536 )

How this?
I usually use: Mul factor = FSvoltage / 2^15
it is the same as MUL factor = FSvoltagePP / 2^16

* use FSvoltage = 1.024 for a +/-1.204V full scale
* is the same as FSvoltagePP = 2.048V for a +/-1.024V full scale
* 2^15 for a bipolar value = +/-32768
* 2^16 for unipolar value = 65536

Use int16 for bipolar values
use uint16 for unipolar values.

the calculation is:

ADCVoltage = ADCValue * factor,
where ADCValue is tha binary result of an ADC conversion. (Same for unipolar and bipolar values)
ADCVoltage usually is a float.


Klaus
 

    V

    Points: 2
    Helpful Answer Positive Rating
Re: ADS1118 interfacing to pic30f by using SPI


Code C - [expand]
1
//Mul factor = Operating voltage * 16bit resolution (2^16 =65536 )


Where this code came from, How could we know your mistake without looking at your code ? ? ?
 

tanq for your replies again

Code:
include headers
#define OPV (6.144*2) //Peak to peak FS
#define bit16 (65536U)    //2^16 
#define MF 	(OPV / bit16)



int main()
{
	ADPCFG = 1; //ALL PINS in ANALOG form

	TRISGbits.TRISG6 = 0;   // SCK is an output
	TRISGbits.TRISG7 = 1;   // SDI is an input
	TRISGbits.TRISG8 = 0;  	// SDO is an output
	TRISGbits.TRISG9 = 0;   // CHIP SELECT AS O/P

	CS =1;

	uart_init();	//Uart Init
	SPI2_Init();	//SPI INIT

	while (1)
	{
		CS =0;
		WriteSPI2(0x0000);
		WriteSPI2(0x80EB);     //04EB working
	
		Delay();
		Delay();
		Delay();

		result = ReadSPI2();
		temp = ReadSPI2();
		CS =1;


		Delay();
		Delay();
		Delay();
		Delay();


		digi_result= (result * MF));
		result =0;

		printf("V %.3f\n",(float)digi_result);
		digi_result=0;
		}	

	

	}


}

These are the modifications done in my code
I am using 5.094(max) volts input because according to data sheet above 4 volts we have to choose +/-6.144 V,

i am getting the output with 60 or 50 milli Volts difference...
but for 16 bit resolution we need to get accuracy in Micro volts...
according to hardware there is no ripples(noise) in input voltage. is there any chances to increase accuracy??




4 Pullup resistors are connected to SDO,SDI,SCLK,CS

And Variable pot is connected to ADS1118 analog channel AIN0 (ADS1118 -4th pin) to vary the in put voltage to ADS1118
 

did you really compiled this code, there is a extra ')' in the line

Code C - [expand]
1
digi_result = (result * MF));


instead of this line try

Code C - [expand]
1
digi_result = result * 6.144 * 2 / 65536;


I mean the resolution can be reduced by multiplication after division

What kind error you are having linear or constant ?
for example for input voltage 1 and 3 what are the output voltages?
How do you saying you are getting error? did you used any standard meters?

If you are receiving some data then that is done with controller. for accuracy of readings you have to concentrate on ADC side.
 

Hi Venkadesh_M

did you really compiled this code, there is a extra ')' in the line

yes i am compiling my Code, to understanding the others i am renaming and editing my original code with valid variable names that is y mistake happened sorry for the mistake...


I mean the resolution can be reduced by multiplication after division

What kind error you are having linear or constant ?for example for input voltage 1 and 3 what are the output voltages?

its linear error happening..

INUPUT Vs OUTPUT

0.000 V(Min) ==> 12.016 V (diff is 12.016V)
0.856 V ==> 0.305 V (diff is 551 V )
2.061 V ==> 1.904 V (diff is 0.157 V)
2.547 V ==> 2.433 V (diff is 0.114 V)
3.163 V ==> 3.088 V (diff is 0.075 V)
4.530 V ==> 4.489 V (diff is 0.041 V)
5.094 V(Max) ==> 5.067 V (diff is 0.027 V)




How do you saying you are getting error? did you used any standard meters?

i am testing with fluke multimeter
 

I found your problem. your problem is you are using 16 bit mode in +/- 6.144V
that means - 0.0001 V is your maximum in twos complement so you are getting the max voltage.

try this

Code C - [expand]
1
2
3
4
if( result & 0x8000 )
digi_result = 0;
else
digi_result = result * 6.144 * 2 / 65536;



please don use macro here. use the code as it is for maximum resolution
 

at lower data rate (8 samples per second) without pullups in my hardware getting output with constant difference like

INPUT vs Output
0.000 ==> 0.000V
0.578 ==> 0.000V (0.578)
0.587 ==> 0.009V (0.578)
0.184 ==> 0.768V (0.584)
0.623 ==> 0.042V (0.581)
1.349 ==> 0.766V (0.583)
2.538 ==> 1.962V (0.576)
3.907 ==> 3.331V (0.576)
5.096 ==> 4.521V (0.575)

At higher data rate (860 samples per sec) output voltage is drastically fluctuating
example 1:
Input voltage 2.578 ==> Output Voltage will be fluctuating like
1.953 V
2.068 V
2.047 V
2.031 V

Example 2: Input voltage 3.450
Output voltage will be
3.046V
2.746V
3.046V
2.737V
3.043V


Is there any modifications required in Software or Hardware to rectify these constant difference???
 


Code C - [expand]
1
2
3
4
5
6
result += 3087;
 
if( result & 0x8000 )
   digi_result = 0;
else
   digi_result = result * 6.144 * 2 / 65536;



- - - Updated - - -

Are you using any diode on measuring circuit.

0.578 v sounds like diode or transistor base voltage...
 

thank you so much Venkadesh_M

Are you using any diode on measuring circuit.

0.578 v sounds like diode or transistor base voltage...

I am Only using 10k Variable pot and ADS1118 ...
after adding 3087 to the result getting accuracy upto 10 mV
 

Actually speaking something wrong with the hardware. That has been calibrated on software.

Are you having a actual schematic? did you anywhere used a diode or transistor in the circuit?
 

Hi,

maybe it´s time for a drawing of your circuit with all the connections and voltages on your ADC.


Klaus
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top