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

Explorando Sensores MEMS: Acelerómetros, Giroscopios y Magnetómetros para Proyectos Arduino

En este tutorial aprenderemos cómo funcionan el acelerómetro MEMS, el giroscopio y el magnetómetro y cómo usarlos con la placa Arduino. También con el IDE Processing haremos algunas aplicaciones prácticas usando los sensores. Puedes ver el siguiente video o leer el tutorial escrito a continuación.

¿Qué es MEMS?

Los MEMS son sistemas o dispositivos muy pequeños, compuestos por microcomponentes que van desde 0.001 mm a 0.1 mm de tamaño. Estos componentes están hechos de silicio, polímeros, metales y/o cerámicas, y generalmente se combinan con una CPU (microcontrolador) para completar el sistema.

Ahora explicaremos brevemente cómo funciona cada uno de estos sensores de Micro-Sistemas Electro-Mecánicos (MEMS).

Acelerómetro MEMS

Mide la aceleración midiendo el cambio en la capacitancia. Su microestructura se ve algo así. Tiene una masa unida a un resorte que está confinada a moverse en una dirección y placas externas fijas. Así que cuando se aplica una aceleración en la dirección particular, la masa se moverá y la capacitancia entre las placas y la masa cambiará. Este cambio en la capacitancia será medido, procesado y corresponderá a un valor de aceleración particular.

Explorando Sensores MEMS: Acelerómetros, Giroscopios y Magnetómetros para Proyectos Arduino

Giroscopio MEMS

El giroscopio mide la velocidad angular usando el Efecto Coriolis. Cuando una masa se mueve en una dirección particular con una velocidad particular y cuando se aplica una velocidad angular externa como se muestra con la flecha verde, ocurrirá una fuerza, como se muestra con la flecha azul-roja, que causará un desplazamiento perpendicular de la masa. Así que, similar al acelerómetro, este desplazamiento causará un cambio en la capacitancia que será medido, procesado y corresponderá a una velocidad angular particular.

Explorando Sensores MEMS: Acelerómetros, Giroscopios y Magnetómetros para Proyectos Arduino

La microestructura del giroscopio se ve algo así. Una masa que se mueve constantemente, u oscila, y cuando se aplica la velocidad angular externa, una parte flexible de la masa se moverá y hará el desplazamiento perpendicular.

Explorando Sensores MEMS: Acelerómetros, Giroscopios y Magnetómetros para Proyectos Arduino

Magnetómetro MEMS

Mide el campo magnético terrestre usando el Efecto Hall o el Efecto Magnetorresistivo. De hecho, casi el 90% de los sensores en el mercado usan el Efecto Hall y aquí está cómo funciona.

Explorando Sensores MEMS: Acelerómetros, Giroscopios y Magnetómetros para Proyectos Arduino

Si tenemos una placa conductora como se muestra en la foto y hacemos fluir corriente a través de ella, los electrones fluirían en línea recta de un lado al otro de la placa. Ahora, si acercamos un campo magnético cerca de la placa, perturbaríamos el flujo recto y los electrones se desviarían hacia un lado de la placa y los polos positivos hacia el otro lado. Eso significa que si ponemos un medidor ahora entre estos dos lados obtendremos algún voltaje que depende de la fuerza del campo magnético y su dirección.

Explorando Sensores MEMS: Acelerómetros, Giroscopios y Magnetómetros para Proyectos Arduino

El otro 10% de los sensores en el mercado usan el Efecto Magnetorresistivo. Estos sensores usan materiales que son sensibles al campo magnético, generalmente compuestos de Hierro (Fe) y Níquel (Ni). Así que cuando estos materiales están expuestos a un campo magnético, cambian su resistencia.

Arduino y Sensores MEMS


Bien, ahora conectemos estos sensores a la placa Arduino y hagamos uso de ellos. Como ejemplo usaré la placa breakout GY-80 que tiene los siguientes sensores: Acelerómetro de 3 ejes ADXL345, Giroscopio de 3 ejes L3G4200D, Magnetómetro de 3 ejes MC5883L y también un Barómetro y un Termómetro que no usaremos en este tutorial.

Puedes conseguir estos componentes en cualquiera de los siguientes sitios:

  • Acelerómetro ADXL345 de 3 ejes………………………………………………………
  • 2 en 1: MPU6050 Giroscopio y Acelerómetro de 6 ejes …………………
  • 3 en 1: GY-80 Campo Magnético Aceleración Giroscopio de 9 ejes……… Amazon
  • 3 en 1: GY-86 10DOF MS5611 HMC5883L MPU6050 Módulo……… Banggood / AliExpress
