Manufaturação industrial
Internet das coisas industrial | Materiais industriais | Manutenção e reparo de equipamentos | Programação industrial |
home  MfgRobots >> Manufaturação industrial >  >> Manufacturing Technology >> Processo de manufatura

O que é MEMS? Acelerômetro, Giroscópio e Magnetômetro com Arduino


Neste tutorial, aprenderemos como o acelerômetro, giroscópio e magnetômetro MEMS funcionam e como usá-los com a placa Arduino. Também com o Processing IDE faremos algumas aplicações práticas usando os sensores. Você pode assistir ao vídeo a seguir ou ler o tutorial escrito abaixo.

O que é MEMS?


Os MEMS são sistemas ou dispositivos muito pequenos, compostos por microcomponentes que variam de 0,001 mm a 0,1 mm de tamanho. Esses componentes são feitos de silício, polímeros, metais e/ou cerâmicas, e geralmente são combinados com uma CPU (Microcontrolador) para completar o sistema.

Agora vamos explicar brevemente como funciona cada um desses sensores Micro-Eletro-Mecânicos (MEMS).

Acelerômetro MEMS


Ele mede a aceleração medindo a mudança na capacitância. Sua micro estrutura se parece com isso. Tem uma massa presa a uma mola que se limita a se mover ao longo de uma direção e placas externas fixas. Portanto, quando uma aceleração na direção específica for aplicada, a massa se moverá e a capacitância entre as placas e a massa mudará. Esta mudança na capacitância será medida, processada e corresponderá a um determinado valor de aceleração.

Giroscópio MEMS


O giroscópio mede a taxa angular usando o Efeito Coriolis. Quando uma massa está se movendo em uma determinada direção com uma determinada velocidade e quando uma taxa angular externa for aplicada, como mostra a seta verde, ocorrerá uma força, como mostra a seta vermelha azul, que causará um deslocamento perpendicular da massa. Assim semelhante ao acelerômetro, esse deslocamento causará mudança na capacitância que será medida, processada e corresponderá a uma determinada taxa angular.

A microestrutura do giroscópio se parece com isso. Uma massa que está em constante movimento, ou oscilando, e quando a taxa angular externa for aplicada uma parte flexível da massa se moveria e faria o deslocamento perpendicular.

Magnetômetro MEMS


Ele mede o campo magnético da terra usando o efeito Hall ou o efeito magneto-resistivo. Na verdade, quase 90% dos sensores do mercado usam o efeito Hall e aqui está como funciona.

Se tivermos uma placa condutora como a mostrada na foto e definirmos a corrente para fluir através dela, os elétrons fluirão direto de um para o outro lado da placa. Agora, se trouxermos algum campo magnético para perto da placa, perturbaríamos o fluxo reto e os elétrons desviariam para um lado da placa e os pólos positivos para o outro lado da placa. Isso significa que se colocarmos um medidor agora entre esses dois lados, obteremos alguma voltagem que depende da força do campo magnético e de sua direção.


Os outros 10% dos sensores do mercado utilizam o Efeito Magneto-resistivo. Esses sensores utilizam materiais sensíveis ao campo magnético, geralmente compostos de Ferro (Fe) e Níquel (Ne). Então, quando esses materiais são expostos ao campo magnético, eles mudam sua resistência.

Sensores Arduino e MEMs



Ok, agora vamos conectar esses sensores à placa Arduino e fazer algum uso deles. Como exemplo vou usar a placa breakout GY-80 que possui os seguintes sensores:Acelerômetro de 3 Eixos ADXL345, Giroscópio de 3 Eixos L3G4200D, Magnetômetro de 3 Eixos MC5883L e também um Barômetro e um Termômetro que não usaremos neste tutorial.

Você pode obter esses componentes em qualquer um dos sites abaixo:
  • Acelerador de 3 eixos ADXL345………………………………………………………
  • 2 em 1:giroscópio e acelerômetro de 6 eixos MPU6050 …………………
  • 3 em 1:Giroscópio de aceleração de campo magnético de 9 eixos GY-80……… Amazon 
  • 3 em 1: GY-86 10DOF MS5611 HMC5883L MPU6050 Módulo……… Banggood  / AliExpress

Esta placa usa o protocolo de comunicação I2C, o que significa que podemos usar todos os sensores com apenas dois fios. Portanto, para fazer a comunicação entre o Arduino e os sensores, precisamos conhecer seus endereços exclusivos de dispositivos e seus endereços de registros internos para obter os dados deles. Esses endereços podem ser encontrados nas fichas técnicas dos sensores:
  • ADXL345  Acelerômetro         Folha de dados
  • L3G4200D  Giroscópio              Folha de dados
  • MC5883L  Magnetômetro        Folha de dados

Para mais detalhes sobre como a comunicação I2C funciona, você pode conferir meu outro Tutorial do Protocolo de Comunicação I2C.

