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

¿Qué es MEMS? Acelerómetro, giroscopio y magnetómetro con Arduino

En este tutorial, aprenderemos cómo funcionan el acelerómetro, el giroscopio y el magnetómetro MEMS y cómo usarlos con la placa Arduino. También con el IDE de Processing haremos algunas aplicaciones prácticas usando los sensores. Puede 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ámica, 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-Electro-Mechanical-Systems (MEMS).

Acelerómetro MEMS

Mide la aceleración midiendo el cambio en la capacitancia. Su micro estructura se parece a esto. Tiene una masa unida a un resorte que está confinado para moverse a lo largo de una dirección y placas exteriores fijas. Entonces, cuando se aplique 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 se medirá, procesará y corresponderá a un valor de aceleración particular.

Giroscopio MEMS

El giroscopio mide la velocidad angular utilizando el efecto Coriolis. Cuando una masa se mueve en una dirección particular con una velocidad particular y cuando se aplica una tasa angular externa como se muestra con la flecha verde, se producirá una fuerza, como se muestra con la flecha roja azul, que provocará un desplazamiento perpendicular de la masa. Tan similar al acelerómetro, este desplazamiento provocará un cambio en la capacitancia que se medirá, procesará y corresponderá a una tasa angular particular.

La microestructura del giroscopio se parece a esto. Una masa que está en constante movimiento u oscilación, y cuando se aplica la tasa angular externa, una parte flexible de la masa se movería y haría el desplazamiento perpendicular.

Magnetómetro MEMS

Mide el campo magnético terrestre utilizando efecto Hall o efecto magnetorresistivo. En realidad, casi el 90 % de los sensores del mercado utilizan el efecto Hall y así es como funciona.

Si tenemos una placa conductora como la que se muestra en la foto y establecemos que la corriente fluya a través de ella, los electrones fluirán directamente de un lado al otro de la placa. Ahora bien, si traemos un campo magnético cerca de la placa, perturbaremos el flujo directo y los electrones se desviarán hacia un lado de la placa y los polos positivos hacia el otro lado de la placa. Eso significa que si colocamos un medidor ahora entre estos dos lados, obtendremos un voltaje que depende de la fuerza del campo magnético y su dirección.


El otro 10% de los sensores del mercado utilizan el Efecto Magnetorresistivo. Estos sensores utilizan materiales sensibles al campo magnético, generalmente compuestos de hierro (Fe) y níquel (Ne). Entonces, cuando estos materiales se exponen a un campo magnético, cambian su resistencia.

Sensores Arduino y MEMs


Bien, ahora conectemos estos sensores a la placa Arduino y hagamos algún uso de ellos. Como ejemplo, usaré la placa de conexión 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.

Puede obtener estos componentes en cualquiera de los siguientes sitios:

  • Acelerador de 3 ejes ADXL345 …………………………………………………………
  • 2 en 1:MPU6050 giroscopio y acelerómetro de 6 ejes …………………
  • 3 en 1:giroscopio de aceleración de campo magnético de 9 ejes GY-80………… Amazon 
  • 3 en 1: GY-86 10DOF MS5611 HMC5883L MPU6050 Módulo………… Banggood  /AliExpress

Esta placa usa el protocolo de comunicación I2C, lo que significa que podemos usar todos los sensores con solo dos cables. Entonces, para establecer la comunicación entre Arduino y los sensores, necesitamos conocer las direcciones únicas de sus dispositivos y sus direcciones de registro interno 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        
  • L3G4200D  Giroscopio              Hoja de datos
  • Hoja de datos del magnetómetro MC5883L        

Para obtener más detalles sobre cómo funciona la comunicación I2C, puede consultar mi otro tutorial sobre el protocolo de comunicación I2C.

Código fuente

Ahora veamos los códigos para obtener los datos de los sensores. Comenzaremos 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 del acelerómetro de Arduino

