Componentes · 10 min de leitura

Guia do MPU6050 com Arduino: acelerômetro, giroscópio e ângulo de inclinação

MPU6050 com Arduino: ligação, endereço I2C, valores brutos, calibração, ângulo de inclinação com atan2 e filtro complementar, além de código com a biblioteca da Adafruit, ESP32 e Pico.

O MPU6050 reúne um acelerômetro de 3 eixos e um giroscópio de 3 eixos em um chip minúsculo e é o sensor de movimento mais usado em projetos com Arduino. Ele mede o quanto a placa está inclinada, para que lado e com que velocidade está girando, e se está sendo sacudida ou se caiu. Robôs autoequilibrados, drones, estabilizadores de câmera (gimbals), contadores de passos e jogos controlados por movimento são feitos com esse sensor. O MPU6050 se liga ao Arduino com só quatro fios, via I2C.

Neste artigo você vai aprender passo a passo como o MPU6050 funciona, seus eixos e valores brutos, a ligação I2C, a leitura com e sem biblioteca, a calibração, o cálculo dos ângulos de inclinação com atan2 e o filtro complementar, que junta os pontos fortes dos dois sensores. Depois vamos montar um alarme de detecção de queda com ESP32 e escrever código em MicroPython para o Raspberry Pi Pico.

Módulo acelerômetro e giroscópio MPU6050 GY-521
O MPU6050 em uma placa GY-521: pinos VCC, GND, SCL, SDA, XDA, XCL, AD0 e INT; as direções dos eixos X e Y estão impressas na placa.

O que é o MPU6050 e como ele funciona?

O MPU6050, fabricado pela InvenSense (hoje TDK), é uma IMU, uma unidade de medição inercial. Dentro dele há minúsculas estruturas mecânicas de silício (MEMS). O acelerômetro mede o quanto uma pequena massa presa por molas se desloca sob aceleração; como ele sente a gravidade mesmo parado, um sensor deitado sobre a mesa mostra cerca de 1 g (9,81 m/s²) no eixo Z, o que permite calcular a inclinação em relação ao chão. O giroscópio mede a velocidade angular, ou seja, quantos graus por segundo o sensor está girando, a partir da força de Coriolis que age sobre estruturas que vibram. As medições são convertidas em números por ADCs de 16 bits dentro do chip e lidas via I2C. O chip também tem um sensor de temperatura e um processador digital de movimento (DMP) que pode assumir os cálculos de movimento.

CaracterísticaValor
SensoresAcelerômetro de 3 eixos + giroscópio de 3 eixos + temperatura
Faixa do acelerômetro±2, ±4, ±8, ±16 g
Faixa do giroscópio±250, ±500, ±1000, ±2000 °/s
Resolução16 bits (de -32768 a 32767 por eixo)
InterfaceI2C, até 400 kHz
Endereço I2C0x68 (AD0 no GND) ou 0x69 (AD0 em 3,3 V)
Tensão do chip2,375–3,46 V (a placa GY-521 aceita 3,3–5 V)
CorrenteCerca de 3,9 mA (5 µA em repouso)
ExtrasDMP, FIFO de 1024 bytes, interrupção por movimento, I2C auxiliar para um sensor externo

Eixos, valores brutos e sensibilidade

As setas na placa mostram os eixos X e Y; o eixo Z é perpendicular à placa e aponta para cima. O sensor dá um número de 16 bits com sinal para cada eixo. Para converter esse número bruto em uma unidade física, você o divide pela sensibilidade da faixa escolhida. Por exemplo, na faixa padrão de ±2 g, um valor bruto de 16384 significa 1 g; de um sensor deitado na mesa você vai ler az ≈ 16384 e ax, ay ≈ 0. Para o giroscópio na faixa de ±250 °/s, um valor bruto de 131 corresponde a uma rotação de 1 grau por segundo. Uma faixa maior mede movimentos mais bruscos, mas mostra pequenas variações com menos detalhe, então escolha a faixa mais estreita que atenda ao seu projeto.