Código-fonte


Agora vamos ver os códigos para obter os dados dos sensores. Começaremos com o acelerômetro e haverá algumas explicações antes de cada código, bem como algumas descrições adicionais nos comentários do código .

Código do Acelerômetro do Arduino


Primeiro precisamos incluir a Biblioteca de Fios do Arduino e definir os endereços dos registradores do sensor. Na seção de configuração, precisamos iniciar a Wire Library e iniciar a comunicação serial, pois usaremos o monitor serial para mostrar os resultados. Também aqui precisamos ativar o sensor ou habilitar a medição enviando o byte apropriado para o registrador Power_CTL e aqui está como fazemos isso. Usando a função Wire.beginTransmission() selecionamos para qual sensor vamos falar, o Acelerômetro de 3 Eixos neste caso. Então usando a função Wire.write() informamos para qual registrador interno falaremos. Após isso enviaremos o byte apropriado para habilitar a medição. Usando a função Wire.endTransmission() terminaremos a transmissão e isso transmitirá os dados para os registradores.

Na seção de loop, precisamos ler os dados para cada eixo. Começaremos com o Eixo X. Então primeiro vamos selecionar para quais registradores falaremos, os dois registradores internos do Eixo X neste caso. Em seguida, usando a função Wire.requestFrom(), solicitaremos os dados transmitidos ou os dois bytes dos dois registradores. O Wire.available() A função retornará o número de bytes disponíveis para recuperação e se esse número corresponder aos bytes solicitados, no nosso caso 2 bytes, usando o comando Wire.read() vamos ler os bytes dos dois registradores do eixo X.

Os dados de saída dos registros são o complemento de dois, com X0 como o byte menos significativo e X1 como o byte mais significativo, portanto, precisamos converter esses bytes em valores flutuantes de -1 a +1, dependendo da direção do eixo X - relativo à aceleração da Terra ou à gravidade. Repetiremos este procedimento para os outros dois eixos e ao final imprimiremos esses valores no monitor serial.
#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 do giroscópio do Arduino


Para obter os dados do giroscópio, teremos um código semelhante ao anterior. Então primeiro temos que definir os endereços dos registradores e algumas variáveis ​​para os dados. Na seção de configuração temos que acordar e colocar o sensor no modo normal usando o CTRL_REG1 e também selecionar a sensibilidade do sensor. Para este exemplo, selecionarei o modo de sensibilidade de 2000dps.

Na seção de loop semelhante ao acelerômetro, leremos os dados para os eixos X, Y e Z. Em seguida, os dados brutos devem ser convertidos em valores de ângulo. Da folha de dados do sensor podemos ver que para o modo de sensibilidade de 2000dps corresponde uma unidade de 70 mdps/dígito. Isso significa que temos que multiplicar os dados brutos de saída por 0,07 para obter a taxa angular em graus por segundo. Então, se multiplicar a taxa angular pelo tempo, isso nos dará o valor do ângulo. Portanto, precisamos calcular o intervalo de tempo de cada seção do loop e podemos fazer isso usando a função millis() na parte superior e inferior da seção do loop, e armazenaremos seu valor nessa variável “dt”. Portanto, para cada loop executado, calcularemos o ângulo e o adicionaremos ao valor final do ângulo. Faremos o mesmo para os outros dois eixos e ao final imprimiremos os resultados no monitor serial.
#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 do magnetômetro do Arduino


Novamente, usaremos uma técnica semelhante à anterior. Primeiro precisamos definir os endereços dos registradores e na seção de configuração colocar o sensor no modo de medição contínua. Na seção de loop, obteremos os dados brutos para cada eixo com o mesmo método dos sensores anteriores.

Em seguida, precisamos converter os dados brutos em valor de campo magnético ou unidades de Gauss. A partir da folha de dados do sensor podemos ver que o modo de sensibilidade padrão é 0,92mG/dígito. Isso significa que precisamos multiplicar os dados brutos por 0,00092 para obter o campo magnético da Terra em unidades de Gauss. Ao final imprimiremos os valores no 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)

Aqui está uma aplicação legal do sensor, uma bússola digital MEMS, feita usando o Processing IDE. Você pode encontrar mais detalhes e o código-fonte deste exemplo no  seguinte link:

Processo de manufatura

  1. O que é um magnetômetro?
  2. O que eu faço com os dados ?!
  3. Jogo Arduino Gyroscope com MPU-6050
  4. Diversão do giroscópio com anel NeoPixel
  5. Monitoramento de CO2 com Sensor K30
  6. Comunicação para surdos-cegos com 1Sheeld / Arduino
  7. Aceitar moeda de controle com Arduino
  8. Arduino com Bluetooth para controlar um LED!
  9. Sensor capacitivo de impressão digital com um Arduino ou ESP8266
  10. Brincando com Nextion Display