Primero debemos incluir la biblioteca de cables de Arduino y definir las direcciones de registro del sensor. En la sección de configuración, debemos iniciar la biblioteca de cables e iniciar la comunicación en serie, ya que usaremos el monitor en serie 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 así es como lo hacemos. Usando la función Wire.beginTransmission() seleccionamos con 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. Luego 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 de bucle necesitamos leer los datos de cada eje. Comenzaremos con el eje X. Entonces, 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. El Cable.disponible() la función devolverá el número de bytes disponibles para la recuperación y si ese número coincide con nuestros bytes solicitados, en nuestro caso 2 bytes, usando Wire.read() función vamos a leer 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, por lo que debemos convertir estos bytes en valores flotantes de -1 a +1 según la dirección del eje X relativo. a la aceleración de la Tierra oa la gravedad. Repetiremos este procedimiento para los otros dos ejes y al final imprimiremos estos valores en el monitor serie.

#include <Wire.h>

//--- Accelerometer Register Addresses
#define Power_Register 0x2D
#define X_Axis_Register_DATAX0 0x32 // Hexadecima address for the DATAX0 internal register.
#define X_Axis_Register_DATAX1 0x33 // Hexadecima address for the DATAX1 internal register.
#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;  //Device address in which is also included the 8th bit for selecting the mode, read in this case.

int X0,X1,X_out;
int Y0,Y1,Y_out;
int Z1,Z0,Z_out;
float Xa,Ya,Za;

void setup() {
  Wire.begin(); // Initiate the Wire library    
  Serial.begin(9600);    
  delay(100);
  
  Wire.beginTransmission(ADXAddress);
  Wire.write(Power_Register); // Power_CTL Register
  // Enable measurement
  Wire.write(8); // Bit D3 High for measuring enable (0000 1000)
  Wire.endTransmission();
}

void loop() {
  // X-axis
  Wire.beginTransmission(ADXAddress); // Begin transmission to the Sensor 
  //Ask the particular registers for data
  Wire.write(X_Axis_Register_DATAX0);
  Wire.write(X_Axis_Register_DATAX1);  
  Wire.endTransmission(); // Ends the transmission and transmits the data from the two registers
  Wire.requestFrom(ADXAddress,2); // Request the transmitted two bytes from the two registers
  if(Wire.available()<=2) {  // 
    X0 = Wire.read(); // Reads the data from the register
    X1 = Wire.read();
    /* Converting the raw data of the X-Axis into X-Axis Acceleration
     - The output data is Two's complement 
     - X0 as the least significant byte
     - X1 as the most significant byte */ 
    X1=X1<<8;
    X_out =X0+X1;
    Xa=X_out/256.0; // Xa = output value from -1 to +1, Gravity acceleration acting on the X-Axis
  }
  // Y-Axis
  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;
  }
  // Z-Axis
  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;
  }
  // Prints the data on the Serial Monitor
  Serial.print("Xa= ");
  Serial.print(Xa);
  Serial.print("   Ya= ");
  Serial.print(Ya);
  Serial.print("   Za= ");
  Serial.println(Za);
}
Code language: Arduino (arduino)

Código de giroscopio de Arduino

Para obtener los datos del giroscopio tendremos un código similar al anterior. Entonces, primero tenemos que definir las direcciones de registro y algunas variables para los datos. En la sección de configuración 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 2000 dps.

En la sección de bucle similar al acelerómetro, leeremos los datos para los ejes X, Y y Z. Luego, los datos sin procesar deben convertirse en valores de ángulo. De la hoja de datos del sensor podemos ver que para el modo de sensibilidad de 2000 dps corresponde una unidad de 70 mdps/dígito. Esto significa que tenemos que multiplicar los datos de salida sin procesar 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. Entonces, necesitamos calcular el intervalo de tiempo de cada sección del ciclo y podemos hacerlo usando la función millis() en la parte superior e inferior de la sección del ciclo, y almacenaremos su valor en esta variable "dt". Entonces, para cada bucle ejecutado, calcularemos el ángulo y lo agregaremos al valor del ángulo final. Haremos lo mismo con los otros dos ejes y al final imprimiremos los resultados en el monitor serie.

#include <Wire.h>