AjusteFaixa do acelerômetroLSB/gFaixa do giroscópioLSB/(°/s)
0±2 g16384±250 °/s131
1±4 g8192±500 °/s65,5
2±8 g4096±1000 °/s32,8
3±16 g2048±2000 °/s16,4

O chip também mede temperatura: °C = valor bruto / 340 + 36,53. Isso mostra a temperatura do próprio chip, e não a do ambiente, mas, como o ponto zero do giroscópio varia com a temperatura, é útil para correções avançadas.

Ligação do MPU6050: Arduino Uno, ESP32 e Pico

Pino do MPU6050Arduino UnoESP32Raspberry Pi Pico
VCC5V3V33V3(OUT)
GNDGNDGNDGND
SCLA5GPIO 22GP5
SDAA4GPIO 21GP4
AD0Desconectado (endereço 0x68)Desconectado (endereço 0x68)Desconectado (endereço 0x68)
INTD2 (opcional)Qualquer GPIO (opcional)Qualquer pino GP (opcional)
XDA, XCLNão ligarNão ligarNão ligar

Como a placa GY-521 tem um regulador de 3,3 V, você pode ligar o VCC no pino 5V do Uno. O pino AD0 é puxado para o GND na placa por um resistor de 4,7 kΩ, então o endereço é 0x68 quando ele fica desconectado; se você quiser dois MPU6050 no mesmo barramento, ligue o AD0 de um deles em 3,3 V para mudar o endereço para 0x69. O pino INT avisa quando há dados novos prontos ou quando um movimento é detectado; em projetos simples você não precisa ligá-lo. Depois da ligação, é um bom hábito conferir se o sensor aparece com um sketch scanner I2C; você descobre como em display LCD I2C.

Não confunda SDA e SCL com XDA e XCL. XDA e XCL são um barramento I2C auxiliar que o MPU6050 usa para ligar a si mesmo um sensor de bússola externo; se você ligar o Arduino ali, o sensor nunca será encontrado. Além disso, algumas placas MPU6050 simples não têm regulador e só podem ser alimentadas com 3,3 V; se você não vê o pequeno chip regulador na sua placa, não dê 5 V a ela.

Começo rápido com biblioteca: Adafruit MPU6050

  1. Abra o Gerenciador de Bibliotecas na Arduino IDE e busque Adafruit MPU6050.
  2. Quando a instalação perguntar sobre as dependências, escolha Instalar tudo para que a Adafruit Unified Sensor e a Adafruit BusIO também sejam instaladas.
  3. Ligue o sensor como na tabela, carregue o sketch abaixo e abra o Monitor Serial em 115200 baud.
  4. Abra o Plotter Serial pelo menu Ferramentas para acompanhar os seis eixos em gráficos ao vivo; as curvas de aceleração mudam quando você inclina a placa, e as do giroscópio quando você a gira.
C++ (Arduino IDE)
1#include <Wire.h>
2#include <Adafruit_MPU6050.h>
3#include <Adafruit_Sensor.h>
4
5Adafruit_MPU6050 mpu;
6
7void setup() {
8  Serial.begin(115200);
9  if (!mpu.begin()) {                             // varsayılan adres 0x68 / default address 0x68
10    Serial.println("MPU6050 bulunamadi / not found");
11    while (true) delay(10);
12  }
13  mpu.setAccelerometerRange(MPU6050_RANGE_4_G);   // ±4 g
14  mpu.setGyroRange(MPU6050_RANGE_500_DEG);        // ±500 °/s
15  mpu.setFilterBandwidth(MPU6050_BAND_21_HZ);     // titreşimi süz / filter out vibration
16}
17
18void loop() {
19  sensors_event_t a, g, t;
20  mpu.getEvent(&a, &g, &t);
21  Serial.print("ax:");  Serial.print(a.acceleration.x);   // m/s²
22  Serial.print(" ay:"); Serial.print(a.acceleration.y);
23  Serial.print(" az:"); Serial.print(a.acceleration.z);
24  Serial.print(" gx:"); Serial.print(g.gyro.x);           // rad/s
25  Serial.print(" gy:"); Serial.print(g.gyro.y);
26  Serial.print(" gz:"); Serial.print(g.gyro.z);
27  Serial.print(" T:");  Serial.println(t.temperature);    // °C
28  delay(100);
29}

