Desarrollo de algunas aplicaciones del
ACELERÓMETRO ADXL345 en la tarjeta de Desarrollo ChipKit ®
(PARTE 1)
Hola, en esta ocasión te
presentaremos 3 aplicaciones muy útiles que el ACELERÓMETRO ADXL345 de Analog
Devices ® puede implementar:
ª
Control
de actuadores (en este caso SERVOMOTORES de acuerdo a la inclinación del
sensor)
ª
Detección
de TAP (movimiento de pulso corto)
ª
Detección
de Caída Libre.
Vayamos!!!
- · El acelerómetro ADXL345.
El ADXL345 es un acelerómetro delgado
y de baja potencia, con tres ejes de medición de alta resolución (13 bits)
hasta ± 16 g. La salida digital de Datos tiene el formato de complemento a dos de 16 bits y es accesible a través de las
interfaces SPI (3- o 4 conexiones) o interfaz digital I2C.
El ADXL345 es muy adecuado para
aplicaciones de dispositivos móviles. Este mide la aceleración estática de la
gravedad en la inclinación, así como la aceleración dinámica resultante de movimiento
o choque. Su alta resolución (4mg / LSB) permite resolución de los cambios de
inclinación de tan poco como 0,25 °.
ª
Control
de actuadores (SERVOMOTORES)
Como leímos el ADXL345 tiene la
capacidad de detectar su inclinación y mandar por medio de una interfaz I2C
o SPI las coordenadas de su posición.
Para esto primeramente te
invitamos a que corrobores el
funcionamiento de tu acelerómetro mediante una aplicación que implementaras en
tu ChipKit, necesitas tener simplemente las librería Wire.h la cual ya viene en
la paquetería básica del ChipKit o que puedes descargar aquí, asegúrate que las palabras clave CORRESPONDAN
con las funciones de la librería ya que algunas que están heredadas de la plataforma
Arduino sufren modificaciones como:
Wire.write → Wire.send
Wire.read →Wire.receive
Abre tu IDE y teclea el siguiente código:
#include <Wire.h>
#define accel_module (0x53)
byte values[6] ;
char output[512];
void setup(){
Wire.begin();
Serial.begin(9600);
Wire.beginTransmission(accel_module);
Wire.send(0x2D);
Wire.send(0);
Wire.endTransmission();
Wire.beginTransmission(accel_module);
Wire.send(0x2D);
Wire.send(16);
Wire.endTransmission();
Wire.beginTransmission(accel_module);
Wire.send(0x2D);
Wire.send(8);
Wire.endTransmission();
}
void loop(){
int xyzregister = 0x32;
int x, y, z;
Wire.beginTransmission(accel_module);
Wire.send(xyzregister);
Wire.endTransmission();
Wire.beginTransmission(accel_module);
Wire.requestFrom(accel_module, 6);
int i = 0;
while(Wire.available()){
values[i] = Wire.receive();
i++;
}
Wire.endTransmission();
x = (((int)values[1]) << 8) |
values[0];
y = (((int)values[3])<< 8) |
values[2];
z = (((int)values[5]) << 8) |
values[4];
sprintf(output, "%d %d
%d", x, y, z);
Serial.print(output);
Serial.write(10);
delay(1000);
}
Corre
el programa, deberás de ver el despliegue de las coordenadas en el monitor
serial.
El
monitor serial arroja las coordenadas del acelerómetro de acuerdo a su gravedad
estática, con estos valores implementaremos nuestra aplicación!!!
Implementamos entonces el siguiente circuito:
Para el primer inciso:
ChipKit ofrece ya una librería heredada de Arduino la cual nos ayuda a manipular un servomotor, con el siguiente código podrás enlazar la información recibida por nuestro ADXL345 para manipular en:
EJE X -> SERVO 1
EJE Y -> SERVO 2.
CÓDIGO:
#include
<Wire.h>
#include
<Servo.h>
Servo myservox; //
servo for x axis
Servo myservoy; //
servo for y axis
#define DEVICE
(0x53) //ADXL345 device address
#define TO_READ
(6) //num of bytes we are going to read
each time (two bytes for each axis)
#define TRIGGER
16 // pin analog2 (16) connect to CS
Adxl345, active high
byte buff[TO_READ]
; //6 bytes buffer for saving data read
from the device
int i;
void setup()
{
pinMode(TRIGGER,OUTPUT);
digitalWrite(TRIGGER,HIGH);
Wire.begin(); // join i2c bus (address optional for
master)
myservox.attach(9); // attaches the servo on pin 9 to the servo
object
myservoy.attach(10); // attaches the servo on
pin 10 to the servo object
myservox.write(90); // tell servo x to go to position 90 deg
delay(25); // makesure servo move
myservoy.write(90); // tell servo y to go to position 90 deg
delay(25); // makesure servo move
//Turning on the ADXL345
writeTo(DEVICE, 0x2D, 0);
writeTo(DEVICE, 0x2D, 16);
writeTo(DEVICE, 0x2D, 8);
}
void loop()
{
int regAddress = 0x32; //first axis-acceleration-data register on
the ADXL345
int x, y, z;
digitalWrite(TRIGGER,LOW);
delay(10);
digitalWrite(TRIGGER,HIGH);
readFrom(DEVICE, regAddress, TO_READ, buff);
//read the acceleration data from the ADXL345
//each axis reading comes in 10 bit
resolution, ie 2 bytes. Least Significat
Byte first!!
//thus we are converting both bytes in to one
int
//read 5 times and average them
x=0;
y=0;
z=0;
for(i=1;i<=5;i++){
x += (((int)buff[1]) << 8) |
buff[0];
y += (((int)buff[3])<< 8) | buff[2];
z += (((int)buff[5]) << 8) | buff[4];
delay(10);
}
x/=5;
y/=5;
z/=5;
if(x<-255)x= -255; else if
(x>255)x=255;
if(y<-255)y= -255; else if
(y>255)y=255;
x=map(x, -255, 255, 0, 180); // map range y
y=map(y, -255, 255, 0, 180); // map range y
myservox.write(x); // tell servo to go to position in
variable x
delay(25);
myservoy.write(180-y); // tell servo to go to position in
variable y
delay(25);
//It appears that delay is needed in order
not to clog the port
delay(200);
}
//----------------
Functions
//Writes val to
address register on device
void writeTo(int
device, byte address, byte val) {
Wire.beginTransmission(device); //start
transmission to device
Wire.send(address); // send register address
Wire.send(val); // send value to write
Wire.endTransmission(); //end transmission
}
//reads num bytes
starting from address register on device in to buff array
void readFrom(int
device, byte address, int num, byte buff[]) {
Wire.beginTransmission(device); //start
transmission to device
Wire.send(address); //sends address to read from
Wire.endTransmission(); //end transmission
Wire.beginTransmission(device); //start
transmission to device
Wire.requestFrom(device, num); // request 6 bytes from device
int i = 0;
while(Wire.available()) //device may send less than requested
(abnormal)
{
buff[i] = Wire.receive(); // receive a byte
i++;
}
Wire.endTransmission(); //end transmission
}
TAP y Caída Libre
La librería heredada para tap y caida libre tambien son de amplia apertura a través de la RED, donde al igual que este código no es necesario hacer ligeras modificaciones:
#include <Wire.h>
#include <ADXL345.h>
#include <Servo.h>
Servo myservox; // servo for x axis
Servo myservoy; // servo for y axis
#define DEVICE (0x53) //ADXL345 device address
#define TO_READ (6) //num of bytes we are going to read each time (two bytes for each axis)
#define TRIGGER 16 // pin analog2 (16) connect to CS Adxl345, active high
byte buff[TO_READ] ; //6 bytes buffer for saving data read from the device
int i;
ADXL345 accelerometer;
void setup(void)
{
Serial.begin(9600);
pinMode(4, OUTPUT);
pinMode(5, OUTPUT);
pinMode(30, OUTPUT);
// Initialize ADXL345
Serial.println("Initialize ADXL345");
if (!accelerometer.begin())
{
Serial.println("Could not find a valid ADXL345 sensor, check wiring!");
delay(500);
}
// Set tap detection on Z-Axis
accelerometer.setTapDetectionX(0); // Don't check tap on X-Axis
accelerometer.setTapDetectionY(0); // Don't check tap on Y-Axis
accelerometer.setTapDetectionZ(1); // Check tap on Z-Axis
// or
// accelerometer.setTapDetectionXYZ(1); // Check tap on X,Y,Z-Axis
accelerometer.setTapThreshold(2.5); // Recommended 2.5 g
accelerometer.setTapDuration(0.02); // Recommended 0.02 s
accelerometer.setDoubleTapLatency(0.10); // Recommended 0.10 s
accelerometer.setDoubleTapWindow(0.30); // Recommended 0.30 s
//Values for Free Fall detection
accelerometer.setFreeFallThreshold(0.35); // Recommended 0.3 -0.6 g
accelerometer.setFreeFallDuration(0.1); // Recommended 0.1 s
// Select INT 1 for get activities
accelerometer.useInterrupt(ADXL345_INT1);
// Check settings
checkSetup();
pinMode(TRIGGER,OUTPUT);
digitalWrite(TRIGGER,HIGH);
Wire.begin(); // join i2c bus (address optional for master)
myservox.attach(9); // attaches the servo on pin 9 to the servo object
myservoy.attach(10); // attaches the servo on pin 10 to the servo object
myservox.write(90); // tell servo x to go to position 90 deg
delay(25); // makesure servo move
myservoy.write(90); // tell servo y to go to position 90 deg
delay(25); // makesure servo move
//Turning on the ADXL345
writeTo(DEVICE, 0x2D, 0);
writeTo(DEVICE, 0x2D, 16);
writeTo(DEVICE, 0x2D, 8);
}
void checkSetup()
{
Serial.print("Look tap on axis = ");
if (accelerometer.getTapDetectionX()) { Serial.print(" X "); }
if (accelerometer.getTapDetectionY()) { Serial.print(" Y "); }
if (accelerometer.getTapDetectionZ()) { Serial.print(" Z "); }
Serial.println();
Serial.print("Tap Threshold = "); Serial.println(accelerometer.getTapThreshold());
Serial.print("Tap Duration = "); Serial.println(accelerometer.getTapDuration());
Serial.print("Double Tap Latency = "); Serial.println(accelerometer.getDoubleTapLatency());
Serial.print("Double Tap Window = "); Serial.println(accelerometer.getDoubleTapWindow());
Serial.print("Free Fall Threshold = "); Serial.println(accelerometer.getFreeFallThreshold());
Serial.print("Free Fall Duration = "); Serial.println(accelerometer.getFreeFallDuration());
}
void loop(void)
{
// Read values for activities
delay(50);
Vector norm = accelerometer.readNormalize();
// Read activities
Activites activ = accelerometer.readActivites();
if (activ.isFreeFall)
{
Serial.println("Free Fall Detected! led");
digitalWrite(30, HIGH);
delay(500);
digitalWrite(30, LOW);
}else
if (activ.isDoubleTap)
{
Serial.println("Double Tap Detected led");
digitalWrite(4, HIGH);
delay(500);
digitalWrite(4, LOW);
} else
if (activ.isTap)
{
Serial.println("Tap Detected led");
digitalWrite(5, HIGH);
delay(500);
digitalWrite(5, LOW);
}
int regAddress = 0x32; //first axis-acceleration-data register on the ADXL345
int x, y, z;
digitalWrite(TRIGGER,LOW);
delay(10);
digitalWrite(TRIGGER,HIGH);
readFrom(DEVICE, regAddress, TO_READ, buff); //read the acceleration data from the ADXL345
//each axis reading comes in 10 bit resolution, ie 2 bytes. Least Significat Byte first!!
//thus we are converting both bytes in to one int
//read 5 times and average them
x=0;
y=0;
z=0;
for(i=1;i<=5;i++){
x += (((int)buff[1]) << 8) | buff[0];
y += (((int)buff[3])<< 8) | buff[2];
z += (((int)buff[5]) << 8) | buff[4];
delay(10);
}
x/=5;
y/=5;
z/=5;
if(x<-255)x= -255; else if (x>255)x=255;
if(y<-255)y= -255; else if (y>255)y=255;
x=map(x, -255, 255, 0, 180); // map range y
y=map(y, -255, 255, 0, 180); // map range y
myservox.write(x); // tell servo to go to position in variable x
delay(25);
myservoy.write(180-y); // tell servo to go to position in variable y
delay(25);
//It appears that delay is needed in order not to clog the port
delay(200);
}
//---------------- Functions
//Writes val to address register on device
void writeTo(int device, byte address, byte val) {
Wire.beginTransmission(device); //start transmission to device
Wire.send(address); // send register address
Wire.send(val); // send value to write
Wire.endTransmission(); //end transmission
}
//reads num bytes starting from address register on device in to buff array
void readFrom(int device, byte address, int num, byte buff[]) {
Wire.beginTransmission(device); //start transmission to device
Wire.send(address); //sends address to read from
Wire.endTransmission(); //end transmission
Wire.beginTransmission(device); //start transmission to device
Wire.requestFrom(device, num); // request 6 bytes from device
int i = 0;
while(Wire.available()) //device may send less than requested (abnormal)
{
buff[i] = Wire.receive(); // receive a byte
i++;
}
Wire.endTransmission(); //end transmission
}
TE COMPARTIMOS EL VIDEO!!!!
Wire.write → Wire.send
Wire.read →Wire.receive
Archivo PDE:#include <Wire.h>
#include <ADXL345.h>
#include <Servo.h>
Servo myservox; // servo for x axis
Servo myservoy; // servo for y axis
#define DEVICE (0x53) //ADXL345 device address
#define TO_READ (6) //num of bytes we are going to read each time (two bytes for each axis)
#define TRIGGER 16 // pin analog2 (16) connect to CS Adxl345, active high
byte buff[TO_READ] ; //6 bytes buffer for saving data read from the device
int i;
ADXL345 accelerometer;
void setup(void)
{
Serial.begin(9600);
pinMode(4, OUTPUT);
pinMode(5, OUTPUT);
pinMode(30, OUTPUT);
// Initialize ADXL345
Serial.println("Initialize ADXL345");
if (!accelerometer.begin())
{
Serial.println("Could not find a valid ADXL345 sensor, check wiring!");
delay(500);
}
// Set tap detection on Z-Axis
accelerometer.setTapDetectionX(0); // Don't check tap on X-Axis
accelerometer.setTapDetectionY(0); // Don't check tap on Y-Axis
accelerometer.setTapDetectionZ(1); // Check tap on Z-Axis
// or
// accelerometer.setTapDetectionXYZ(1); // Check tap on X,Y,Z-Axis
accelerometer.setTapThreshold(2.5); // Recommended 2.5 g
accelerometer.setTapDuration(0.02); // Recommended 0.02 s
accelerometer.setDoubleTapLatency(0.10); // Recommended 0.10 s
accelerometer.setDoubleTapWindow(0.30); // Recommended 0.30 s
//Values for Free Fall detection
accelerometer.setFreeFallThreshold(0.35); // Recommended 0.3 -0.6 g
accelerometer.setFreeFallDuration(0.1); // Recommended 0.1 s
// Select INT 1 for get activities
accelerometer.useInterrupt(ADXL345_INT1);
// Check settings
checkSetup();
pinMode(TRIGGER,OUTPUT);
digitalWrite(TRIGGER,HIGH);
Wire.begin(); // join i2c bus (address optional for master)
myservox.attach(9); // attaches the servo on pin 9 to the servo object
myservoy.attach(10); // attaches the servo on pin 10 to the servo object
myservox.write(90); // tell servo x to go to position 90 deg
delay(25); // makesure servo move
myservoy.write(90); // tell servo y to go to position 90 deg
delay(25); // makesure servo move
//Turning on the ADXL345
writeTo(DEVICE, 0x2D, 0);
writeTo(DEVICE, 0x2D, 16);
writeTo(DEVICE, 0x2D, 8);
}
void checkSetup()
{
Serial.print("Look tap on axis = ");
if (accelerometer.getTapDetectionX()) { Serial.print(" X "); }
if (accelerometer.getTapDetectionY()) { Serial.print(" Y "); }
if (accelerometer.getTapDetectionZ()) { Serial.print(" Z "); }
Serial.println();
Serial.print("Tap Threshold = "); Serial.println(accelerometer.getTapThreshold());
Serial.print("Tap Duration = "); Serial.println(accelerometer.getTapDuration());
Serial.print("Double Tap Latency = "); Serial.println(accelerometer.getDoubleTapLatency());
Serial.print("Double Tap Window = "); Serial.println(accelerometer.getDoubleTapWindow());
Serial.print("Free Fall Threshold = "); Serial.println(accelerometer.getFreeFallThreshold());
Serial.print("Free Fall Duration = "); Serial.println(accelerometer.getFreeFallDuration());
}
void loop(void)
{
// Read values for activities
delay(50);
Vector norm = accelerometer.readNormalize();
// Read activities
Activites activ = accelerometer.readActivites();
if (activ.isFreeFall)
{
Serial.println("Free Fall Detected! led");
digitalWrite(30, HIGH);
delay(500);
digitalWrite(30, LOW);
}else
if (activ.isDoubleTap)
{
Serial.println("Double Tap Detected led");
digitalWrite(4, HIGH);
delay(500);
digitalWrite(4, LOW);
} else
if (activ.isTap)
{
Serial.println("Tap Detected led");
digitalWrite(5, HIGH);
delay(500);
digitalWrite(5, LOW);
}
int regAddress = 0x32; //first axis-acceleration-data register on the ADXL345
int x, y, z;
digitalWrite(TRIGGER,LOW);
delay(10);
digitalWrite(TRIGGER,HIGH);
readFrom(DEVICE, regAddress, TO_READ, buff); //read the acceleration data from the ADXL345
//each axis reading comes in 10 bit resolution, ie 2 bytes. Least Significat Byte first!!
//thus we are converting both bytes in to one int
//read 5 times and average them
x=0;
y=0;
z=0;
for(i=1;i<=5;i++){
x += (((int)buff[1]) << 8) | buff[0];
y += (((int)buff[3])<< 8) | buff[2];
z += (((int)buff[5]) << 8) | buff[4];
delay(10);
}
x/=5;
y/=5;
z/=5;
if(x<-255)x= -255; else if (x>255)x=255;
if(y<-255)y= -255; else if (y>255)y=255;
x=map(x, -255, 255, 0, 180); // map range y
y=map(y, -255, 255, 0, 180); // map range y
myservox.write(x); // tell servo to go to position in variable x
delay(25);
myservoy.write(180-y); // tell servo to go to position in variable y
delay(25);
//It appears that delay is needed in order not to clog the port
delay(200);
}
//---------------- Functions
//Writes val to address register on device
void writeTo(int device, byte address, byte val) {
Wire.beginTransmission(device); //start transmission to device
Wire.send(address); // send register address
Wire.send(val); // send value to write
Wire.endTransmission(); //end transmission
}
//reads num bytes starting from address register on device in to buff array
void readFrom(int device, byte address, int num, byte buff[]) {
Wire.beginTransmission(device); //start transmission to device
Wire.send(address); //sends address to read from
Wire.endTransmission(); //end transmission
Wire.beginTransmission(device); //start transmission to device
Wire.requestFrom(device, num); // request 6 bytes from device
int i = 0;
while(Wire.available()) //device may send less than requested (abnormal)
{
buff[i] = Wire.receive(); // receive a byte
i++;
}
Wire.endTransmission(); //end transmission
}
TE COMPARTIMOS EL VIDEO!!!!