//--- Gyro Register Addresses
#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; //Device address in which is also included the 8th bit for selecting the mode, read in this case.

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 - Power Mode
  Wire.write(15);   // Normal mode: 15d - 00001111b   
  Wire.endTransmission();
  
  Wire.beginTransmission(Gyro);
  Wire.write(0x23); // CTRL_REG4 - Sensitivity, Scale Selection
  Wire.write(48);   // 2000dps: 48d - 00110000b
  Wire.endTransmission();
}

void loop()
{
  start=millis();
  //---- X-Axis
  Wire.beginTransmission(Gyro); // transmit to device
  Wire.write(Gyro_gX0);
  Wire.endTransmission();
  Wire.requestFrom(Gyro,1); 
  if(Wire.available()<=1)   
  {
    gX0 = Wire.read();
  }
  Wire.beginTransmission(Gyro); // transmit to device
  Wire.write(Gyro_gX1);
  Wire.endTransmission();
  Wire.requestFrom(Gyro,1); 
  if(Wire.available()<=1)   
  {
    gX1 = Wire.read();
  }

  //---- Y-Axis
  Wire.beginTransmission(Gyro); // transmit to device
  Wire.write(Gyro_gY0);
  Wire.endTransmission();
  Wire.requestFrom(Gyro,1); 
  if(Wire.available()<=1)   
  {
    gY0 = Wire.read();
  }
  Wire.beginTransmission(Gyro); // transmit to device
  Wire.write(Gyro_gY1);
  Wire.endTransmission();
  Wire.requestFrom(Gyro,1); 
  if(Wire.available()<=1)   
  {
    gY1 = Wire.read();
  }
  
  //---- Z-Axis
  Wire.beginTransmission(Gyro); // transmit to device
  Wire.write(Gyro_gZ0);
  Wire.endTransmission();
  Wire.requestFrom(Gyro,1); 
  if(Wire.available()<=1)   
  {
    gZ0 = Wire.read();
  }
  Wire.beginTransmission(Gyro); // transmit to device
  Wire.write(Gyro_gZ1);
  Wire.endTransmission();
  Wire.requestFrom(Gyro,1); 
  if(Wire.available()<=1)   
  {
    gZ1 = Wire.read();
  }
  
  //---------- X - Axis
  
  // Raw Data
  gX1=gX1<<8;
  gX_out =gX0+gX1;
  
  // From the datasheet: 70 mdps/digit
  Xg=gX_out*0.07; // Angular rate
  // Angular_rate * dt = angle
  angleXc = Xg*dt;
  angleX = angleX + angleXc;

  //---------- Y - Axis
  gY1=gY1<<8;
  gY_out =gY0+gY1;
  Yg=gY_out*0.07;
  angleYc = Yg*dt;
  angleY = angleY + angleYc;
  
  //---------- Z - Axis
  gZ1=gZ1<<8;
  gZ_out =gZ0+gZ1;
  Zg=gZ_out*0.07;
  angleZc = Zg*dt;
  angleZ = angleZ + angleZc;

  
  // Prints the data on the Serial Monitor
  Serial.print("angleX= ");
  Serial.print(angleX);
  Serial.print("   angleY= ");
  Serial.print(angleY);
  Serial.print("   angleZ= ");
  Serial.println(angleZ);
  
  delay(10);
  // Calculating dt
  finished=millis();
  elapsed=finished-start;
  dt=elapsed/1000.0;
  start = elapsed = 0;
  
}Code language: Arduino (arduino)

Código de Magnetómetro Arduino

Nuevamente utilizaremos una técnica similar a la anterior. Primero necesitamos definir las direcciones de los registros y en la sección de configuración configurar el sensor en modo de medición continua. En la sección de bucle obtendremos los datos sin procesar para cada eje con el mismo método que para los sensores anteriores.

Luego necesitamos convertir los datos sin procesar en valor de campo magnético o unidades de Gauss. En la hoja de datos del sensor podemos ver que el modo de sensibilidad predeterminado es 0,92 mG/dígito. Eso significa que necesitamos multiplicar los datos sin procesar por 0,00092 para obtener el campo magnético terrestre en unidades Gauss. Al finalizar imprimiremos los valores en el monitor serial.