A biblioteca da Adafruit dá os resultados direto em unidades físicas: aceleração em m/s², velocidade angular em rad/s e temperatura em °C. Para converter um valor do giroscópio em graus por segundo, basta multiplicar por 57,3. O filtro passa-baixa interno escolhido com setFilterBandwidth reduz o ruído de vibração: 21 Hz é um bom ponto de partida para movimentos da mão, e, se você quiser captar impactos curtos, escolha 94 ou 260 Hz. Na inicialização a biblioteca lê o registrador de identidade do chip (WHO_AM_I), e begin() retorna false se ele não for 0x68.

Leitura sem biblioteca, calibração e ângulo de inclinação

As bibliotecas facilitam a vida, mas ler os registradores direto é um ótimo jeito de entender o que acontece dentro do sensor. O MPU6050 inicia em modo de repouso; primeiro você precisa acordá-lo escrevendo 0 no registrador 0x6B (PWR_MGMT_1). Depois você lê 14 bytes a partir do endereço 0x3B: 6 bytes de aceleração, 2 bytes de temperatura e 6 bytes do giroscópio. Cada valor tem dois bytes, com o byte alto primeiro. Estes são os principais registradores usados no código e que vale a pena conhecer:

RegistradorEndereçoFunção
SMPLRT_DIV0x19Divisor da taxa de amostragem
CONFIG0x1AFiltro passa-baixa interno (DLPF)
GYRO_CONFIG0x1BFaixa do giroscópio (±250 … ±2000 °/s)
ACCEL_CONFIG0x1CFaixa do acelerômetro (±2 … ±16 g)
ACCEL_XOUT_H0x3BEndereço onde começam as medições (14 bytes)
PWR_MGMT_10x6BRepouso e fonte de clock; escrever 0 acorda o sensor
WHO_AM_I0x75Identidade; retorna 0x68 em um MPU6050 original

Com o sensor parado, a única força que o acelerômetro vê é a gravidade. Olhando como a gravidade se divide entre os eixos, você encontra dois ângulos: o ângulo de rolagem em torno do eixo X é roll = atan2(ay, az), e o ângulo de arfagem em torno do eixo Y é pitch = atan2(−ax, √(ay² + az²)). Diferente do arco tangente comum, o atan2 dá o sinal correto nos quatro quadrantes e não divide por zero quando az se aproxima de zero. Por exemplo, se você lê ay = 8192 e az = 14189, roll = atan2(8192, 14189) ≈ 30°. Já a rotação em torno do eixo Z (yaw) é invisível para o acelerômetro, porque não muda a forma como a gravidade se divide entre os eixos.

Os dois sensores têm um ponto fraco. O acelerômetro é preciso no longo prazo, mas tem muito ruído durante movimentos e vibrações, porque mede a aceleração do próprio movimento somada à gravidade. O giroscópio é suave no curto prazo, mas, para obter um ângulo, você soma a velocidade angular ao longo do tempo (angle += rate × dt), e até um pequeno offset se acumula e arrasta o ângulo devagar. O filtro complementar junta os dois: angle = 0.98 × (angle + gyro × dt) + 0.02 × ângulo do acelerômetro. Ele confia no giroscópio no curto prazo e no acelerômetro no longo prazo. A 100 Hz (dt = 0,01 s), esses coeficientes dão uma constante de tempo de cerca de meio segundo: τ = 0,98 × 0,01 / 0,02 = 0,49 s.

A calibração importa pelo menos tanto quanto o filtro. Mesmo um giroscópio totalmente parado pode mostrar um offset constante de alguns °/s; se você não o corrigir, o ângulo calculado se desvia dezenas de graus em segundos. O sketch abaixo tira a média de 500 leituras na inicialização, com o sensor parado, e a subtrai de todas as leituras seguintes. Coloque a placa em uma superfície plana e não toque nela durante a calibração; depois acompanhe as curvas de roll, pitch e yaw no Plotter Serial.

