domingo, 22 de marzo de 2015

Desarrollo de algunas aplicaciones del ACELERÓMETRO ADXL345 en la tarjeta de Desarrollo ChipKit ®

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:


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!!!!



viernes, 6 de marzo de 2015

Desarrollo del circuito para medición de una señal de 110V/30A.

Desarrollo  del  circuito para medición de una señal de 110V/30A.

Objetivo:
Desarrollar el circuito propuesto en la entrada anterior, mediante la tarjeta de desarrollo Chip-Kit© que sea capaz desplegar en una interfaz digital los siguientes parámetros de una señal de 110 Volts  / 30 Amperes:
ª       Voltaje
ª       Corriente
ª       Frecuencia
ª       Energía

ª       Potencia

Metodología:
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:
int i=0;
int lecturas[75]; // inicia matriz
int valor1=0;
int valor2=0;
int valor3=0;
int pend1=0;
int pend2=0;

void setup()
{

analogReference(EXTERNAL);
Serial.begin (9600); //inicia comunicacion serial

for(int cont=0;cont<75;cont++) // for
{ // notese el delay
lecturas[cont]=analogRead(A0);
delayMicroseconds(500);
}

// for(int cont1=0;cont1<75;cont1++)  
// {
// Serial.println(lecturas[cont1]);
// }
}

void loop(){
if(i>70)
{
i=0;
setup();
}

valor1=lecturas;
i++;
valor2=lecturas;
i++;
valor3=lecturas;

pend1=valor2-valor1;
// Serial.println();
// Serial.print("Pend1: ";
// Serial.print(pend1);
// delay(1000);

pend2=valor3-valor2;
// Serial.println();
// Serial.print("Pend2: ";
// Serial.print(pend2);
// delay(1000);

if (pend1>0 && pend2<0&& i>3)
{
Serial.println();
Serial.print ("V= ";
Serial.print (valor2*0.3123); // 2.80/1023*855.3/5.3/1.4142 = 0.3123
Serial.print ("t";
Serial.print ("i=";
Serial.print (i);
Serial.println ();
delay (1000);
i=0;
setup();
}
i--;
}

Ø   Catálogo de elementos de este proyecto.

CIRCUITO PCB!