Hi!!
Sorry about delay. To get better to read im gonna post each code here in the following order: my program, ADXL345 library (.h/.cpp) and L3G4200D library (.h/.cpp).
The datasheets are available:
ADXL345: https://www.sparkfun.com/datasheets/Sensors/Accelerometer/ADXL345.pdf (I2C chapter page 10)
L3G4200D: http://www.pololu.com/file/0J491/L3G4200D.pdf (I2C chapter page 13)
I think is necessary to create a new object for each Acce and each Gyro but i've no idea what do beyond that. mayday mayday! XD
thank you!
My program:
#include <Wire.h>
//ACCE
#include <ADXL345.h>
ADXL345 acc;
const float alpha = 0.5;
double pitch, roll, yaw, xa=0, ya=0, za=0, xaa=0, yaa=0, zaa=0;
//GYRO
#include <L3G4200D.h>
L3G4200D gyro;
int sampleNum=500;
int dc_offset_x=0;
int dc_offset_y=0;
int dc_offset_z=0;
double noise=0;
unsigned long time;
int sampleTime=20;
int rate_x;
int rate_y;
int rate_z;
int prev_rate_x=0;
int prev_rate_y=0;
int prev_rate_z=0;
double x=0;
double y=0;
double z=0;
void setup() {
Serial.begin(9600);
Wire.begin();
//ACCE
acc.begin();
//GYRO
gyro.enableDefault();
//Calculate initial DC offset and noise level of gyro
for(int n=0;n<sampleNum;n++){
gyro.read();
dc_offset_x+=(int)gyro.g.x;
dc_offset_y+=(int)gyro.g.y;
dc_offset_z+=(int)gyro.g.z;
}
dc_offset_x=dc_offset_x/sampleNum;
dc_offset_y=dc_offset_y/sampleNum;
dc_offset_z=dc_offset_z/sampleNum;
for(int n=0;n<sampleNum;n++){
gyro.read();
if((int)gyro.g.z-dc_offset_z>noise)
noise=(int)gyro.g.z-dc_offset_z;
else if((int)gyro.g.z-dc_offset_z<-noise)
noise=-(int)gyro.g.z-dc_offset_z;
}
noise=noise/100; //gyro returns hundredths of degrees/sec
delay(100);
}
//GYRO
void giroscopio(){
if(millis() - time > sampleTime){
time = millis(); // update the time to get the next sample
gyro.read();
rate_x=((int)gyro.g.x-dc_offset_x)/100;
rate_y=((int)gyro.g.y-dc_offset_y)/100;
rate_z=((int)gyro.g.z-dc_offset_z)/100;
if(rate_x >= noise || rate_x <= -noise)
x += ((double)(prev_rate_x + rate_x) * sampleTime * 1.32) / 2000;
if(rate_y >= noise || rate_y <= -noise)
y += ((double)(prev_rate_y + rate_y) * sampleTime * 1.32) / 2000;
if(rate_z >= noise || rate_z <= -noise)
z += ((double)(prev_rate_z + rate_z) * sampleTime * 1.32) / 2000;
// remember the current speed for the next loop rate integration.
prev_rate_x = rate_x;
prev_rate_y = rate_y;
prev_rate_z = rate_z;
// Keep our angle between 0-359 degrees
if (x < 0)
x += 360;
else if (x >= 360)
x -= 360;
if (y < 0)
y += 360;
else if (y >= 360)
y -= 360;
if (z < 0)
z += 360;
else if (z >= 360)
z -= 360;
}
}
//ACCE
void acelerometro(){
acc.read(&xa, &ya, &za);
//Low Pass Filter
xa = xa * alpha + (xa * (1.0 - alpha));
ya = ya * alpha + (ya * (1.0 - alpha));
za = za * alpha + (za * (1.0 - alpha));
xa=xa/sqrt(xa*xa+ya*ya+za*za);
ya=ya/sqrt(xa*xa+ya*ya+za*za);
za=za/sqrt(xa*xa+ya*ya+za*za);
}
void acelerometro_angulo(){
xaa=acos(xa)*180/PI;
yaa=acos(ya)*180/PI;
zaa=acos(za)*180/PI;
}
void acelerometro_pr(){
//Roll & Pitch Equations
roll = (atan2(-ya, za)*180.0)/M_PI;
pitch = (atan2(xa, sqrt(ya*ya + za*za))*180.0)/M_PI;
yaw=0;
if(roll<0) roll+=360;
if((zaa>90)&&(zaa<180)) pitch=(pitch-180)*(-1); //está no segundo ou terceiro quadrante. força range de 90 ate 270
else if((zaa<90)&&(pitch<0)) pitch+=360; //está no quarto quadrante. força range de 270 ate 0
}
void loop(){
acelerometro(); // medidas de aceleraçao
acelerometro_angulo(); //medidas de angulos entre o sensor e os eixos
acelerometro_pr(); //medidas em pitch e roll
giroscopio();
//ANGULOS DE ROTACAO (ACELEROMETRO) - PROCESSING/MATLAB:
Serial.print(roll, 4); //sobre eixo x
Serial.print(",");
Serial.print(-pitch, 4);
Serial.print(",");
Serial.print(yaw); // sobre eixo
// Serial.print('\n');
Serial.print(",");
//ANGULOS DE ROTACAO (GIROSCOPIO) - PROCESSING:
Serial.print(-x, 4); //sobre eixo x
Serial.print(",");
Serial.print(y, 4);
Serial.print(",");
Serial.print(-z, 4); // sobre eixo
Serial.print(",");
//
Serial.print(-x, 4); //sobre eixo x
Serial.print(",");
Serial.print(y, 4);
Serial.print(",");
Serial.print(-z, 4); // sobre eixo
Serial.print('\n');
delay(1);
}
ADXL345 library (.h)
/********************************************************************************
* ADXL345 Library - ADXL345.h *
* *
* Copyright (C) 2012 Anil Motilal Mahtani Mirchandani(anil.mmm@gmail.com) *
* *
* License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> *
* This is free software: you are free to change and redistribute it. *
* There is NO WARRANTY, to the extent permitted by law. *
* *
*********************************************************************************/
#ifndef _ADXL345_H
#define _ADXL345_H
#include <Arduino.h>
// All functions return -1 on error and 0 on success
class ADXL345
{
private:
/* ADXL345 Registers */
enum info_t
{
DEVID = 0x00,
THRESH_TAP = 0x1D,
OFSX = 0x1E,
OFSY = 0x1F,
OFSZ = 0x20,
DUR = 0x21,
Latent = 0x22,
Window = 0x23,
THRESH_ACT = 0x24,
THRESH_INACT = 0x25,
TIME_INACT = 0x26,
ACT_INACT_CTL = 0x27,
THRESH_FF = 0x28,
TIME_FF = 0x29,
TAP_AXES = 0x2A,
ACT_TAP_STATUS = 0x2B,
BW_RATE = 0x2C,
POWER_CTL = 0x2D,
INT_ENABLE = 0x2E,
INT_MAP = 0x2F,
INT_SOURCE = 0x30,
DATA_FORMAT = 0x31,
DATAX0 = 0x32,
DATAX1 = 0x33,
DATAY0 = 0x34,
DATAY1 = 0x35,
DATAZ0 = 0x36,
DATAZ1 = 0x37,
FIFO_CTL = 0x38,
FIFO_STATUS = 0x39,
ADDRESS = 0xA7 >> 1
};
int zG[3];
int readRegister(byte reg_addr, int nbytes, byte *buffer);
int writeRegister(byte reg_addr, int nbytes, byte *buffer);
public:
enum range_t
{
RANGE_16G = 0x0B,
RANGE_8G = 0x0A,
RANGE_4G = 0x09,
RANGE_2G = 0x08
};
ADXL345();
void begin();
void end();
//G Reading
void read(double *x, double *y, double *z);
//Raw reading
void read(int *x, int *y, int *z);
//Unit must be res_t
void setRange(range_t range);
//Unit must be G
void setZeroG(double x, double y, double z);
//Unit must be "Raw"
void setZeroG(int x, int y, int z);
};
#endif // _ADXL345_H