C++ (Arduino IDE)
1#include <Wire.h>
2
3const int MPU_ADDR = 0x68;           // AD0 GND'de ya da boşta / AD0 to GND or floating
4const float GYRO_LSB = 131.0;        // ±250 °/s aralığında 1 °/s / 1 °/s at the ±250 °/s range
5const float ALPHA = 0.98;            // tamamlayıcı filtre katsayısı / complementary filter weight
6
7int16_t ax, ay, az, tempRaw, gx, gy, gz;
8float gxOff = 0, gyOff = 0, gzOff = 0;   // jiroskop sapmaları / gyro offsets
9float roll = 0, pitch = 0, yaw = 0;
10unsigned long lastMicros;
11
12void writeReg(uint8_t reg, uint8_t val) {
13  Wire.beginTransmission(MPU_ADDR);
14  Wire.write(reg);
15  Wire.write(val);
16  Wire.endTransmission();
17}
18
19int16_t read16() {
20  uint8_t hi = Wire.read();          // önce yüksek bayt / high byte first
21  uint8_t lo = Wire.read();
22  return (int16_t)(((uint16_t)hi << 8) | lo);
23}
24
25void readMPU() {
26  Wire.beginTransmission(MPU_ADDR);
27  Wire.write(0x3B);                  // ACCEL_XOUT_H
28  Wire.endTransmission(false);       // hattı bırakma, tekrar başlat / repeated start
29  Wire.requestFrom(MPU_ADDR, 14);    // ivme 6 + sıcaklık 2 + jiroskop 6 bayt / accel 6 + temp 2 + gyro 6 bytes
30  ax = read16(); ay = read16(); az = read16();
31  tempRaw = read16();
32  gx = read16(); gy = read16(); gz = read16();
33}
34
35void calibrateGyro() {
36  const int N = 500;
37  long sx = 0, sy = 0, sz = 0;
38  for (int i = 0; i < N; i++) {
39    readMPU();
40    sx += gx; sy += gy; sz += gz;
41    delay(3);
42  }
43  gxOff = sx / (float)N;
44  gyOff = sy / (float)N;
45  gzOff = sz / (float)N;
46}
47
48void setup() {
49  Serial.begin(115200);
50  Wire.begin();
51  Wire.setClock(400000);             // 400 kHz hızlı mod / 400 kHz fast mode
52  writeReg(0x6B, 0x00);              // PWR_MGMT_1: uykudan uyandır / wake up
53  writeReg(0x1A, 0x03);              // CONFIG: alçak geçiren filtre ~44 Hz / low-pass ~44 Hz
54  writeReg(0x1B, 0x00);              // GYRO_CONFIG: ±250 °/s
55  writeReg(0x1C, 0x00);              // ACCEL_CONFIG: ±2 g
56  delay(100);
57  Serial.println("Kalibrasyon: sensoru oynatma / calibrating: keep still");
58  calibrateGyro();
59  readMPU();
60  roll  = atan2(ay, az) * RAD_TO_DEG;                                    // başlangıç açıları / initial angles
61  pitch = atan2(-ax, sqrt((float)ay * ay + (float)az * az)) * RAD_TO_DEG;
62  lastMicros = micros();
63}
64
65void loop() {
66  readMPU();
67  unsigned long now = micros();
68  float dt = (now - lastMicros) / 1000000.0;   // saniye / seconds
69  lastMicros = now;
70
71  float accRoll  = atan2(ay, az) * RAD_TO_DEG;                           // ivmeölçerden açı / angle from accelerometer
72  float accPitch = atan2(-ax, sqrt((float)ay * ay + (float)az * az)) * RAD_TO_DEG;
73  float gxRate = (gx - gxOff) / GYRO_LSB;      // °/s
74  float gyRate = (gy - gyOff) / GYRO_LSB;
75  float gzRate = (gz - gzOff) / GYRO_LSB;
76
77  roll  = ALPHA * (roll  + gxRate * dt) + (1 - ALPHA) * accRoll;        // tamamlayıcı filtre / complementary filter
78  pitch = ALPHA * (pitch + gyRate * dt) + (1 - ALPHA) * accPitch;
79  yaw  += gzRate * dt;                         // yalnız jiroskop: zamanla kayar / gyro only: drifts over time
80
81  Serial.print("roll:");   Serial.print(roll, 1);
82  Serial.print(" pitch:"); Serial.print(pitch, 1);
83  Serial.print(" yaw:");   Serial.println(yaw, 1);
84  delay(10);                                   // yaklaşık 100 Hz / about 100 Hz
85}
Linha de códigoO que faz
writeReg(0x6B, 0x00)Acorda o sensor do modo de repouso
writeReg(0x1A, 0x03)Ativa o filtro interno em cerca de 44 Hz
Wire.requestFrom(MPU_ADDR, 14)Lê aceleração, temperatura e giroscópio de uma vez
calibrateGyro()Encontra o offset do giroscópio tirando a média de 500 leituras
atan2(ay, az) * RAD_TO_DEGCalcula o ângulo de rolagem em graus a partir do acelerômetro
ALPHA * (...) + (1 - ALPHA) * ...Filtro complementar: junta giroscópio e acelerômetro
yaw += gzRate * dtCalcula o yaw só com o giroscópio, para você ver o desvio ao longo do tempo
Balance a placa de leve olhando o Plotter Serial: o ângulo bruto do acelerômetro pula para todo lado, enquanto o ângulo filtrado fica calmo. Para uma resposta mais rápida, baixe o ALPHA para 0.95; para menos tremido, suba para 0.99. Para um resultado ainda mais estável, o exemplo de DMP da biblioteca MPU6050 da Electronic Cats obtém os ângulos a partir de dados em quatérnio calculados no próprio processador do sensor.

