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

Explorando Sensores MEMS: Acelerômetros, Giroscópios e Magnetômetros para Projetos Arduino

Neste tutorial, aprenderemos como o acelerômetro MEMS, giroscópio e magnetômetro funcionam e como usá-los com a placa Arduino. Também com o IDE Processing, 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 de microcomponentes variando de 0,001 mm a 0,1 mm de tamanho. Estes 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, explicaremos brevemente como cada um destes sensores Micro-Eletro-Mecânicos (MEMS) funciona.

Acelerômetro MEMS

Mede aceleração medindo mudança na capacitância. Sua microestrutura parece algo assim. Tem uma massa presa a uma mola que está confinada a mover-se em uma direção e placas externas fixas. Então, quando uma aceleração na direção particular 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 valor de aceleração particular.

Explorando Sensores MEMS: Acelerômetros, Giroscópios e Magnetômetros para Projetos Arduino

Giroscópio MEMS

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

Explorando Sensores MEMS: Acelerômetros, Giroscópios e Magnetômetros para Projetos Arduino

A microestrutura do giroscópio parece algo assim. Uma massa que está constantemente se movendo, ou oscilando, e quando a taxa angular externa for aplicada, uma parte flexível da massa se moverá e fará o deslocamento perpendicular.

Explorando Sensores MEMS: Acelerômetros, Giroscópios e Magnetômetros para Projetos Arduino

Magnetômetro MEMS

Mede o campo magnético da Terra usando Efeito Hall ou Efeito Magnetorresistivo. Na verdade, quase 90% dos sensores no mercado usam o Efeito Hall e aqui está como funciona.

Explorando Sensores MEMS: Acelerômetros, Giroscópios e Magnetômetros para Projetos Arduino

Se tivermos uma placa condutiva como mostrado na foto e definirmos corrente para fluir através dela, os elétrons fluiriam em linha reta de um lado ao outro da placa. Agora, se trouxermos algum campo magnético perto da placa, perturbaríamos o fluxo reto e os elétrons desviariam para um lado da placa e os polos positivos para o outro lado. Isso significa que, se colocarmos um medidor agora entre estes dois lados, obteremos alguma tensão que depende da força do campo magnético e sua direção.

Explorando Sensores MEMS: Acelerômetros, Giroscópios e Magnetômetros para Projetos Arduino

Os outros 10% dos sensores no mercado usam o Efeito Magnetorresistivo. Estes sensores usam materiais sensíveis ao campo magnético, geralmente compostos de Ferro (Fe) e Níquel (Ni). Então, quando estes materiais são expostos a campo magnético, eles mudam sua resistência.

Arduino e Sensores MEMS


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

Você pode obter estes componentes em qualquer um dos sites abaixo:

Explorando Sensores MEMS: Acelerômetros, Giroscópios e Magnetômetros para Projetos Arduino

Esta placa usa o protocolo de comunicação I2C, o que significa que podemos usar todos os sensores com apenas dois fios. Então, para fazer a comunicação entre o Arduino e os sensores, precisamos saber seus endereços de dispositivo únicos e seus endereços de registro internos para obter os dados deles. Estes endereços podem ser encontrados nas datasheets dos sensores:

Para mais detalhes de 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 dados dos sensores. Começaremos com o acelerômetro e haverá alguma explicação antes de cada código, bem como descrição adicional nos comentários do código.

Código Arduino Acelerômetro

Primeiro, precisamos incluir a biblioteca Arduino Wire e definir os endereços dos registradores do sensor. Na seção setup, precisamos iniciar a biblioteca Wire 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 com qual sensor vamos falar, o Acelerômetro 3-Eixos neste caso. Então, usando a função Wire.write(), dizemos a qual registro interno vamos falar. 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 loop, precisamos ler os dados para cada eixo. Começaremos com o Eixo X. Então, primeiro selecionaremos para quais registradores vamos falar, os dois registradores internos do Eixo X neste caso. Então, usando a função Wire.requestFrom(), solicitaremos os dados transmitidos ou os dois bytes dos dois registradores. A função Wire.available() retornará o número de bytes disponíveis para recuperação e, se esse número corresponder aos nossos bytes solicitados, no nosso caso 2 bytes, usando a função Wire.read(), leremos os bytes dos dois registradores do eixo X.

Os dados de saída dos registradores são complemento de dois, com X0 como byte menos significativo e X1 como byte mais significativo, então precisamos converter estes bytes em valores float 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, no final, imprimiremos estes valores no monitor serial.