Explorando Sensores MEMS: Acelerómetros, Giroscopios y Magnetómetros para Proyectos Arduino

Esta placa usa el protocolo de comunicación I2C, lo que significa que podemos usar todos los sensores con solo dos cables. Para hacer la comunicación entre el Arduino y los sensores necesitamos conocer sus direcciones de dispositivo únicas y sus direcciones de registros internos para obtener los datos de ellos. Estas direcciones se pueden encontrar en las hojas de datos de los sensores:

  • Hoja de datos del Acelerómetro ADXL345
  • Hoja de datos del Giroscopio L3G4200D
  • Hoja de datos del Magnetómetro MC5883L

Para más detalles sobre cómo funciona la comunicación I2C, puedes consultar mi otro Tutorial del Protocolo de Comunicación I2C.

Código Fuente

Ahora veamos los códigos para obtener los datos de los sensores. Empezaremos con el acelerómetro y habrá alguna explicación antes de cada código, así como alguna descripción adicional en los comentarios del código.

Código Arduino para Acelerómetro

Primero necesitamos incluir la librería Wire de Arduino y definir las direcciones de los registros del sensor. En la sección setup necesitamos iniciar la librería Wire e iniciar la comunicación serial ya que usaremos el monitor serial para mostrar los resultados. También aquí necesitamos activar el sensor, o habilitar la medición enviando el byte apropiado al registro Power_CTL y aquí está cómo lo hacemos. Usando la función Wire.beginTransmission() seleccionamos a qué sensor hablaremos, el Acelerómetro de 3 ejes en este caso. Luego usando la función Wire.write() le decimos a qué registro interno hablaremos. Después de esto enviaremos el byte apropiado para habilitar la medición. Usando la función Wire.endTransmission() terminaremos la transmisión y eso transmitirá los datos a los registros.

En la sección loop necesitamos leer los datos para cada eje. Empezaremos con el eje X. Así que primero seleccionaremos a qué registros hablaremos, los dos registros internos del eje X en este caso. Luego usando la función Wire.requestFrom() solicitaremos los datos transmitidos o los dos bytes de los dos registros. La función Wire.available() devolverá el número de bytes disponibles para recuperación y si ese número coincide con nuestros bytes solicitados, en nuestro caso 2 bytes, usando la función Wire.read() leeremos los bytes de los dos registros del eje X.

Los datos de salida de los registros son complemento a dos, con X0 como el byte menos significativo y X1 como el byte más significativo, así que necesitamos convertir estos bytes en valores float de -1 a +1 dependiendo de la dirección del eje X relativa a la aceleración terrestre o la gravedad. Repetiremos este procedimiento para los otros dos ejes y al final imprimiremos estos valores en el monitor serial.

