MCU & FPGA Sensores MPU6050 em projetos reais: do “dado cru” ao ângulo (e preparando terreno para o DMP)

MPU6050 em projetos reais: do “dado cru” ao ângulo (e preparando terreno para o DMP)



Inclinação por acelerômetro: pitch e roll com trigonometria (vetor gravidade + atan2)

Quando o MPU6050 está parado (ou em movimento lento, sem acelerações lineares fortes), o acelerômetro mede principalmente o vetor da gravidade projetado nos eixos do sensor. Em outras palavras, o que você lê como \(a_x, a_y, a_z\) (em g ou m/s²) é, na maior parte do tempo, a “sombra” do vetor gravidade em cada eixo. A inclinação do corpo aparece porque, ao girar o sensor no espaço, a gravidade “muda de eixo” no referencial do sensor.

A trigonometria entra assim: se você imaginar o vetor gravidade com módulo próximo de 1 g, então os ângulos de inclinação podem ser obtidos pela relação entre componentes desse vetor. O motivo de usarmos atan2 e não atan é que atan2(y, x) resolve corretamente o quadrante (sinais) e se comporta melhor perto de divisões por zero. O resultado sai em radianos, e então convertemos para graus multiplicando por \(180/\pi\).

Modelo geométrico (sem inventar “mágica”)

Assumindo a convenção comum para IMUs: X para frente, Y para a esquerda e Z para cima (isso depende de como sua placa está desenhada, mas a matemática funciona igual), os ângulos mais usados são:

  • Roll (ϕ): rotação em torno do eixo X (como “inclinar a cabeça para o lado”).
  • Pitch (θ): rotação em torno do eixo Y (como “olhar para cima/baixo”).

Com base nas projeções do vetor gravidade, uma forma clássica e robusta de obter os ângulos pelo acelerômetro é:

\[
\phi = \text{atan2}(a_y, a_z)
\]

\[
\theta = \text{atan2}(-a_x, \sqrt{a_y^2 + a_z^2})
\]

Essas expressões surgem ao considerar que o vetor gravidade, no referencial do sensor, pode ser visto como um vetor 3D cuja direção determina a inclinação. O termo \(\sqrt{a_y^2 + a_z^2}\) funciona como uma “normalização parcial” que deixa o cálculo do pitch mais estável quando \(a_z\) se aproxima de zero.

Código em C: calcula pitch/roll a partir dos dados convertidos

Aqui eu vou usar a struct mpu6050_si_t que a gente já criou na seção anterior (valores em g). Se você estiver usando m/s², também funciona — o importante é que as proporções sejam preservadas. A única coisa que muda é que, em m/s², o vetor gravidade tem módulo ~9.80665 em repouso, mas a trigonometria usa as razões, então dá no mesmo.

#include <math.h>
#include <stdint.h>

typedef struct {
    float roll_deg;   // ϕ
    float pitch_deg;  // θ
} mpu6050_tilt_t;

/**
 * @brief Converte radianos para graus.
 */
static float rad2deg(float rad) {
    return rad * (180.0f / (float)M_PI);
}

/**
 * @brief Estima roll e pitch usando apenas o acelerômetro.
 *
 * Pressuposto: aceleração linear pequena (sensor parado ou movimento suave).
 * Se houver aceleração forte (ex.: chacoalhar, arrancar, frear), o ângulo “distorce”.
 */
void mpu6050_tilt_from_accel(const float ax_g,
                            const float ay_g,
                            const float az_g,
                            mpu6050_tilt_t *out)
{
    // Roll (ϕ): rotação em torno de X. Usa componentes Y e Z do vetor gravidade.
    const float roll_rad = atan2f(ay_g, az_g);

    // Pitch (θ): rotação em torno de Y.
    // O denominador sqrt(ay^2 + az^2) estabiliza o cálculo.
    const float denom = sqrtf(ay_g * ay_g + az_g * az_g);
    const float pitch_rad = atan2f(-ax_g, denom);

    out->roll_deg  = rad2deg(roll_rad);
    out->pitch_deg = rad2deg(pitch_rad);
}

Por que isso funciona (ligando matemática ao “mundo físico”)

Em repouso ideal, você tem aproximadamente \(\sqrt{a_x^2 + a_y^2 + a_z^2} \approx 1g\). Se o sensor estiver “de barriga para cima”, \(a_z\) tende a estar próximo de (+1) e \(a_x, a_y\) próximos de 0. Ao inclinar, parte dessa gravidade “escorre” para \(a_x\) e \(a_y\). O atan2 compara dois catetos do triângulo que você forma ao projetar esse vetor no plano adequado. No roll, por exemplo, você está olhando para o plano YZ: o ângulo no plano YZ é exatamente a inclinação em torno de X. No pitch, você olha o plano X contra a magnitude do “resto” (YZ) para obter um ângulo mais bem condicionado.

Um jeito prático de validar no osciloscópio/serial é conferir se, em repouso, o módulo fica próximo de 1 g e se os ângulos respondem “certinho” quando você inclina lentamente. Se você inclinar rápido ou der uma sacudida, o acelerômetro mede gravidade + aceleração linear, então a estimativa de ângulo “contamina” — isso não é bug, é a física do sensor.

Exemplo de uso (amarrando com a seção anterior)

Supondo que você já leu raw e converteu para si (como na primeira seção), o uso típico fica assim:

mpu6050_raw_t raw;
mpu6050_si_t  si;
mpu6050_tilt_t tilt;

if (mpu6050_read_raw(&raw)) {
    mpu6050_convert_to_si(&cfg, &raw, &si);

    mpu6050_tilt_from_accel(si.ax_g, si.ay_g, si.az_g, &tilt);

    // Agora você tem tilt.roll_deg e tilt.pitch_deg
    // Ex.: imprimir via UART, enviar por BLE, etc.
}
0 0 votos
Classificação do artigo
Inscrever-se
Notificar de
guest
0 Comentários
mais antigos
mais recentes Mais votado
Feedbacks embutidos
Ver todos os comentários

Related Post

Sensores de gases da série A2 da Alphasense: uma introdução aos riscos ambientais e à saúde humanaSensores de gases da série A2 da Alphasense: uma introdução aos riscos ambientais e à saúde humana

Aprenda como integrar sensores eletroquímicos da série A2 da Alphasense com o microcontrolador ESP32 utilizando o front-end analógico LMP91000. Um guia didático com exemplos de código, riscos ambientais dos gases

0
Adoraria saber sua opinião, comente.x