·Aplicación
de Sensor de Choque con Acelerómetro ADXL345.
Los
sistemas de detección de choque son comúnmente usados en el dispositivo de bolsa
de aire (en inglés, airbag)
es un sistema de seguridad pasiva instalado en los automóviles modernos.
Este sistema fue patentado el 23 de octubre de 1971 por la firma Mercedes-Benz,
después de cinco años de desarrollo y pruebas del nuevo sistema. El primer
modelo que lo incorporó fue el Mercedes-BenzClase S W126 de 1981 y después
fue instalado en el Clase E W123.
El sistema de la bolsa
de aire se compone de:
·Detectores de impacto situados normalmente en la
parte interior del vehículo, la parte que empezará a desacelerarse antes en
caso de colisión, aunque cada vez se ponen más sensores, distribuidos por todo
el vehículo de manera que no se produzcan errores en su activación.
·Dispositivos de inflado, que gracias a una reacción química producen en un espacio de
tiempo muy reducido una gran cantidad de gas (de un modo
explosivo).
·Bolsas de nylon infladas
normalmente con el nitrógeno resultante de la reacción
química.
Su función es la de, en caso de colisión (con aceleración mayor que 3 G),
amortiguar con las bolsas inflables el impacto de los ocupantes del vehículo
contra el volante, el panel de instrumentos y el parabrisas en caso de los
airbag delanteros y contra ventanas laterales en los delanteros y traseros. Se
estima que en caso de impacto frontal, su uso puede reducir el riesgo de muerte
en un 30%.
Teniendo en cuenta estos factores simularemos un sistemas de detección de choque para despliegue de bolsa de aire con nuestro acelerometro.
1) Simularemos la bolsa de aire activada con el encendido de un LED.
2) Reduciremos la norma de desaceleración a 1G ya que es para fines didácticos:
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ómetroADXL345.
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
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:
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 }
Antes que nada nos
enfrentamos ante una señal de corriente alterna la cual no puede ser
introducida en algún sensor o transductor viables para nuestro ChipKit®.
Circuito.
Cada parámetro tiene
su propio proceso de sensado y medición, lo cual se detalla a continuación:
ØCorriente:
Esta señal la
mediremos apoyándonos de manera directa con el Sensor ACS714-Electr-30AT de
Allegro MicroSystems.
Como se comentó en la entrada
anterior, este sensor es bidreccional teniendo un rango de lectura de -30A a 30A,
nos haremos valer de un offset por medio de un OPAMP para aprovechar esta
resolución ya que solo tendremos voltajes de 0 a 30A.
Con la versatilidad que ofrece
este sensor, tenemos una salida en el rango de mV la cuál le daremos
tratamiento aritmético con el Chip Kit para su despliegue.
Seudocódigo:
ØVoltaje:
Mediremos de manera
directa con el Lector Analógico del microcontrolador, ya que fue lo que
exactamente hicimos en la entrada anterior, sin embargo, la tenemos que adaptar
para su lectura, a grandes rasgos su proceso será así:
De la parte complementaria
positiva que arroja la señal atenuada del transformador con relación 9:1 para
tener un rango de voltaje tolerable para el chipKit, quien por medio de su
lector analógico AnalogRead(), hará en primera instancia la lectura, la cual
mediante un proceso matemático determinará voltaje eficaz.
Seudocódigo.
Para este parámetro
la señal se atenúa y se filtra después del filtrado se utiliza un comparador
que se activa cada vez que la señal pasa por 0, cuando se activa el comparador
manda un pulso al Lector Analógico del microcontrolador.
Esquema:
El cruce por cero ofrece la
capacidad de realizar una interrupción en el flanco de subida, lo cual activará
un contador en el software para deducir así la frecuencia de la señal.
ØENERGÍA
Y POTENCIA
Para estas
cuantificaciones, se elaborará con matemática elaborada por el software: