Rastreo de orientación con Arduino y acelerómetro ADXL345: Guía paso a paso
En este tutorial aprenderemos a medir ángulo y rastrear orientación usando Arduino y el sensor acelerómetro ADXL345. Puedes ver el vídeo o leer el tutorial escrito para más detalles. Primero explico cómo funciona el sensor y cómo leer sus datos, y luego con el entorno Processing haremos visualización 3D de la orientación del acelerómetro. El ADXL345 es un acelerómetro 3 ejes que mide fuerzas de aceleración estáticas y dinámicas. La fuerza gravitatoria terrestre es ejemplo típico de fuerza estática; fuerzas dinámicas pueden ser vibraciones, movimientos, etc. Unidad de medida: m/s². Pero sensores suelen expresar en "g" (gravedad). 1 g = fuerza gravitatoria terrestre = 9.8 m/s². Si acelerómetro está plano, eje Z hacia arriba (opuesto a gravedad), salida Z = 1g. Ejes X e Y = 0 (gravedad perpendicular, no les afecta). Si volteamos sensor, Z = -1g. Salidas por orientación a gravedad varían de -1g a +1g. Con estos datos y trigonometría, calculamos ángulo de inclinación del sensor. El sensor usa protocolo I2C: 2 hilos comunicación + 2 alimentación. Componentes necesarios: Descripción: Incluimos Con En Empezamos en primer registro, Valores de salida dependen de sensibilidad seleccionada (±2g a ±16g). Default ±2g → dividir por 256 para obtener -1 a +1g. 256 LSB/g = 256 cuentas por g. Según aplicación elegimos sensibilidad. Para rastreo orientación ±2g basta; para detectar aceleraciones altas (movimientos bruscos, golpes) usamos otros rangos via registro DATA_FORMAT bits D1, D0. Al leer datos, los imprimimos en monitor serial para verificar. En mi caso, valores no eran exactos, especialmente Z con error notable de 0.1g. Para solucionar: calibrar usando 3 registros offset. Posicionamos sensor plano, imprimimos valores RAW (sin dividir por 256). Vemos cuánto se desvían salidas. En mi caso Z ~283 (diferencia +27). Dividimos entre 4 → valor para registro offset Z. Subimos código y Z sale exactamente 256 (1g correcto). Calibramos otros ejes mismo método. Nota: calibración no se guarda permanentemente en registros; hay que escribir estos valores en cada encendido del sensor. Tras calibración, calculamos Roll y Pitch (rotación eje X, rotación eje Y) en grados con estas fórmulas: Detalles fórmulas: Application Note Freescale Semiconductor. Hagamos ejemplo visualización 3D. Mismo código enviando Roll y Pitch por puerto serial. Código Arduino completo: En Processing recibimos valores y rotamos objeto 3D. Código Processing completo: Descripción: Incluimos librería serial, definimos puerto y baud rate (debe coincidir con sketch Arduino). Leemos datos entrantes y ponemos en variables roll, pitch. En Al ejecutar, objeto 3D aparece y sigue orientación del acelerómetro. Notamos que objeto tiembla un poco: acelerómetro capta no solo gravedad, sino pequeñas fuerzas de movimiento de mano. Para suavizar: filtro paso bajo (Low-pass filter). Implementé en código Arduino: toma 94% estado anterior + 6% estado actual. Con filtro, movimiento más suave, pero respuesta más lenta. También notamos que falta Yaw (rotación eje Z). Con solo acelerómetro 3 ejes no podemos calcular Yaw. Para mejorar rastreo orientación, necesitamos sensor adicional: giroscopio, y fusionar sus datos con acelerómetro. O usamos ADXL345 + giroscopio aparte, o MPU6050 IMU que integra ambos en un chip. Tutorial detallado MPU6050 en mi próximo vídeo. ¡Espero que hayas disfrutado y aprendido! Preguntas en comentarios y revisa mi Colección Proyectos Arduino.Resumen

Cómo funciona el acelerómetro ADXL345



Cómo leer datos ADXL345 con Arduino

Código Arduino ADXL345
/* Arduino y ADXL345 Acelerómetro por Dejan, https://howtomechatronics.com */
#include <Wire.h> // Wire library - I2C communication
int ADXL345 = 0x53; // Dirección I2C ADXL345
float X_out, Y_out, Z_out; // Salidas
void setup() {
Serial.begin(9600);
Wire.begin(); // Inicia librería Wire
// Poner ADXL345 en modo medición
Wire.beginTransmission(ADXL345);
Wire.write(0x2D); // Acceder registro POWER_CTL - 0x2D
Wire.write(8); // (8dec -> 0000 1000 bin) Bit D3 HIGH para habilitar medición
Wire.endTransmission();
delay(10);
}
void loop() {
// === Leer datos acelerómetro ===
Wire.beginTransmission(ADXL345);
Wire.write(0x32); // Registro inicial 0x32 (ACCEL_XOUT_H)
Wire.endTransmission(false);
Wire.requestFrom(ADXL345, 6, true); // Leer 6 registros (2 por eje)
X_out = (Wire.read() | Wire.read() << 8); // Valor eje X
X_out = X_out / 256; // Rango ±2g: dividir raw por 256 (datasheet)
Y_out = (Wire.read() | Wire.read() << 8); // Valor eje Y
Y_out = Y_out / 256;
Z_out = (Wire.read() | Wire.read() << 8); // Valor eje Z
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);
}Wire.h para I2C. Cada dispositivo I2C tiene dirección única (en datasheet ADXL345). Definimos dirección y variables salidas. En setup(): iniciamos Wire y ponemos acelerómetro en modo medición. En datasheet vemos que hay que poner bit D3 del registro POWER_CTL HIGH.
beginTransmission() iniciamos comunicación, write() indica registro a acceder, otro write() pone bit D3 HIGH escribiendo 8 decimal (bit D3 HIGH).// Set ADXL345 in measuring mode
Wire.beginTransmission(ADXL345);
Wire.write(0x2D); // Access/ talk to POWER_CTL Register - 0x2D
Wire.write(8); // (8dec -> 0000 1000 binary) Bit D3 High for measuring enable
Wire.endTransmission();loop() leemos datos. Cada eje en 2 bytes/registros; direcciones en datasheet.
requestFrom() pide leer 6 registros. Con read() leemos cada registro, combinamos apropiadamente (complemento a dos) para 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
X_out = (Wire.read() | Wire.read() << 8); // X-axis value
X_out = X_out / 256; // For a range of +-2g, divide raw by 256
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;

Calibración acelerómetro ADXL345


// Este código va en la sección SETUP
// Calibración Offset
// Eje X
Wire.beginTransmission(ADXL345);
Wire.write(0x1E); // Registro offset X
Wire.write(1);
Wire.endTransmission();
delay(10);
// Eje Y
Wire.beginTransmission(ADXL345);
Wire.write(0x1F); // Registro offset Y
Wire.write(-2);
Wire.endTransmission();
delay(10);
// Eje Z
Wire.beginTransmission(ADXL345);
Wire.write(0x20); // Registro offset Z
Wire.write(-7);
Wire.endTransmission();
delay(10);// Calcular Roll y Pitch (rotación eje X, rotación eje Y)
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;Arduino y ADXL345 – Rastreo orientación 3D

/* Arduino y ADXL345 Acelerómetro - Visualización 3D por Dejan, https://howtomechatronics.com */
#include <Wire.h>
int ADXL345 = 0x53;
float X_out, Y_out, Z_out;
float roll, pitch, rollF, pitchF = 0;
void setup() {
Serial.begin(9600);
Wire.begin();
// Modo medición
Wire.beginTransmission(ADXL345);
Wire.write(0x2D); // POWER_CTL Register
Wire.write(8); // Bit D3 HIGH
Wire.endTransmission();
delay(10);
// Calibración Offset
// 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() {
// Leer acelerómetro
Wire.beginTransmission(ADXL345);
Wire.write(0x32); // ACCEL_XOUT_H
Wire.endTransmission(false);
Wire.requestFrom(ADXL345, 6, true);
X_out = (Wire.read() | Wire.read() << 8); X_out = X_out / 256;
Y_out = (Wire.read() | Wire.read() << 8); Y_out = Y_out / 256;
Z_out = (Wire.read() | Wire.read() << 8); Z_out = Z_out / 256;
// Calcular Roll y Pitch
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;
// Filtro paso bajo
rollF = 0.94 * rollF + 0.06 * roll;
pitchF = 0.94 * pitchF + 0.06 * pitch;
Serial.print(rollF); Serial.print("/"); Serial.println(pitchF);
}/* Arduino y ADXL345 Acelerómetro - Visualización 3D por 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); // Puerto serial y baud rate = Arduino sketch
myPort.bufferUntil('\n');
}
void draw() {
translate(width/2, height/2, 0);
background(33);
textSize(22);
text("Roll: " + int(roll) + " Pitch: " + int(pitch), -100, 265);
// Rotar objeto
rotateX(radians(roll));
rotateZ(radians(-pitch));
// Objeto 3D
textSize(30);
fill(0, 76, 153);
box(386, 40, 200); // Dibujar caja
textSize(25);
fill(255, 255, 255);
text("www.HowToMechatronics.com", -183, 10, 101);
}
// Leer datos Puerto Serial
void serialEvent(Serial myPort) {
data = myPort.readStringUntil('\n');
if (data != null) {
data = trim(data);
// Separar en "/"
String items[] = split(data, '/');
if (items.length > 1) {
roll = float(items[0]);
pitch = float(items[1]);
}
}
}draw() usamos para rotar objeto 3D (caja con color y texto).// Low-pass filter
rollF = 0.94 * rollF + 0.06 * roll;
pitchF = 0.94 * pitchF + 0.06 * pitch;
Proceso de manufactura
- Control Preciso de Servo con Arduino y MPU6050 (SG90 / MG996R)
- Módulo GPS u-blox LEA‑6H 02: Guía de integración con Arduino y Python
- Leer Temperatura y Humedad con DHT11 en Blynk – Tutorial Paso a Paso con Arduino
- Dominando reconocimiento y síntesis de voz en Arduino Due
- Genera Tonos Musicales con Arduino: Guía Paso a Paso
- Conexión de Arduino a NMEA‑0183: Guía Paso a Paso
- Domina Modbus en Arduino: Guía Paso a Paso
- Cafetera inteligente con Arduino, control por Bluetooth y monitorización de temperatura
- Crea una Tira LED Inteligente Animada Controlada por Alexa con Arduino
- Proyecto LED Controlado por Voz: Arduino Micro + BitVoicer Server para Reconocimiento Voz
- Construye tu Propio Robot Asistente IA con Arduino y Python