|
|
View previous topic :: View next topic |
Author |
Message |
Mucit23
Joined: 10 May 2014 Posts: 8
|
ADXL345 Problem? |
Posted: Sat May 10, 2014 9:03 am |
|
|
Hi friends,
I'm using pic16F877 with ADXL345 Accelerometer. I'm running ADXL345 in I2C mode. I can communicate with the sensor.
For example, when I read the registers DEVICE_ID, I'm reading the value 0xe5
When I read the data from the sensor, Every time I get the value 0x00.
This is My ADXL345 library,
Code: | // ADXL345 Registers
#define ADXL345_DEVID 0x00 // R Device ID
#define ADXL345_THRESH_TAP 0x1D // R/W Tap threshold
#define ADXL345_OFSX 0x1E // R/W X-axis offset
#define ADXL345_OFSY 0x1F // R/W Y-axis offset
#define ADXL345_OFSZ 0x20 // R/W Z-axis offset
#define ADXL345_DUR 0x21 // R/W Tap duration
#define ADXL345_Latent 0x22 // R/W Tap latency
#define ADXL345_Window 0x23 // R/W Tap window
#define ADXL345_THRESH_ACT 0x24 // R/W Activity threshold
#define ADXL345_THRESH_INACT 0x25 // R/W Inactivity threshold
#define ADXL345_TIME_INACT 0x26 // R/W Inactivity time
#define ADXL345_ACT_INACT_CTL 0x27 // R/W Axis enable control for activity and inactivity detection
#define ADXL345_THRESH_FF 0x28 // R/W Free-fall threshold
#define ADXL345_TIME_FF 0x29 // R/W Free-fall time
#define ADXL345_TAP_AXES 0x2A // R/W Axis control for single tap/double tap
#define ADXL345_ACT_TAP_STATUS 0x2B // R Source of single tap/double tap
#define ADXL345_BW_RATE 0x2C // R/W Data Rate and power mode control
#define ADXL345_POWER_CTL 0x2D // R/W Power-saving features control
#define ADXL345_INT_ENABLE 0x2E // R/W Interrupt enable control
#define ADXL345_INT_MAP 0x2F // R/W Interrupt mapping control
#define ADXL345_INT_SOURCE 0x30 // R Source of interrupts
#define ADXL345_DATA_FORMAT 0x31 // R/W Data format control
#define ADXL345_DATAX0 0x32 // R X-Axis Data 0
#define ADXL345_DATAX1 0x33 // R X-Axis Data 1
#define ADXL345_DATAY0 0x34 // R Y-Axis Data 0
#define ADXL345_DATAY1 0x35 // R Y-Axis Data 1
#define ADXL345_DATAZ0 0x36 // R Z-Axis Data 0
#define ADXL345_DATAZ1 0x37 // R Z-Axis Data 1
#define ADXL345_FIFO_CTL 0x38 // R/W FIFO control
#define ADXL345_FIFO_STATUS 0x39 // R FIFO status
#define ADXL345_OUTPUTS 0x32
void adxl345_init(){
i2c_start();
i2c_write(0xA6);
//delay for ack in the slave device
//Put the ADXL345 into +/- 4G range by writing the value 0x01 to the DATA_FORMAT register.
i2c_write(ADXL345_DATA_FORMAT);
i2c_write(0x01);
i2c_stop();
delay_ms(10);
i2c_start();
i2c_write(0xA6);
i2c_write(ADXL345_FIFO_CTL);
i2c_write(0x00);//FIFO inactive
i2c_stop();
//Put the ADXL345 into Measurement Mode by writing 0x08 to the POWER_CTL register.
delay_ms(10);
i2c_start();
i2c_write(0xA6);
i2c_write(ADXL345_BW_RATE);
i2c_write(0x0c);
i2c_stop();
delay_ms(10);
i2c_start();
i2c_write(0xA6);
i2c_write(ADXL345_POWER_CTL);
i2c_write(0x08); //Measurement mode
i2c_stop();
}
int adxl345_read(int add){
int retval;
i2c_start();
i2c_write(0xA6);
i2c_write(add);
i2c_start();
i2c_write(0xA7);
retval=i2c_read(0);
i2c_stop();
return retval;
} |
main code,
Code: |
#include <16F877A.h>
#device ADC=10
#FUSES NOWDT //No Watch Dog Timer
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES HS
#use delay(crystal=10000000)
#use I2C(master, sda=PIN_C4, scl=PIN_C3, slow)
#use fast_io(a)
#use fast_io(b)
#use fast_io(c)
#use fast_io(d)
#use fast_io(e)
#include <lcd_driver.c>
#include <ADXL345.c>
int8 accel_data[6];
int16 xaxis=0,yaxis=0,zaxis=0;
unsigned int8 temp=0;
void main()
{
set_tris_a(0x00);
set_tris_b(0x00);
set_tris_c(0x00);
set_tris_d(0x00);
set_tris_e(0x00);
output_a(0x00);
output_b(0x00);
output_c(0x00);
output_d(0x00);
output_e(0x00);
output_float(pin_c3);
output_float(pin_c4);
setup_ccp1(CCP_OFF);
setup_ccp2(CCP_OFF);
setup_spi(SPI_DISABLED);
delay_ms(500);
lcd_init();
adxl345_init();
printf(lcd_putc,"\f");
lcd_gotoxy(1,1);
temp=adxl345_read(ADXL345_DEVID );
printf(lcd_putc,"ADXL345_ID=%02X",temp);
while(TRUE)
{
accel_data[0]=adxl345_read(32); //Read X axis(LSB)
accel_data[1]=adxl345_read(33); //Read X axis(MSB)
accel_data[2]=adxl345_read(34); //Read Y axis(LSB)
accel_data[3]=adxl345_read(35); //Read Y axis(MSB)
accel_data[4]=adxl345_read(36); //Read Z axis(LSB)
accel_data[5]=adxl345_read(37); //Read Z axis(MSB)
xaxis=(int16)((accel_data[1]<<8)|accel_data[0]);
yaxis=(int16)((accel_data[3]<<8)|accel_data[2]);
zaxis=(int16)((accel_data[5]<<8)|accel_data[4]);
lcd_gotoxy(1,2);
printf(lcd_putc,"X%03ld Y%03ld Z%03ld",xaxis, yaxis, zaxis);
delay_ms(100);
output_toggle(pin_a0);
}
}
|
Result
What could be the problem? |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9243 Location: Greensville,Ontario
|
|
Posted: Sat May 10, 2014 4:33 pm |
|
|
you should printout the 'raw data'( to confirm you're actually reading it.
so after reading the high byte ,low byte data.. print out those valuse _before_ you create the 16bit data(xaxis,yaxis,zaxis).
you have 2 possible errors
1) NOT reading the actual data
2) a 'math' error (hint you can use make16())
You're using a 5 volt PIC and a 3 volt sensor, what interface are you using ?
hth
jay |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19538
|
|
Posted: Sun May 11, 2014 12:50 am |
|
|
The basic 'read' for the data is not being done the way that they recommend.
For the 8 bytes from the data registers, you should send the address of the first register, and then read all eight bytes in one sequence. As it stands, it ought probably to work (if the interface is correctly buffering the 3v levels to 5v....), but has the risk that parts of the registers will change between one read and the next. So potentially garbage.
Then the data pairs should be combined with make16 as temtronic says, but doesn't want to be combined into an int16. It wants to be a _signed_ int16.
Then you are running without the FIFO. You have the chip set to update at 8Hz. Unbuffered. You therefore need to wait for the chip to say it has done a reading, before taking the data. Much better to enable the interrupt output, and take the reading when this says that data is available, but as it stands, you need to wait 1/8th second after setting the register, and then read at 1/8th second intervals. |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Sun May 11, 2014 3:24 am |
|
|
At quick glance I noted this: Code: | #define ADXL345_DATAX0 0x32 // R X-Axis Data 0
#define ADXL345_DATAX1 0x33 // R X-Axis Data 1
#define ADXL345_DATAY0 0x34 // R Y-Axis Data 0
#define ADXL345_DATAY1 0x35 // R Y-Axis Data 1
#define ADXL345_DATAZ0 0x36 // R Z-Axis Data 0
#define ADXL345_DATAZ1 0x37 // R Z-Axis Data 1
accel_data[0]=adxl345_read(32); //Read X axis(LSB)
accel_data[1]=adxl345_read(33); //Read X axis(MSB)
accel_data[2]=adxl345_read(34); //Read Y axis(LSB)
accel_data[3]=adxl345_read(35); //Read Y axis(MSB)
accel_data[4]=adxl345_read(36); //Read Z axis(LSB)
accel_data[5]=adxl345_read(37); //Read Z axis(MSB) | Why are you using the hard coded values 32, 33, etc. instead of the defines? It would make the code 'self documenting', but even more important: 0x32 != 32 |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19538
|
|
Posted: Sun May 11, 2014 3:38 am |
|
|
Brilliant spot....
Register 32, is the user offset adjustment, so will be zero.
Suggest:
Code: |
#define ADXL_read_addr 0xA7;
#define ADXL_write_addr 0xA6;
struct data_block
{
signed int16 x;
signed int16 y;
signed int16 z;
};
union
{
int8 registers[6];
struct data_block axes;
} data;
void read_xyz(void)
{
int8 ctr;
i2c_start();
i2c_write(ADXL_write_addr);
i2c_write(ADXL345_DATAX0);
i2c_start();
i2c_write(ADXL_read_addr);
for (ctr=0;ctr<6;ctr++)
{
data.registers[ctr]=i2c_read(ctr==5); //NACK on 5
}
i2c_stop();
return;
}
//you then call 'read_xyz', and have the values in data.axes.x to
//data.axes.z - Signed int16 values.
|
Best Wishes |
|
|
Mucit23
Joined: 10 May 2014 Posts: 8
|
|
Posted: Sun May 11, 2014 3:30 pm |
|
|
Thank you for your answers. I solved the problem. |
|
|
|
|
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
|