|
|
View previous topic :: View next topic |
Author |
Message |
alkkla2000
Joined: 15 Aug 2012 Posts: 6
|
spi with SCA100T problem |
Posted: Wed Jan 02, 2013 9:06 am |
|
|
Hi Everybody,
I am new user of CCS. I am trying to use SCA100T tilt sensor with SPI mode. But I couldn't get stable x and y angles.
SCA100T SPI interface document
http://www.muratamems.fi/sites/default/files/documents/tn15_spi_interface_specification.pdf
SCA100T datasheet
http://www.muratamems.fi/sites/default/files/documents/sca100t_inclinometer_datasheet_8261800b2_0.pdf
There is my code.
Code: |
#include <18F452.h>
#fuses HS,NOWDT,NOPROTECT,NOBROWNOUT,NOLVP,NOPUT,NOWRT,NODEBUG,NOCPD
#use delay (clock=20000000)
#include <stdio.h>
#include <math.h>
#include <lcd.c>
#include <stdlib.h>
// 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
// SCA100T pins.
#define SCA100T_CS PIN_B0 // Chip select pin
// SCA100T commands.
#define RWTR 0x08
#define MEAS 0x00
#define RDAX 0x10
#define RDAY 0x11
void spi_delay(int8 n){
while(n--);
}
void spi_start(void){
output_low(SCA100T_CS);
spi_delay(10);
}
void spi_stop(){
output_high(SCA100T_CS);
spi_delay(10);
}
void spi_writebyte(int8 data){
spi_start();
spi_write(data);
spi_stop();
}
void spi_init(){
spi_start();
spi_writebyte(MEAS);
spi_stop();
}
void main()
{
int8 msb_x,msb_y,lsb_x,lsb_y;
int16 angle_x,angle_y;
set_tris_A(0xFF);
set_tris_B(0x00);
set_tris_C(0x91);
set_tris_D(0x03);
set_tris_E(0xFF);
setup_spi(SPI_MASTER | SPI_MODE_0_0 | SPI_CLK_DIV_64);
spi_init();
lcd_init();
printf(lcd_putc, "\f"); // Clear the LCD.
printf(lcd_putc, "TILT ANGLE");
delay_ms(2000);
while(1)
{
msb_x=0;
lsb_x=0;
angle_x=0;
msb_y=0;
lsb_y=0;
angle_y=0;
output_low(SCA100T_CS);
spi_write(RDAX);
msb_x = spi_read(RDAX);
lsb_x = spi_read(RDAX);
angle_x = make16(msb_x, lsb_x);
angle_x=angle_x & 0x07ff;
output_high(SCA100T_CS);
printf(lcd_putc, "\f"); // Clear the LCD.
printf(lcd_putc,"\fTILT_X:%lu",angle_x);
delay_ms(3000);
output_low(SCA100T_CS);
spi_write(RDAY);
msb_y = spi_read(RDAY);
lsb_y = spi_read(RDAY);
angle_y = make16(msb_y, lsb_y);
angle_y=angle_y & 0x07ff;
output_high(SCA100T_CS);
printf(lcd_putc, "\f"); // Clear the LCD.
printf(lcd_putc,"\fTILT_Y:%lu",angle_y);
delay_ms(3000);
}
} |
|
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9226 Location: Greensville,Ontario
|
|
Posted: Wed Jan 02, 2013 10:17 am |
|
|
hmm...
'stable'
How 'stable' is the platform the sensor is on?
.ie: solid block of steel or just 'on the bench'?
Your program only reads once every 6 seconds.
.. I'd be reading/displaying data more often.
hth
jay |
|
|
alkkla2000
Joined: 15 Aug 2012 Posts: 6
|
|
Posted: Wed Jan 02, 2013 3:14 pm |
|
|
temtronic wrote: | hmm...
'stable'
How 'stable' is the platform the sensor is on?
.ie: solid block of steel or just 'on the bench'?
Your program only reads once every 6 seconds.
.. I'd be reading/displaying data more often.
hth
jay |
Dear temtronic,
I think stable means that, If I don't move(touch) the sensor, the sensor data doesn't change should not be a much changes. But on the code, I am getting different data(for exam, 26, 265,743,...) for each 6 seconds. 6 second is for tracing data changes. Of course, I will change the second. I think, I don't adjust read_spi time? But I am new user of CCS and I am student. I don't understand where is the problem. I will be very appreciate if somebody help me?
Regards |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
|
alkkla2000
Joined: 15 Aug 2012 Posts: 6
|
|
Posted: Fri Jan 04, 2013 3:39 am |
|
|
Dear PCM Programmer,
I built my own circuit. I used AP1512A-33 adjustable DC-DC converter, and I have adjusted 5V for output. I added my circuit schema below link. I will be so appreciate if you/someone help me.
Regards
Andac
http://i45.tinypic.com/13z8weo.jpg |
|
|
RF_Developer
Joined: 07 Feb 2011 Posts: 839
|
|
Posted: Fri Jan 04, 2013 3:51 am |
|
|
You need to swap the SPI data signals.
The PIC is the master, the SCA100T is the slave. MISO (Master In Slave Out) from the SCA100T should go to SDI (Serial Data In, RC4) on the PIC. MOSI (Master Out Slave In) should go to SDO (Serial Data Out, RC5).
As you have wired it, both devices have their inputs floating. This means the PIC will read noise instead of real data. The outputs clash as they drive each other :-( This may not have caused any damage.
RF Developer |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Fri Jan 04, 2013 4:00 am |
|
|
Code: | // 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 | Where did this list come from?
The hard coded values are dangerous because when you change to another processor or compiler version the values may be wrong.
I suggest you use the following code: Code: | // SPI Mode | MOTOROLA | MICROCHIP | CCS | Clock line idle | Data clocked in at
//----------------------------------------------------------------|-----------------|-------------------
// | CPOL CPHA| CKP CKE | | |
// 0 | 0 0 | 0 1 | SPI_L_TO_H | SPI_XMIT_L_TO_H | low | low to high edge
// 1 | 0 1 | 0 0 | SPI_L_TO_H | low | high to low edge
// 2 | 1 0 | 1 1 | SPI_H_TO_L | high | high to low edge
// 3 | 1 1 | 1 0 | SPI_H_TO_L | SPI_XMIT_L_TO_H | high | low to high edge
#define SPI_MODE_0 (SPI_L_TO_H | SPI_XMIT_L_TO_H)
#define SPI_MODE_1 (SPI_L_TO_H)
#define SPI_MODE_2 (SPI_H_TO_L)
#define SPI_MODE_3 (SPI_H_TO_L | SPI_XMIT_L_TO_H)
// Example:
setup_spi(SPI_MASTER | SPI_MODE_0 | SPI_CLK_DIV_64 ); |
|
|
|
alkkla2000
Joined: 15 Aug 2012 Posts: 6
|
|
Posted: Fri Jan 04, 2013 9:18 am |
|
|
Dear RF Developer,
Thank you for your correction. Also, I have connected according to your advice.
My connection is:
RC3------SCK
RC4------MISO
RC5------MOSI
RB0------CSB
But it is same. I can not get stable values.
Dear Ckielstra,
Thank you for your suggestion. I correct my code for your suggestion.
And I add RS232 connection and get angle values. I have added code and angle values below.
So I still have unstable x and y angle values. Please help me. I will be so appreciate...
My code is:
Code: |
#include <18F452.h>
#fuses HS,NOWDT,NOPROTECT,NOBROWNOUT,NOLVP,NOPUT,NOWRT,NODEBUG,NOCPD
#use delay (clock=20000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, stream=PIC)
#include <stdio.h>
#include <math.h>
#include <lcd.c>
#include <stdlib.h>
// SPI Mode | MOTOROLA | MICROCHIP | CCS | Clock line idle | Data clocked in at
//----------------------------------------------------------------|-----------------|-------------------
// | CPOL CPHA| CKP CKE | | |
// 0 | 0 0 | 0 1 | SPI_L_TO_H | SPI_XMIT_L_TO_H | low | low to high edge
// 1 | 0 1 | 0 0 | SPI_L_TO_H | low | high to low edge
// 2 | 1 0 | 1 1 | SPI_H_TO_L | high | high to low edge
// 3 | 1 1 | 1 0 | SPI_H_TO_L | SPI_XMIT_L_TO_H | high | low to high edge
#define SPI_MODE_0 (SPI_L_TO_H | SPI_XMIT_L_TO_H)
#define SPI_MODE_1 (SPI_L_TO_H)
#define SPI_MODE_2 (SPI_H_TO_L)
#define SPI_MODE_3 (SPI_H_TO_L | SPI_XMIT_L_TO_H)
// SCA100T pins.
#define SCA100T_CS PIN_B0 // Chip select pin
// SCA100T commands.
#define RWTR 0x08
#define MEAS 0x00
#define RDAX 0x10
#define RDAY 0x11
void spi_delay(int8 n){
while(n--);
}
void spi_start(void){
output_low(SCA100T_CS);
spi_delay(10);
}
void spi_stop(){
output_high(SCA100T_CS);
spi_delay(10);
}
void spi_writebyte(int8 data){
spi_start();
spi_write(data);
spi_stop();
}
void spi_init(){
spi_start();
spi_writebyte(MEAS);
spi_stop();
}
void main()
{
int8 msb_x,msb_y,lsb_x,lsb_y;
int16 angle_x,angle_y;
set_tris_A(0xFF);
set_tris_B(0x00);
set_tris_C(0x91);
set_tris_D(0x03);
set_tris_E(0xFF);
output_high(SCA100T_CS);
setup_spi(SPI_MASTER | SPI_MODE_0 | SPI_CLK_DIV_64 );
// setup_spi(SPI_MASTER | SPI_MODE_0_0 | SPI_CLK_DIV_64);
spi_init();
lcd_init();
printf(lcd_putc, "\f"); // Clear the LCD.
printf(lcd_putc, "TILT ANGLE");
delay_ms(3000);
printf("angle_x,angle_y\n\r");
while(1)
{
msb_x=0;
lsb_x=0;
angle_x=0;
msb_y=0;
lsb_y=0;
angle_y=0;
output_low(SCA100T_CS);
spi_write(0x10);
msb_x = spi_read(0x10);
lsb_x = spi_read(0x10);
output_high(SCA100T_CS);
angle_x = make16(msb_x, lsb_x);
angle_x=angle_x & 0x07ff;
output_low(SCA100T_CS);
spi_write(0x11);
msb_y = spi_read(0x11);
lsb_y = spi_read(0x11);
output_high(SCA100T_CS);
angle_y = make16(msb_y, lsb_y);
angle_y=angle_y & 0x07ff;
printf(lcd_putc, "\f"); // Clear the LCD.
printf(lcd_putc,"\fT_X:%lu",angle_x);
printf(lcd_putc,"\nT_Y:%lu",angle_y);
printf("%lu %lu\n\r"angle_x,angle_y);
delay_ms(2000);
}
}
|
reading angle values via RS 232:
Code: | angle_x angle_y
706 482
706 194
994 322
1506 1218
866 354
1922 1346
546 1666
706 1378
98 1538
1122 290
258 1506
1858 1890
1634 994
130 1954
1826 1026
1730 994
994 610
1346 386
1250 450 |
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19510
|
|
Posted: Fri Jan 04, 2013 12:18 pm |
|
|
Several comments:
First, getting a really smooth analog supply from a switch mode inverter, is 'not easy'. You would be much better off, using the switcher to give something like (say) 7vDC, and then using a linear regulator to generate the supply for the circuit. I'd not be at all surprised to find you have significant HF noise on your supply.
Then you need to be really careful with your ground layout. Either use a ground plane (and even then be very careful to not have the actual placement of parts so that digital circuits draw power 'past' analog circuits on the plane), or use very careful connections back to a _single_ point at the supply.
Then consider having the supply at the inclinometer chip, fed _back_ to the Vref pin on the PIC, and run the PIC analog code using Vref, rather than Vdd. The chip's output is ratiometric to it's supply, so if the PIC's ADC is run from the same point, you have a better chance of success.
Best Wishes |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9226 Location: Greensville,Ontario
|
|
Posted: Fri Jan 04, 2013 12:35 pm |
|
|
everything T says and...
try a test using battery only power, see what results you get for 5-10 minutes
also
what are the connections between the sensor and the PIC? Same PCB ? unshielded cabling, individual wires ? What kind of decoupling ( caps,low pass filters,chokes ,???) What 'noise' generators are nearby? Cellphones, Wifi, welders,fishtank heaters,??????
I have LM35s all over the house here and get rock steady data 24/7 for the past 10 years |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Jan 04, 2013 2:23 pm |
|
|
There are several things wrong with your SPI code.
1. You are giving spi_read() a non-zero parameter. The SCA100T data
sheet doesn't show this. It shows that you should use a parameter of
0x00. This bug in your code probably doesn't affect the output, but you
should at least follow the data sheet. Change your X-coordinate code to this:
Quote: |
spi_write(0x10);
msb_x = spi_read(0x00);
lsb_x = spi_read(0x00);
|
Change the Y code to this:
Quote: |
spi_write(0x11);
msb_y = spi_read(0x00);
lsb_y = spi_read(0x00);
|
2. The SCA100T data sheet clearly says you need a minimum delay
of 150 us between SPI operations, which you don't have. You need to
add the delay statement shown below in bold. (To be extra safe you
could make it be longer, such as 200 us):
Quote: |
output_low(SCA100T_CS);
spi_write(0x10);
msb_x = spi_read(0x00);
lsb_x = spi_read(0x00);
output_high(SCA100T_CS);
angle_x = make16(msb_x, lsb_x);
angle_x=angle_x & 0x07ff;
delay_us(150);
output_low(SCA100T_CS);
spi_write(0x11);
msb_y = spi_read(0x00);
lsb_y = spi_read(0x00);
output_high(SCA100T_CS);
|
3. You are mis-interpreting the output data. You are treating the data
as if it's right-justified in a 16-bit word. But the SCA100T data sheet
shows that it's left justified. So with your mask of 0x7FF, you are
looking at only the bottom 6 bits (shifted left by 5 bits), which would
certainly fluctuate more than the whole 11-bit value, since those are the
LSB bits.
Since the SCA100T outputs 11-bits of data, you need to right-shift it
by 5 bits to make it be right-justified. See the lines shown in bold below:
Quote: |
output_low(SCA100T_CS);
spi_write(0x10);
msb_x = spi_read(0x00);
lsb_x = spi_read(0x00);
output_high(SCA100T_CS);
angle_x = make16(msb_x, lsb_x);
angle_x >>= 5; // Right-justify the output word.
// angle_x=angle_x & 0x07ff;
delay_us(150);
output_low(SCA100T_CS);
spi_write(0x11);
msb_y = spi_read(0x00);
lsb_y = spi_read(0x00);
output_high(SCA100T_CS);
angle_y = make16(msb_y, lsb_y);
angle_y >>= 5; // Right-justify the output word.
// angle_y=angle_y & 0x07ff;
|
Even after you do all of this, the output will still probably fluctuate
somewhat. You can look at averaging algorithms in the forum archives.
Sherpa Doug was always promoting his Olympic Scoring algorithm.
Other people have posted their smoothing functions as well.
Also, in your schematic you have mis-labeled the PIC's RC4 and RC5
signals. This is in the lower right corner of your schematic. RC4 is SDI
so it must be MISO. RC5 is SDO, so it must be MOSI. |
|
|
alkkla2000
Joined: 15 Aug 2012 Posts: 6
|
|
Posted: Mon Jan 07, 2013 1:48 am |
|
|
Dear Temtronic and Ttelmah,
Thank you for your suggestion. I am using breadboard, and I will consider your suggestion.
Dear PCM programmer,
Thank you so much for your correction of my code. I control the datasheet again and I realized my mistakes. I couldn't see delay time. Thank you so much for your remark.
And I don't exactly know what is right & left justified. I need to read some documents. Thank you for your all information again. I am so appreciate for your help. Data is fluctuating and I will look averaging algorithms.
Regards |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19510
|
|
Posted: Mon Jan 07, 2013 2:11 am |
|
|
Ouch.
Switch mode inverter on breadboard. Read the data sheet for the inverter. Look particularly at their comments about board layout. Can a breadboard do this?...
Probably at least 50% of the problem.
Go to a linear regulator, and apply the code fixes from PCM programmer, and you have a good chance things will change.
Best Wishes |
|
|
alkkla2000
Joined: 15 Aug 2012 Posts: 6
|
|
Posted: Mon Jan 07, 2013 2:39 am |
|
|
Dear Ttelmah,
I agree with you. I will do my layout board. And I thank you again for all suggestion.
Regards |
|
|
|
|
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
|