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));
}
|
|
|