CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

ADXL345 in i2c mode

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
henyhollar



Joined: 09 Aug 2009
Posts: 10
Location: Nigeria

View user's profile Send private message

adxl345 help
PostPosted: Tue Dec 20, 2011 10:26 pm     Reply with quote

I am working with adxl345 in I2c mode with the code below. But it seems not to be working somebody pls help. I have read the manual over and over again without success
Code:

#include <18F4520.h>
#use delay(clock=20000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
#use i2c(Master, sda=PIN_C4, scl=PIN_C3, FORCE_HW, RESTART_WDT)
#fuses HS,NOPROTECT, BROWNOUT, PUT, NOLVP


char DEV_ADD = 0x53;   //SDO/ADDRESS Pin is tied low
char FIFO_MODE = 0x38;
char POWER_CTL = 0x2D;   //Power Control Register
char DATA_FORMAT = 0x31;
char DATAX0 = 0x32;   //X-Axis Data 0
char DATAX1 = 0x33;   //X-Axis Data 1
char DATAY0 = 0x34;   //Y-Axis Data 0
char DATAY1 = 0x35;   //Y-Axis Data 1
char DATAZ0 = 0x36;   //Z-Axis Data 0
char DATAZ1 = 0x37;   //Z-Axis Data 1


//This buffer will hold values read from the ADXL345 registers.
unsigned char values[10];

//These variables will be used to hold the x,y and z axis accelerometer values.
int x,y,z;
int i=0;

int1 indicator=0;

//Function declearation
void initialize();
void readRegister(int max);

#INT_SSP
void i2c_isr(){
 
  printf("Device responding..");
  x = ((int)values[1]<<8)|(int)values[0];
        //The Y value is stored in values[2] and values[3].
  y = ((int)values[3]<<8)|(int)values[2];
        //The Z value is stored in values[4] and values[5].
  z = ((int)values[5]<<8)|(int)values[4];
 
  printf("%2u %2u %2u\n\r",x,y,z);
   

}
     
void main(){
 
  set_tris_b(0x00);
 
 
 
  printf("Program starting...");
 
  enable_interrupts(INT_SSP);
  enable_interrupts(GLOBAL);
   
  initialize();
 
  while (true){
 
   

   
  //if (indicator==0)
     
 
  //Reading 6 bytes of data starting at register DATAX0 will retrieve the x,y and z acceleration values from the ADXL345.
  //The results of the read operation will get stored to the values[] buffer.
 

        printf("In do loop...");
        output_toggle(PIN_B0);
        readRegister(6);
     
        //The ADXL345 gives 10-bit acceleration values, but they are stored as bytes (8-bits). To get the full value, two bytes must be combined for each axis.
        //The X value is stored in values[0] and values[1].
       
       
        //Print the results to the terminal.
        //putc(((int)values[1]<<8)|(int)values[0]);
       
     
        //values[9]=0;
        //disable_interrupts(GLOBAL);
        //disable_interrupts(INT_SSP);
        delay_ms(1000);
  }
}


void initialize(){
         output_toggle(PIN_B1);
         delay_ms(2000);
         printf("Initialize...");
         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(DATA_FORMAT);
         i2c_write(0x01);
         i2c_stop();
         
         delay_ms(1);
         i2c_start();
         i2c_write(0xA6);
         i2c_write(FIFO_MODE);
         i2c_write(0x40);
         i2c_stop();
         
         //Put the ADXL345 into Measurement Mode by writing 0x08 to the POWER_CTL register.
         delay_ms(1);
         i2c_start();
         i2c_write(0xA6);
         i2c_write(0x2c);
         i2c_write(0x0c);
         i2c_stop();
         
         delay_ms(1);
         i2c_start();
         i2c_write(0xA6);
         i2c_write(POWER_CTL);
         i2c_write(0x08); //Measurement mode 
         i2c_stop();
         
         output_toggle(PIN_B1);
         delay_ms(2000);
      }
     
     
void readRegister(int max){
         //int i=0;
         i2c_start();
         i2c_write(0xA6);
         i2c_write(DATAX0);
         //i2c_stop();
         i2c_start();
         i2c_write(0xA7);
         //values[i]=i2c_read(1);
         
         for(i=0;i<6;i++){
             //putc(values[i]);
            //while(!i2c_poll());
             values[i++]=i2c_read(1);
                     }
         i2c_stop();
         
         }
Ttelmah



Joined: 11 Mar 2010
Posts: 19520

View user's profile Send private message

PostPosted: Wed Dec 21, 2011 3:01 am     Reply with quote