MPU6050 com ESP32: um alarme de detecção de queda

No ESP32 a ligação é a mesma do Uno, só que os pinos I2C são o GPIO 21 (SDA) e o GPIO 22 (SCL), e o módulo é alimentado pelo 3V3. Todos os sketches acima rodam sem mudanças no ESP32; se quiser, você pode definir os pinos explicitamente com Wire.begin(21, 22). O exemplo abaixo é um detector de queda. Em um objeto em queda livre, o acelerômetro lê quase 0 g, porque o corpo do sensor e a massa dentro dele caem juntos; o impacto que vem depois produz um pico de vários g. Se o sketch detectar uma queda livre de pelo menos 100 ms seguida, em até meio segundo, de um impacto acima de 2,5 g, ele toca um buzzer ativo no GPIO 25 por um segundo. Uma queda livre de 100 ms corresponde a uma queda de cerca de 5 cm (h = ½ × g × t²).

C++ (Arduino IDE)
1#include <Wire.h>
2#include <Adafruit_MPU6050.h>
3#include <Adafruit_Sensor.h>
4
5Adafruit_MPU6050 mpu;
6const int BUZZER_PIN = 25;           // aktif buzzer / active buzzer
7const float FREE_FALL_G = 0.4;       // serbest düşüş eşiği / free-fall threshold
8const float IMPACT_G = 2.5;          // darbe eşiği / impact threshold
9unsigned long fallStart = 0, fallEnd = 0;
10
11void setup() {
12  Serial.begin(115200);
13  pinMode(BUZZER_PIN, OUTPUT);
14  Wire.begin(21, 22);                // SDA, SCL
15  if (!mpu.begin(0x68, &Wire)) {
16    Serial.println("MPU6050 bulunamadi / not found");
17    while (true) delay(10);
18  }
19  mpu.setAccelerometerRange(MPU6050_RANGE_8_G);   // darbeler için geniş aralık / wide range for impacts
20  mpu.setFilterBandwidth(MPU6050_BAND_94_HZ);     // kısa darbeleri kaçırma / keep short peaks
21}
22
23void loop() {
24  sensors_event_t a, g, t;
25  mpu.getEvent(&a, &g, &t);
26  float x = a.acceleration.x, y = a.acceleration.y, z = a.acceleration.z;
27  float total = sqrt(x * x + y * y + z * z) / SENSORS_GRAVITY_STANDARD;   // toplam ivme, g / total acceleration in g
28  unsigned long now = millis();
29
30  if (total < FREE_FALL_G) {
31    if (fallStart == 0) fallStart = now;             // düşüş başladı / fall started
32  } else if (fallStart != 0) {
33    if (now - fallStart > 100) fallEnd = now;        // en az 100 ms süren düşüş / fall of at least 100 ms
34    fallStart = 0;
35  }
36
37  if (fallEnd != 0 && now - fallEnd < 500 && total > IMPACT_G) {   // düşüşten sonra 0,5 s içinde darbe / impact within 0.5 s
38    Serial.println("DUSME ALGILANDI / FALL DETECTED");
39    digitalWrite(BUZZER_PIN, HIGH);
40    delay(1000);
41    digitalWrite(BUZZER_PIN, LOW);
42    fallEnd = 0;
43  }
44  if (fallEnd != 0 && now - fallEnd >= 500) fallEnd = 0;   // darbe gelmedi, sıfırla / no impact, reset
45  delay(5);
46}