#include <Wire.h>
//--- Direcciones de Registros del Acelerómetro
#define Power_Register 0x2D
#define X_Axis_Register_DATAX0 0x32 // Dirección hexadecimal para el registro interno DATAX0.
#define X_Axis_Register_DATAX1 0x33 // Dirección hexadecimal para el registro interno DATAX1.
#define Y_Axis_Register_DATAY0 0x34
#define Y_Axis_Register_DATAY1 0x35
#define Z_Axis_Register_DATAZ0 0x36
#define Z_Axis_Register_DATAZ1 0x37
int ADXAddress = 0x53; //Dirección del dispositivo en la que también está incluido el bit 8 para seleccionar el modo, lectura en este caso.
int X0,X1,X_out;
int Y0,Y1,Y_out;
int Z1,Z0,Z_out;
float Xa,Ya,Za;
void setup() {
  Wire.begin(); // Inicia la librería Wire
  Serial.begin(9600);
  delay(100);
  Wire.beginTransmission(ADXAddress);
  Wire.write(Power_Register); // Registro Power_CTL
  // Habilitar medición
  Wire.write(8); // Bit D3 Alto para habilitar medición (0000 1000)
  Wire.endTransmission();
}
void loop() {
  // Eje X
  Wire.beginTransmission(ADXAddress); // Iniciar transmisión al Sensor
  //Pedir los registros particulares para datos
  Wire.write(X_Axis_Register_DATAX0);
  Wire.write(X_Axis_Register_DATAX1);
  Wire.endTransmission(); // Termina la transmisión y transmite los datos de los dos registros
  Wire.requestFrom(ADXAddress,2); // Solicita los dos bytes transmitidos de los dos registros
  if(Wire.available()<=2) {
    // X0 = Wire.read(); // Lee los datos del registro
    X1 = Wire.read();
    /* Convertir los datos crudos del Eje X en Aceleración del Eje X - Los datos de salida son complemento a dos - X0 como byte menos significativo - X1 como byte más significativo */
    X1=X1<<8;
    X_out =X0+X1;
    Xa=X_out/256.0; // Xa = valor de salida de -1 a +1, aceleración de gravedad actuando en el Eje X
  }
  // Eje Y
  Wire.beginTransmission(ADXAddress);
  Wire.write(Y_Axis_Register_DATAY0);
  Wire.write(Y_Axis_Register_DATAY1);
  Wire.endTransmission();
  Wire.requestFrom(ADXAddress,2);
  if(Wire.available()<=2) {
    Y0 = Wire.read();
    Y1 = Wire.read();
    Y1=Y1<<8;
    Y_out =Y0+Y1;
    Ya=Y_out/256.0;
  }
  // Eje Z
  Wire.beginTransmission(ADXAddress);
  Wire.write(Z_Axis_Register_DATAZ0);
  Wire.write(Z_Axis_Register_DATAZ1);
  Wire.endTransmission();
  Wire.requestFrom(ADXAddress,2);
  if(Wire.available()<=2) {
    Z0 = Wire.read();
    Z1 = Wire.read();
    Z1=Z1<<8;
    Z_out =Z0+Z1;
    Za=Z_out/256.0;
  }
  // Imprime los datos en el Monitor Serial
  Serial.print("Xa= ");
  Serial.print(Xa);
  Serial.print(" Ya= ");
  Serial.print(Ya);
  Serial.print(" Za= ");
  Serial.println(Za);
} Lenguaje: Arduino (arduino)

Código Arduino para Giroscopio

Para obtener los datos del giroscopio tendremos un código similar al anterior. Así que primero tenemos que definir las direcciones de los registros y algunas variables para los datos. En la sección setup tenemos que despertar y poner el sensor en modo normal usando el CTRL_REG1 y también seleccionar la sensibilidad del sensor. Para este ejemplo seleccionaré el modo de sensibilidad de 2000dps.

En la sección loop, similar al acelerómetro, leeremos los datos para los ejes X, Y y Z. Luego los datos crudos tienen que convertirse en valores de ángulo. Desde la hoja de datos del sensor podemos ver que para el modo de sensibilidad de 2000dps corresponde una unidad de 70 mdps/dígito. Esto significa que tenemos que multiplicar los datos de salida crudos por 0.07 para obtener la velocidad angular en grados por segundo. Luego, si multiplicamos la velocidad angular por el tiempo, nos dará el valor del ángulo. Así que necesitamos calcular el intervalo de tiempo de cada sección del loop y podemos hacerlo usando la función millis() al principio y al final de la sección loop, y almacenaremos su valor en esta variable "dt". Así que para cada loop ejecutado calcularemos el ángulo y lo sumaremos al valor final del ángulo. Haremos lo mismo para los otros dos ejes y al final imprimiremos los resultados en el monitor serial.

