Manufactura industrial
Internet industrial de las cosas | Materiales industriales | Mantenimiento y reparación de equipos | Programación industrial |
home  MfgRobots >> Manufactura industrial >  >> Manufacturing Technology >> Proceso de manufactura

Cómo rastrear la orientación con Arduino y el acelerómetro ADXL345

En este tutorial, aprenderemos a medir el ángulo y la orientación del seguimiento con Arduino y el sensor del acelerómetro ADXL345. Puede ver el siguiente video o leer el tutorial escrito a continuación para obtener más detalles.

Resumen

Primero, explicaré cómo funciona el sensor y cómo leer los datos de él, y luego, usando el entorno de desarrollo Processing, haremos una visualización en 3D de la orientación del acelerómetro.

Cómo funciona el acelerómetro ADXL345

Para empezar, veamos cómo funciona el sensor ADXL345. Este es un acelerómetro de 3 ejes que puede medir fuerzas de aceleración tanto estáticas como dinámicas. La fuerza gravitatoria terrestre es un ejemplo típico de fuerza estática, mientras que las fuerzas dinámicas pueden ser causadas por vibraciones, movimientos, etc.

La unidad de medida de la aceleración es el metro por segundo al cuadrado (m/s^2). Sin embargo, los sensores de acelerómetro suelen expresar las medidas en “g” o gravedad. Una "g" es el valor de la fuerza gravitacional de la tierra que es igual a 9,8 metros por segundo al cuadrado.

Entonces, si tenemos un acelerómetro colocado plano, con su eje Z apuntando hacia arriba, opuesto a la fuerza gravitacional, la salida del eje Z del sensor será de 1 g. Por otro lado, las salidas X e Y serán cero, porque la fuerza gravitacional es perpendicular a estos ejes y no los afecta en absoluto.

Si volteamos el sensor boca abajo, la salida del eje Z será -1 g. Esto significa que las salidas del sensor debido a su orientación a la gravedad pueden variar de -1g a +1g.

Entonces, de acuerdo con estos datos y usando algunas matemáticas de trigonometría, podemos calcular el ángulo en el que se coloca el sensor.

Cómo leer los datos del acelerómetro ADXL345 con Arduino

Ok, ahora veamos cómo podemos leer los datos del acelerómetro ADXL345 usando el Arduino. Este sensor utiliza el protocolo I2C para la comunicación con Arduino, por lo que solo necesitamos dos cables para conectarlo, más los dos cables para alimentarlo.

Puede obtener los componentes necesarios para este tutorial de Arduino desde los siguientes enlaces:

  • Acelerómetro ADXL345 ………………. Amazonas / Banggood / AliExpress
  • Placa Arduino ………………………….. 
  • Protoboard y cables de salto ………… 

Código Arduino del acelerómetro ADXL345

Aquí está el código Arduino para leer los datos del acelerómetro ADXL345.

/*
    Arduino and ADXL345 Accelerometer Tutorial
     by Dejan, https://howtomechatronics.com
*/

#include <Wire.h>  // Wire library - used for I2C communication

int ADXL345 = 0x53; // The ADXL345 sensor I2C address

float X_out, Y_out, Z_out;  // Outputs

void setup() {
  Serial.begin(9600); // Initiate serial communication for printing the results on the Serial monitor
  Wire.begin(); // Initiate the Wire library
  // Set ADXL345 in measuring mode
  Wire.beginTransmission(ADXL345); // Start communicating with the device 
  Wire.write(0x2D); // Access/ talk to POWER_CTL Register - 0x2D
  // Enable measurement
  Wire.write(8); // (8dec -> 0000 1000 binary) Bit D3 High for measuring enable 
  Wire.endTransmission();
  delay(10);
}

void loop() {
  // === Read acceleromter data === //
  Wire.beginTransmission(ADXL345);
  Wire.write(0x32); // Start with register 0x32 (ACCEL_XOUT_H)
  Wire.endTransmission(false);
  Wire.requestFrom(ADXL345, 6, true); // Read 6 registers total, each axis value is stored in 2 registers
  X_out = ( Wire.read()| Wire.read() << 8); // X-axis value
  X_out = X_out/256; //For a range of +-2g, we need to divide the raw values by 256, according to the datasheet
  Y_out = ( Wire.read()| Wire.read() << 8); // Y-axis value
  Y_out = Y_out/256;
  Z_out = ( Wire.read()| Wire.read() << 8); // Z-axis value
  Z_out = Z_out/256;

  Serial.print("Xa= ");
  Serial.print(X_out);
  Serial.print("   Ya= ");
  Serial.print(Y_out);
  Serial.print("   Za= ");
  Serial.println(Z_out);
}Code language: Arduino (arduino)

Descripción: Entonces, primero debemos incluir la biblioteca Wire.h que se usa para la comunicación I2C. Si desea obtener más información sobre cómo funciona la comunicación I2C y cómo usarla con Arduino, puede consultar mi otro tutorial detallado.

Cada dispositivo que utiliza la comunicación I2C tiene una dirección I2C única, y esta dirección se puede encontrar en la hoja de datos del sensor (hoja de datos ADXL345). Entonces, una vez que definimos la dirección y las variables para las tres salidas, en la sección de configuración, primero debemos inicializar la biblioteca de cables y luego configurar el acelerómetro en modo de medición. Para hacer eso, si volvemos a mirar la hoja de datos, podemos ver que necesitamos establecer el bit D3 del registro POWER_CTL en ALTO.

Entonces, usando la función beginTransmission() comenzamos la comunicación, luego usando la función write() le decimos a qué registro queremos acceder, y nuevamente usando la función write() establecemos el bit D3 en ALTO, escribiendo el número 8 en decimal que corresponde a poner el bit D3 en ALTO.

// Set ADXL345 in measuring mode
  Wire.beginTransmission(ADXL345); // Start communicating with the device 
  Wire.write(0x2D); // Access/ talk to POWER_CTL Register - 0x2D
  // Enable measurement
  Wire.write(8); // (8dec -> 0000 1000 binary) Bit D3 High for measuring enable 
  Wire.endTransmission();Code language: Arduino (arduino)

En la sección de bucle ahora leemos los datos del sensor. Los datos de cada eje se almacenan en dos bytes o registros. Podemos ver las direcciones de estos registros en la hoja de datos.

Para leerlos todos, comenzamos con el primer registro, y luego, usando la función requestionFrom(), solicitamos leer los 6 registros. Luego, utilizando la función read(), leemos los datos de cada registro y, dado que las salidas son complementos a dos, las combinamos adecuadamente para obtener los valores correctos.

// === Read acceleromter data === //
  Wire.beginTransmission(ADXL345);
  Wire.write(0x32); // Start with register 0x32 (ACCEL_XOUT_H)
  Wire.endTransmission(false);
  Wire.requestFrom(ADXL345, 6, true); // Read 6 registers total, each axis value is stored in 2 registers
  X_out = ( Wire.read()| Wire.read() << 8); // X-axis value
  X_out = X_out/256; //For a range of +-2g, we need to divide the raw values by 256, according to the datasheet
  Y_out = ( Wire.read()| Wire.read() << 8); // Y-axis value
  Y_out = Y_out/256;
  Z_out = ( Wire.read()| Wire.read() << 8); // Z-axis value
  Z_out = Z_out/256;Code language: Arduino (arduino)

Los valores de salida del sensor en realidad dependen de la sensibilidad seleccionada, que puede variar de +- 2 g a +-16 g. La sensibilidad predeterminada es +-2g, por eso necesitamos dividir la salida por 256 para obtener valores de -1 a +1g. El 256 LSB/g significa que tenemos 256 cuentas por g.

Dependiendo de la aplicación podemos seleccionar la sensibilidad adecuada. En este caso, para la orientación del seguimiento, una sensibilidad de +-2g está bien, pero para aplicaciones en las que necesitamos detectar una mayor fuerza de aceleración de movimientos repentinos, golpes, etc., podemos elegir algunos de los otros rangos de sensibilidad usando el registro DATA_FORMAT y sus bits D1 y D0.

Calibración del acelerómetro ADXL345

Sin embargo, una vez que leemos los datos, simplemente podemos imprimirlos en el monitor serie para verificar si los valores son los esperados. En mi caso, los valores que estaba obteniendo no eran exactamente como deberían ser, especialmente el eje Z que tenía un error notable de 0,1 g.

Para resolver este problema, necesitamos calibrar el acelerómetro usando los 3 registros de calibración compensados, y así es como podemos hacerlo. Por lo tanto, debemos colocar el sensor plano e imprimir los valores RAW sin dividirlos por 256.

Desde aquí ahora podemos notar cuánto están apagadas las salidas, en mi caso, la salida Z estaba alrededor de 283. Esa es una diferencia de 27 en positivo. Ahora necesitamos dividir este valor por 4, y eso nos dará el número que necesitamos para escribir en el registro de compensación del eje Z. Si cargamos el código ahora, la salida del eje Z será exactamente 256, o 1 g, como debería ser.