#include <Wire.h>
//--- Endereços dos Registradores do Acelerômetro
#define Power_Register 0x2D
#define X_Axis_Register_DATAX0 0x32
#define X_Axis_Register_DATAX1 0x33
#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; // Endereço do dispositivo incluindo 8º bit para modo leitura
int X0,X1,X_out; int Y0,Y1,Y_out; int Z1,Z0,Z_out;
float Xa,Ya,Za;

void setup() {
  Wire.begin(); // Inicia biblioteca Wire
  Serial.begin(9600);
  delay(100);
  Wire.beginTransmission(ADXAddress);
  Wire.write(Power_Register); // Registrador Power_CTL
  // Habilita medição
  Wire.write(8); // Bit D3 High para medição (0000 1000)
  Wire.endTransmission();
}

void loop() {
  // Eixo X
  Wire.beginTransmission(ADXAddress);
  Wire.write(X_Axis_Register_DATAX0);
  Wire.write(X_Axis_Register_DATAX1);
  Wire.endTransmission();
  Wire.requestFrom(ADXAddress,2);
  if(Wire.available() <= 2) {
    X0 = Wire.read();
    X1 = Wire.read();
    X1 = X1 << 8;
    X_out = X0 + X1;
    Xa = X_out / 256.0; // Xa = valor de saída -1 a +1
  }
  // Eixo 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;
  }
  // Eixo 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 dados no Monitor Serial
  Serial.print("Xa= "); Serial.print(Xa);
  Serial.print(" Ya= "); Serial.print(Ya);
  Serial.print(" Za= "); Serial.println(Za);
}

Código Arduino Giroscópio

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

Na seção loop, similar ao acelerômetro, leremos os dados para os eixos X, Y e Z. Então, os dados brutos têm que ser convertidos em valores de ângulo. Da datasheet do sensor, podemos ver que para o modo de sensibilidade 2000dps corresponde uma unidade de 70 mdps/dígito. Isso significa que temos que multiplicar os dados de saída brutos por 0.07 para obter a taxa angular em graus por segundo. Então, se multiplicarmos a taxa angular pelo tempo, obteremos o valor do ângulo. Precisamos calcular o intervalo de tempo de cada seção loop e podemos fazer isso usando a função millis() no topo e no final da seção loop, e armazenaremos seu valor nesta variável "dt". Então, para cada loop executado, calcularemos o ângulo e o adicionaremos ao valor final do ângulo. Faremos o mesmo para os outros dois eixos e, no final, imprimiremos os resultados no monitor serial.

#include <Wire.h>
//--- Endereços dos Registradores do Giroscópio
#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; // Endereço do dispositivo
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 Energia
  Wire.write(15); // Modo normal: 15d - 00001111b
  Wire.endTransmission();
  Wire.beginTransmission(Gyro);
  Wire.write(0x23); // CTRL_REG4 - Sensibilidade, Seleção de Escala
  Wire.write(48); // 2000dps: 48d - 00110000b
  Wire.endTransmission();
}

void loop() {
  start = millis();
  // Eixo X
  Wire.beginTransmission(Gyro); Wire.write(Gyro_gX0); Wire.endTransmission();
  Wire.requestFrom(Gyro,1);
  if(Wire.available() <= 1) { gX0 = Wire.read(); }
  Wire.beginTransmission(Gyro); Wire.write(Gyro_gX1); Wire.endTransmission();
  Wire.requestFrom(Gyro,1);
  if(Wire.available() <= 1) { gX1 = Wire.read(); }
  // Eixo Y
  Wire.beginTransmission(Gyro); Wire.write(Gyro_gY0); Wire.endTransmission();
  Wire.requestFrom(Gyro,1);
  if(Wire.available() <= 1) { gY0 = Wire.read(); }
  Wire.beginTransmission(Gyro); Wire.write(Gyro_gY1); Wire.endTransmission();
  Wire.requestFrom(Gyro,1);
  if(Wire.available() <= 1) { gY1 = Wire.read(); }
  // Eixo Z
  Wire.beginTransmission(Gyro); Wire.write(Gyro_gZ0); Wire.endTransmission();
  Wire.requestFrom(Gyro,1);
  if(Wire.available() <= 1) { gZ0 = Wire.read(); }
  Wire.beginTransmission(Gyro); Wire.write(Gyro_gZ1); Wire.endTransmission();
  Wire.requestFrom(Gyro,1);
  if(Wire.available() <= 1) { gZ1 = Wire.read(); }

  // Eixo X - Dados Brutos
  gX1 = gX1 << 8; gX_out = gX0 + gX1;
  Xg = gX_out * 0.07; // Taxa angular
  angleXc = Xg * dt; angleX = angleX + angleXc;
  // Eixo Y
  gY1 = gY1 << 8; gY_out = gY0 + gY1;
  Yg = gY_out * 0.07; angleYc = Yg * dt; angleY = angleY + angleYc;
  // Eixo Z
  gZ1 = gZ1 << 8; gZ_out = gZ0 + gZ1;
  Zg = gZ_out * 0.07; angleZc = Zg * dt; angleZ = angleZ + angleZc;

  // Imprime dados no 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;
}

