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.

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.

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.

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.

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.

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:
- ADXL345 Acelerômetro 3-Eixos
- 2 em 1: MPU6050 Giroscópio 6-Eixos & Acelerômetro
- 3 em 1: GY-80 Campo Magnético 9-Eixos Aceleração Giroscópio
- 3 em 1: GY-86 10DOF MS5611 HMC5883L MPU6050 Módulo

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:
- Datasheet do Acelerômetro ADXL345
- Datasheet do Giroscópio L3G4200D
- Datasheet do Magnetômetro MC5883L
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:

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