A partir daí, você pode usar o Wi-Fi do ESP32 para, por exemplo, mandar uma notificação no Telegram para o seu celular se um parente idoso cair, ou mostrar os ângulos ao vivo em uma página web. Ajuste os limites com seus próprios testes: uma caixa caindo de uma mesa e um sensor usado no pulso produzem picos diferentes. Para escolher e ligar um buzzer, veja O que é buzzer?.

MPU6050 com Raspberry Pi Pico (MicroPython)

No Pico não é preciso biblioteca extra; a classe I2C embutida do MicroPython consegue ler os registradores direto. Ligue o sensor no barramento I2C0, com SDA no GP4 e SCL no GP5. Usamos struct.unpack para transformar os 14 bytes em sete números de 16 bits com sinal; “>” significa big-endian (byte alto primeiro) e “h” significa 16 bits com sinal. O código primeiro mostra os endereços I2C que encontra; se você não vir 0x68 na lista, confira a ligação. Para manter a simplicidade não adicionamos calibração; se precisar, você pode aplicar exatamente do mesmo jeito o método da média do sketch do Arduino.

MicroPython
1from machine import Pin, I2C
2import math, struct, time
3
4MPU = 0x68
5i2c = I2C(0, sda=Pin(4), scl=Pin(5), freq=400000)
6print("Bulunan adresler / found addresses:", [hex(a) for a in i2c.scan()])
7
8i2c.writeto_mem(MPU, 0x6B, b"\x00")     # uykudan uyandır / wake up
9i2c.writeto_mem(MPU, 0x1A, b"\x03")     # alçak geçiren filtre ~44 Hz / low-pass ~44 Hz
10i2c.writeto_mem(MPU, 0x1B, b"\x00")     # jiroskop ±250 °/s / gyro ±250 °/s
11i2c.writeto_mem(MPU, 0x1C, b"\x00")     # ivmeölçer ±2 g / accelerometer ±2 g
12roll = pitch = 0.0
13last = time.ticks_us()
14
15while True:
16    data = i2c.readfrom_mem(MPU, 0x3B, 14)
17    ax, ay, az, t, gx, gy, gz = struct.unpack(">hhhhhhh", data)   # büyük endian, işaretli / big-endian, signed
18    now = time.ticks_us()
19    dt = time.ticks_diff(now, last) / 1000000
20    last = now
21    acc_roll = math.degrees(math.atan2(ay, az))
22    acc_pitch = math.degrees(math.atan2(-ax, math.sqrt(ay * ay + az * az)))
23    roll = 0.98 * (roll + gx / 131 * dt) + 0.02 * acc_roll        # tamamlayıcı filtre / complementary filter
24    pitch = 0.98 * (pitch + gy / 131 * dt) + 0.02 * acc_pitch
25    temp = t / 340 + 36.53                                        # °C
26    print("roll {:.1f}  pitch {:.1f}  T {:.1f}".format(roll, pitch, temp))
27    time.sleep_ms(10)