#include <Wire.h>
//--- Direcciones de Registros del Giroscopio
#define Gyro_gX0 0x28
#define Gyro_gX1 0x29
#define Gyro_gY0 0x2A
#define Gyro_gY1 0x2B
#define Gyro_gZ0 0x2C
#define Gyro_gZ1 0x2D
int Gyro = 0x69; //Dirección del dispositivo en la que también está incluido el bit 8 para seleccionar el modo, lectura en este caso.
int gX0, gX1, gX_out;
int gY0, gY1, gY_out;
int gZ0, gZ1, gZ_out;
float Xg,Yg,Zg;
float angleX,angleY,angleZ,angleXc,angleYc,angleZc;
unsigned long start, finished, elapsed;
float dt=0.015;
void setup() {
  Wire.begin();
  Serial.begin(9600);
  delay(100);
  Wire.beginTransmission(Gyro);
  Wire.write(0x20); // CTRL_REG1 - Modo de Energía
  Wire.write(15); // Modo normal: 15d - 00001111b
  Wire.endTransmission();
  Wire.beginTransmission(Gyro);
  Wire.write(0x23); // CTRL_REG4 - Sensibilidad, Selección de Escala
  Wire.write(48); // 2000dps: 48d - 00110000b
  Wire.endTransmission();
}
void loop() {
  start=millis();
  //---- Eje X
  Wire.beginTransmission(Gyro); // transmitir al dispositivo
  Wire.write(Gyro_gX0);
  Wire.endTransmission();
  Wire.requestFrom(Gyro,1);
  if(Wire.available()<=1) {
    gX0 = Wire.read();
  }
  Wire.beginTransmission(Gyro); // transmitir al dispositivo
  Wire.write(Gyro_gX1);
  Wire.endTransmission();
  Wire.requestFrom(Gyro,1);
  if(Wire.available()<=1) {
    gX1 = Wire.read();
  }
  //---- Eje Y
  Wire.beginTransmission(Gyro); // transmitir al dispositivo
  Wire.write(Gyro_gY0);
  Wire.endTransmission();
  Wire.requestFrom(Gyro,1);
  if(Wire.available()<=1) {
    gY0 = Wire.read();
  }
  Wire.beginTransmission(Gyro); // transmitir al dispositivo
  Wire.write(Gyro_gY1);
  Wire.endTransmission();
  Wire.requestFrom(Gyro,1);
  if(Wire.available()<=1) {
    gY1 = Wire.read();
  }
  //---- Eje Z
  Wire.beginTransmission(Gyro); // transmitir al dispositivo
  Wire.write(Gyro_gZ0);
  Wire.endTransmission();
  Wire.requestFrom(Gyro,1);
  if(Wire.available()<=1) {
    gZ0 = Wire.read();
  }
  Wire.beginTransmission(Gyro); // transmitir al dispositivo
  Wire.write(Gyro_gZ1);
  Wire.endTransmission();
  Wire.requestFrom(Gyro,1);
  if(Wire.available()<=1) {
    gZ1 = Wire.read();
  }
  //---------- Eje X
  // Datos Crudos
  gX1=gX1<<8;
  gX_out =gX0+gX1;
  // De la hoja de datos: 70 mdps/dígito
  Xg=gX_out*0.07; // Velocidad angular
  // Velocidad_angular * dt = ángulo
  angleXc = Xg*dt;
  angleX = angleX + angleXc;
  //---------- Eje Y
  gY1=gY1<<8;
  gY_out =gY0+gY1;
  Yg=gY_out*0.07;
  angleYc = Yg*dt;
  angleY = angleY + angleYc;
  //---------- Eje Z
  gZ1=gZ1<<8;
  gZ_out =gZ0+gZ1;
  Zg=gZ_out*0.07;
  angleZc = Zg*dt;
  angleZ = angleZ + angleZc;
  // Imprime los datos en el Monitor Serial
  Serial.print("angleX= ");
  Serial.print(angleX);
  Serial.print(" angleY= ");
  Serial.print(angleY);
  Serial.print(" angleZ= ");
  Serial.println(angleZ);
  delay(10);
  // Calculando dt
  finished=millis();
  elapsed=finished-start;
  dt=elapsed/1000.0;
  start = elapsed = 0;
}Lenguaje: Arduino (arduino)

Código Arduino para Magnetómetro

De nuevo usaremos una técnica similar a la anterior. Primero necesitamos definir las direcciones de los registros y en la sección setup poner el sensor en modo de medición continua. En la sección loop obtendremos los datos crudos para cada eje con el mismo método que para los sensores anteriores.

Luego necesitamos convertir los datos crudos en valor de campo magnético o unidades Gauss. Desde la hoja de datos del sensor podemos ver que el modo de sensibilidad por defecto es 0.92mG/dígito. Eso significa que necesitamos multiplicar los datos crudos por 0.00092 para obtener el campo magnético terrestre en unidades Gauss. Al final imprimiremos los valores en el monitor serial.