First, get rid of the INT_SSP.
Basically this is not wanted/needed for a master device (it triggers when a byte - or control signal - has been received, which is always controlled by the master). As written, this will cause real problems because of the time involved. It takes over 19mSec to execute, and will be triggering multiple times during the I2C transaction, taking the timings way beyond those that are likely to work....
Then you have the problem of voltage. The ADXL345, is designed for 2.5v operation (up to an absolute max of 3.6v). The PIC you are using operates down to 4.2v minimum. If your pullups go to the PIC supply rail, the signal on the ADXL, will be above there maximum ratings, while if they go to the ADXL supply rail, the signals will not go high enough to be accepted by the PIC. YOu _need_ either to be using a PIC that operates at lower voltages, or to have buffer amplifiers on the I2C signals (device like the P82B96).
Then you have the obvious thing that CS on the ADXL needs to be high to switch it to I2C mode - is it?.
Then have you got the ALT_ADDRESS pin grounded?. The addresses you are using (A6, and A7), only apply if this pin is grounded. The default addresses are 3A and 3B.
I stopped reading at this point.....

Take a deep breath, step back, redesign your hardware so you either have a buffer or use a lower voltage PIC, check the connection to ALT_ADDRESS, and then come back if you still can't get it working.

Best Wishes
RF_Developer



Joined: 07 Feb 2011
Posts: 839

View user's profile Send private message

PostPosted: Wed Dec 21, 2011 3:42 am     Reply with quote

Also (int)values[i]<<8 will always give you 0. in CCS C int is 8 bits (and the same as unsigned char by the way), so shifting any int by 8 bits in either direction will shift all the bits out leaving you with zeros. You seem to be wanting to produce 16 bit int, so your casting should be:

(int16)values[5]<<8 || values[4]

AND x, y and z must be int16 (or anything else larger than int which is 8 bits).

RF Developer.
henyhollar



Joined: 09 Aug 2009
Posts: 10
Location: Nigeria

View user's profile Send private message

adxl345 help
PostPosted: Thu Dec 22, 2011 6:26 pm     Reply with quote

Thank you so much for your contributions. I will get to carry out all your suggestions and i will get the result over to you. I guess I have seen a green light, my next post shall be a success IJN
henyhollar



Joined: 09 Aug 2009
Posts: 10
Location: Nigeria

View user's profile Send private message

adxl345 help
PostPosted: Wed Jan 18, 2012 6:51 am     Reply with quote

Thank you all for the help, I got the adxl345 responding now. But how can I address multiple adxl345s on the i2c bus ? The devid on the device is read only.
Ttelmah



Joined: 11 Mar 2010
Posts: 19520

View user's profile Send private message

PostPosted: Wed Jan 18, 2012 8:09 am     Reply with quote

On a single bus, you can only have two devices.
All you do is pull the SDO pin, which is unused when operating in I2C mode, high on one, and low on the other at boot time (physically wire this pin high/low in the circuit). This switches the device between addresses 0x3A/3B and 0x53/54.
If you need to go beyond two devices, then you need to implement multiple I2C busses.
DEVID, doesn't come into this. Even if you could change it, it wouldn't alter the I2C addressing.

Best Wishes
henyhollar



Joined: 09 Aug 2009
Posts: 10
Location: Nigeria

View user's profile Send private message

help
PostPosted: Sat Jan 28, 2012 10:27 pm     Reply with quote

Please, how do I make sure that the adxl345 returns values only when data is available and not some constant values on x,y and z axes even when the device is static ? Also I am not getting negative values from the device and this gives me a concern if the device is working properly as I claimed above.
temtronic



Joined: 01 Jul 2010
Posts: 9229
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Sun Jan 29, 2012 2:14 pm     Reply with quote

Post your new program. It could be bad formatting of the print fucntion or wrong handling of the data from the sensor.
henyhollar



Joined: 09 Aug 2009
Posts: 10
Location: Nigeria

View user's profile Send private message

adxl345 help
PostPosted: Mon Jan 30, 2012 4:03 pm     Reply with quote

Yes it is temtronic. I am getting something more promising now. Thank you so much.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Jan 30, 2012 8:44 pm     Reply with quote

Also, your readRegister() function has a bug. It doesn't do a NACK on
the last i2c_read(). It needs to do it. Look at the MULTIPLE BYTE READ
diagram on page 18 of the ADXL345 data sheet:
http://www.analog.com/static/imported-files/data_sheets/ADXL345.pdf
It shows the last read operation must do a NACK at the end. This is
done in CCS by using a 0 parameter for i2c_read(). You need to fix
your code.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
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