| cleberalbert 
 
 
 Joined: 25 Feb 2014
 Posts: 34
 Location: Brazil
 
 
			    
 
 | 
			
				| ADXL345 Digital Accelerometer Driver + Processing |  
				|  Posted: Wed Mar 26, 2014 2:15 pm |   |  
				| 
 |  
				| This driver is for use with ADXL345 Digital Accelerometer using the I2C protocol. The code was done on CCS 5.018, is commented and is working well, tested by PIC18F4520 and Processing 2.1.1 by serial port on a PC. The code for Processing (.pde) is also below.
 
 This program can give the raw values, the three critical flight dynamics parameters (roll, pitch and yaw=0) and angles of rotation between the vector gravity and each sensor's axis (orthogonal coordinates system).
 
 
  	  | Code: |  	  | #include <18F4520.h>
 #case
 
 #FUSES HS
 #FUSES PUT
 #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 NOXINST                  //Extended set extension and Indexed Addressing mode disabled (Legacy mode)
 
 #use delay(crystal=20MHz)
 #use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,ERRORS)
 #use i2c(master, fast, sda=PIN_C4, scl=PIN_C3)
 
 #include <math.h>
 
 #define ADXL345_Address  0XA6 //0xA6 //0x53//0x3a
 #define ACC_READ_ADDR  0XA7//0xA7 //0x53//0x3b
 #define ACC_PWRCTRL_ADDR  0x2d
 #define ACC_MEASURE_MODE  0x08
 #define ACC_DATA_FORMAT  0x31
 #define ACC_OUT_LSB_X 0x32
 #define ACC_OUT_MSB_X 0x33
 #define ACC_OUT_LSB_Y 0x34
 #define ACC_OUT_MSB_Y 0x35
 #define ACC_OUT_LSB_Z 0x36
 #define ACC_OUT_MSB_Z 0x37
 #define ACC_ALPHA  0.5
 
 int8 accel_data[6]; // position 0,2 and 4 are respective x,y and z high significant bits. position 1,3 and 5 are respective x,y and z low significant bits.
 
 signed int16 acc_x;
 signed int16 acc_y;
 signed int16 acc_z;
 
 float acc_x1;
 float acc_y1;
 float acc_z1;
 float acc_R;
 float acc_teta=0;
 float acc_gama=0;
 float acc_fi=0;
 float acc_roll=0;
 float acc_pitch=0;
 float acc_yaw=0;
 
 void initializingADXL345();
 void accelerometer();
 void acce_cartesian_coordinates();
 void acce_spherical_coordinates();
 void acce_flight_coordinates();
 void writeRegisterI2C(int8 deviceAddress, int8 address, int8 val);
 int8 readRegisterI2C(int8 deviceAddress, int8 address);
 
 void main()
 {
 
 initializingADXL345();// initialize
 
 while(TRUE)
 {
 output_high(PIN_A0);
 
 accelerometer();
 acce_spherical_coordinates();
 acce_flight_coordinates();
 
 output_low(PIN_A0);
 }
 }
 
 void initializingADXL345(){
 // Tell the accelerometer to wake up
 writeRegisterI2C(ADXL345_Address, ACC_DATA_FORMAT, 0X01);
 writeRegisterI2C(ADXL345_Address, ACC_PWRCTRL_ADDR, ACC_MEASURE_MODE);
 }
 
 void writeRegisterI2C(int8 deviceAddress, int8 address, int8 val){
 i2c_start();               // start transmission to device
 i2c_write(deviceAddress);  // send device address
 i2c_write(address);        // send register address
 i2c_write(val);            // send value to write
 i2c_stop();                // end transmission
 }
 
 int8 readRegisterI2C(int8 deviceAddress, int8 address){
 int v;
 i2c_start();                  // start transmission to device
 i2c_write(deviceAddress);     // This is where you have to _write_ the register number you want
 i2c_write(address);           // register to read
 i2c_start();                  // restart - the bus is now set to _read_
 i2c_write(deviceAddress + 1); // now turn the bus round
 v = i2c_read(0);
 i2c_stop();                   // This will update x, y, and z with new values
 return v;
 }
 
 void accelerometer(){
 // Read data from the accel
 accel_data[0] = readRegisterI2C(ADXL345_Address, ACC_OUT_MSB_X); //most significant byte
 accel_data[1] = readRegisterI2C(ADXL345_Address, ACC_OUT_LSB_X); //least significant byte
 accel_data[2] = readRegisterI2C(ADXL345_Address, ACC_OUT_MSB_Y); //most significant byte
 accel_data[3] = readRegisterI2C(ADXL345_Address, ACC_OUT_LSB_Y); //least significant byte
 accel_data[4] = readRegisterI2C(ADXL345_Address, ACC_OUT_MSB_Z); //most significant byte
 accel_data[5] = readRegisterI2C(ADXL345_Address, ACC_OUT_LSB_Z); //least significant byte
 
 //Concatenate data
 acc_x=make16(accel_data[0],accel_data[1]);
 acc_y=make16(accel_data[2],accel_data[3]);
 acc_z=make16(accel_data[4],accel_data[5]);
 
 //Low Pass Filter
 acc_x=acc_x*ACC_ALPHA+(acc_x*(1.0-ACC_ALPHA));
 acc_y=acc_y*ACC_ALPHA+(acc_y*(1.0-ACC_ALPHA));
 acc_z=acc_z*ACC_ALPHA+(acc_z*(1.0-ACC_ALPHA));
 
 //Convert the values to versors
 acc_R=sqrt((float)acc_x*(float)acc_x+(float)acc_y*(float)acc_y+(float)acc_z*(float)acc_z);
 acc_x1=acc_x/acc_R;
 acc_y1=acc_y/acc_R;
 acc_z1=acc_z/acc_R;
 
 printf("%ld %ld %ld\n",acc_x,acc_y,acc_z); //print the raw values
 }
 
 void acce_spherical_coordinates(){ //angles of rotation beetwen the vector gravity and each sensor's axis (orthogonal coordinates system).
 acc_teta=acos(acc_x1)*180/PI;
 acc_gama=acos(acc_y1)*180/PI;
 acc_fi=acos(acc_z1)*180/PI;
 
 //printf("%f, %f, %f\n",acc_teta,acc_gama,acc_fi);
 }
 
 void acce_flight_coordinates(){ //The three critical flight dynamics parameters are the angles of rotation in three dimensions about the vector gravity
 acc_roll=180-(atan2(-acc_y1,acc_z1)*180.0)/PI;
 acc_pitch=180-(atan2(acc_x1,sqrt((float)acc_y1*(float)acc_y1+(float)acc_z1*(float)acc_z1))*180.0)/PI;
 acc_yaw=0;
 
 if((acc_fi>90)&&(acc_fi<180)) acc_pitch=(acc_pitch-180)*(-1); //está no segundo ou terceiro quadrante. força range de 90 ate 270
 if(acc_pitch<0) acc_pitch=acc_pitch+360; //está no quarto quadrante. força range de 270 ate 0
 
 //printf("%f, %f, %f\n",acc_roll,acc_pitch,acc_yaw);
 }
 
 | 
 
 Processing code (.pde):
 
 
  	  | Code: |  	  | import processing.opengl.*;
 import processing.serial.*;
 
 Serial sp;
 byte[] buff;
 float[] r;
 
 int SIZE = 150, SIZEX = 200;
 int OFFSET_X = -28, OFFSET_Y = 9;    //These offsets are chip specific, and vary.  Play with them to get the best ones for you
 long lastTime = 0;
 void setup() {
 size(SIZEX, SIZE, P3D);
 sp = new Serial(this, "COM6",  9600);
 buff = new byte[128];
 r = new float[3];
 lastTime = millis();
 
 }
 
 float protz, protx;
 void draw() {
 if ( millis() - lastTime > 1500 ) {
 //perspective( 45, 4.0/3.0, 1, 5000 );
 translate(SIZEX/2, SIZE/2, -400);
 background(0);
 buildShape(protz, protx);
 
 int bytes = sp.readBytesUntil((byte)10, buff);
 String mystr = (new String(buff, 0, bytes)).trim();
 if(mystr.split(" ").length != 3) {
 println(mystr);
 return;
 }
 setVals(r, mystr);
 
 float z = r[0], x = r[1];
 if(abs(protz - r[0]) < 0.05)
 z = protz;
 if(abs(protx - r[1]) < 0.05)
 x = protx;
 background(0);
 buildShape(z, x);
 
 protz = z;
 protx = x;
 //println(r[0] + ", " + r[1] + ", " + r[2]);
 }}
 
 void buildShape(float rotz, float rotx) {
 pushMatrix();
 scale(6,6,14);
 rotateZ(rotz);
 rotateX(rotx);
 fill(255);
 stroke(0);
 box(60, 10, 10);
 fill(0, 255, 0);
 box(10, 9, 40);
 translate(0, -10, 20);
 fill(255, 0, 0);
 box(5, 12, 10);
 popMatrix();
 }
 
 void setVals(float[] r, String s) {
 int i = 0;
 r[0] = -(float)(Integer.parseInt(s.substring(0, i = s.indexOf(" "))) +OFFSET_X)*HALF_PI/256;
 r[1] = -(float)(Integer.parseInt(s.substring(i+1, i = s.indexOf(" ", i+1))) + OFFSET_Y)*HALF_PI/256;
 r[2] = (float) Integer.parseInt(s.substring(i+1));
 
 
 }
 
 | 
 |  |