#include <Wire.h> //Librería I2C de Arduino
#define Magnetometer_mX0 0x03
#define Magnetometer_mX1 0x04
#define Magnetometer_mZ0 0x05
#define Magnetometer_mZ1 0x06
#define Magnetometer_mY0 0x07
#define Magnetometer_mY1 0x08
int mX0, mX1, mX_out;
int mY0, mY1, mY_out;
int mZ0, mZ1, mZ_out;
float Xm,Ym,Zm;
#define Magnetometer 0x1E //Dirección I2C de 7 bits del HMC5883
void setup(){
  //Inicializar comunicaciones Serial e I2C
  Serial.begin(9600);
  Wire.begin();
  delay(100);
  Wire.beginTransmission(Magnetometer);
  Wire.write(0x02); // Seleccionar registro de modo
  Wire.write(0x00); // Modo de medición continua
  Wire.endTransmission();
}
void loop(){
  //---- Eje X
  Wire.beginTransmission(Magnetometer); // transmitir al dispositivo
  Wire.write(Magnetometer_mX1);
  Wire.endTransmission();
  Wire.requestFrom(Magnetometer,1);
  if(Wire.available()<=1) {
    mX0 = Wire.read();
  }
  Wire.beginTransmission(Magnetometer); // transmitir al dispositivo
  Wire.write(Magnetometer_mX0);
  Wire.endTransmission();
  Wire.requestFrom(Magnetometer,1);
  if(Wire.available()<=1) {
    mX1 = Wire.read();
  }
  //---- Eje Y
  Wire.beginTransmission(Magnetometer); // transmitir al dispositivo
  Wire.write(Magnetometer_mY1);
  Wire.endTransmission();
  Wire.requestFrom(Magnetometer,1);
  if(Wire.available()<=1) {
    mY0 = Wire.read();
  }
  Wire.beginTransmission(Magnetometer); // transmitir al dispositivo
  Wire.write(Magnetometer_mY0);
  Wire.endTransmission();
  Wire.requestFrom(Magnetometer,1);
  if(Wire.available()<=1) {
    mY1 = Wire.read();
  }
  //---- Eje Z
  Wire.beginTransmission(Magnetometer); // transmitir al dispositivo
  Wire.write(Magnetometer_mZ1);
  Wire.endTransmission();
  Wire.requestFrom(Magnetometer,1);
  if(Wire.available()<=1) {
    mZ0 = Wire.read();
  }
  Wire.beginTransmission(Magnetometer); // transmitir al dispositivo
  Wire.write(Magnetometer_mZ0);
  Wire.endTransmission();
  Wire.requestFrom(Magnetometer,1);
  if(Wire.available()<=1) {
    mZ1 = Wire.read();
  }
  //---- Eje X
  mX1=mX1<<8;
  mX_out =mX0+mX1;
  // Datos crudos
  // De la hoja de datos: 0.92 mG/dígito
  Xm = mX_out*0.00092; // Unidad Gauss
  //* El campo magnético terrestre varía de 0.25 a 0.65 Gauss, así que estos son los valores que necesitamos obtener aproximadamente.
  //---- Eje Y
  mY1=mY1<<8;
  mY_out =mY0+mY1;
  Ym = mY_out*0.00092;
  //---- Eje Z
  mZ1=mZ1<<8;
  mZ_out =mZ0+mZ1;
  Zm = mZ_out*0.00092;
  //Imprime valores de cada eje
  Serial.print("x: ");
  Serial.print(Xm);
  Serial.print(" y: ");
  Serial.print(Ym);
  Serial.print(" z: ");
  Serial.println(Zm);
  delay(50);
}Lenguaje: Arduino (arduino)

Aquí hay una aplicación genial del sensor, una brújula digital MEMS, hecha usando el IDE Processing. Puedes encontrar más detalles y el código fuente de este ejemplo en el siguiente enlace:

Explorando Sensores MEMS: Acelerómetros, Giroscopios y Magnetómetros para Proyectos Arduino

Proceso de manufactura

  1. Construye un Juego Giroscópico en Tiempo Real con Arduino Nano y Sensor MPU-6050
  2. Pantalla LED Interactiva con Giroscopio, Anillo NeoPixel y Arduino
  3. Sensor K30 CO₂: Monitorización en tiempo real de la calidad del aire interior
  4. Facilitar la comunicación sordo‑ciego usando 1Sheeld y Arduino
  5. Alcancía Inteligente: Controla un Aceptador de Monedas con Arduino Nano
  6. Controla un LED por Bluetooth con Arduino – Guía DIY paso a paso
  7. Integración del sensor de huella capacitivo DFRobot (ID809) con Arduino o ESP8266
  8. Proyecto HMI Interactivo con Nextion, Arduino Mega y Múltiples Sensores
  9. Brazo Robótico de 6 Grados de Libertad Controlado por Nunchuk con Arduino
  10. ¿Qué es un Magnetómetro? Fundamentos, Principios y Aplicaciones Reales
  11. Aprovechar los datos en el Internet de la Fiabilidad: estrategias para una gestión efectiva