// This code goes in the SETUP section
// Off-set Calibration
  //X-axis
  Wire.beginTransmission(ADXL345);
  Wire.write(0x1E);  // X-axis offset register
  Wire.write(1);
  Wire.endTransmission();
  delay(10);
  //Y-axis
  Wire.beginTransmission(ADXL345);
  Wire.write(0x1F); // Y-axis offset register
  Wire.write(-2);
  Wire.endTransmission();
  delay(10);
  
  //Z-axis
  Wire.beginTransmission(ADXL345);
  Wire.write(0x20); // Z-axis offset register
  Wire.write(-7);
  Wire.endTransmission();
  delay(10);Code language: Arduino (arduino)

Si es necesario, debemos calibrar el otro eje usando el mismo método. Y solo una nota rápida de que esta calibración no se escribe permanentemente en los registros. Necesitamos escribir estos valores en los registros en cada encendido del sensor.

Una vez que hayamos terminado con la calibración, ahora podemos finalmente calcular el Roll and Pitch, o la rotación alrededor del eje X y la rotación alrededor del eje Y en grados, usando estas dos fórmulas.

// Calculate Roll and Pitch (rotation around X-axis, rotation around Y-axis)
  roll = atan(Y_out / sqrt(pow(X_out, 2) + pow(Z_out, 2))) * 180 / PI;
  pitch = atan(-1 * X_out / sqrt(pow(Y_out, 2) + pow(Z_out, 2))) * 180 / PI;Code language: Arduino (arduino)

Para obtener más detalles sobre cómo funcionan estas fórmulas, puede consultar esta nota de aplicación de Freescale Semiconductor.

Rastreo de orientación del acelerómetro Arduino y ADXL345:visualización 3D

Bien, ahora hagamos el ejemplo de visualización 3D del acelerómetro.

Entonces, estamos usando el mismo código, que envía los valores de Roll y Pitch a través del puerto serial. Aquí está el código completo de Arduino:

/*
    Arduino and ADXL345 Accelerometer - 3D Visualization Example 
     by Dejan, https://howtomechatronics.com
*/
#include <Wire.h>  // Wire library - used for I2C communication

int ADXL345 = 0x53; // The ADXL345 sensor I2C address

float X_out, Y_out, Z_out;  // Outputs
float roll,pitch,rollF,pitchF=0;

void setup() {
  Serial.begin(9600); // Initiate serial communication for printing the results on the Serial monitor
 
  Wire.begin(); // Initiate the Wire library
  // Set ADXL345 in measuring mode
  Wire.beginTransmission(ADXL345); // Start communicating with the device
  Wire.write(0x2D); // Access/ talk to POWER_CTL Register - 0x2D
  // Enable measurement
  Wire.write(8); // Bit D3 High for measuring enable (8dec -> 0000 1000 binary)
  Wire.endTransmission();
  delay(10);

  //Off-set Calibration
  //X-axis
  Wire.beginTransmission(ADXL345);
  Wire.write(0x1E);
  Wire.write(1);
  Wire.endTransmission();
  delay(10);
  //Y-axis
  Wire.beginTransmission(ADXL345);
  Wire.write(0x1F);
  Wire.write(-2);
  Wire.endTransmission();
  delay(10);

  //Z-axis
  Wire.beginTransmission(ADXL345);
  Wire.write(0x20);
  Wire.write(-9);
  Wire.endTransmission();
  delay(10);
}

void loop() {
  // === Read acceleromter data === //
  Wire.beginTransmission(ADXL345);
  Wire.write(0x32); // Start with register 0x32 (ACCEL_XOUT_H)
  Wire.endTransmission(false);
  Wire.requestFrom(ADXL345, 6, true); // Read 6 registers total, each axis value is stored in 2 registers
  X_out = ( Wire.read() | Wire.read() << 8); // X-axis value
  X_out = X_out / 256; //For a range of +-2g, we need to divide the raw values by 256, according to the datasheet
  Y_out = ( Wire.read() | Wire.read() << 8); // Y-axis value
  Y_out = Y_out / 256;
  Z_out = ( Wire.read() | Wire.read() << 8); // Z-axis value
  Z_out = Z_out / 256;

  // Calculate Roll and Pitch (rotation around X-axis, rotation around Y-axis)
  roll = atan(Y_out / sqrt(pow(X_out, 2) + pow(Z_out, 2))) * 180 / PI;
  pitch = atan(-1 * X_out / sqrt(pow(Y_out, 2) + pow(Z_out, 2))) * 180 / PI;

  // Low-pass filter
  rollF = 0.94 * rollF + 0.06 * roll;
  pitchF = 0.94 * pitchF + 0.06 * pitch;

  Serial.print(rollF);
  Serial.print("/");
  Serial.println(pitchF);
}Code language: Arduino (arduino)

Ahora, en el entorno de desarrollo de procesamiento, necesitamos recibir estos valores y usarlos para rotar el objeto 3D que crearemos. Aquí está el código de procesamiento completo:

/*
    Arduino and ADXL345 Accelerometer - 3D Visualization Example 
     by Dejan, https://howtomechatronics.com
*/

import processing.serial.*;
import java.awt.event.KeyEvent;
import java.io.IOException;

Serial myPort;

String data="";
float roll, pitch;

void setup() {
  size (960, 640, P3D);
  myPort = new Serial(this, "COM8", 9600); // starts the serial communication
  myPort.bufferUntil('\n');
}

void draw() {
  translate(width/2, height/2, 0);
  background(33);
  textSize(22);
  text("Roll: " + int(roll) + "     Pitch: " + int(pitch), -100, 265);

  // Rotate the object
  rotateX(radians(roll));
  rotateZ(radians(-pitch));
  
  // 3D 0bject
  textSize(30);  
  fill(0, 76, 153);
  box (386, 40, 200); // Draw box
  textSize(25);
  fill(255, 255, 255);
  text("www.HowToMechatronics.com", -183, 10, 101);

  //delay(10);
  //println("ypr:\t" + angleX + "\t" + angleY); // Print the values to check whether we are getting proper values
}

// Read data from the Serial Port
void serialEvent (Serial myPort) { 
  // reads the data from the Serial Port up to the character '.' and puts it into the String variable "data".
  data = myPort.readStringUntil('\n');

  // if you got any bytes other than the linefeed:
  if (data != null) {
    data = trim(data);
    // split the string at "/"
    String items[] = split(data, '/');
    if (items.length > 1) {

      //--- Roll,Pitch in degrees
      roll = float(items[0]);
      pitch = float(items[1]);
    }
  }
}Code language: Arduino (arduino)

Descripción: Entonces, aquí, debemos incluir la biblioteca en serie, definir el puerto en serie y la velocidad en baudios que debe coincidir con la velocidad en baudios del boceto Arduino cargado. Luego leemos los datos entrantes y los colocamos en las variables de balanceo y cabeceo apropiadas. En el ciclo de dibujo principal, usamos estos valores para rotar el objeto 3D, y en este caso es un cuadro simple con un color particular y un texto en él.

Si ejecutamos el boceto, aparecerá el objeto 3D y seguirá la orientación del sensor del acelerómetro. Podemos notar aquí que el objeto en realidad está un poco inestable y eso se debe a que el acelerómetro captura no solo la fuerza gravitatoria, sino también pequeñas fuerzas generadas por los movimientos de nuestra mano. Para obtener un resultado más suave, podemos usar un filtro de paso bajo simple. Aquí implementé un filtro de este tipo en el código Arduino, que toma el 94 % del estado anterior y agrega el 6 % del estado o ángulo actual.

// Low-pass filter
  rollF = 0.94 * rollF + 0.06 * roll;
  pitchF = 0.94 * pitchF + 0.06 * pitch;Code language: Arduino (arduino)

Con este filtro, podemos notar que el objeto se mueve mucho más suave ahora, pero también hay un efecto secundario y es una respuesta más lenta. También podemos notar que nos falta el Yaw, o la rotación alrededor del eje Z. Usando solo los datos del acelerómetro de 3 ejes, no podemos calcular la Yaw.

Para hacer eso y mejorar el rendimiento general de nuestro sensor de seguimiento de orientación, necesitamos incluir un sensor adicional, un giroscopio, y fusionar sus datos con el acelerómetro.

Entonces, podemos usar el acelerómetro ADXL345 en combinación con un sensor de giroscopio, o usar la IMU MPU6050 que tiene un acelerómetro de 3 ejes y un giroscopio de 3 ejes integrados en un solo chip. Puede encontrar un tutorial más detallado sobre este sensor en mi próximo video.

Espero que hayas disfrutado este tutorial y hayas aprendido algo nuevo. Siéntase libre de hacer cualquier pregunta en la sección de comentarios a continuación y no olvide consultar mi colección de proyectos Arduino.


Proceso de manufactura

  1. Control del servomotor con Arduino y MPU6050
  2. Módulo GPS u-blox LEA-6H 02 con Arduino y Python
  3. Cómo leer la temperatura y la humedad en Blynk con DHT11
  4. Reconocimiento y síntesis de voz con Arduino
  5. Cómo hacer música con un Arduino
  6. Cómo utilizar NMEA-0183 con Arduino
  7. Cómo utilizar Modbus con Arduino
  8. Máquina de café inteligente con Arduino y Bluetooth
  9. Luz inteligente animada con Alexa y Arduino
  10. Reconocimiento de voz con Arduino y BitVoicer Server
  11. Robot asistente de IA con Arduino y Python