|
|
View previous topic :: View next topic |
Author |
Message |
hemnath
Joined: 03 Oct 2012 Posts: 242 Location: chennai
|
problem in interfacing LTC2410 with 18LF2520 |
Posted: Mon Jul 06, 2015 2:08 am |
|
|
Hardware Connections:
18LF2520 --------- LTC2410
PIN C4 ---------- SDO
PIN C3 --------- SCK
PIN C1 --------- CS
Below is the test code:
Code: |
#include "18F2520.h"
#fuses INTRC, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP // Internal oscillator
#use delay(clock=1000000) // 1Mhz
#define A2D_CSI PIN_C1
#define A2D_SCLK PIN_C3
#define A2D_SDO PIN_C4
int32 Read_A2D(void)
{
int32 A2D_COUNTS;
int i;
output_high(A2D_SCLK);
delay_us(100);
output_high(A2D_CSI);
output_low(A2D_SCLK);
output_low(A2D_CSI);
while((input(A2D_SDO))==1); //wait for /EOC to go low...
for(i=4;i>0;i--) //I don't need to use these first 4 bits
{
output_high(A2D_SCLK);
delay_us(5);
output_low(A2D_SCLK);
delay_us(5);
}
for(i=20;i>0;i--) //Set i = number of bits to read
{
output_high(A2D_SCLK);
delay_us(5);
shift_left(&A2D_COUNTS,4,input(A2D_SDO));
output_low(A2D_SCLK);
delay_us(5);
}
output_high(A2D_CSI);
return A2D_COUNTS;
}
void main()
{
int32 A2D_value;
setup_adc_ports(NO_ANALOGS|VSS_VDD); // No analogs
setup_adc(ADC_OFF|ADC_TAD_MUL_0);
setup_comparator (NC_NC_NC_NC); // Disable comparator
while(1)
{
A2D_value = Read_A2D();
delay_ms(200);
// display the adc value on lcd
}
} |
When i run this code, I get the output of 709931 in the display. When the change the input voltage at LTC2410, the display value is not changing.
Please help |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19537
|
|
Posted: Mon Jul 06, 2015 2:54 am |
|
|
Look again at the data sheet.
You are operating the CS line. This means it'll be running in _internal_ SCK mode, which means _it_ generates the SCK, and you have to sample when it says....
I think you want to be in the external serial clock mode, Figure 7. |
|
|
hemnath
Joined: 03 Oct 2012 Posts: 242 Location: chennai
|
|
Posted: Mon Jul 06, 2015 4:05 am |
|
|
Very Sorry. There is a mistake on the hardware.
SCK and SDO are wrongly connected. Now solved the problem.
I require a solution for a problem.
Voltage at IN+: 0.7V
Voltage at IN-: 0.7V
When I increase the voltage at IN+, the LTC2410 produces the output code which increases from 0. I see it on LCD.
When I decrease the voltage at IN-, it produces some 6 digit value on the display.
What are those values? how to calculate it. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9241 Location: Greensville,Ontario
|
|
Posted: Mon Jul 06, 2015 5:31 am |
|
|
It could be 'garbage' caused by the LCD display driver if you're not decoding the 32 bit data correctly from the ADC.
It also could be 'noise' or EMI....
You should post examples of input voltages VS results as well as the 'math' and LCD driver for more help.
Unless you're really,really good at analog PCB design getting that ADC to run 'right' will be a huge challenge!
Jay |
|
|
ezflyr
Joined: 25 Oct 2010 Posts: 1019 Location: Tewksbury, MA
|
|
Posted: Mon Jul 06, 2015 7:54 am |
|
|
Hi,
For clarity and simplicity, I'd rewrite your 'ReadA2D' routine to extract all 24 bits of data from the LTC2410 in one pass. Once you have all the data, it's a simple matter to shift the data to remove the unwanted/unneeded bits.
John |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9241 Location: Greensville,Ontario
|
|
Posted: Mon Jul 06, 2015 8:05 am |
|
|
Had a quick read of the ADC datasheet and you do need to read in all 32 bits, after that then parse to get the 24 bits of the adc result.
Also be sure to have a solid 1ms delay before reading the ADC for the first time. It needs '0.5 ms' after power up to properly initialize itself.
Jay |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19537
|
|
Posted: Mon Jul 06, 2015 9:10 am |
|
|
Particularly so, because you need the sign bit.... |
|
|
hemnath
Joined: 03 Oct 2012 Posts: 242 Location: chennai
|
|
Posted: Mon Jul 06, 2015 11:29 pm |
|
|
Thanks. Let me read all 32 bits and parse it to get 24 bits.
Meanwhile i tried to measure the pulses at SCO and SCK lines. There are no pulses seen on the scope.
This looks to be strange. |
|
|
hemnath
Joined: 03 Oct 2012 Posts: 242 Location: chennai
|
|
Posted: Mon Jul 06, 2015 11:59 pm |
|
|
modified code to capture the 32 bit data.
Code: | int32 Read_A2D(void)
{
int32 A2D_COUNTS;
int i;
output_high(A2D_SCLK);
delay_us(100);
output_high(A2D_CSI);
output_low(A2D_SCLK);
output_low(A2D_CSI);
while((input(A2D_SDO))==1); //wait for /EOC to go low...
for(i=32;i>0;i--) //Set i = number of bits to read
{
output_high(A2D_SCLK);
delay_us(5);
shift_left(&A2D_COUNTS,0,input(A2D_SDO));
output_low(A2D_SCLK);
delay_us(5);
}
output_high(A2D_CSI);
return A2D_COUNTS;
} |
Is this routine is correct to capture the 32 bit data? |
|
|
ezflyr
Joined: 25 Oct 2010 Posts: 1019 Location: Tewksbury, MA
|
|
Posted: Tue Jul 07, 2015 8:08 am |
|
|
Hi hemnath,
Here is a routine I've used for years with the TC77 temperature sensor. You could easily modify it to suit your needs:
Code: |
for (iIndex=16; iIndex!=0; iIndex--)
{
output_high(TC77_SCK); //clock hi
if (input(TC77_Data))
bit_set(Data,iIndex - 1);
output_low(TC77_SCK); //clock lo
delay_us(10);
}
|
john |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19537
|
|
Posted: Tue Jul 07, 2015 11:17 am |
|
|
Lets start with a simple comment. _Use the tools_....
The chip uses a sub version of SPI. The compiler can do this for you.
So:
Code: |
#include "18F2520.h"
#fuses INTRC, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP // Internal oscillator
#use delay(clock=1000000) // 1Mhz
#define A2D_CSI PIN_C1
#define A2D_SCLK PIN_C3
#define A2D_SDO PIN_C4
#use spi(MASTER, DI=A2D_SDO, CLK=A2D_SCLK, BAUD=100000, BITS=32, MODE=1, stream=LTC)
signed int32 Read_A2D(void)
{
union
{
signed int32 rval;
unsigned int32 raw;
} temp=0;
temp.raw=spi_xfer(LTC,0,32);
//Now need to sign extend the value
if (bit_test(temp.raw,29))
{
//-ve value
temp.raw |=0xE000; //turn on top 3 bits
}
else
{
temp.raw &=0x01FFF; //only use low 28bits
}
return temp.rval;
}
void main()
{
signed int32 A2D_value;
setup_adc_ports(NO_ANALOGS|VSS_VDD); // No analogs
setup_adc(ADC_OFF|ADC_TAD_MUL_0);
output_low(A2D_CSI);
setup_comparator (NC_NC_NC_NC); // Disable comparator
//Now need to trigger a dummy read to start the conversion
A2D_value=Read_A2D();
while(1)
{
delay_ms(200); //delay before reading the first time
A2D_value = Read_A2D();
// display the adc value on lcd
//remember this is a _signed_ value
}
}
|
Now, no guarantees, but mode 1, should hold the clock low between the words, and sample on the rising edge (correct for this chip).
The sample will begin each time the transfer finishes (hence trigger a dummy sample before starting the loop), so there will always need to be enough time for the sample to complete between each reading (or you can read the EOC bit).
The data is a 29bit signed value. If the top bit is set (so -ve), then all the bits above this need to be set to give a signed int32.
Realise that you will get values like 'FFF7' if you look at the value in hex - this is -8. Display as a signed value to get the 'useable' value. |
|
|
hemnath
Joined: 03 Oct 2012 Posts: 242 Location: chennai
|
|
Posted: Tue Jul 07, 2015 10:32 pm |
|
|
@Ttelmah: I tried to display the values. But the values keeps on changing as,
7141, 2339, 8125, 7929, 6839, ....
@ezflyr: Thank you. I will try your code. |
|
|
hemnath
Joined: 03 Oct 2012 Posts: 242 Location: chennai
|
|
Posted: Tue Jul 07, 2015 10:42 pm |
|
|
@ezflyr: Tried your code. To convert 32 bit to 24 bit, i used the below routine inside the while loop
Code: | delay_ms(200); //delay before reading the first time
A2D_value = Read_A2D();
bit_clear(A2D_value, 31);bit_clear(A2D_value, 30);bit_clear(A2D_value, 29);
A2D_value = A2D_value >> 5;
// to display the value
|
It displays 6884860 on LCD. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19537
|
|
Posted: Thu Jul 09, 2015 1:15 am |
|
|
That does not convert the value.
You need to understand how signed values work.
The commonest form is called 2's complement.
Here 0000000 = 0
00000001 = 1
11111111 = -1
Now if you have (say) a 4 bit 2's complement value, stored in an 8bit integer, the conversion becomes:
Code: |
if (bit_test(val,3))
{
//here a -ve number - we need to set _all_ the bits between
//the 'sign' bit in this number, and the top of the byte
val |= 0b11110000; //turn on top four bits
}
else
{
//here a +ve number. We need to ensure all the upper bits
//are 0
val &= 0b00001111; //turn off the top four bits
}
|
Now if you start with 'val' equal to 1, it gets left as 1.
However if it is 0b1111 (-1 in a 4bit value), it gets converted to
0b11111111 which is -1 in a 8bit value.
Then printf, using %3d, would print -1, as required.
This is called 'sign extending'. The sign bit has to be 'extended' to the top of the number.
Unless you do sign extending, you will get insane values if you are close to zero, and values go -ve. This is what your code is showing.
Now, a comment here, my code outputs the whole 29bits. You need to divide the _signed_ value by 32.
Code: |
A2D_value = Read_A2D();
A2D_value/=32;
|
You must use division (not rotation), or you are back to the same problem with the sign.....
Now seriously, depending on how noisy the environment is the values from my code, are then quite reasonable:
223, 73, 253, 247, 213
Depending on your Vref, this would correspond to a few _uV_.....
It's worth then also understanding that you are dealing with a device sensitive to the tiniest signal. _Fractions_ of a uV/count. This is not something that can be tested on a conventional breadboard (except possibly by placing it inside a Faraday cage). If you have this on a simple board on the bench, expect to see hundreds of counts if you just move your hands near it. You need a really good grounded test station, with the board laid out with well designed analog paths kept separate from the digital circuitry, and a super stable Vref. |
|
|
hemnath
Joined: 03 Oct 2012 Posts: 242 Location: chennai
|
|
Posted: Thu Jul 09, 2015 4:46 am |
|
|
Thanks Ttelmah for your valuable comments.
I have designed a PCB and components are soldered and testing on it. (Not testing on breadboard).
Measured Vref: 3.2938V
Measured Input signal, Vin = IN+ - IN- => 0.00048V.
I wrote a simple routine to capture all 32 bits data and parsing it to convert to 24 bit.
But the problem is, even when my reference voltage and input signal is stable, the value on the display keeps on rolling for steady input signal. Well There could be any other problem with the below routine.
Code: | int32 Read_A2D(void)
{
int i;
signed int32 data = 0;
output_high(A2D_SCLK);
delay_us(100);
output_high(A2D_CSI);
output_low(A2D_SCLK);
output_low(A2D_CSI);
data = 0;
for (i = 32; i!=0; i--)
{
output_high(A2D_SCLK); //clock hi
delay_us(5);
if (input(A2D_SDO))
bit_set(Data, i - 1);
output_low(A2D_SCLK); //clock low
delay_us(5);
}
output_high(A2D_CSI);
return data;
} |
Values rolls like: 3125, 1518, 1497, 702, 1078, 2352, 1976, ... My input signal will change worst case of 4uV.
For 1uV = 5 bits will get increase. For these change in 4uV, max of 20 bits should get increased, right? but it is changing in the order of 1000. |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|