<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>posicionamento - MCU &amp; FPGA</title>
	<atom:link href="https://mcu.tec.br/categorias/algoritimos/posicionamento/feed/" rel="self" type="application/rss+xml" />
	<link>https://mcu.tec.br</link>
	<description>Microcontroladores &#38; FPGA</description>
	<lastBuildDate>Sun, 15 Feb 2026 12:28:03 +0000</lastBuildDate>
	<language>pt-BR</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=7.0</generator>

<image>
	<url>https://mcu.tec.br/wp-content/uploads/2025/02/Robo-para-o-site-MCU.tec_.br-512x512-1-150x150.png</url>
	<title>posicionamento - MCU &amp; FPGA</title>
	<link>https://mcu.tec.br</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>MPU9250: como usar uma IMU 9 eixos e extrair dados realmente “úteis”</title>
		<link>https://mcu.tec.br/algoritimos/posicionamento/mpu9250-como-usar-uma-imu-9-eixos-e-extrair-dados-realmente-uteis/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=mpu9250-como-usar-uma-imu-9-eixos-e-extrair-dados-realmente-uteis</link>
		
		<dc:creator><![CDATA[Carlos Delfino]]></dc:creator>
		<pubDate>Sun, 15 Feb 2026 12:27:33 +0000</pubDate>
				<category><![CDATA[posicionamento]]></category>
		<guid isPermaLink="false">https://mcu.tec.br/?p=1338</guid>

					<description><![CDATA[<p>Aprenda a usar o MPU9250, uma IMU de 9 eixos que integra acelerômetro, giroscópio e magnetômetro, para medir movimento e orientação em três dimensões com qualidade prática de engenharia. Este guia mostra como estruturar a aquisição de dados por I²C ou SPI, converter leituras cruas para unidades físicas, remover bias de giroscópio, lidar com ruído e aplicar filtragem eficiente em microcontroladores. Você verá como transformar sinais em informações úteis como roll, pitch e yaw, entendendo as projeções trigonométricas e por que o magnetômetro precisa de calibração para evitar erros de rumo. O artigo inclui exemplos de algoritmos em linguagem C, com arquitetura de firmware organizada, e finaliza com scripts em Python para visualizar eixos e conceitos geométricos 3D, servindo como referência para depuração e validação do seu pipeline.</p>
<p>The post <a href="https://mcu.tec.br/algoritimos/posicionamento/mpu9250-como-usar-uma-imu-9-eixos-e-extrair-dados-realmente-uteis/">MPU9250: como usar uma IMU 9 eixos e extrair dados realmente “úteis”</a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></description>
										<content:encoded><![CDATA[<p class="wp-block-paragraph">O MPU9250 ficou popular porque entrega, num único encapsulamento, um acelerômetro de 3 eixos, um giroscópio de 3 eixos e um magnetômetro de 3 eixos (na prática, são dois “dies”: o bloco accel/gyro e o AK8963 para bússola). Isso permite estimar orientação 3D (roll, pitch, yaw), detectar padrões de movimento, vibração e eventos transitórios, além de fornecer insumos para navegação inercial e estabilização. Ele é muito bom para aprendizado e prototipagem, mas hoje está marcado como fim de vida/NRND pela própria TDK/InvenSense, então a recomendação é não projetar produto novo em cima dele. (<a href="https://invensense.tdk.com/products/motion-tracking/9-axis/mpu-9250/?utm_source=chatgpt.com">TDK InvenSense</a>)</p>


<div class="wp-block-image">
<figure class="alignright size-full is-resized"><img fetchpriority="high" decoding="async" width="410" height="424" src="https://mcu.tec.br/wp-content/uploads/2026/02/image-34.png" alt="" class="wp-image-1339" style="aspect-ratio:0.967032967032967;width:330px;height:auto" srcset="https://mcu.tec.br/wp-content/uploads/2026/02/image-34.png 410w, https://mcu.tec.br/wp-content/uploads/2026/02/image-34-290x300.png 290w" sizes="(max-width: 410px) 100vw, 410px" /></figure>
</div>


<p class="wp-block-paragraph">A parte “enganosa” das IMUs é que ler registradores e imprimir “Ax, Ay, Az” quase nunca resolve o problema real. O valor está cru, com bias (offset), ruído, drift, saturação, escalas diferentes, e no caso do magnetômetro ainda existe distorção de hard-iron/soft-iron. O objetivo aqui é te mostrar um caminho de uso que funciona na prática: inicialização correta, aquisição consistente, calibração e, por fim, fusão de sensores para produzir orientação e métricas refinadas.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">1) Arquitetura do MPU9250 e o que isso muda no firmware</h3>



<p class="wp-block-paragraph">O MPU9250 tem dois “mundos” que você precisa coordenar:</p>



<ol class="wp-block-list">
<li><strong>Accel/Gyro</strong> (bloco principal) acessado direto pelo barramento do host (I²C ou SPI).</li>



<li><strong>Magnetômetro (AK8963)</strong> acessado de duas formas: ou você coloca o MPU em “pass-through / bypass” e fala direto com o AK8963 no endereço I²C <strong>0x0C</strong>, ou você usa o barramento auxiliar interno do MPU (modo “master”) para o MPU ler o magnetômetro e disponibilizar os dados ao host. A própria especificação descreve o uso do pass-through e cita explicitamente o endereço do AK8963. (<a href="https://invensense.tdk.com/wp-content/uploads/2015/02/PS-MPU-9250A-01-v1.1.pdf?utm_source=chatgpt.com">TDK InvenSense</a>)</li>
</ol>



<p class="wp-block-paragraph">Para simplificar e reduzir “magia” no início, muitos projetos usam <strong>pass-through</strong>: o host configura e lê o magnetômetro como se fosse outro dispositivo I²C no mesmo barramento. Isso também facilita depuração com ferramentas como <code>i2cdetect</code>, embora existam armadilhas de configuração.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">2) O “pipeline” certo: do dado cru ao dado refinado</h3>



<p class="wp-block-paragraph">Um pipeline robusto costuma seguir esta lógica (mesmo que você implemente em etapas):</p>



<ol class="wp-block-list">
<li><strong>Leitura atômica</strong> de accel/gyro (idealmente usando burst read para garantir coerência temporal).</li>



<li><strong>Conversão de escala</strong> (LSB → unidades físicas).</li>



<li><strong>Compensação de bias</strong> (offset) e, se necessário, escala fina (ganho).</li>



<li><strong>Filtragem leve</strong> (LPF) para reduzir ruído sem destruir dinâmica.</li>



<li><strong>Fusão de sensores</strong> para estimar orientação:
<ul class="wp-block-list">
<li>Complementary filter (simples e bom) para roll/pitch</li>



<li>Madgwick/Mahony (quaternions) para roll/pitch/yaw com magnetômetro</li>
</ul>
</li>



<li><strong>Calibração do magnetômetro</strong> (hard-iron/soft-iron) para yaw confiável.</li>
</ol>



<p class="wp-block-paragraph">A ideia é: se você pular a calibração e fusão, yaw vai “dançar”, gyro vai derivar e vibração vira um festival de falso-positivo.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">3) Base de firmware em C: leitura, escala e filtros</h2>



<p class="wp-block-paragraph">Abaixo vai um esqueleto que separa responsabilidades: driver (registradores) e processamento (algoritmos). Eu vou deixar as funções <code>i2c_read</code> e <code>i2c_write</code> como “portáveis” (você adapta para STM32 HAL, ESP-IDF, baremetal etc.).</p>



<h3 class="wp-block-heading">3.1 Tipos e constantes úteis</h3>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>#include &lt;stdint.h>
#include &lt;stdbool.h>
#include &lt;math.h>

/* Endereços I2C típicos do MPU9250: 0x68 (AD0=0) ou 0x69 (AD0=1). */
#define MPU9250_ADDR 0x68

/* Magnetômetro AK8963 no pass-through/bypass: 0x0C */
#define AK8963_ADDR  0x0C  /* citado na especificação do MPU9250 :contentReference&#91;oaicite:2&#93;{index=2} */

/* Exemplo de faixas (você escolhe conforme aplicação) */
typedef enum {
  ACC_FS_2G = 0,
  ACC_FS_4G,
  ACC_FS_8G,
  ACC_FS_16G
} acc_fs_t;

typedef enum {
  GYR_FS_250DPS = 0,
  GYR_FS_500DPS,
  GYR_FS_1000DPS,
  GYR_FS_2000DPS
} gyr_fs_t;

typedef struct {
  float ax, ay, az;   /* m/s^2 */
  float gx, gy, gz;   /* rad/s */
  float mx, my, mz;   /* uT (ou unidade relativa, depende do seu fator) */
  float temp_c;
  uint32_t t_us;      /* timestamp (opcional) */
} imu_sample_t;

typedef struct {
  /* Bias estimado (offset) */
  float acc_bias&#91;3&#93;;
  float gyr_bias&#91;3&#93;;
  float mag_bias&#91;3&#93;;

  /* Matriz 3x3 de correção do magnetômetro (soft-iron) */
  float mag_softiron&#91;3&#93;&#91;3&#93;;

  /* Fatores de escala em unidades físicas por LSB */
  float acc_lsb_to_mps2;
  float gyr_lsb_to_rads;
  float mag_lsb_to_uT; /* depende do modo do AK8963 e do datasheet dele */
} imu_cal_t;
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">#</span><span style="color: #D8DEE9">include</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&lt;</span><span style="color: #D8DEE9">stdint</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">h</span><span style="color: #81A1C1">&gt;</span></span>
<span class="line"><span style="color: #D8DEE9FF">#</span><span style="color: #D8DEE9">include</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&lt;</span><span style="color: #D8DEE9">stdbool</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">h</span><span style="color: #81A1C1">&gt;</span></span>
<span class="line"><span style="color: #D8DEE9FF">#</span><span style="color: #D8DEE9">include</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&lt;</span><span style="color: #D8DEE9">math</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">h</span><span style="color: #81A1C1">&gt;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88">/* Endereços I2C típicos do MPU9250: 0x68 (AD0=0) ou 0x69 (AD0=1). */</span></span>
<span class="line"><span style="color: #D8DEE9FF">#</span><span style="color: #D8DEE9">define</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">MPU9250_ADDR</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0x68</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88">/* Magnetômetro AK8963 no pass-through/bypass: 0x0C */</span></span>
<span class="line"><span style="color: #D8DEE9FF">#</span><span style="color: #D8DEE9">define</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">AK8963_ADDR</span><span style="color: #D8DEE9FF">  </span><span style="color: #B48EAD">0x0C</span><span style="color: #D8DEE9FF">  </span><span style="color: #616E88">/* citado na especificação do MPU9250 :contentReference&#91;oaicite:2&#93;{index=2} */</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88">/* Exemplo de faixas (você escolhe conforme aplicação) */</span></span>
<span class="line"><span style="color: #D8DEE9">typedef</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">enum</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #D8DEE9">ACC_FS_2G</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #D8DEE9">ACC_FS_4G</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #D8DEE9">ACC_FS_8G</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #D8DEE9">ACC_FS_16G</span></span>
<span class="line"><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">acc_fs_t</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9">typedef</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">enum</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #D8DEE9">GYR_FS_250DPS</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #D8DEE9">GYR_FS_500DPS</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #D8DEE9">GYR_FS_1000DPS</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #D8DEE9">GYR_FS_2000DPS</span></span>
<span class="line"><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">gyr_fs_t</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9">typedef</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">struct</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #D8DEE9">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">ax</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">ay</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">az</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF">   </span><span style="color: #616E88">/* m/s^2 */</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #D8DEE9">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">gx</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">gy</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">gz</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF">   </span><span style="color: #616E88">/* rad/s */</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #D8DEE9">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">mx</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">my</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">mz</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF">   </span><span style="color: #616E88">/* uT (ou unidade relativa, depende do seu fator) */</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #D8DEE9">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">temp_c</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #D8DEE9">uint32_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">t_us</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF">      </span><span style="color: #616E88">/* timestamp (opcional) */</span></span>
<span class="line"><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">imu_sample_t</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9">typedef</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">struct</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #616E88">/* Bias estimado (offset) */</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #D8DEE9">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">acc_bias</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #B48EAD">3</span><span style="color: #D8DEE9FF">&#93;</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #D8DEE9">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">gyr_bias</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #B48EAD">3</span><span style="color: #D8DEE9FF">&#93;</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #D8DEE9">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">mag_bias</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #B48EAD">3</span><span style="color: #D8DEE9FF">&#93;</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #616E88">/* Matriz 3x3 de correção do magnetômetro (soft-iron) */</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #D8DEE9">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">mag_softiron</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #B48EAD">3</span><span style="color: #D8DEE9FF">&#93;&#91;</span><span style="color: #B48EAD">3</span><span style="color: #D8DEE9FF">&#93;</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #616E88">/* Fatores de escala em unidades físicas por LSB */</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #D8DEE9">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">acc_lsb_to_mps2</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #D8DEE9">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">gyr_lsb_to_rads</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #D8DEE9">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">mag_lsb_to_uT</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF"> </span><span style="color: #616E88">/* depende do modo do AK8963 e do datasheet dele */</span></span>
<span class="line"><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">imu_cal_t</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span></code></pre></div>



<h3 class="wp-block-heading">3.2 Funções “portáveis” de barramento</h3>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>/**
 * @brief Lê N bytes de um registrador.
 * @return true se sucesso.
 */
bool i2c_read(uint8_t dev, uint8_t reg, uint8_t *buf, uint16_t len);

/**
 * @brief Escreve 1 byte em um registrador.
 */
bool i2c_write(uint8_t dev, uint8_t reg, uint8_t value);
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #616E88">/**</span></span>
<span class="line"><span style="color: #616E88"> * </span><span style="color: #ECEFF4">@</span><span style="color: #8FBCBB">brief</span><span style="color: #616E88"> Lê N bytes de um registrador.</span></span>
<span class="line"><span style="color: #616E88"> * </span><span style="color: #ECEFF4">@</span><span style="color: #8FBCBB">return</span><span style="color: #616E88"> true se sucesso.</span></span>
<span class="line"><span style="color: #616E88"> */</span></span>
<span class="line"><span style="color: #D8DEE9">bool</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">i2c_read</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">uint8_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">dev</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">uint8_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">reg</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">uint8_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">buf</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">uint16_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">len</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88">/**</span></span>
<span class="line"><span style="color: #616E88"> * </span><span style="color: #ECEFF4">@</span><span style="color: #8FBCBB">brief</span><span style="color: #616E88"> Escreve 1 byte em um registrador.</span></span>
<span class="line"><span style="color: #616E88"> */</span></span>
<span class="line"><span style="color: #D8DEE9">bool</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">i2c_write</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">uint8_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">dev</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">uint8_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">reg</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">uint8_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">value</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span></code></pre></div>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">4) Inicialização prática: o mínimo que evita dor de cabeça</h2>



<p class="wp-block-paragraph">Aqui entram três pontos: clock, ranges e habilitar leitura coerente. Para o magnetômetro via pass-through, você também precisa habilitar o bypass no MPU e configurar o AK8963. O documento de especificação descreve o “pass-through mode” justamente para permitir que o host acesse o AK8963 diretamente. (<a href="https://invensense.tdk.com/wp-content/uploads/2015/02/PS-MPU-9250A-01-v1.1.pdf?utm_source=chatgpt.com">TDK InvenSense</a>)</p>



<p class="wp-block-paragraph"><strong>Observação importante:</strong> os endereços de registradores (PWR_MGMT_1, INT_PIN_CFG etc.) ficam no register map do MPU9250. Se você já usa uma lib, ótimo; se não, use o RM oficial para confirmar endereços e bits. (<a href="https://invensense.tdk.com/wp-content/uploads/2015/02/RM-MPU-9250A-00-v1.6.pdf?utm_source=chatgpt.com">TDK InvenSense</a>)</p>



<p class="wp-block-paragraph">Exemplo (conceitual, com registradores “nomeados” via defines que você tiraria do RM):</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>/* Estes defines você deve mapear pelo Register Map oficial. :contentReference&#91;oaicite:5&#93;{index=5} */
#define REG_PWR_MGMT_1     0x6B
#define REG_PWR_MGMT_2     0x6C
#define REG_CONFIG         0x1A
#define REG_GYRO_CONFIG    0x1B
#define REG_ACCEL_CONFIG   0x1C
#define REG_ACCEL_CONFIG2  0x1D
#define REG_INT_PIN_CFG    0x37
#define REG_USER_CTRL      0x6A

/* Bits típicos: consultar RM */
#define BIT_BYPASS_EN      0x02  /* INT_PIN_CFG */
#define BIT_I2C_MST_EN     0x20  /* USER_CTRL (se usar master interno) */

static bool mpu9250_init_basic(acc_fs_t acc_fs, gyr_fs_t gyr_fs)
{
  /* 1) Acorda o chip e seleciona clock (ex.: PLL) */
  if (!i2c_write(MPU9250_ADDR, REG_PWR_MGMT_1, 0x01)) return false;

  /* 2) Configura filtros digitais (DLPF) conforme seu fs e ruído */
  if (!i2c_write(MPU9250_ADDR, REG_CONFIG, 0x03)) return false;

  /* 3) Faixa do giroscópio */
  uint8_t gcfg = (uint8_t)(gyr_fs &lt;&lt; 3);
  if (!i2c_write(MPU9250_ADDR, REG_GYRO_CONFIG, gcfg)) return false;

  /* 4) Faixa do acelerômetro */
  uint8_t acfg = (uint8_t)(acc_fs &lt;&lt; 3);
  if (!i2c_write(MPU9250_ADDR, REG_ACCEL_CONFIG, acfg)) return false;

  /* 5) Config do accel DLPF */
  if (!i2c_write(MPU9250_ADDR, REG_ACCEL_CONFIG2, 0x03)) return false;

  return true;
}

/* Habilita pass-through para acessar AK8963 direto no I2C (0x0C). :contentReference&#91;oaicite:6&#93;{index=6} */
static bool mpu9250_enable_mag_passthrough(void)
{
  /* Desabilita master interno (se estiver ligado) e ativa bypass */
  if (!i2c_write(MPU9250_ADDR, REG_USER_CTRL, 0x00)) return false;
  if (!i2c_write(MPU9250_ADDR, REG_INT_PIN_CFG, BIT_BYPASS_EN)) return false;
  return true;
}
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #616E88">/* Estes defines você deve mapear pelo Register Map oficial. :contentReference&#91;oaicite:5&#93;{index=5} */</span></span>
<span class="line"><span style="color: #D8DEE9FF">#</span><span style="color: #D8DEE9">define</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">REG_PWR_MGMT_1</span><span style="color: #D8DEE9FF">     </span><span style="color: #B48EAD">0x6B</span></span>
<span class="line"><span style="color: #D8DEE9FF">#</span><span style="color: #D8DEE9">define</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">REG_PWR_MGMT_2</span><span style="color: #D8DEE9FF">     </span><span style="color: #B48EAD">0x6C</span></span>
<span class="line"><span style="color: #D8DEE9FF">#</span><span style="color: #D8DEE9">define</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">REG_CONFIG</span><span style="color: #D8DEE9FF">         </span><span style="color: #B48EAD">0x1A</span></span>
<span class="line"><span style="color: #D8DEE9FF">#</span><span style="color: #D8DEE9">define</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">REG_GYRO_CONFIG</span><span style="color: #D8DEE9FF">    </span><span style="color: #B48EAD">0x1B</span></span>
<span class="line"><span style="color: #D8DEE9FF">#</span><span style="color: #D8DEE9">define</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">REG_ACCEL_CONFIG</span><span style="color: #D8DEE9FF">   </span><span style="color: #B48EAD">0x1C</span></span>
<span class="line"><span style="color: #D8DEE9FF">#</span><span style="color: #D8DEE9">define</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">REG_ACCEL_CONFIG2</span><span style="color: #D8DEE9FF">  </span><span style="color: #B48EAD">0x1D</span></span>
<span class="line"><span style="color: #D8DEE9FF">#</span><span style="color: #D8DEE9">define</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">REG_INT_PIN_CFG</span><span style="color: #D8DEE9FF">    </span><span style="color: #B48EAD">0x37</span></span>
<span class="line"><span style="color: #D8DEE9FF">#</span><span style="color: #D8DEE9">define</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">REG_USER_CTRL</span><span style="color: #D8DEE9FF">      </span><span style="color: #B48EAD">0x6A</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88">/* Bits típicos: consultar RM */</span></span>
<span class="line"><span style="color: #D8DEE9FF">#</span><span style="color: #D8DEE9">define</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">BIT_BYPASS_EN</span><span style="color: #D8DEE9FF">      </span><span style="color: #B48EAD">0x02</span><span style="color: #D8DEE9FF">  </span><span style="color: #616E88">/* INT_PIN_CFG */</span></span>
<span class="line"><span style="color: #D8DEE9FF">#</span><span style="color: #D8DEE9">define</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">BIT_I2C_MST_EN</span><span style="color: #D8DEE9FF">     </span><span style="color: #B48EAD">0x20</span><span style="color: #D8DEE9FF">  </span><span style="color: #616E88">/* USER_CTRL (se usar master interno) */</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9">static</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">bool</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">mpu9250_init_basic</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">acc_fs_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">acc_fs</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">gyr_fs_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">gyr_fs</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #616E88">/* 1) Acorda o chip e seleciona clock (ex.: PLL) */</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #81A1C1">!</span><span style="color: #88C0D0">i2c_write</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">MPU9250_ADDR</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">REG_PWR_MGMT_1</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0x01</span><span style="color: #D8DEE9FF">)) </span><span style="color: #81A1C1">return</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">false;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #616E88">/* 2) Configura filtros digitais (DLPF) conforme seu fs e ruído */</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #81A1C1">!</span><span style="color: #88C0D0">i2c_write</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">MPU9250_ADDR</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">REG_CONFIG</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0x03</span><span style="color: #D8DEE9FF">)) </span><span style="color: #81A1C1">return</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">false;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #616E88">/* 3) Faixa do giroscópio */</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #D8DEE9">uint8_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">gcfg</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">uint8_t</span><span style="color: #D8DEE9FF">)(</span><span style="color: #D8DEE9">gyr_fs</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&lt;&lt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">3</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #81A1C1">!</span><span style="color: #88C0D0">i2c_write</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">MPU9250_ADDR</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">REG_GYRO_CONFIG</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">gcfg</span><span style="color: #D8DEE9FF">)) </span><span style="color: #81A1C1">return</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">false;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #616E88">/* 4) Faixa do acelerômetro */</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #D8DEE9">uint8_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">acfg</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">uint8_t</span><span style="color: #D8DEE9FF">)(</span><span style="color: #D8DEE9">acc_fs</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&lt;&lt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">3</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #81A1C1">!</span><span style="color: #88C0D0">i2c_write</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">MPU9250_ADDR</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">REG_ACCEL_CONFIG</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">acfg</span><span style="color: #D8DEE9FF">)) </span><span style="color: #81A1C1">return</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">false;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #616E88">/* 5) Config do accel DLPF */</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #81A1C1">!</span><span style="color: #88C0D0">i2c_write</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">MPU9250_ADDR</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">REG_ACCEL_CONFIG2</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0x03</span><span style="color: #D8DEE9FF">)) </span><span style="color: #81A1C1">return</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">false;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #81A1C1">return</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">true;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88">/* Habilita pass-through para acessar AK8963 direto no I2C (0x0C). :contentReference&#91;oaicite:6&#93;{index=6} */</span></span>
<span class="line"><span style="color: #D8DEE9">static</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">bool</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">mpu9250_enable_mag_passthrough</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #616E88">/* Desabilita master interno (se estiver ligado) e ativa bypass */</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #81A1C1">!</span><span style="color: #88C0D0">i2c_write</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">MPU9250_ADDR</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">REG_USER_CTRL</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0x00</span><span style="color: #D8DEE9FF">)) </span><span style="color: #81A1C1">return</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">false;</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #81A1C1">!</span><span style="color: #88C0D0">i2c_write</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">MPU9250_ADDR</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">REG_INT_PIN_CFG</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">BIT_BYPASS_EN</span><span style="color: #D8DEE9FF">)) </span><span style="color: #81A1C1">return</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">false;</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #81A1C1">return</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">true;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span></code></pre></div>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">5) Aquisição coerente: burst read e conversão para unidades físicas</h2>



<p class="wp-block-paragraph">A leitura ideal é em “bloco”, porque isso reduz a chance de pegar metade do sample antigo e metade do novo (especialmente quando você lê eixos separados).</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>#define REG_ACCEL_XOUT_H 0x3B  /* base do bloco accel/temp/gyro no RM */

/* Layout típico do burst: accel(6), temp(2), gyro(6) => 14 bytes */
static bool mpu9250_read_accel_gyro_raw(int16_t acc&#91;3&#93;, int16_t gyr&#91;3&#93;, int16_t *temp)
{
  uint8_t buf&#91;14&#93;;
  if (!i2c_read(MPU9250_ADDR, REG_ACCEL_XOUT_H, buf, 14)) return false;

  acc&#91;0&#93; = (int16_t)((buf&#91;0&#93; &lt;&lt; 8) | buf&#91;1&#93;);
  acc&#91;1&#93; = (int16_t)((buf&#91;2&#93; &lt;&lt; 8) | buf&#91;3&#93;);
  acc&#91;2&#93; = (int16_t)((buf&#91;4&#93; &lt;&lt; 8) | buf&#91;5&#93;);

  *temp = (int16_t)((buf&#91;6&#93; &lt;&lt; 8) | buf&#91;7&#93;);

  gyr&#91;0&#93; = (int16_t)((buf&#91;8&#93;  &lt;&lt; 8) | buf&#91;9&#93;);
  gyr&#91;1&#93; = (int16_t)((buf&#91;10&#93; &lt;&lt; 8) | buf&#91;11&#93;);
  gyr&#91;2&#93; = (int16_t)((buf&#91;12&#93; &lt;&lt; 8) | buf&#91;13&#93;);

  return true;
}

/* Converte valores crus para físico, já aplicando bias */
static void imu_convert_apply_cal(
  const int16_t acc_raw&#91;3&#93;,
  const int16_t gyr_raw&#91;3&#93;,
  const imu_cal_t *cal,
  float acc_mps2&#91;3&#93;,
  float gyr_rads&#91;3&#93;
){
  /* LSB -> unidade e remove bias */
  for (int i = 0; i &lt; 3; i++) {
    acc_mps2&#91;i&#93; = (float)acc_raw&#91;i&#93; * cal->acc_lsb_to_mps2 - cal->acc_bias&#91;i&#93;;
    gyr_rads&#91;i&#93; = (float)gyr_raw&#91;i&#93; * cal->gyr_lsb_to_rads - cal->gyr_bias&#91;i&#93;;
  }
}
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">#</span><span style="color: #D8DEE9">define</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">REG_ACCEL_XOUT_H</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0x3B</span><span style="color: #D8DEE9FF">  </span><span style="color: #616E88">/* base do bloco accel/temp/gyro no RM */</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88">/* Layout típico do burst: accel(6), temp(2), gyro(6) =&gt; 14 bytes */</span></span>
<span class="line"><span style="color: #D8DEE9">static</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">bool</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">mpu9250_read_accel_gyro_raw</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">int16_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">acc</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #B48EAD">3</span><span style="color: #D8DEE9FF">&#93;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">int16_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">gyr</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #B48EAD">3</span><span style="color: #D8DEE9FF">&#93;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">int16_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">temp</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #D8DEE9">uint8_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">buf</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #B48EAD">14</span><span style="color: #D8DEE9FF">&#93;</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #81A1C1">!</span><span style="color: #88C0D0">i2c_read</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">MPU9250_ADDR</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">REG_ACCEL_XOUT_H</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">buf</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">14</span><span style="color: #D8DEE9FF">)) </span><span style="color: #81A1C1">return</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">false;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #D8DEE9">acc</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #B48EAD">0</span><span style="color: #D8DEE9FF">&#93; </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">int16_t</span><span style="color: #D8DEE9FF">)((</span><span style="color: #D8DEE9">buf</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #B48EAD">0</span><span style="color: #D8DEE9FF">&#93; </span><span style="color: #81A1C1">&lt;&lt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">8</span><span style="color: #D8DEE9FF">) </span><span style="color: #81A1C1">|</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">buf</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #B48EAD">1</span><span style="color: #D8DEE9FF">&#93;)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #D8DEE9">acc</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #B48EAD">1</span><span style="color: #D8DEE9FF">&#93; </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">int16_t</span><span style="color: #D8DEE9FF">)((</span><span style="color: #D8DEE9">buf</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #B48EAD">2</span><span style="color: #D8DEE9FF">&#93; </span><span style="color: #81A1C1">&lt;&lt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">8</span><span style="color: #D8DEE9FF">) </span><span style="color: #81A1C1">|</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">buf</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #B48EAD">3</span><span style="color: #D8DEE9FF">&#93;)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #D8DEE9">acc</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #B48EAD">2</span><span style="color: #D8DEE9FF">&#93; </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">int16_t</span><span style="color: #D8DEE9FF">)((</span><span style="color: #D8DEE9">buf</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #B48EAD">4</span><span style="color: #D8DEE9FF">&#93; </span><span style="color: #81A1C1">&lt;&lt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">8</span><span style="color: #D8DEE9FF">) </span><span style="color: #81A1C1">|</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">buf</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #B48EAD">5</span><span style="color: #D8DEE9FF">&#93;)</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">temp</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">int16_t</span><span style="color: #D8DEE9FF">)((</span><span style="color: #D8DEE9">buf</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #B48EAD">6</span><span style="color: #D8DEE9FF">&#93; </span><span style="color: #81A1C1">&lt;&lt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">8</span><span style="color: #D8DEE9FF">) </span><span style="color: #81A1C1">|</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">buf</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #B48EAD">7</span><span style="color: #D8DEE9FF">&#93;)</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #D8DEE9">gyr</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #B48EAD">0</span><span style="color: #D8DEE9FF">&#93; </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">int16_t</span><span style="color: #D8DEE9FF">)((</span><span style="color: #D8DEE9">buf</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #B48EAD">8</span><span style="color: #D8DEE9FF">&#93;  </span><span style="color: #81A1C1">&lt;&lt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">8</span><span style="color: #D8DEE9FF">) </span><span style="color: #81A1C1">|</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">buf</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #B48EAD">9</span><span style="color: #D8DEE9FF">&#93;)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #D8DEE9">gyr</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #B48EAD">1</span><span style="color: #D8DEE9FF">&#93; </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">int16_t</span><span style="color: #D8DEE9FF">)((</span><span style="color: #D8DEE9">buf</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #B48EAD">10</span><span style="color: #D8DEE9FF">&#93; </span><span style="color: #81A1C1">&lt;&lt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">8</span><span style="color: #D8DEE9FF">) </span><span style="color: #81A1C1">|</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">buf</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #B48EAD">11</span><span style="color: #D8DEE9FF">&#93;)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #D8DEE9">gyr</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #B48EAD">2</span><span style="color: #D8DEE9FF">&#93; </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">int16_t</span><span style="color: #D8DEE9FF">)((</span><span style="color: #D8DEE9">buf</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #B48EAD">12</span><span style="color: #D8DEE9FF">&#93; </span><span style="color: #81A1C1">&lt;&lt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">8</span><span style="color: #D8DEE9FF">) </span><span style="color: #81A1C1">|</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">buf</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #B48EAD">13</span><span style="color: #D8DEE9FF">&#93;)</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #81A1C1">return</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">true;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88">/* Converte valores crus para físico, já aplicando bias */</span></span>
<span class="line"><span style="color: #D8DEE9">static</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">imu_convert_apply_cal</span><span style="color: #D8DEE9FF">(</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #D8DEE9">const</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">int16_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">acc_raw</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #B48EAD">3</span><span style="color: #D8DEE9FF">&#93;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #D8DEE9">const</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">int16_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">gyr_raw</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #B48EAD">3</span><span style="color: #D8DEE9FF">&#93;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #D8DEE9">const</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">imu_cal_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">cal</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #D8DEE9">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">acc_mps2</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #B48EAD">3</span><span style="color: #D8DEE9FF">&#93;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #D8DEE9">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">gyr_rads</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #B48EAD">3</span><span style="color: #D8DEE9FF">&#93;</span></span>
<span class="line"><span style="color: #D8DEE9FF">)</span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #616E88">/* LSB -&gt; unidade e remove bias */</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #81A1C1">for</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">int</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">i</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">i</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&lt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">3</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">i</span><span style="color: #81A1C1">++</span><span style="color: #D8DEE9FF">) </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">acc_mps2</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #D8DEE9">i</span><span style="color: #D8DEE9FF">&#93; </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">float</span><span style="color: #D8DEE9FF">)</span><span style="color: #D8DEE9">acc_raw</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #D8DEE9">i</span><span style="color: #D8DEE9FF">&#93; </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">cal</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">acc_lsb_to_mps2</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">cal</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">acc_bias</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #D8DEE9">i</span><span style="color: #D8DEE9FF">&#93;</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">gyr_rads</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #D8DEE9">i</span><span style="color: #D8DEE9FF">&#93; </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">float</span><span style="color: #D8DEE9FF">)</span><span style="color: #D8DEE9">gyr_raw</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #D8DEE9">i</span><span style="color: #D8DEE9FF">&#93; </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">cal</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">gyr_lsb_to_rads</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">cal</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">gyr_bias</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #D8DEE9">i</span><span style="color: #D8DEE9FF">&#93;</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span></code></pre></div>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">6) Calibração essencial: bias do giroscópio e “leveling” do acelerômetro</h2>



<h3 class="wp-block-heading">6.1 Bias do giroscópio (parado)</h3>



<p class="wp-block-paragraph">O gyro sempre tem um offset. Se você integrar gyro “cru”, a orientação deriva mesmo com o sensor parado. O método mais robusto para começar é: durante 2–5 s com o dispositivo imóvel, calcule a média de Gx,Gy,Gz e chame isso de bias.</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>static void calibrate_gyro_bias(imu_cal_t *cal, int samples, float dt_s)
{
  (void)dt_s; /* aqui dt não é necessário, mas você pode checar estabilidade */
  double sum&#91;3&#93; = {0,0,0};

  for (int n = 0; n &lt; samples; n++) {
    int16_t acc_raw&#91;3&#93;, gyr_raw&#91;3&#93;, temp_raw;
    if (!mpu9250_read_accel_gyro_raw(acc_raw, gyr_raw, &amp;temp_raw)) continue;

    sum&#91;0&#93; += (double)gyr_raw&#91;0&#93;;
    sum&#91;1&#93; += (double)gyr_raw&#91;1&#93;;
    sum&#91;2&#93; += (double)gyr_raw&#91;2&#93;;
  }

  cal->gyr_bias&#91;0&#93; = (float)(sum&#91;0&#93;/samples) * cal->gyr_lsb_to_rads;
  cal->gyr_bias&#91;1&#93; = (float)(sum&#91;1&#93;/samples) * cal->gyr_lsb_to_rads;
  cal->gyr_bias&#91;2&#93; = (float)(sum&#91;2&#93;/samples) * cal->gyr_lsb_to_rads;
}
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9">static</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">calibrate_gyro_bias</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">imu_cal_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">cal</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">int</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">samples</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">dt_s</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">  (</span><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF">)</span><span style="color: #D8DEE9">dt_s</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF"> </span><span style="color: #616E88">/* aqui dt não é necessário, mas você pode checar estabilidade */</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #D8DEE9">double</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">sum</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #B48EAD">3</span><span style="color: #D8DEE9FF">&#93; </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span><span style="color: #B48EAD">0</span><span style="color: #ECEFF4">,</span><span style="color: #B48EAD">0</span><span style="color: #ECEFF4">,</span><span style="color: #B48EAD">0</span><span style="color: #ECEFF4">}</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #81A1C1">for</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">int</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">n</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">n</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&lt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">samples</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">n</span><span style="color: #81A1C1">++</span><span style="color: #D8DEE9FF">) </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">int16_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">acc_raw</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #B48EAD">3</span><span style="color: #D8DEE9FF">&#93;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">gyr_raw</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #B48EAD">3</span><span style="color: #D8DEE9FF">&#93;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">temp_raw</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #81A1C1">!</span><span style="color: #88C0D0">mpu9250_read_accel_gyro_raw</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">acc_raw</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">gyr_raw</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">temp_raw</span><span style="color: #D8DEE9FF">)) </span><span style="color: #81A1C1">continue;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">sum</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #B48EAD">0</span><span style="color: #D8DEE9FF">&#93; </span><span style="color: #81A1C1">+=</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">double</span><span style="color: #D8DEE9FF">)</span><span style="color: #D8DEE9">gyr_raw</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #B48EAD">0</span><span style="color: #D8DEE9FF">&#93;</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">sum</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #B48EAD">1</span><span style="color: #D8DEE9FF">&#93; </span><span style="color: #81A1C1">+=</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">double</span><span style="color: #D8DEE9FF">)</span><span style="color: #D8DEE9">gyr_raw</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #B48EAD">1</span><span style="color: #D8DEE9FF">&#93;</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">sum</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #B48EAD">2</span><span style="color: #D8DEE9FF">&#93; </span><span style="color: #81A1C1">+=</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">double</span><span style="color: #D8DEE9FF">)</span><span style="color: #D8DEE9">gyr_raw</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #B48EAD">2</span><span style="color: #D8DEE9FF">&#93;</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #ECEFF4">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #D8DEE9">cal</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">gyr_bias</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #B48EAD">0</span><span style="color: #D8DEE9FF">&#93; </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">float</span><span style="color: #D8DEE9FF">)(</span><span style="color: #D8DEE9">sum</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #B48EAD">0</span><span style="color: #D8DEE9FF">&#93;</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9">samples</span><span style="color: #D8DEE9FF">) </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">cal</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">gyr_lsb_to_rads</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #D8DEE9">cal</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">gyr_bias</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #B48EAD">1</span><span style="color: #D8DEE9FF">&#93; </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">float</span><span style="color: #D8DEE9FF">)(</span><span style="color: #D8DEE9">sum</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #B48EAD">1</span><span style="color: #D8DEE9FF">&#93;</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9">samples</span><span style="color: #D8DEE9FF">) </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">cal</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">gyr_lsb_to_rads</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #D8DEE9">cal</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">gyr_bias</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #B48EAD">2</span><span style="color: #D8DEE9FF">&#93; </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">float</span><span style="color: #D8DEE9FF">)(</span><span style="color: #D8DEE9">sum</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #B48EAD">2</span><span style="color: #D8DEE9FF">&#93;</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9">samples</span><span style="color: #D8DEE9FF">) </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">cal</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">gyr_lsb_to_rads</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span></code></pre></div>


<div class="wp-block-image">
<figure class="alignleft size-full"><img decoding="async" width="454" height="421" src="https://mcu.tec.br/wp-content/uploads/2026/02/image-35.png" alt="" class="wp-image-1340" srcset="https://mcu.tec.br/wp-content/uploads/2026/02/image-35.png 454w, https://mcu.tec.br/wp-content/uploads/2026/02/image-35-300x278.png 300w" sizes="(max-width: 454px) 100vw, 454px" /></figure>
</div>


<p class="wp-block-paragraph">Para o acelerômetro, o bias depende muito de como você define “referência”: em repouso, ele mede gravidade projetada no frame do sensor. Um jeito prático: faça uma calibração simples em repouso com o sensor em uma orientação conhecida (por exemplo, Z apontando para cima), e ajuste apenas o eixo da gravidade. Para calibração “de verdade”, você faz a técnica de 6 faces (±X, ±Y, ±Z), mas isso já vira um procedimento de bancada.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">7) Filtro passa-baixa simples (IIR) e por que ele é suficiente em muita coisa</h2>



<p class="wp-block-paragraph">Em IMU, um filtro IIR de 1ª ordem é o “feijão com arroz” porque custa quase nada e reduz ruído.</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>typedef struct {
  float y&#91;3&#93;;
  float alpha; /* 0..1  (quanto menor, mais filtrado) */
} lpf1_t;

static void lpf1_init(lpf1_t *f, float alpha)
{
  f->alpha = alpha;
  f->y&#91;0&#93; = f->y&#91;1&#93; = f->y&#91;2&#93; = 0.0f;
}

static void lpf1_update(lpf1_t *f, const float x&#91;3&#93;, float out&#91;3&#93;)
{
  for (int i = 0; i &lt; 3; i++) {
    f->y&#91;i&#93; = f->alpha * f->y&#91;i&#93; + (1.0f - f->alpha) * x&#91;i&#93;;
    out&#91;i&#93; = f->y&#91;i&#93;;
  }
}
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9">typedef</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">struct</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #D8DEE9">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">y</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #B48EAD">3</span><span style="color: #D8DEE9FF">&#93;</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #D8DEE9">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">alpha</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF"> </span><span style="color: #616E88">/* 0..1  (quanto menor, mais filtrado) */</span></span>
<span class="line"><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">lpf1_t</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9">static</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">lpf1_init</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">lpf1_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">f</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">alpha</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #D8DEE9">f</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">alpha</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">alpha</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #D8DEE9">f</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">y</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #B48EAD">0</span><span style="color: #D8DEE9FF">&#93; </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">f</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">y</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #B48EAD">1</span><span style="color: #D8DEE9FF">&#93; </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">f</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">y</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #B48EAD">2</span><span style="color: #D8DEE9FF">&#93; </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> 0</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">0</span><span style="color: #D8DEE9">f</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9">static</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">lpf1_update</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">lpf1_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">f</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">const</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">x</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #B48EAD">3</span><span style="color: #D8DEE9FF">&#93;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">out</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #B48EAD">3</span><span style="color: #D8DEE9FF">&#93;)</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #81A1C1">for</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">int</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">i</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">i</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&lt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">3</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">i</span><span style="color: #81A1C1">++</span><span style="color: #D8DEE9FF">) </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">f</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">y</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #D8DEE9">i</span><span style="color: #D8DEE9FF">&#93; </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">f</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">alpha</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">f</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">y</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #D8DEE9">i</span><span style="color: #D8DEE9FF">&#93; </span><span style="color: #81A1C1">+</span><span style="color: #D8DEE9FF"> (1</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">0</span><span style="color: #D8DEE9">f</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">f</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">alpha</span><span style="color: #D8DEE9FF">) </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">x</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #D8DEE9">i</span><span style="color: #D8DEE9FF">&#93;</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">out</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #D8DEE9">i</span><span style="color: #D8DEE9FF">&#93; </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">f</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">y</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #D8DEE9">i</span><span style="color: #D8DEE9FF">&#93;</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #ECEFF4">}</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">Escolha de <code>alpha</code>: se seu loop é 200 Hz, <code>alpha</code> entre 0,85 e 0,98 costuma funcionar bem para suavizar sem “matar” dinâmica. Para vibração e manutenção preditiva, você pode filtrar menos (alpha menor) e trabalhar com FFT/PSD em janelas curtas.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">8) Orientação “refinada”: Complementary Filter (rápido e bom) e caminho para quaternions</h2>



<h3 class="wp-block-heading">8.1 Roll e Pitch com Complementary Filter</h3>



<p class="wp-block-paragraph">O acelerômetro dá uma boa referência de inclinação (porque a gravidade aponta “para baixo”), mas é ruidoso e sofre com acelerações lineares. O gyro é suave e rápido, mas deriva. O filtro complementar mistura os dois: <strong>gyro domina no curto prazo, accel corrige no longo prazo</strong>.</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>typedef struct {
  float roll;   /* rad */
  float pitch;  /* rad */
  float alpha;  /* ex.: 0.98 */
} comp_t;

static void comp_init(comp_t *c, float alpha)
{
  c->roll = 0.0f;
  c->pitch = 0.0f;
  c->alpha = alpha;
}

static void comp_update(comp_t *c, const float acc&#91;3&#93;, const float gyr&#91;3&#93;, float dt)
{
  /* roll_acc = atan2(Ay, Az) ; pitch_acc = atan2(-Ax, sqrt(Ay^2+Az^2)) */
  float roll_acc  = atan2f(acc&#91;1&#93;, acc&#91;2&#93;);
  float pitch_acc = atan2f(-acc&#91;0&#93;, sqrtf(acc&#91;1&#93;*acc&#91;1&#93; + acc&#91;2&#93;*acc&#91;2&#93;));

  /* Integra gyro (assumindo gyr[] em rad/s) */
  float roll_g  = c->roll  + gyr&#91;0&#93;*dt;
  float pitch_g = c->pitch + gyr&#91;1&#93;*dt;

  /* Mistura */
  c->roll  = c->alpha*roll_g  + (1.0f - c->alpha)*roll_acc;
  c->pitch = c->alpha*pitch_g + (1.0f - c->alpha)*pitch_acc;
}
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9">typedef</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">struct</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #D8DEE9">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">roll</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF">   </span><span style="color: #616E88">/* rad */</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #D8DEE9">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">pitch</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF">  </span><span style="color: #616E88">/* rad */</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #D8DEE9">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">alpha</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF">  </span><span style="color: #616E88">/* ex.: 0.98 */</span></span>
<span class="line"><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">comp_t</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9">static</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">comp_init</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">comp_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">c</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">alpha</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #D8DEE9">c</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">roll</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> 0</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">0</span><span style="color: #D8DEE9">f</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #D8DEE9">c</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">pitch</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> 0</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">0</span><span style="color: #D8DEE9">f</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #D8DEE9">c</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">alpha</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">alpha</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9">static</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">comp_update</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">comp_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">c</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">const</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">acc</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #B48EAD">3</span><span style="color: #D8DEE9FF">&#93;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">const</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">gyr</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #B48EAD">3</span><span style="color: #D8DEE9FF">&#93;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">dt</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #616E88">/* roll_acc = atan2(Ay, Az) ; pitch_acc = atan2(-Ax, sqrt(Ay^2+Az^2)) */</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #D8DEE9">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">roll_acc</span><span style="color: #D8DEE9FF">  </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">atan2f</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">acc</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #B48EAD">1</span><span style="color: #D8DEE9FF">&#93;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">acc</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #B48EAD">2</span><span style="color: #D8DEE9FF">&#93;)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #D8DEE9">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">pitch_acc</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">atan2f</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9">acc</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #B48EAD">0</span><span style="color: #D8DEE9FF">&#93;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">sqrtf</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">acc</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #B48EAD">1</span><span style="color: #D8DEE9FF">&#93;</span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">acc</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #B48EAD">1</span><span style="color: #D8DEE9FF">&#93; </span><span style="color: #81A1C1">+</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">acc</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #B48EAD">2</span><span style="color: #D8DEE9FF">&#93;</span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">acc</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #B48EAD">2</span><span style="color: #D8DEE9FF">&#93;))</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #616E88">/* Integra gyro (assumindo gyr[] em rad/s) */</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #D8DEE9">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">roll_g</span><span style="color: #D8DEE9FF">  </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">c</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">roll</span><span style="color: #D8DEE9FF">  </span><span style="color: #81A1C1">+</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">gyr</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #B48EAD">0</span><span style="color: #D8DEE9FF">&#93;</span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">dt</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #D8DEE9">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">pitch_g</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">c</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">pitch</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">+</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">gyr</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #B48EAD">1</span><span style="color: #D8DEE9FF">&#93;</span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">dt</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #616E88">/* Mistura */</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #D8DEE9">c</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">roll</span><span style="color: #D8DEE9FF">  </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">c</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">alpha</span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">roll_g</span><span style="color: #D8DEE9FF">  </span><span style="color: #81A1C1">+</span><span style="color: #D8DEE9FF"> (1</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">0</span><span style="color: #D8DEE9">f</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">c</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">alpha</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">roll_acc</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #D8DEE9">c</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">pitch</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">c</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">alpha</span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">pitch_g</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">+</span><span style="color: #D8DEE9FF"> (1</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">0</span><span style="color: #D8DEE9">f</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">c</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">alpha</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">pitch_acc</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span></code></pre></div>


<div class="wp-block-image">
<figure class="alignright size-full"><img decoding="async" width="441" height="421" src="https://mcu.tec.br/wp-content/uploads/2026/02/image-36.png" alt="" class="wp-image-1341" srcset="https://mcu.tec.br/wp-content/uploads/2026/02/image-36.png 441w, https://mcu.tec.br/wp-content/uploads/2026/02/image-36-300x286.png 300w" sizes="(max-width: 441px) 100vw, 441px" /></figure>
</div>


<p class="wp-block-paragraph">Isso já resolve uma quantidade enorme de aplicações: estabilização simples, detecção de inclinação, controle de plataforma, etc. Mas ainda falta yaw (rumo).</p>



<h3 class="wp-block-heading">8.2 Yaw e magnetômetro: onde quase todo mundo sofre</h3>



<p class="wp-block-paragraph">Yaw com magnetômetro só fica bom se você fizer duas coisas:</p>



<ol class="wp-block-list">
<li><strong>Hard-iron</strong>: remover offset (a “nuvem” de pontos do mag não fica centrada no zero).</li>



<li><strong>Soft-iron</strong>: corrigir escala/rotação (a nuvem vira uma elipse em vez de esfera).</li>
</ol>



<p class="wp-block-paragraph">O procedimento prático é coletar dados do magnetômetro girando o dispositivo em várias orientações, ajustar uma elipse e transformar para esfera. Em firmware embarcado simples, você pode aplicar uma aproximação: bias = (max+min)/2 por eixo e escala = (max-min)/2 para normalizar. Não é perfeito, mas melhora muito.</p>



<p class="wp-block-paragraph">Aplicação de correção (bias + matriz soft-iron):</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>static void mag_apply_cal(const imu_cal_t *cal, const float m_raw&#91;3&#93;, float m_corr&#91;3&#93;)
{
  float v&#91;3&#93; = {
    m_raw&#91;0&#93; - cal->mag_bias&#91;0&#93;,
    m_raw&#91;1&#93; - cal->mag_bias&#91;1&#93;,
    m_raw&#91;2&#93; - cal->mag_bias&#91;2&#93;
  };

  /* m_corr = SoftIron * v */
  for (int r = 0; r &lt; 3; r++) {
    m_corr&#91;r&#93; =
      cal->mag_softiron&#91;r&#93;&#91;0&#93;*v&#91;0&#93; +
      cal->mag_softiron&#91;r&#93;&#91;1&#93;*v&#91;1&#93; +
      cal->mag_softiron&#91;r&#93;&#91;2&#93;*v&#91;2&#93;;
  }
}
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9">static</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">mag_apply_cal</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">const</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">imu_cal_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">cal</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">const</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">m_raw</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #B48EAD">3</span><span style="color: #D8DEE9FF">&#93;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">m_corr</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #B48EAD">3</span><span style="color: #D8DEE9FF">&#93;)</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #D8DEE9">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">v</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #B48EAD">3</span><span style="color: #D8DEE9FF">&#93; </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    m_raw</span><span style="color: #88C0D0">&#91;</span><span style="color: #B48EAD">0</span><span style="color: #88C0D0">&#93; - cal-&gt;mag_bias&#91;</span><span style="color: #B48EAD">0</span><span style="color: #88C0D0">&#93;,</span></span>
<span class="line"><span style="color: #88C0D0">    m_raw&#91;</span><span style="color: #B48EAD">1</span><span style="color: #88C0D0">&#93; - cal-&gt;mag_bias&#91;</span><span style="color: #B48EAD">1</span><span style="color: #88C0D0">&#93;,</span></span>
<span class="line"><span style="color: #88C0D0">    m_raw&#91;</span><span style="color: #B48EAD">2</span><span style="color: #88C0D0">&#93; - cal-&gt;mag_bias&#91;</span><span style="color: #B48EAD">2</span><span style="color: #88C0D0">&#93;</span></span>
<span class="line"><span style="color: #88C0D0">  };</span></span>
<span class="line"></span>
<span class="line"><span style="color: #88C0D0">  </span><span style="color: #616E88">/* m_corr = SoftIron * v */</span></span>
<span class="line"><span style="color: #88C0D0">  for (int r = 0; r &lt; 3; r++) {</span></span>
<span class="line"><span style="color: #88C0D0">    m_corr&#91;</span><span style="color: #D8DEE9">r</span><span style="color: #88C0D0">&#93; =</span></span>
<span class="line"><span style="color: #88C0D0">      cal-&gt;mag_softiron&#91;</span><span style="color: #D8DEE9">r</span><span style="color: #88C0D0">&#93;&#91;</span><span style="color: #B48EAD">0</span><span style="color: #88C0D0">&#93;*v&#91;</span><span style="color: #B48EAD">0</span><span style="color: #88C0D0">&#93; +</span></span>
<span class="line"><span style="color: #88C0D0">      cal-&gt;mag_softiron&#91;</span><span style="color: #D8DEE9">r</span><span style="color: #88C0D0">&#93;&#91;</span><span style="color: #B48EAD">1</span><span style="color: #88C0D0">&#93;*v&#91;</span><span style="color: #B48EAD">1</span><span style="color: #88C0D0">&#93; +</span></span>
<span class="line"><span style="color: #88C0D0">      cal-&gt;mag_softiron&#91;</span><span style="color: #D8DEE9">r</span><span style="color: #88C0D0">&#93;&#91;</span><span style="color: #B48EAD">2</span><span style="color: #88C0D0">&#93;*v&#91;</span><span style="color: #B48EAD">2</span><span style="color: #88C0D0">&#93;;</span></span>
<span class="line"><span style="color: #88C0D0">  }</span></span>
<span class="line"><span style="color: #88C0D0">}</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">Depois disso, para obter yaw “tilt-compensated” (compensado por roll/pitch), você projeta o vetor magnético no plano horizontal do mundo (ou do corpo) usando a orientação atual. Se você já estiver em quaternions (Madgwick/Mahony), isso fica limpo. Se você estiver em roll/pitch, dá para fazer com trigonometria também, mas o ideal para robustez é migrar para quaternion.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">9) Leitura do magnetômetro (pass-through) e sincronismo</h2>



<p class="wp-block-paragraph">Quando você usa pass-through, o host lê o AK8963 em 0x0C diretamente, o que é exatamente o que o modo foi feito para permitir. (<a href="https://invensense.tdk.com/wp-content/uploads/2015/02/PS-MPU-9250A-01-v1.1.pdf?utm_source=chatgpt.com">TDK InvenSense</a>) A atenção aqui é garantir que você está lendo no ritmo correto e respeitando o “data ready” do magnetômetro (senão você repete amostras).</p>



<p class="wp-block-paragraph">Um pseudo-exemplo (registradores do AK8963 você pega do datasheet/register map do AK):</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>/* Endereços do AK8963 (exemplo comum) */
#define AK8963_ST1   0x02
#define AK8963_HXL   0x03
#define AK8963_CNTL1 0x0A

static bool ak8963_init_16bit_100hz(void)
{
  /* Exemplo: modo contínuo 100Hz e saída 16-bit (depende do CNTL1) */
  return i2c_write(AK8963_ADDR, AK8963_CNTL1, 0x16);
}

static bool ak8963_read_raw(int16_t mag&#91;3&#93;)
{
  uint8_t st1;
  if (!i2c_read(AK8963_ADDR, AK8963_ST1, &amp;st1, 1)) return false;

  if (!(st1 &amp; 0x01)) {
    /* dado ainda não pronto */
    return false;
  }

  uint8_t buf&#91;7&#93;;
  if (!i2c_read(AK8963_ADDR, AK8963_HXL, buf, 7)) return false;

  /* Atenção: AK8963 costuma ser little-endian */
  mag&#91;0&#93; = (int16_t)((buf&#91;1&#93; &lt;&lt; 8) | buf&#91;0&#93;);
  mag&#91;1&#93; = (int16_t)((buf&#91;3&#93; &lt;&lt; 8) | buf&#91;2&#93;);
  mag&#91;2&#93; = (int16_t)((buf&#91;5&#93; &lt;&lt; 8) | buf&#91;4&#93;);

  return true;
}
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #616E88">/* Endereços do AK8963 (exemplo comum) */</span></span>
<span class="line"><span style="color: #D8DEE9FF">#</span><span style="color: #D8DEE9">define</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">AK8963_ST1</span><span style="color: #D8DEE9FF">   </span><span style="color: #B48EAD">0x02</span></span>
<span class="line"><span style="color: #D8DEE9FF">#</span><span style="color: #D8DEE9">define</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">AK8963_HXL</span><span style="color: #D8DEE9FF">   </span><span style="color: #B48EAD">0x03</span></span>
<span class="line"><span style="color: #D8DEE9FF">#</span><span style="color: #D8DEE9">define</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">AK8963_CNTL1</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0x0A</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9">static</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">bool</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">ak8963_init_16bit_100hz</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #616E88">/* Exemplo: modo contínuo 100Hz e saída 16-bit (depende do CNTL1) */</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #81A1C1">return</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">i2c_write</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">AK8963_ADDR</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">AK8963_CNTL1</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0x16</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9">static</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">bool</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">ak8963_read_raw</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">int16_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">mag</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #B48EAD">3</span><span style="color: #D8DEE9FF">&#93;)</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #D8DEE9">uint8_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">st1</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #81A1C1">!</span><span style="color: #88C0D0">i2c_read</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">AK8963_ADDR</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">AK8963_ST1</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">st1</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">1</span><span style="color: #D8DEE9FF">)) </span><span style="color: #81A1C1">return</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">false;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #81A1C1">!</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">st1</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0x01</span><span style="color: #D8DEE9FF">)) </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #616E88">/* dado ainda não pronto */</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">return</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">false;</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #ECEFF4">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #D8DEE9">uint8_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">buf</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #B48EAD">7</span><span style="color: #D8DEE9FF">&#93;</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #81A1C1">!</span><span style="color: #88C0D0">i2c_read</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">AK8963_ADDR</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">AK8963_HXL</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">buf</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">7</span><span style="color: #D8DEE9FF">)) </span><span style="color: #81A1C1">return</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">false;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #616E88">/* Atenção: AK8963 costuma ser little-endian */</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #D8DEE9">mag</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #B48EAD">0</span><span style="color: #D8DEE9FF">&#93; </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">int16_t</span><span style="color: #D8DEE9FF">)((</span><span style="color: #D8DEE9">buf</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #B48EAD">1</span><span style="color: #D8DEE9FF">&#93; </span><span style="color: #81A1C1">&lt;&lt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">8</span><span style="color: #D8DEE9FF">) </span><span style="color: #81A1C1">|</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">buf</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #B48EAD">0</span><span style="color: #D8DEE9FF">&#93;)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #D8DEE9">mag</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #B48EAD">1</span><span style="color: #D8DEE9FF">&#93; </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">int16_t</span><span style="color: #D8DEE9FF">)((</span><span style="color: #D8DEE9">buf</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #B48EAD">3</span><span style="color: #D8DEE9FF">&#93; </span><span style="color: #81A1C1">&lt;&lt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">8</span><span style="color: #D8DEE9FF">) </span><span style="color: #81A1C1">|</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">buf</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #B48EAD">2</span><span style="color: #D8DEE9FF">&#93;)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #D8DEE9">mag</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #B48EAD">2</span><span style="color: #D8DEE9FF">&#93; </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">int16_t</span><span style="color: #D8DEE9FF">)((</span><span style="color: #D8DEE9">buf</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #B48EAD">5</span><span style="color: #D8DEE9FF">&#93; </span><span style="color: #81A1C1">&lt;&lt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">8</span><span style="color: #D8DEE9FF">) </span><span style="color: #81A1C1">|</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">buf</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #B48EAD">4</span><span style="color: #D8DEE9FF">&#93;)</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #81A1C1">return</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">true;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span></code></pre></div>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">10) Nota de engenharia: NRND/EOL e o que fazer com isso</h2>



<p class="wp-block-paragraph">A TDK/InvenSense marca o MPU-9250 como fim de vida / não recomendado para novos projetos, então em produto final vale considerar sucessores (ex.: ICM-20948 e outros, dependendo do que você precisa). (<a href="https://invensense.tdk.com/products/motion-tracking/9-axis/mpu-9250/?utm_source=chatgpt.com">TDK InvenSense</a>) Para aprendizado, laboratório, hobby e protótipos, ele continua sendo excelente justamente porque existe muito material, exemplos e bibliotecas.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h1 class="wp-block-heading">Exemplos de gráficos em Python (no final, como referência)</h1>



<p class="wp-block-paragraph">Abaixo está um script <strong>didático</strong> que gera dados sintéticos (simulados) de aceleração, giroscópio, magnetômetro e também a orientação (Euler) usada como referência do exemplo. Ele serve para você enxergar a “cara” típica dos eixos e como eles variam no tempo. É útil para validar pipeline, filtros e escalas antes de plugar no hardware.</p><p>The post <a href="https://mcu.tec.br/algoritimos/posicionamento/mpu9250-como-usar-uma-imu-9-eixos-e-extrair-dados-realmente-uteis/">MPU9250: como usar uma IMU 9 eixos e extrair dados realmente “úteis”</a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1338</post-id>	</item>
	</channel>
</rss>
