View previous topic :: View next topic |
Author |
Message |
dsaari
Joined: 05 May 2006 Posts: 25
|
SPI Comm. to Inclinometer |
Posted: Sat Aug 05, 2006 9:54 pm |
|
|
Hello,
I am new to SPI communication interfaces but have worked with I2C before. I have read just enough to be dangerous but I have hit a stumbling block. I have searched the forum for help but can't seem to figure it out. I am playing around with a new chip I got from Digikey. It is an inclinometer made by VTI Technologies. It can be accessed via SPI to read the inclination, acceleration and temperature of the device. I am sure there is more but inclination is all I want. The device is working because it has an analog output also which I have interfaced to and it does work. The device is part number SCA61T-FA1H1G and the datasheets for it are here. http://www.vti.fi/att/en/customer/TN15_SPI_Interface_Specification.pdf & http://www.vti.fi/att/en/customer/DN_sca61T_Rev_2_150905.pdf
I am trying to interface to a 16F876 PIC with the onboard hardware SPI. I know the PICs hardware SPI is configured for 8bit and the acceleration data returns in 11bits. I don't want acceleration though. It does appear that the inclination data is 8bit though. I have tried many different things and the latest unsuccessful attempt at some code is attached here. The problem is that it hangs up and never gets to the printf statement. If anyone has any ideas or direction, I would really appreciate it.
Code: | #fuses NOWDT, HS, NOPUT, NOPROTECT, NOBROWNOUT, NOLVP, NOCPD, NOWRT, NODEBUG
#use delay(clock=20000000)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=9)
#define ST PIN_B2 //self test
#define CS PIN_B1 //chip select
void main()
{
int8 MEAS = 0x00;
int8 RWTR = 0x08;
int8 STX = 0x0e;
int8 RDAX = 0x10;
int8 data = 0x00;
setup_spi (SPI_MASTER | SPI_H_TO_L | SPI_CLK_DIV_64);
output_low(ST);
output_high(CS);
delay_ms( 200 );
while (TRUE)
{
output_low(CS);
delay_us(200);
data = spi_read(MEAS);
delay_us( 200 );
output_high(CS);
delay_ms( 200 );
printf("Data = %4u\n\r", data);
}
} |
|
|
|
jecottrell
Joined: 16 Jan 2005 Posts: 559 Location: Tucson, AZ
|
|
Posted: Sun Aug 06, 2006 12:00 am |
|
|
From what little experience I have, I recall that SPI requires a command to be sent then a dummy byte to be sent to get the slave to clock out the response. Read explanation here:
http://www.ccsinfo.com/forum/viewtopic.php?t=26091
(first response by Ttelmah)
I think your general approach should be :
Code: |
spi_write(MEAS);
data = spi_read(0x00);
|
Don't worry, the pros will be along in the morning to give you some better ideas.
Good luck,
John |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Aug 06, 2006 12:10 am |
|
|
I see several problems.
1. You have the PIC configured for SPI mode 2. But the SCA61T spec
has a timing diagram which shows Mode 0 should be used (Figure 3).
2. The SCA61T spec says that the chip is in Measure Mode upon
power-on reset. You don't need to put it in that mode.
Unfortunately, the SPI spec sheet is awful. They never tell you
what you can do in Measure Mode. So I'm going to assume
that you can send the commands shown in Table 2.
3. The number of bits normally used for RS232 is 8 bits, not 9.
4. You should prevent the program from falling off the end of main().
Put in a while(1); statement at the end, or put a loop there.
One of the SPI commands is RWTR, which is Read/Write Temperature
register. They don't tell you the width of the register. You're left to
infer that it may be 11 bits. They also don't tell you exactly what it is
that this register holds. Is it the temperature in degrees Centigrade, or
the Temperature error offset ? What are the units that you're reading ?
What is the range of the readings ? Is it in two's complement mode ?
They don't say. This is really an astonishingly poor data sheet.
The following program should get you started. I don't know for sure
that it will work, but it ought to do something. I think it will read 11 bits
of the Temperature Register, and left justify them in a 16-bit word.
So you'll likely get a maximum output value of 0xFFE0. The minimum
might be 0x0000. By using two spi_write() commands, I'm sending it
16 clocks during the read cycle, where the timing diagram shows 11.
Most devices would just ignore the extra clocks. I don't know that this
chip will do that. Anyway, this is a test program.
Code: |
#include <16F877.H>
#use delay(clock=20000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
// SPI modes.
#define SPI_MODE_0_0 0x4000
#define SPI_MODE_0_1 0x0000
#define SPI_MODE_1_0 0x0010
#define SPI_MODE_1_1 0x4010
// SCA61T pins.
#define SCA61T_ST PIN_B2 // Self test pin
#define SCA61T_CS PIN_B1 // Chip select pin
// SCA61T commands.
#define RWTR 0x08
//=================================
void main()
{
int8 lsb;
int8 msb;
int16 result;
output_low(SCA61T_ST); // Disable self-test mode
output_high(SCA61T_CS); // Init CS pin
setup_spi(SPI_MASTER | SPI_MODE_0_0 | SPI_CLK_DIV_64);
while(1)
{
output_low(SCA61T_CS);
spi_write(RWTR);
msb = spi_read(0x00);
lsb = spi_read(0x00);
output_high(SCA61T_CS);
result = make16(msb, lsb);
printf("Temp. reg. = %lx\n\r", result);
delay_ms(1000);
}
} |
|
|
|
dsaari
Joined: 05 May 2006 Posts: 25
|
|
Posted: Sun Aug 06, 2006 7:28 am |
|
|
Thanks a lot, I did get the temperature to work based on your reply. The temperature is an 8bit response so I didn't need the LSB part of your code. They have a data sheet just for temperature, it is here http://www.vti.fi/att/en/customer/TN6_Internal_Temperature_Sensing.pdf I was pretty close to getting it in some of my earlier attempts. I still cannot get the inclination angle out of it though. I tried to apply the same concept as for temperature but 00 just comes back. Sometimes instead of 00 I get FF back, it's random. I've got to be close. Here's what I'm trying which isn't working. Thoughts?
Code: | #include <16F876.h>
#use delay(clock=20000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
// SPI modes.
#define SPI_MODE_0_0 0x4000
#define SPI_MODE_0_1 0x0000
#define SPI_MODE_1_0 0x0010
#define SPI_MODE_1_1 0x4010
// SCA61T pins.
#define SCA61T_ST PIN_B2 // Self test pin
#define SCA61T_CS PIN_B1 // Chip select pin
// SCA61T commands.
#define RWTR 0x08
#define MEAS 0x00
//=================================
void main()
{
int8 temp;
int8 angle;
output_low(SCA61T_ST); // Disable self-test mode
output_high(SCA61T_CS); // Init CS pin
setup_spi(SPI_MASTER | SPI_MODE_0_0 | SPI_CLK_DIV_64);
while(TRUE)
{
output_low(SCA61T_CS);
spi_write(RWTR);
temp = spi_read(0x00);
output_high(SCA61T_CS);
printf("Temp. reg. = %u\n\r", temp);
delay_ms(1000);
output_low(SCA61T_CS);
spi_write(MEAS);
angle = spi_read(0x00);
output_high(SCA61T_CS);
printf("meas reg. = %u\n\r", angle);
delay_ms(1000);
}
} |
|
|
|
bsodmike
Joined: 05 Aug 2006 Posts: 52
|
|
Posted: Sun Aug 06, 2006 9:24 am |
|
|
Hiya,
I've been following this interesting thread. I don't think that MEAS is going to get you any data in return. RDAX/Y should return the accel info, but you might be needing to pass something else to access the angle...
Good luck, Mike |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Aug 06, 2006 9:31 am |
|
|
You don't need to send the MEAS command. The data sheet says
that the chip is put into Measure Mode at power-up.
You need to send the command necessary to read the Inclination
register. They don't say what this command is. The SPI appnote
gives the command to read the acceleration. But your chip reads
the inclination. Maybe the commands are the same. So try the
code that I posted, except use the RDAX command, instead of RWTR.
You will need this #define statement:
|
|
|
bsodmike
Joined: 05 Aug 2006 Posts: 52
|
|
Posted: Sun Aug 06, 2006 9:34 am |
|
|
Sorry, I'm confused now. I thought this chip can do all 3? Sounds like it from the website...terrible docs tbh. |
|
|
dsaari
Joined: 05 May 2006 Posts: 25
|
|
Posted: Sun Aug 06, 2006 10:16 am |
|
|
Alright I think I got it with all of your help. I really do appreciate it. What a great first SPI project (sarcasm detected). Apparently RDAX is not acceleration but rather inclination. I accessed the register and when I tilt the chip this value changes. When I stop the value retains itself, so it's not acceleration anyway. What some terrible documentation on their part. I wrote to tell them that too. You'ld think at $60/device they would do a better job.
Thanks again for all the help |
|
|
bsodmike
Joined: 05 Aug 2006 Posts: 52
|
|
Posted: Sun Aug 06, 2006 11:26 pm |
|
|
dsaari,
Out of curiosity, did you try RDAY? It should *hopefully* return the tilt angle on the y-axis?
Thanks for clearing this up m8
Mike |
|
|
dsaari
Joined: 05 May 2006 Posts: 25
|
|
Posted: Mon Aug 07, 2006 6:25 pm |
|
|
Mike,
I didn't try RDAY because the device I bought was only a single axis inclinometer. It shows in the datasheet that would be a valid command for a different device. RDAX is definately tilt angle and not acceleration though. It appears to be very accurate as far as I can tell. I am going to do some further testing to see if it varies after time, especially in different temperatures. Perhaps I'll need an algorithm to take in account the temperature which is also readily available via SPI. Who knows, we'll see how that goes.
Thanks again |
|
|
TDK29
Joined: 14 Jun 2010 Posts: 2
|
|
Posted: Mon Jun 14, 2010 4:29 am |
|
|
Hi guys,
lets dig a bit in old graves ;)
I have a problem reading 11 bit from the SCA61T (with a PIC 18F4620)
Here's my code snippet:
Code: |
output_low(PIN_A5);
spi_write(0x10);
value = spi_read(0x10); //16 bit unsigned int
value2 = spi_read(0x10);
value <<= 3;
value2 >>= 5;
value += value2;
|
I guess we should get now values between 0 and 2048.
Well, we do, but the last 3 bits we read are floating extremely! If we print only value2, it jumps between 0 and 255, although the SCA61T is lying on the ground.
I hope someone here is able to help us solving our problem
Best regards and thanks in advance,
TDK |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
|
|