Ideias de projetos com MPU6050

  • Nível de bolha digital: mostre os ângulos de roll e pitch em um display OLED de 0,96 polegada com uma bolha que se move.
  • Servo controlado por movimento: conforme você inclina o sensor na mão, um servo motor gira para o mesmo ângulo; ideal para um braço robótico ou uma cabeça de câmera.
  • Jogo controlado por inclinação: jogue Pong ou um jogo de labirinto inclinando a placa em vez de usar um joystick.
  • Robô autoequilibrado: processe o ângulo de pitch com um laço PID e mantenha o robô em pé com motores CC acionados por um L298N.
  • Contador de passos: meça a caminhada contando os picos regulares da aceleração total.
  • Registrador de vibração: meça a trepidação de uma máquina ou de uma máquina de lavar e gere um alerta quando um limite for ultrapassado.

Erros comuns e como corrigir

SintomaCausa provávelSolução
begin() retorna false (“MPU6050 not found”, sensor não encontrado)Erro de ligação, endereço errado ou chip cloneEncontre o endereço com um scanner I2C; se o WHO_AM_I não for 0x68 (por exemplo, 0x70), use o código sem biblioteca
Todos os valores são 0O sensor está em modo de repousoEscreva 0 no registrador 0x6B
Os valores são -1 ou congelamFio solto, barramento I2C longoEncurte os fios, solde os pinos
O ângulo se desvia com o sensor paradoOffset do giroscópio não corrigidoCalibre na inicialização, com o sensor parado
O ângulo pula durante o movimentoSó o acelerômetro está sendo usadoAdicione um filtro complementar
O yaw não para de se desviarO MPU6050 não tem bússolaAdicione um magnetômetro como o QMC5883L ou use um sensor de 9 eixos
O roll fica errado quando o pitch se aproxima de ±90°Singularidade dos ângulos de EulerEvite essa região ou use a saída em quatérnio do DMP
Ao montar o sensor no seu projeto, fixe bem a placa com parafuso ou fita dupla face; uma placa solta mede a própria vibração. Calibrar na temperatura em que o sensor vai trabalhar também reduz o desvio.

Apesar do preço baixo, o MPU6050 abre a porta para a medição de movimento: primeiro conheça os valores brutos, depois calcule os ângulos e, por fim, suavize-os com um filtro. Para ver outros sensores I2C e para que servem, dê uma olhada no Guia de sensores para Arduino. No app BlueGrays você encontra projetos de controle de servo, display I2C, joystick e robôs, com esquemas do circuito e código passo a passo, que você pode combinar com o MPU6050.

Perguntas frequentes

Para que serve o MPU6050?

O MPU6050 mede a inclinação, a velocidade de rotação e a aceleração de um objeto. Ele é usado em robôs autoequilibrados, drones e gimbals, contadores de passos, detecção de quedas e impactos e jogos controlados por movimento.

O endereço do MPU6050 é 0x68 ou 0x69?

O endereço é 0x68 quando o pino AD0 está desconectado ou ligado ao GND, e 0x69 quando está ligado em 3,3 V. Na placa GY-521, o AD0 é puxado para o GND por um resistor, então o endereço padrão é 0x68. Para ter certeza, rode um sketch scanner I2C.

O MPU6050 funciona com 5 V?

O chip MPU6050 em si funciona com no máximo 3,46 V, mas, graças ao regulador da placa GY-521, o pino VCC pode receber 5 V. As linhas I2C ficam no nível de 3,3 V, que o Arduino Uno lê sem problemas. Placas simples sem regulador não podem receber 5 V.

Como calcular ângulos com o MPU6050?