Código Arduino Magnetômetro

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

Então, precisamos converter os dados brutos em valor de campo magnético ou unidades Gauss. Da datasheet 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 Gauss. No final, imprimiremos os valores no monitor serial.

#include <Wire.h> // Biblioteca I2C 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 // Endereço I2C 7-bit do HMC5883

void setup() {
  Serial.begin(9600); Wire.begin(); delay(100);
  Wire.beginTransmission(Magnetometer);
  Wire.write(0x02); // Seleciona registrador de modo
  Wire.write(0x00); // Modo de medição contínua
  Wire.endTransmission();
}

void loop() {
  // Eixo X
  Wire.beginTransmission(Magnetometer); Wire.write(Magnetometer_mX1); Wire.endTransmission();
  Wire.requestFrom(Magnetometer,1);
  if(Wire.available() <= 1) { mX0 = Wire.read(); }
  Wire.beginTransmission(Magnetometer); Wire.write(Magnetometer_mX0); Wire.endTransmission();
  Wire.requestFrom(Magnetometer,1);
  if(Wire.available() <= 1) { mX1 = Wire.read(); }
  // Eixo Y
  Wire.beginTransmission(Magnetometer); Wire.write(Magnetometer_mY1); Wire.endTransmission();
  Wire.requestFrom(Magnetometer,1);
  if(Wire.available() <= 1) { mY0 = Wire.read(); }
  Wire.beginTransmission(Magnetometer); Wire.write(Magnetometer_mY0); Wire.endTransmission();
  Wire.requestFrom(Magnetometer,1);
  if(Wire.available() <= 1) { mY1 = Wire.read(); }
  // Eixo Z
  Wire.beginTransmission(Magnetometer); Wire.write(Magnetometer_mZ1); Wire.endTransmission();
  Wire.requestFrom(Magnetometer,1);
  if(Wire.available() <= 1) { mZ0 = Wire.read(); }
  Wire.beginTransmission(Magnetometer); Wire.write(Magnetometer_mZ0); Wire.endTransmission();
  Wire.requestFrom(Magnetometer,1);
  if(Wire.available() <= 1) { mZ1 = Wire.read(); }

  // Eixo X
  mX1 = mX1 << 8; mX_out = mX0 + mX1;
  Xm = mX_out * 0.00092; // Unidade Gauss
  // Eixo Y
  mY1 = mY1 << 8; mY_out = mY0 + mY1;
  Ym = mY_out * 0.00092;
  // Eixo Z
  mZ1 = mZ1 << 8; mZ_out = mZ0 + mZ1;
  Zm = mZ_out * 0.00092;

  // Imprime valores de cada eixo
  Serial.print("x: "); Serial.print(Xm);
  Serial.print(" y: "); Serial.print(Ym);
  Serial.print(" z: "); Serial.println(Zm);
  delay(50);
}

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

Explorando Sensores MEMS: Acelerômetros, Giroscópios e Magnetômetros para Projetos Arduino

Processo de manufatura

  1. O que é um Magnetômetro? Fundamentos, Princípios e Aplicações Reais
  2. Aproveitando Dados na Internet da Confiabilidade: Estratégias para Gestão Eficaz
  3. Construa um Jogo em Tempo Real com Giroscópio: Arduino Nano + Sensor MPU-6050
  4. Display Interativo de Giroscópio com Anel NeoPixel e Arduino
  5. Sensor K30 CO₂: Monitoramento de Qualidade do Ar Interno em Tempo Real
  6. Facilitando Comunicação Surdo-Cego com 1Sheeld e Arduino
  7. Mealheiro Inteligente: Controlar Aceitador de Moedas com Arduino Nano
  8. Controlar um LED via Bluetooth com Arduino – Guia DIY Simples
  9. Integrando Sensor de Impressão Digital Capacitivo DFRobot com Arduino ou ESP8266
  10. Projeto HMI Interativo com Nextion, Arduino Mega e Sensores