#include <Wire.h> //I2C Arduino Library

#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 //I2C 7bit address of HMC5883

void setup(){
  //Initialize Serial and I2C communications
  Serial.begin(9600);
  Wire.begin();
  delay(100);
  
  Wire.beginTransmission(Magnetometer); 
  Wire.write(0x02); // Select mode register
  Wire.write(0x00); // Continuous measurement mode
  Wire.endTransmission();
}

void loop(){
 
  //---- X-Axis
  Wire.beginTransmission(Magnetometer); // transmit to device
  Wire.write(Magnetometer_mX1);
  Wire.endTransmission();
  Wire.requestFrom(Magnetometer,1); 
  if(Wire.available()<=1)   
  {
    mX0 = Wire.read();
  }
  Wire.beginTransmission(Magnetometer); // transmit to device
  Wire.write(Magnetometer_mX0);
  Wire.endTransmission();
  Wire.requestFrom(Magnetometer,1); 
  if(Wire.available()<=1)   
  {
    mX1 = Wire.read();
  }

  //---- Y-Axis
  Wire.beginTransmission(Magnetometer); // transmit to device
  Wire.write(Magnetometer_mY1);
  Wire.endTransmission();
  Wire.requestFrom(Magnetometer,1); 
  if(Wire.available()<=1)   
  {
    mY0 = Wire.read();
  }
  Wire.beginTransmission(Magnetometer); // transmit to device
  Wire.write(Magnetometer_mY0);
  Wire.endTransmission();
  Wire.requestFrom(Magnetometer,1); 
  if(Wire.available()<=1)   
  {
    mY1 = Wire.read();
  }
  
  //---- Z-Axis
  Wire.beginTransmission(Magnetometer); // transmit to device
  Wire.write(Magnetometer_mZ1);
  Wire.endTransmission();
  Wire.requestFrom(Magnetometer,1); 
  if(Wire.available()<=1)   
  {
    mZ0 = Wire.read();
  }
  Wire.beginTransmission(Magnetometer); // transmit to device
  Wire.write(Magnetometer_mZ0);
  Wire.endTransmission();
  Wire.requestFrom(Magnetometer,1); 
  if(Wire.available()<=1)   
  {
    mZ1 = Wire.read();
  }
  
  //---- X-Axis
  mX1=mX1<<8;
  mX_out =mX0+mX1; // Raw data
  // From the datasheet: 0.92 mG/digit
  Xm = mX_out*0.00092; // Gauss unit
  //* Earth magnetic field ranges from 0.25 to 0.65 Gauss, so these are the values that we need to get approximately.

  //---- Y-Axis
  mY1=mY1<<8;
  mY_out =mY0+mY1;
  Ym = mY_out*0.00092;

  //---- Z-Axis
  mZ1=mZ1<<8;
  mZ_out =mZ0+mZ1;
  Zm = mZ_out*0.00092;
 
  //Print out values of each axis
  Serial.print("x: ");
  Serial.print(Xm);
  Serial.print("  y: ");
  Serial.print(Ym);
  Serial.print("  z: ");
  Serial.println(Zm);
  
  delay(50);
}Code language: Arduino (arduino)

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


Proceso de manufactura

  1. ¿Qué es un magnetómetro?
  2. ¡¿Qué hago con los datos ?!
  3. Juego de giroscopio Arduino con MPU-6050
  4. Diversión con giroscopio con NeoPixel Ring
  5. Monitoreo de CO2 con sensor K30
  6. Comunicación para personas sordociegas con 1Sheeld / Arduino
  7. Controlar el aceptador de monedas con Arduino
  8. ¡Arduino con Bluetooth para controlar un LED!
  9. Sensor capacitivo de huellas dactilares con Arduino o ESP8266
  10. Jugando con Nextion Display
  11. Brazo robótico controlado por Nunchuk (con Arduino)