Com o sensor parado, os ângulos vêm do acelerômetro com roll = atan2(ay, az) e pitch = atan2(−ax, √(ay² + az²)). Para resultados precisos durante o movimento, a velocidade angular do giroscópio é integrada ao longo do tempo e combinada com o ângulo do acelerômetro por um filtro complementar ou de Kalman.

O MPU6050 consegue medir o yaw?

Por períodos curtos, sim: o yaw pode ser calculado integrando a velocidade angular no eixo Z. Mas, como o MPU6050 não tem magnetômetro, o yaw se desvia com o tempo e não consegue saber a direção absoluta (o norte). Para uma direção estável você precisa de um sensor de bússola como o QMC5883L ou de uma IMU de 9 eixos.

Qual é a diferença entre o MPU6050 e o MPU9250?

O MPU6050 é um sensor de 6 eixos com acelerômetro e giroscópio. O MPU9250 adiciona um magnetômetro de 3 eixos, chegando a 9 eixos, e por isso mede o yaw sem desvio; ele também suporta SPI. Como o MPU9250 foi descontinuado, sucessores como o ICM-20948 são os preferidos em projetos novos.

Ver todos os projetos
Uso de servo motor
#35Iniciante
Premium

Uso de servo motor

O braço de um pequeno servo motor gira para três posições em sequência: o início, o meio e o fim do percurso, esperando dois segundos em cada parada. O Arduino informa ao motor em qual ângulo ficar, e

4.7(48)
67
Controle de servos com joystick
#60Intermediário
Premium

Controle de servos com joystick

Controle dois motores com um joystick, como ao girar uma câmera de segurança. Empurre a alavanca para os lados e o servo motor inferior gira lentamente; mova para cima ou para baixo e o servo superior

4.7(42)
58
Servo motor com ESP32 (controle por potenciômetro)
#118Intermediário
Premium

Servo motor com ESP32 (controle por potenciômetro)

Neste projeto, controlamos um servo motor SG90 com um potenciômetro. Ajustamos o ângulo do servo mapeando o valor analógico lido do potenciômetro para a faixa de 0 a 180 graus. A biblioteca ESP32Servo gera sinais para o servo nos GPIOs do ESP32 adequados e capazes de operar como saída; este projeto usa o GPIO 18. Esse é um método básico de controle para braços robóticos, estabilizadores de câmera e mecanismos de portas automáticas.

4.3(29)
42
Jogo de bola e raquetes - SSD1306
#86Intermediário
Premium

Jogo de bola e raquetes - SSD1306

Uma bola, duas raquetes e você: jogue tênis de mesa, um dos primeiros videogames, em um pequeno display OLED. Dois botões movem sua raquete à direita para cima e para baixo, enquanto o computador cont

4.5(47)
65
Uso do display LCD com I2C
#32Iniciante
Premium

Uso do display LCD com I2C

Dê ao seu Arduino um display próprio e faça-o escrever sua primeira mensagem. O display LCD de duas linhas é conectado com poucos fios; primeiro aparece uma saudação na linha de cima, depois uma segun

4.8(53)
70
Display LCD I2C com ESP32 (16x2)
#119Intermediário
Premium

Display LCD I2C com ESP32 (16x2)

Neste projeto, exibimos texto conectando um display LCD de 16x2 caracteres ao ESP32 pelo protocolo I2C. Com o I2C, controlamos o display usando apenas dois pinos de dados (SDA e SCL), dispensando o uso de seis ou mais pinos da conexão paralela tradicional. O código mostra uma mensagem fixa na primeira linha e um contador que aumenta a cada segundo na segunda linha. Na inicialização, também executamos um scanner I2C para mostrar o endereço do display no Monitor Serial (geralmente 0x27 ou 0x3F).

4.9(23)
40
Robô que desvia de obstáculos
#81Avançado
Premium

Robô que desvia de obstáculos

Que tal construir um veículo inteligente que encontra seu próprio caminho? O robô que desvia de obstáculos monitora o ambiente constantemente com o sensor ultrassônico na parte da frente. Ao encontrar

5.0(38)
49