<?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>filtro digital - MCU &amp; FPGA</title>
	<atom:link href="https://mcu.tec.br/tags/filtro-digital/feed/" rel="self" type="application/rss+xml" />
	<link>https://mcu.tec.br</link>
	<description>Microcontroladores &#38; FPGA</description>
	<lastBuildDate>Sun, 15 Feb 2026 14:26:27 +0000</lastBuildDate>
	<language>pt-BR</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=7.1.3</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>filtro digital - MCU &amp; FPGA</title>
	<link>https://mcu.tec.br</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Filtro notch discreto (notch IIR) e média sincronizada (sync averaging)</title>
		<link>https://mcu.tec.br/algoritimos/filstros/filtro-notch-discreto-notch-iir-e-media-sincronizada-sync-averaging/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=filtro-notch-discreto-notch-iir-e-media-sincronizada-sync-averaging</link>
		
		<dc:creator><![CDATA[Carlos Delfino]]></dc:creator>
		<pubDate>Tue, 24 Feb 2026 14:23:52 +0000</pubDate>
				<category><![CDATA[Filstros]]></category>
		<category><![CDATA[ADC DMA microcontrolador]]></category>
		<category><![CDATA[análise de sinais repetitivos]]></category>
		<category><![CDATA[Biquad]]></category>
		<category><![CDATA[biquad digital]]></category>
		<category><![CDATA[DSP em microcontroladores]]></category>
		<category><![CDATA[encoder sincronização]]></category>
		<category><![CDATA[esp32]]></category>
		<category><![CDATA[filtro digital]]></category>
		<category><![CDATA[filtro digital em C]]></category>
		<category><![CDATA[filtro notch IIR]]></category>
		<category><![CDATA[firmware tempo real]]></category>
		<category><![CDATA[média sincronizada]]></category>
		<category><![CDATA[microcontroladores]]></category>
		<category><![CDATA[processamento de sinais]]></category>
		<category><![CDATA[processamento digital de sinais embarcados]]></category>
		<category><![CDATA[remoção de 60Hz]]></category>
		<category><![CDATA[RP2040]]></category>
		<category><![CDATA[sistemas embarcados]]></category>
		<category><![CDATA[SNR em sistemas embarcados]]></category>
		<category><![CDATA[stm32]]></category>
		<category><![CDATA[synchronous averaging]]></category>
		<category><![CDATA[tempo real]]></category>
		<category><![CDATA[zero crossing]]></category>
		<guid isPermaLink="false">https://mcu.tec.br/?p=1356</guid>

					<description><![CDATA[<p>Fechando a ideia: o notch discreto e a média sincronizada resolvem problemas parecidos (melhorar a qualidade do sinal), mas por “mecanismos” bem diferentes, e isso muda totalmente quando cada um é a melhor escolha. O notch é a ferramenta certa quando você conhece uma frequência indesejada bem definida e relativamente estável e quer arrancá-la do sinal com o mínimo de impacto no restante do espectro. Em firmware, isso costuma ser “hum” de 50/60 Hz, tons de chaveamento, ou uma ressonância estreita que aparece como pico bem localizado. O ponto crítico é que o notch é tão bom quanto a precisão do seu (f_0) e a escolha de (Q): se a interferência varia de frequência, um notch muito estreito deixa passar; se você alarga demais, começa a “machucar” conteúdo útil perto de (f_0). Além disso, como é um IIR, você precisa cuidar de estabilidade numérica e do formato de implementação (a forma direta II transposta tende a ser mais robusta em ponto flutuante e também costuma ser a melhor porta de entrada para depois migrar para ponto fixo).</p>
<p>Já a média sincronizada não é “um filtro de frequência” no sentido clássico; ela é uma técnica de extração por coerência: tudo que está alinhado com o período de referência fica mais forte, e o que não está alinhado tende a desaparecer. Por isso ela é superior quando o sinal útil é repetitivo e você tem um marcador de fase confiável, como encoder em máquina rotativa, o próprio PWM em conversores/inversores, ou zero-cross da rede. O ganho prático é enorme porque ela aumenta SNR sem precisar “inventar” um modelo espectral do ruído, mas ela também tem uma fragilidade: se o sincronismo for ruim (jitter, período variável, marcador inconsistente) a média “borrará” a forma de onda e pode até criar artefatos que parecem sinal real. Em projetos de rede elétrica, por exemplo, se você fixa (N) como “amostras por ciclo” sem acompanhar a variação real da frequência, a média começa a perder fase ao longo dos ciclos; nesse caso, ou você mede o período e ajusta (N) dinamicamente, ou você reamostra o ciclo para um grid fixo antes de acumular.</p>
<p>Na prática, em pipeline embarcado, uma combinação muito comum é usar notch primeiro para remover uma interferência tonal forte e depois usar média sincronizada para revelar a forma repetitiva de interesse com ruído bem mais baixo. Isso funciona especialmente bem quando a interferência não é coerente com o período que você está usando para sincronizar; se for coerente, a média pode reforçar a interferência, e aí o notch vira praticamente obrigatório antes. Se o seu sistema estiver no limite de CPU, o notch custa um número fixo e pequeno de multiplicações por amostra, enquanto a média sincronizada pode custar pouco por amostra mas “cobra” um custo por período quando você atualiza a forma média; dá para manter determinismo atualizando médias de forma incremental, ou reduzindo taxa, ou usando buffers e processamento em tarefa de menor prioridade.</p>
<p>Se você me disser qual é o seu caso (por exemplo: remover 60 Hz do ADC de shunt, ou extrair assinatura de vibração sincronizada com encoder, ou limpar ripple de PWM), eu adapto os coeficientes, a estratégia de sincronismo e o código para um cenário mais “pé no chão” com ADC+DMA, saturação, e versão em ponto fixo (Q31) pronta para rodar liso em Cortex-M.</p>
<p>The post <a href="https://mcu.tec.br/algoritimos/filstros/filtro-notch-discreto-notch-iir-e-media-sincronizada-sync-averaging/">Filtro notch discreto (notch IIR) e média sincronizada (sync averaging)</a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></description>
										<content:encoded><![CDATA[<p class="wp-block-paragraph">Em sistemas embarcados, “tirar uma frequência específica do sinal” costuma aparecer em dois cenários muito práticos: remover uma interferência estreita e persistente (por exemplo, 50/60 Hz de rede, ou um tom de comutação) e aumentar SNR (relação sinal-ruído) quando o fenômeno de interesse é repetitivo e existe uma referência de fase (por exemplo, rotação com encoder, comutação PWM, ou zero-cross da rede). O filtro notch discreto resolve muito bem o primeiro caso porque ele cria uma atenuação profunda numa frequência central (f_0) com pouca alteração do resto do espectro. Já a média sincronizada resolve muito bem o segundo porque ela soma ciclos “alinhados” no tempo/fase, reforçando o componente coerente e cancelando ruído não correlacionado e componentes que não encaixam exatamente naquele período.</p>



<p class="wp-block-paragraph">Quando o firmware precisa ser previsível (tempo real), o desenho do filtro não é só “matemático”: você escolhe estruturas e limites para garantir custo computacional constante, estado pequeno e estabilidade numérica, principalmente se você for para ponto fixo ou tiver ADC+DMA alimentando o pipeline. (Essa preocupação de arquitetura e previsibilidade é típica de projetos de tempo real.)</p>



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



<h2 class="wp-block-heading">1) Notch discreto: o “biquad” que apaga uma frequência</h2>



<p class="wp-block-paragraph">Um notch digital clássico pode ser implementado como um biquad IIR (segunda ordem) com zeros exatamente na frequência que você quer cancelar e polos próximos, controlando a largura do “buraco” via fator de qualidade (Q). Quanto maior o (Q), mais estreito é o notch (ótimo para interferência tonal estável), mas maior a sensibilidade a variação de (f_0) e a quantização dos coeficientes. Em termos práticos: para hum de rede em 60 Hz, se o sinal tiver variação de frequência (rede oscilando, ou a interferência “escorregando”), um (Q) alto demais pode deixar “vazar” parte do ruído. Para tom de comutação de um inversor ou fonte chaveada, se o clock for estável, dá para usar (Q) alto e atacar de forma cirúrgica.</p>



<p class="wp-block-paragraph">O biquad notch mais comum pode ser escrito como:</p>



<p class="wp-block-paragraph">\[<br>H(z)=\frac{1 &#8211; 2\cos(\omega_0)z^{-1} + z^{-2}}{1 &#8211; 2r\cos(\omega_0)z^{-1} + r^2 z^{-2}}<br>\]



<p class="wp-block-paragraph">onde \(\omega_0=2\pi f_0/F_s\) e (r) controla a “proximidade” dos polos aos zeros (quanto mais perto de 1, mais estreito e mais profundo). Uma ligação prática entre (r) e (Q) é aproximar a largura de banda por \(BW \approx f_0/Q\) e usar \(r \approx e^{-\pi BW/F_s}\). Isso funciona muito bem para firmware porque você calcula coeficientes uma vez (ou quando \(f_0\) muda) e o processamento por amostra fica constante.</p>



<h3 class="wp-block-heading">Código em C: biquad notch (float) com inicialização por \(F_s, f_0, Q\)</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;math.h>
#include &lt;stdint.h>

#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif

typedef struct {
    // Coeficientes normalizados (a0 = 1)
    float b0, b1, b2;
    float a1, a2;

    // Estados (forma direta II transposta)
    float z1, z2;
} NotchBiquad;

/**
 * @brief Inicializa um filtro notch IIR (biquad) em forma direta II transposta.
 * @param f     Ponteiro para a estrutura do filtro.
 * @param Fs    Frequência de amostragem (Hz).
 * @param f0    Frequência central do notch (Hz).
 * @param Q     Fator de qualidade (adimensional). Ex.: 10..50 típicos.
 *
 * Observação prática:
 *  - Q maior => notch mais estreito, mais sensível a variações de f0 e quantização.
 *  - Q menor => notch mais largo, remove mais “vizinhança” de frequências.
 */
static inline void notch_init(NotchBiquad *f, float Fs, float f0, float Q)
{
    const float w0 = 2.0f * (float)M_PI * (f0 / Fs);

    // Largura de banda aproximada (Hz)
    const float BW = f0 / Q;

    // Polo raio r (aprox.) -> define a largura do notch
    const float r = expf(-(float)M_PI * (BW / Fs));

    const float c = cosf(w0);

    // Numerador (zeros no círculo unitário em ±w0)
    const float b0 = 1.0f;
    const float b1 = -2.0f * c;
    const float b2 = 1.0f;

    // Denominador (polos em raio r)
    const float a0 = 1.0f;
    const float a1 = -2.0f * r * c;
    const float a2 = r * r;

    // Normaliza por a0 (a0=1 aqui, mas mantemos o padrão)
    f->b0 = b0 / a0;
    f->b1 = b1 / a0;
    f->b2 = b2 / a0;
    f->a1 = a1 / a0;
    f->a2 = a2 / a0;

    f->z1 = 0.0f;
    f->z2 = 0.0f;
}

/**
 * @brief Processa 1 amostra pelo biquad notch (DF-II Transposta).
 * @param f Estrutura do filtro.
 * @param x Amostra de entrada.
 * @return  Amostra filtrada.
 */
static inline float notch_process(NotchBiquad *f, float x)
{
    // DF-II transposta:
    // y = b0*x + z1
    // z1 = b1*x - a1*y + z2
    // z2 = b2*x - a2*y
    const float y = (f->b0 * x) + f->z1;
    const float z1 = (f->b1 * x) - (f->a1 * y) + f->z2;
    const float z2 = (f->b2 * x) - (f->a2 * y);

    f->z1 = z1;
    f->z2 = z2;
    return y;
}
</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">math</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">stdint</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: #D8DEE9FF">#</span><span style="color: #D8DEE9">ifndef</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">M_PI</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">M_PI</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">3.14159265358979323846</span></span>
<span class="line"><span style="color: #D8DEE9FF">#</span><span style="color: #D8DEE9">endif</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: #ECEFF4">    </span><span style="color: #616E88">// Coeficientes normalizados (a0 = 1)</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">b0</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">b1</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">b2</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">a1</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">a2</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #ECEFF4">    </span><span style="color: #616E88">// Estados (forma direta II transposta)</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">z1</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">z2</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">NotchBiquad</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"> Inicializa um filtro notch IIR (biquad) em forma direta II transposta.</span></span>
<span class="line"><span style="color: #616E88"> * </span><span style="color: #ECEFF4">@</span><span style="color: #8FBCBB">param</span><span style="color: #616E88"> </span><span style="color: #D8DEE9">f</span><span style="color: #616E88">     Ponteiro para a estrutura do filtro.</span></span>
<span class="line"><span style="color: #616E88"> * </span><span style="color: #ECEFF4">@</span><span style="color: #8FBCBB">param</span><span style="color: #616E88"> </span><span style="color: #D8DEE9">Fs</span><span style="color: #616E88">    Frequência de amostragem (Hz).</span></span>
<span class="line"><span style="color: #616E88"> * </span><span style="color: #ECEFF4">@</span><span style="color: #8FBCBB">param</span><span style="color: #616E88"> </span><span style="color: #D8DEE9">f0</span><span style="color: #616E88">    Frequência central do notch (Hz).</span></span>
<span class="line"><span style="color: #616E88"> * </span><span style="color: #ECEFF4">@</span><span style="color: #8FBCBB">param</span><span style="color: #616E88"> </span><span style="color: #D8DEE9">Q</span><span style="color: #616E88">     Fator de qualidade (adimensional). Ex.: 10..50 típicos.</span></span>
<span class="line"><span style="color: #616E88"> *</span></span>
<span class="line"><span style="color: #616E88"> * Observação prática:</span></span>
<span class="line"><span style="color: #616E88"> *  - Q maior =&gt; notch mais estreito, mais sensível a variações de f0 e quantização.</span></span>
<span class="line"><span style="color: #616E88"> *  - Q menor =&gt; notch mais largo, remove mais “vizinhança” de frequências.</span></span>
<span class="line"><span style="color: #616E88"> */</span></span>
<span class="line"><span style="color: #D8DEE9">static</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">inline</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">notch_init</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">NotchBiquad</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">Fs</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">f0</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">Q</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">const</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">float</span><span style="color: #D8DEE9FF"> w0 </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> 2</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">float</span><span style="color: #D8DEE9FF">)</span><span style="color: #D8DEE9">M_PI</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">f0</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">Fs</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #ECEFF4">    </span><span style="color: #616E88">// Largura de banda aproximada (Hz)</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">const</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">float</span><span style="color: #D8DEE9FF"> BW </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">f0</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">Q</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #ECEFF4">    </span><span style="color: #616E88">// Polo raio r (aprox.) -&gt; define a largura do notch</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">const</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">float</span><span style="color: #D8DEE9FF"> r </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">expf</span><span style="color: #D8DEE9FF">(</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">M_PI</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">BW</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">Fs</span><span style="color: #D8DEE9FF">))</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">const</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">float</span><span style="color: #D8DEE9FF"> c </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">cosf</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">w0</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #ECEFF4">    </span><span style="color: #616E88">// Numerador (zeros no círculo unitário em ±w0)</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">const</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">float</span><span style="color: #D8DEE9FF"> b0 </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: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">const</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">float</span><span style="color: #D8DEE9FF"> b1 </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">2</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">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">const</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">float</span><span style="color: #D8DEE9FF"> b2 </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: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #ECEFF4">    </span><span style="color: #616E88">// Denominador (polos em raio r)</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">const</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">float</span><span style="color: #D8DEE9FF"> a0 </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: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">const</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">float</span><span style="color: #D8DEE9FF"> a1 </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">2</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">r</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">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">const</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">float</span><span style="color: #D8DEE9FF"> a2 </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">r</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">r</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #ECEFF4">    </span><span style="color: #616E88">// Normaliza por a0 (a0=1 aqui, mas mantemos o padrão)</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">b0</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">b0</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">a0</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">b1</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">b1</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">a0</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">b2</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">b2</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">a0</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">a1</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">a1</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">a0</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">a2</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">a2</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">a0</span><span style="color: #81A1C1">;</span></span>
<span class="line"></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">z1</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">f</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">z2</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: #ECEFF4">}</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"> Processa 1 amostra pelo biquad notch (DF-II Transposta).</span></span>
<span class="line"><span style="color: #616E88"> * </span><span style="color: #ECEFF4">@</span><span style="color: #8FBCBB">param</span><span style="color: #616E88"> </span><span style="color: #D8DEE9">f</span><span style="color: #616E88"> Estrutura do filtro.</span></span>
<span class="line"><span style="color: #616E88"> * </span><span style="color: #ECEFF4">@</span><span style="color: #8FBCBB">param</span><span style="color: #616E88"> </span><span style="color: #D8DEE9">x</span><span style="color: #616E88"> Amostra de entrada.</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">  Amostra filtrada.</span></span>
<span class="line"><span style="color: #616E88"> */</span></span>
<span class="line"><span style="color: #D8DEE9">static</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">inline</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">notch_process</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">NotchBiquad</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">x</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #ECEFF4">    </span><span style="color: #616E88">// DF-II transposta:</span></span>
<span class="line"><span style="color: #ECEFF4">    </span><span style="color: #616E88">// y = b0*x + z1</span></span>
<span class="line"><span style="color: #ECEFF4">    </span><span style="color: #616E88">// z1 = b1*x - a1*y + z2</span></span>
<span class="line"><span style="color: #ECEFF4">    </span><span style="color: #616E88">// z2 = b2*x - a2*y</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">const</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">float</span><span style="color: #D8DEE9FF"> y </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">b0</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">) </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">z1</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">const</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">float</span><span style="color: #D8DEE9FF"> z1 </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">b1</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">) </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">a1</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">y</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">z2</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">const</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">float</span><span style="color: #D8DEE9FF"> z2 </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">b2</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">) </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">a2</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">y</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"></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">z1</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">z1</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">z2</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">z2</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">return</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">y</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph"><strong>Melhores usos do notch:</strong> quando você conhece (ou mede) a frequência indesejada e ela é estreita, relativamente estável e você quer preservar quase tudo ao redor. Em instrumentação, isso aparece em leitura de shunt/ADC contaminada por rede; em áudio, hum; em controle, ressonância mecânica estreita (desde que não destrua margem de fase indevidamente); em eletrônica de potência, uma componente tonal em corrente/tensão.</p>



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



<h2 class="wp-block-heading">2) Média sincronizada: “soma coerente” alinhada à fase</h2>



<p class="wp-block-paragraph">A média sincronizada (às vezes chamada de synchronous averaging, time synchronous averaging) não é “só uma média móvel”. A sacada é que você escolhe uma janela exatamente igual a um período do fenômeno repetitivo (ou múltiplos inteiros) e reinicia/alinha essa janela usando um evento de referência: um zero-cross, um pulso de encoder, um índice, ou um marcador derivado do PWM. Se você tem (N) amostras por período e faz uma média sobre (K) períodos alinhados, o componente que se repete com a mesma fase soma e cresce proporcionalmente, enquanto ruído aleatório cai como (\sqrt{K}) no RMS. Além disso, componentes que não “encaixam” naquele período tendem a se cancelar.</p>



<p class="wp-block-paragraph">Em termos de filtro, isso se comporta como um filtro tipo comb (pente) extremamente eficiente para rejeitar tudo que não é coerente com o período escolhido. A diferença para um notch é que você não está mirando uma única frequência: você está favorecendo toda a forma de onda repetitiva no domínio do tempo, desde que sincronizada.</p>



<h3 class="wp-block-heading">Código em C: média sincronizada por períodos (com referência externa)</h3>



<p class="wp-block-paragraph">A seguir vai uma implementação simples (e bem útil) para firmware: você acumula amostras de cada posição dentro do período e, a cada período completo, você atualiza a média. Isso é perfeito quando você tem um “gatilho de início de período” (por exemplo, interrupção de índice do encoder ou zero-cross).</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>#include &lt;stdint.h>
#include &lt;string.h>

typedef struct {
    uint16_t N;          // amostras por período
    uint16_t idx;        // posição atual no período &#91;0..N-1&#93;
    uint32_t K;          // quantos períodos já acumulados (limite/controle externo)

    // Buffers de acumulação (use int64 se seu range for grande)
    int64_t *acc;        // soma por posição
    int32_t *avg;        // média por posição (resultado)
} SyncAvg;

/**
 * @brief Inicializa a média sincronizada.
 * @param s       Estrutura.
 * @param acc     Buffer de acumulação de tamanho N (int64_t).
 * @param avg     Buffer de saída média de tamanho N (int32_t).
 * @param N       Amostras por período.
 */
static inline void syncavg_init(SyncAvg *s, int64_t *acc, int32_t *avg, uint16_t N)
{
    s->N = N;
    s->idx = 0;
    s->K = 0;
    s->acc = acc;
    s->avg = avg;

    memset(s->acc, 0, (size_t)N * sizeof(int64_t));
    memset(s->avg, 0, (size_t)N * sizeof(int32_t));
}

/**
 * @brief Deve ser chamado quando ocorre o "marcador" de início de período (ex.: zero-cross ou índice do encoder).
 *        Isso força alinhamento de fase.
 */
static inline void syncavg_period_reset(SyncAvg *s)
{
    s->idx = 0;
}

/**
 * @brief Alimenta a média sincronizada com uma amostra do ADC já alinhada ao relógio de amostragem.
 * @param s Estrutura.
 * @param x Amostra (ex.: ADC já convertido para int32).
 *
 * Funcionamento:
 *  - A cada amostra, acumula na posição idx.
 *  - Ao completar N amostras, fecha um período e atualiza avg[].
 *  - A referência de fase vem de syncavg_period_reset() (externa).
 */
static inline void syncavg_push_sample(SyncAvg *s, int32_t x)
{
    s->acc&#91;s->idx&#93; += (int64_t)x;
    s->idx++;

    if (s->idx >= s->N) {
        s->idx = 0;
        s->K++;

        // Atualiza a média inteira por posição (custo O(N) por período).
        // Se N for grande e seu MCU for apertado, dá para atualizar de forma incremental.
        for (uint16_t i = 0; i &lt; s->N; i++) {
            s->avg&#91;i&#93; = (int32_t)(s->acc&#91;i&#93; / (int64_t)s->K);
        }
    }
}
</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">string</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: #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">uint16_t</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: #616E88">// amostras por período</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">uint16_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">idx</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF">        </span><span style="color: #616E88">// posição atual no período &#91;0..N-1&#93;</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">K</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF">          </span><span style="color: #616E88">// quantos períodos já acumulados (limite/controle externo)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #ECEFF4">    </span><span style="color: #616E88">// Buffers de acumulação (use int64 se seu range for grande)</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">int64_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">acc</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF">        </span><span style="color: #616E88">// soma por posição</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">int32_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">avg</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF">        </span><span style="color: #616E88">// média por posição (resultado)</span></span>
<span class="line"><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">SyncAvg</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"> Inicializa a média sincronizada.</span></span>
<span class="line"><span style="color: #616E88"> * </span><span style="color: #ECEFF4">@</span><span style="color: #8FBCBB">param</span><span style="color: #616E88"> </span><span style="color: #D8DEE9">s</span><span style="color: #616E88">       Estrutura.</span></span>
<span class="line"><span style="color: #616E88"> * </span><span style="color: #ECEFF4">@</span><span style="color: #8FBCBB">param</span><span style="color: #616E88"> </span><span style="color: #D8DEE9">acc</span><span style="color: #616E88">     Buffer de acumulação de tamanho N (int64_t).</span></span>
<span class="line"><span style="color: #616E88"> * </span><span style="color: #ECEFF4">@</span><span style="color: #8FBCBB">param</span><span style="color: #616E88"> </span><span style="color: #D8DEE9">avg</span><span style="color: #616E88">     Buffer de saída média de tamanho N (int32_t).</span></span>
<span class="line"><span style="color: #616E88"> * </span><span style="color: #ECEFF4">@</span><span style="color: #8FBCBB">param</span><span style="color: #616E88"> </span><span style="color: #D8DEE9">N</span><span style="color: #616E88">       Amostras por período.</span></span>
<span class="line"><span style="color: #616E88"> */</span></span>
<span class="line"><span style="color: #D8DEE9">static</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">inline</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">syncavg_init</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">SyncAvg</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">s</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">int64_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">acc</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">int32_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">avg</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">N</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">s</span><span style="color: #81A1C1">-&gt;</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: #D8DEE9">N</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">s</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">idx</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>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">s</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">K</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>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">s</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">acc</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">acc</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">s</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">avg</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">avg</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">memset</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">s</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">acc</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">size_t</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: #88C0D0">sizeof</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">int64_t</span><span style="color: #D8DEE9FF">))</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">memset</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">s</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">avg</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">size_t</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: #88C0D0">sizeof</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">int32_t</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: #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"> Deve ser chamado quando ocorre o &quot;marcador&quot; de início de período (ex.: zero-cross ou índice do encoder).</span></span>
<span class="line"><span style="color: #616E88"> *        Isso força alinhamento de fase.</span></span>
<span class="line"><span style="color: #616E88"> */</span></span>
<span class="line"><span style="color: #D8DEE9">static</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">inline</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">syncavg_period_reset</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">SyncAvg</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">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: #D8DEE9">s</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">idx</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>
<span class="line"><span style="color: #ECEFF4">}</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"> Alimenta a média sincronizada com uma amostra do ADC já alinhada ao relógio de amostragem.</span></span>
<span class="line"><span style="color: #616E88"> * </span><span style="color: #ECEFF4">@</span><span style="color: #8FBCBB">param</span><span style="color: #616E88"> </span><span style="color: #D8DEE9">s</span><span style="color: #616E88"> Estrutura.</span></span>
<span class="line"><span style="color: #616E88"> * </span><span style="color: #ECEFF4">@</span><span style="color: #8FBCBB">param</span><span style="color: #616E88"> </span><span style="color: #D8DEE9">x</span><span style="color: #616E88"> Amostra (ex.: ADC já convertido para int32).</span></span>
<span class="line"><span style="color: #616E88"> *</span></span>
<span class="line"><span style="color: #616E88"> * Funcionamento:</span></span>
<span class="line"><span style="color: #616E88"> *  - A cada amostra, acumula na posição idx.</span></span>
<span class="line"><span style="color: #616E88"> *  - Ao completar N amostras, fecha um período e atualiza avg[].</span></span>
<span class="line"><span style="color: #616E88"> *  - A referência de fase vem de syncavg_period_reset() (externa).</span></span>
<span class="line"><span style="color: #616E88"> */</span></span>
<span class="line"><span style="color: #D8DEE9">static</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">inline</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">syncavg_push_sample</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">SyncAvg</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9">s</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">int32_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">x</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">s</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">acc</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #D8DEE9">s</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">idx</span><span style="color: #D8DEE9FF">&#93; </span><span style="color: #81A1C1">+=</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">int64_t</span><span style="color: #D8DEE9FF">)</span><span style="color: #D8DEE9">x</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">s</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">idx</span><span style="color: #81A1C1">++;</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: #D8DEE9">s</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">idx</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&gt;=</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">s</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">N</span><span style="color: #D8DEE9FF">) </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #D8DEE9">s</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">idx</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>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #D8DEE9">s</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">K</span><span style="color: #81A1C1">++;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #ECEFF4">        </span><span style="color: #616E88">// Atualiza a média inteira por posição (custo O(N) por período).</span></span>
<span class="line"><span style="color: #ECEFF4">        </span><span style="color: #616E88">// Se N for grande e seu MCU for apertado, dá para atualizar de forma incremental.</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">uint16_t</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: #D8DEE9">s</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">N</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">s</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">avg</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">int32_t</span><span style="color: #D8DEE9FF">)(</span><span style="color: #D8DEE9">s</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">acc</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">int64_t</span><span style="color: #D8DEE9FF">)</span><span style="color: #D8DEE9">s</span><span style="color: #81A1C1">-&gt;</span><span style="color: #D8DEE9">K</span><span style="color: #D8DEE9FF">)</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: #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"><strong>Melhores usos da média sincronizada:</strong> quando existe um evento/clock de referência que define o período do fenômeno e você quer extrair o comportamento repetitivo com máxima imunidade a ruído. Isso aparece em análise vibroacústica sincronizada com rotação (encoder), em medição de ripple sincronizada com PWM, em leitura de sinais biomédicos quando há marcador, e em sistemas de potência quando você quer “ver” a forma média ao longo de ciclos de rede sem ser enganado por ruído ou eventos transientes fora de fase.</p>



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



<h2 class="wp-block-heading">3) Exemplo prático combinando os dois: remover hum e depois reforçar a forma repetitiva</h2>



<p class="wp-block-paragraph">Em pipeline real, é comum usar notch primeiro para derrubar uma interferência tonal forte e, em seguida, média sincronizada para aumentar SNR do que restou (principalmente se o sinal útil é repetitivo e você tem referência). A ordem pode inverter dependendo do caso: se a interferência também for coerente com o mesmo período, a média pode reforçá-la, então o notch antes costuma ser mais seguro.</p>



<p class="wp-block-paragraph">Abaixo, um esqueleto de uso. Imagine ADC a 4 kHz, hum em 60 Hz, e você quer fazer média sincronizada por ciclo de 60 Hz usando zero-cross (logo \(N \approx 4000/60 \approx 66\) amostras por ciclo; na prática você ajusta para manter N inteiro e usar PLL/medição de período se a rede variar).</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>#include &lt;stdio.h>

// Reaproveita NotchBiquad e SyncAvg já definidos acima.

#define FS_HZ        4000.0f
#define NOTCH_F0_HZ  60.0f
#define NOTCH_Q      25.0f

#define N_SAMPLES_PER_PERIOD  66  // exemplo (depende do seu sincronismo real)

static int64_t acc_buf&#91;N_SAMPLES_PER_PERIOD&#93;;
static int32_t avg_buf&#91;N_SAMPLES_PER_PERIOD&#93;;

int main(void)
{
    NotchBiquad notch;
    notch_init(&amp;notch, FS_HZ, NOTCH_F0_HZ, NOTCH_Q);

    SyncAvg s;
    syncavg_init(&amp;s, acc_buf, avg_buf, N_SAMPLES_PER_PERIOD);

    // Exemplo: loop de aquisição (mock)
    for (int n = 0; n &lt; 20000; n++) {
        // Em firmware real: x_raw vem do ADC (DMA buffer), e zero-cross chama syncavg_period_reset(&amp;s)
        int32_t x_raw = (int32_t)(1000 * sinf(2.0f * (float)M_PI * 10.0f * (n / FS_HZ))); // sinal útil 10 Hz
        x_raw += (int32_t)(300 * sinf(2.0f * (float)M_PI * 60.0f * (n / FS_HZ)));        // hum 60 Hz

        // Notch (float) -> converte de volta para int32
        float y_notch = notch_process(&amp;notch, (float)x_raw);
        int32_t y = (int32_t)y_notch;

        // Evento externo de sincronismo: aqui é só demonstração (a cada N amostras)
        if ((n % N_SAMPLES_PER_PERIOD) == 0) {
            syncavg_period_reset(&amp;s);
        }

        // Média sincronizada
        syncavg_push_sample(&amp;s, y);

        // Quando s.K aumenta, avg_buf contém a forma média por período
        if (s.K > 0 &amp;&amp; (n % (N_SAMPLES_PER_PERIOD * 20)) == 0) {
            printf("K=%lu, avg&#91;0&#93;=%ld, avg&#91;10&#93;=%ld\n",
                   (unsigned long)s.K, (long)avg_buf&#91;0&#93;, (long)avg_buf&#91;10&#93;);
        }
    }

    return 0;
}
</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">stdio</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">// Reaproveita NotchBiquad e SyncAvg já definidos acima.</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">#</span><span style="color: #D8DEE9">define</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">FS_HZ</span><span style="color: #D8DEE9FF">        4000</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">0</span><span style="color: #D8DEE9">f</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">NOTCH_F0_HZ</span><span style="color: #D8DEE9FF">  60</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">0</span><span style="color: #D8DEE9">f</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">NOTCH_Q</span><span style="color: #D8DEE9FF">      25</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">0</span><span style="color: #D8DEE9">f</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">#</span><span style="color: #D8DEE9">define</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">N_SAMPLES_PER_PERIOD</span><span style="color: #D8DEE9FF">  </span><span style="color: #B48EAD">66</span><span style="color: #D8DEE9FF">  </span><span style="color: #616E88">// exemplo (depende do seu sincronismo real)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9">static</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">int64_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">acc_buf</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #D8DEE9">N_SAMPLES_PER_PERIOD</span><span style="color: #D8DEE9FF">&#93;</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9">static</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">int32_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">avg_buf</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #D8DEE9">N_SAMPLES_PER_PERIOD</span><span style="color: #D8DEE9FF">&#93;</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9">int</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">main</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: #D8DEE9">NotchBiquad</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">notch</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">notch_init</span><span style="color: #D8DEE9FF">(¬</span><span style="color: #D8DEE9">ch</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">FS_HZ</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">NOTCH_F0_HZ</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">NOTCH_Q</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">SyncAvg</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">s</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">syncavg_init</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">s</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">acc_buf</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">avg_buf</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">N_SAMPLES_PER_PERIOD</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #ECEFF4">    </span><span style="color: #616E88">// Exemplo: loop de aquisição (mock)</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">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: #B48EAD">20000</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: #ECEFF4">        </span><span style="color: #616E88">// Em firmware real: x_raw vem do ADC (DMA buffer), e zero-cross chama syncavg_period_reset(&amp;s)</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #D8DEE9">int32_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">x_raw</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">int32_t</span><span style="color: #D8DEE9FF">)(</span><span style="color: #B48EAD">1000</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">sinf</span><span style="color: #D8DEE9FF">(2</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">float</span><span style="color: #D8DEE9FF">)</span><span style="color: #D8DEE9">M_PI</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> 10</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">n</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">FS_HZ</span><span style="color: #D8DEE9FF">)))</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF"> </span><span style="color: #616E88">// sinal útil 10 Hz</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #D8DEE9">x_raw</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">+=</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">int32_t</span><span style="color: #D8DEE9FF">)(</span><span style="color: #B48EAD">300</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">sinf</span><span style="color: #D8DEE9FF">(2</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">float</span><span style="color: #D8DEE9FF">)</span><span style="color: #D8DEE9">M_PI</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> 60</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">n</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">FS_HZ</span><span style="color: #D8DEE9FF">)))</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF">        </span><span style="color: #616E88">// hum 60 Hz</span></span>
<span class="line"></span>
<span class="line"><span style="color: #ECEFF4">        </span><span style="color: #616E88">// Notch (float) -&gt; converte de volta para int32</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_notch</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">notch_process</span><span style="color: #D8DEE9FF">(¬</span><span style="color: #D8DEE9">ch</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">x_raw</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #D8DEE9">int32_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">y</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">int32_t</span><span style="color: #D8DEE9FF">)</span><span style="color: #D8DEE9">y_notch</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #ECEFF4">        </span><span style="color: #616E88">// Evento externo de sincronismo: aqui é só demonstração (a cada N amostras)</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">if</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: #D8DEE9">N_SAMPLES_PER_PERIOD</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: #D8DEE9FF">) </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #88C0D0">syncavg_period_reset</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">s</span><span style="color: #D8DEE9FF">)</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: #ECEFF4">        </span><span style="color: #616E88">// Média sincronizada</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">syncavg_push_sample</span><span style="color: #D8DEE9FF">(</span><span style="color: #81A1C1">&amp;</span><span style="color: #D8DEE9">s</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">y</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #ECEFF4">        </span><span style="color: #616E88">// Quando s.K aumenta, avg_buf contém a forma média por período</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">s</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">K</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&gt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&amp;&amp;</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: #D8DEE9">N_SAMPLES_PER_PERIOD</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">20</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: #D8DEE9FF">) </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #88C0D0">printf</span><span style="color: #D8DEE9FF">(</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">K=%lu, avg&#91;0&#93;=%ld, avg&#91;10&#93;=%ld</span><span style="color: #EBCB8B">\n</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span></span>
<span class="line"><span style="color: #D8DEE9FF">                   (</span><span style="color: #D8DEE9">unsigned</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">long</span><span style="color: #D8DEE9FF">)</span><span style="color: #D8DEE9">s</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">K</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">long</span><span style="color: #D8DEE9FF">)</span><span style="color: #D8DEE9">avg_buf</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: #D8DEE9">long</span><span style="color: #D8DEE9FF">)</span><span style="color: #D8DEE9">avg_buf</span><span style="color: #D8DEE9FF">&#91;</span><span style="color: #B48EAD">10</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: #D8DEE9FF">    </span><span style="color: #ECEFF4">}</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: #B48EAD">0</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #ECEFF4">}</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">Fechando a ideia: o notch discreto e a média sincronizada resolvem problemas parecidos (melhorar a qualidade do sinal), mas por “mecanismos” bem diferentes, e isso muda totalmente quando cada um é a melhor escolha. O notch é a ferramenta certa quando você conhece uma frequência indesejada bem definida e relativamente estável e quer arrancá-la do sinal com o mínimo de impacto no restante do espectro. Em firmware, isso costuma ser “hum” de 50/60 Hz, tons de chaveamento, ou uma ressonância estreita que aparece como pico bem localizado. O ponto crítico é que o notch é tão bom quanto a precisão do seu (f_0) e a escolha de (Q): se a interferência varia de frequência, um notch muito estreito deixa passar; se você alarga demais, começa a “machucar” conteúdo útil perto de (f_0). Além disso, como é um IIR, você precisa cuidar de estabilidade numérica e do formato de implementação (a forma direta II transposta tende a ser mais robusta em ponto flutuante e também costuma ser a melhor porta de entrada para depois migrar para ponto fixo).</p>



<p class="wp-block-paragraph">Já a média sincronizada não é “um filtro de frequência” no sentido clássico; ela é uma técnica de extração por coerência: tudo que está alinhado com o período de referência fica mais forte, e o que não está alinhado tende a desaparecer. Por isso ela é superior quando o sinal útil é repetitivo e você tem um marcador de fase confiável, como encoder em máquina rotativa, o próprio PWM em conversores/inversores, ou zero-cross da rede. O ganho prático é enorme porque ela aumenta SNR sem precisar “inventar” um modelo espectral do ruído, mas ela também tem uma fragilidade: se o sincronismo for ruim (jitter, período variável, marcador inconsistente) a média “borrará” a forma de onda e pode até criar artefatos que parecem sinal real. Em projetos de rede elétrica, por exemplo, se você fixa (N) como “amostras por ciclo” sem acompanhar a variação real da frequência, a média começa a perder fase ao longo dos ciclos; nesse caso, ou você mede o período e ajusta (N) dinamicamente, ou você reamostra o ciclo para um grid fixo antes de acumular.</p>



<p class="wp-block-paragraph">Na prática, em pipeline embarcado, uma combinação muito comum é usar notch primeiro para remover uma interferência tonal forte e depois usar média sincronizada para revelar a forma repetitiva de interesse com ruído bem mais baixo. Isso funciona especialmente bem quando a interferência não é coerente com o período que você está usando para sincronizar; se for coerente, a média pode reforçar a interferência, e aí o notch vira praticamente obrigatório antes. Se o seu sistema estiver no limite de CPU, o notch custa um número fixo e pequeno de multiplicações por amostra, enquanto a média sincronizada pode custar pouco por amostra mas “cobra” um custo por período quando você atualiza a forma média; dá para manter determinismo atualizando médias de forma incremental, ou reduzindo taxa, ou usando buffers e processamento em tarefa de menor prioridade.</p><p>The post <a href="https://mcu.tec.br/algoritimos/filstros/filtro-notch-discreto-notch-iir-e-media-sincronizada-sync-averaging/">Filtro notch discreto (notch IIR) e média sincronizada (sync averaging)</a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1356</post-id>	</item>
		<item>
		<title>Filtro Digital com Séries de Taylor e Cepstrum para Detecção de Assobio em RP2040</title>
		<link>https://mcu.tec.br/algoritimos/dsp/filtro-digital-com-series-de-taylor-e-cepstrum-para-deteccao-de-assobio-em-rp2040/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=filtro-digital-com-series-de-taylor-e-cepstrum-para-deteccao-de-assobio-em-rp2040</link>
		
		<dc:creator><![CDATA[Carlos Delfino]]></dc:creator>
		<pubDate>Thu, 15 Jan 2026 20:54:29 +0000</pubDate>
				<category><![CDATA[DSP]]></category>
		<category><![CDATA[análise espectral]]></category>
		<category><![CDATA[BitDogLab]]></category>
		<category><![CDATA[cepstrum]]></category>
		<category><![CDATA[detecção de assobio]]></category>
		<category><![CDATA[DSP embarcado]]></category>
		<category><![CDATA[engenharia de firmware]]></category>
		<category><![CDATA[fft em microcontroladores]]></category>
		<category><![CDATA[filtro digital]]></category>
		<category><![CDATA[processamento digital de sinais]]></category>
		<category><![CDATA[RP2040]]></category>
		<category><![CDATA[séries de taylor]]></category>
		<guid isPermaLink="false">https://mcu.tec.br/?p=1115</guid>

					<description><![CDATA[<p>Aprenda a projetar um filtro digital para separar a frequência fundamental e as harmônicas de um assobio humano utilizando Séries de Taylor em microcontroladores. Este artigo técnico e didático apresenta, passo a passo, a construção de um pipeline completo de processamento digital de sinais no RP2040, incluindo filtragem passa-faixa baseada em operadores diferenciais, cálculo do cepstrum para identificação de periodicidade, uso de janelas, gate por energia e técnicas de suavização temporal. O projeto é implementado integralmente em C, sem bibliotecas externas de DSP, e executa em tempo real na BitDogLab, acionando um LED quando um assobio é corretamente identificado. Ideal para quem deseja aprofundar conhecimentos em DSP embarcado, arquitetura de firmware e matemática aplicada a sistemas embarcados.</p>
<p>The post <a href="https://mcu.tec.br/algoritimos/dsp/filtro-digital-com-series-de-taylor-e-cepstrum-para-deteccao-de-assobio-em-rp2040/">Filtro Digital com Séries de Taylor e Cepstrum para Detecção de Assobio em RP2040</a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></description>
										<content:encoded><![CDATA[<div class="root-eb-toc-ph0zu wp-block-essential-blocks-table-of-contents"><div class="eb-parent-wrapper eb-parent-eb-toc-ph0zu "><div class="eb-toc-container eb-toc-ph0zu  eb-toc-is-not-sticky eb-toc-not-collapsible eb-toc-initially-not-collapsed eb-toc-scrollToTop style-1 list-style-none" data-scroll-top="false" data-scroll-top-icon="fas fa-angle-up" data-collapsible="false" data-sticky-hide-mobile="false" data-sticky="false" data-scroll-target="scroll_to_toc" data-copy-link="false" data-editor-type="" data-hide-desktop="false" data-hide-tab="false" data-hide-mobile="false" data-itemcollapsed="false" data-highlight-scroll="false"><div class="eb-toc-header"><h2 class="eb-toc-title">Table of Contents</h2></div><div class="eb-toc-wrapper " data-headers="[{&quot;level&quot;:2,&quot;content&quot;:&quot;1 \u2014 Motiva\u00e7\u00e3o, Vis\u00e3o Geral do Problema e Arquitetura da Solu\u00e7\u00e3o&quot;,&quot;text&quot;:&quot;1 \u2014 Motiva\u00e7\u00e3o, Vis\u00e3o Geral do Problema e Arquitetura da Solu\u00e7\u00e3o&quot;,&quot;link&quot;:&quot;eb-table-content-0&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;1.1 Motiva\u00e7\u00e3o t\u00e9cnica&quot;,&quot;text&quot;:&quot;1.1 Motiva\u00e7\u00e3o t\u00e9cnica&quot;,&quot;link&quot;:&quot;eb-table-content-1&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;1.2 Problema a ser resolvido&quot;,&quot;text&quot;:&quot;1.2 Problema a ser resolvido&quot;,&quot;link&quot;:&quot;12-problema-a-ser-resolvido&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;1.3 Arquitetura geral do sistema&quot;,&quot;text&quot;:&quot;1.3 Arquitetura geral do sistema&quot;,&quot;link&quot;:&quot;13-arquitetura-geral-do-sistema&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;1.4 Por que S\u00e9ries de Taylor em filtros digitais?&quot;,&quot;text&quot;:&quot;1.4 Por que S\u00e9ries de Taylor em filtros digitais?&quot;,&quot;link&quot;:&quot;eb-table-content-4&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;1.5 O papel do Cepstrum na detec\u00e7\u00e3o do assobio&quot;,&quot;text&quot;:&quot;1.5 O papel do Cepstrum na detec\u00e7\u00e3o do assobio&quot;,&quot;link&quot;:&quot;eb-table-content-5&quot;},{&quot;level&quot;:2,&quot;content&quot;:&quot;2 \u2014 Caracter\u00edsticas do Assobio Humano e Modelagem do Sinal&quot;,&quot;text&quot;:&quot;2 \u2014 Caracter\u00edsticas do Assobio Humano e Modelagem do Sinal&quot;,&quot;link&quot;:&quot;eb-table-content-6&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;2.1 O assobio como sinal f\u00edsico&quot;,&quot;text&quot;:&quot;2.1 O assobio como sinal f\u00edsico&quot;,&quot;link&quot;:&quot;eb-table-content-7&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;2.2 Faixa t\u00edpica de frequ\u00eancias do assobio humano&quot;,&quot;text&quot;:&quot;2.2 Faixa t\u00edpica de frequ\u00eancias do assobio humano&quot;,&quot;link&quot;:&quot;eb-table-content-8&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;2.3 Sinal amostrado no ADC do RP2040&quot;,&quot;text&quot;:&quot;2.3 Sinal amostrado no ADC do RP2040&quot;,&quot;link&quot;:&quot;23-sinal-amostrado-no-adc-do-rp2040&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;2.4 Por que separar fundamental e harm\u00f4nicas?&quot;,&quot;text&quot;:&quot;2.4 Por que separar fundamental e harm\u00f4nicas?&quot;,&quot;link&quot;:&quot;eb-table-content-10&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;2.5 Introdu\u00e7\u00e3o intuitiva \u00e0s S\u00e9ries de Taylor&quot;,&quot;text&quot;:&quot;2.5 Introdu\u00e7\u00e3o intuitiva \u00e0s S\u00e9ries de Taylor&quot;,&quot;link&quot;:&quot;eb-table-content-11&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;2.6 Ponte conceitual: derivadas \u2192 filtros&quot;,&quot;text&quot;:&quot;2.6 Ponte conceitual: derivadas \u2192 filtros&quot;,&quot;link&quot;:&quot;eb-table-content-12&quot;},{&quot;level&quot;:2,&quot;content&quot;:&quot;3 \u2014 Constru\u00e7\u00e3o do Filtro Digital usando S\u00e9ries de Taylor (Teoria + Primeira Implementa\u00e7\u00e3o)&quot;,&quot;text&quot;:&quot;3 \u2014 Constru\u00e7\u00e3o do Filtro Digital usando S\u00e9ries de Taylor (Teoria + Primeira Implementa\u00e7\u00e3o)&quot;,&quot;link&quot;:&quot;eb-table-content-13&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;3.1 Ideia central: Taylor como operador espectral&quot;,&quot;text&quot;:&quot;3.1 Ideia central: Taylor como operador espectral&quot;,&quot;link&quot;:&quot;31-ideia-central-taylor-como-operador-espectral&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;3.2 Derivadas discretas (diferen\u00e7as finitas)&quot;,&quot;text&quot;:&quot;3.2 Derivadas discretas (diferen\u00e7as finitas)&quot;,&quot;link&quot;:&quot;eb-table-content-15&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;3.3 Filtro passa-faixa baseado em Taylor (modelo)&quot;,&quot;text&quot;:&quot;3.3 Filtro passa-faixa baseado em Taylor (modelo)&quot;,&quot;link&quot;:&quot;33-filtro-passa-faixa-baseado-em-taylor-modelo&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;3.4 Estrutura do c\u00f3digo (incremental)&quot;,&quot;text&quot;:&quot;3.4 Estrutura do c\u00f3digo (incremental)&quot;,&quot;link&quot;:&quot;eb-table-content-17&quot;},{&quot;level&quot;:4,&quot;content&quot;:&quot;3.4.1 Estrutura de estado do filtro&quot;,&quot;text&quot;:&quot;3.4.1 Estrutura de estado do filtro&quot;,&quot;link&quot;:&quot;341-estrutura-de-estado-do-filtro&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;3.5 Implementa\u00e7\u00e3o do filtro em C (primeira vers\u00e3o)&quot;,&quot;text&quot;:&quot;3.5 Implementa\u00e7\u00e3o do filtro em C (primeira vers\u00e3o)&quot;,&quot;link&quot;:&quot;eb-table-content-19&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;3.6 Integra\u00e7\u00e3o inicial com o ADC (BitDogLab)&quot;,&quot;text&quot;:&quot;3.6 Integra\u00e7\u00e3o inicial com o ADC (BitDogLab)&quot;,&quot;link&quot;:&quot;eb-table-content-20&quot;},{&quot;level&quot;:4,&quot;content&quot;:&quot;3.6.1 Leitura b\u00e1sica do ADC&quot;,&quot;text&quot;:&quot;3.6.1 Leitura b\u00e1sica do ADC&quot;,&quot;link&quot;:&quot;eb-table-content-21&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;3.7 Primeiro loop funcional (sem cepstrum ainda)&quot;,&quot;text&quot;:&quot;3.7 Primeiro loop funcional (sem cepstrum ainda)&quot;,&quot;link&quot;:&quot;37-primeiro-loop-funcional-sem-cepstrum-ainda&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;3.8 Valida\u00e7\u00e3o pr\u00e1tica (o que observar)&quot;,&quot;text&quot;:&quot;3.8 Valida\u00e7\u00e3o pr\u00e1tica (o que observar)&quot;,&quot;link&quot;:&quot;eb-table-content-23&quot;},{&quot;level&quot;:2,&quot;content&quot;:&quot;4 \u2014 Cepstrum para detectar o assobio (conceito + coleta de frames + log via Taylor)&quot;,&quot;text&quot;:&quot;4 \u2014 Cepstrum para detectar o assobio (conceito + coleta de frames + log via Taylor)&quot;,&quot;link&quot;:&quot;4-cepstrum-para-detectar-o-assobio-conceito-coleta-de-frames-log-via-taylor&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;4.1 O que \u00e9 \u201ccepstrum\u201d e por que ele funciona t\u00e3o bem para assobios&quot;,&quot;text&quot;:&quot;4.1 O que \u00e9 \u201ccepstrum\u201d e por que ele funciona t\u00e3o bem para assobios&quot;,&quot;link&quot;:&quot;eb-table-content-25&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;4.2 Qual cepstrum vamos implementar no RP2040&quot;,&quot;text&quot;:&quot;4.2 Qual cepstrum vamos implementar no RP2040&quot;,&quot;link&quot;:&quot;42-qual-cepstrum-vamos-implementar-no-rp2040&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;4.3 Coleta de frame (buffer) do sinal j\u00e1 filtrado&quot;,&quot;text&quot;:&quot;4.3 Coleta de frame (buffer) do sinal j\u00e1 filtrado&quot;,&quot;link&quot;:&quot;eb-table-content-27&quot;},{&quot;level&quot;:4,&quot;content&quot;:&quot;4.3.1 C\u00f3digo incremental: buffer e coleta&quot;,&quot;text&quot;:&quot;4.3.1 C\u00f3digo incremental: buffer e coleta&quot;,&quot;link&quot;:&quot;eb-table-content-28&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;4.4 Logaritmo aproximado com S\u00e9rie de Taylor (sem logf())&quot;,&quot;text&quot;:&quot;4.4 Logaritmo aproximado com S\u00e9rie de Taylor (sem logf())&quot;,&quot;link&quot;:&quot;eb-table-content-29&quot;},{&quot;level&quot;:4,&quot;content&quot;:&quot;4.4.1 Implementa\u00e7\u00e3o (Taylor truncada)&quot;,&quot;text&quot;:&quot;4.4.1 Implementa\u00e7\u00e3o (Taylor truncada)&quot;,&quot;link&quot;:&quot;eb-table-content-30&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;4.5 Loop j\u00e1 pronto: filtro + coleta de frame&quot;,&quot;text&quot;:&quot;4.5 Loop j\u00e1 pronto: filtro + coleta de frame&quot;,&quot;link&quot;:&quot;eb-table-content-31&quot;},{&quot;level&quot;:2,&quot;content&quot;:&quot;5 \u2014 FFT + log-magnitude (com Taylor) + IFFT \u21d2 Cepstrum e detec\u00e7\u00e3o do assobio (j\u00e1 aciona LED)&quot;,&quot;text&quot;:&quot;5 \u2014 FFT + log-magnitude (com Taylor) + IFFT \u21d2 Cepstrum e detec\u00e7\u00e3o do assobio (j\u00e1 aciona LED)&quot;,&quot;link&quot;:&quot;eb-table-content-32&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;5.1 Estruturas complexas e utilit\u00e1rios m\u00ednimos&quot;,&quot;text&quot;:&quot;5.1 Estruturas complexas e utilit\u00e1rios m\u00ednimos&quot;,&quot;link&quot;:&quot;eb-table-content-33&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;5.2 FFT radix-2 iterativa (in-place) para N=256&quot;,&quot;text&quot;:&quot;5.2 FFT radix-2 iterativa (in-place) para N=256&quot;,&quot;link&quot;:&quot;eb-table-content-34&quot;},{&quot;level&quot;:4,&quot;content&quot;:&quot;5.2.1 Por que radix-2 e N=256&quot;,&quot;text&quot;:&quot;5.2.1 Por que radix-2 e N=256&quot;,&quot;link&quot;:&quot;eb-table-content-35&quot;},{&quot;level&quot;:4,&quot;content&quot;:&quot;5.2.2 Tabela de twiddles (pr\u00e9-c\u00e1lculo)&quot;,&quot;text&quot;:&quot;5.2.2 Tabela de twiddles (pr\u00e9-c\u00e1lculo)&quot;,&quot;link&quot;:&quot;eb-table-content-36&quot;},{&quot;level&quot;:4,&quot;content&quot;:&quot;5.2.3 Bit-reversal (reordena\u00e7\u00e3o)&quot;,&quot;text&quot;:&quot;5.2.3 Bit-reversal (reordena\u00e7\u00e3o)&quot;,&quot;link&quot;:&quot;eb-table-content-37&quot;},{&quot;level&quot;:4,&quot;content&quot;:&quot;5.2.4 FFT direta (forward)&quot;,&quot;text&quot;:&quot;5.2.4 FFT direta (forward)&quot;,&quot;link&quot;:&quot;524-fft-direta-forward&quot;},{&quot;level&quot;:4,&quot;content&quot;:&quot;5.2.5 IFFT (inverse)&quot;,&quot;text&quot;:&quot;5.2.5 IFFT (inverse)&quot;,&quot;link&quot;:&quot;525-ifft-inverse&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;5.3 Montando o espectro: |X[k]| e log(|X[k]|) usando ln_approx (Taylor)&quot;,&quot;text&quot;:&quot;5.3 Montando o espectro: |X[k]| e log(|X[k]|) usando ln_approx (Taylor)&quot;,&quot;link&quot;:&quot;eb-table-content-40&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;5.4 Cepstrum: IFFT do log-magnitude e busca do pico de quefr\u00eancia&quot;,&quot;text&quot;:&quot;5.4 Cepstrum: IFFT do log-magnitude e busca do pico de quefr\u00eancia&quot;,&quot;link&quot;:&quot;eb-table-content-41&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;5.5 Decis\u00e3o e acionamento do LED com histerese&quot;,&quot;text&quot;:&quot;5.5 Decis\u00e3o e acionamento do LED com histerese&quot;,&quot;link&quot;:&quot;eb-table-content-42&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;5.6 Integra\u00e7\u00e3o com o que j\u00e1 temos: processar frame quando encher&quot;,&quot;text&quot;:&quot;5.6 Integra\u00e7\u00e3o com o que j\u00e1 temos: processar frame quando encher&quot;,&quot;link&quot;:&quot;eb-table-content-43&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;5.7 O que voc\u00ea j\u00e1 consegue testar agora&quot;,&quot;text&quot;:&quot;5.7 O que voc\u00ea j\u00e1 consegue testar agora&quot;,&quot;link&quot;:&quot;eb-table-content-44&quot;},{&quot;level&quot;:2,&quot;content&quot;:&quot;6 \u2014 Robustez \u201cde produ\u00e7\u00e3o\u201d: janela (Hann), gate de sil\u00eancio, suaviza\u00e7\u00e3o temporal e integra\u00e7\u00e3o de perif\u00e9ricos no RP2040&quot;,&quot;text&quot;:&quot;6 \u2014 Robustez \u201cde produ\u00e7\u00e3o\u201d: janela (Hann), gate de sil\u00eancio, suaviza\u00e7\u00e3o temporal e integra\u00e7\u00e3o de perif\u00e9ricos no RP2040&quot;,&quot;link&quot;:&quot;eb-table-content-45&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;6.1 Janela Hann (por que e como)&quot;,&quot;text&quot;:&quot;6.1 Janela Hann (por que e como)&quot;,&quot;link&quot;:&quot;61-janela-hann-por-que-e-como&quot;},{&quot;level&quot;:4,&quot;content&quot;:&quot;6.1.1 Tabela da janela (pr\u00e9-calculada)&quot;,&quot;text&quot;:&quot;6.1.1 Tabela da janela (pr\u00e9-calculada)&quot;,&quot;link&quot;:&quot;eb-table-content-47&quot;},{&quot;level&quot;:4,&quot;content&quot;:&quot;6.1.2 Aplicar janela antes da FFT&quot;,&quot;text&quot;:&quot;6.1.2 Aplicar janela antes da FFT&quot;,&quot;link&quot;:&quot;612-aplicar-janela-antes-da-fft&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;6.2 Gate de sil\u00eancio por energia RMS (para cortar falsos positivos)&quot;,&quot;text&quot;:&quot;6.2 Gate de sil\u00eancio por energia RMS (para cortar falsos positivos)&quot;,&quot;link&quot;:&quot;eb-table-content-49&quot;},{&quot;level&quot;:4,&quot;content&quot;:&quot;6.2.1 Fun\u00e7\u00e3o de energia do frame&quot;,&quot;text&quot;:&quot;6.2.1 Fun\u00e7\u00e3o de energia do frame&quot;,&quot;link&quot;:&quot;eb-table-content-50&quot;},{&quot;level&quot;:4,&quot;content&quot;:&quot;6.2.2 Usar o gate antes do cepstrum&quot;,&quot;text&quot;:&quot;6.2.2 Usar o gate antes do cepstrum&quot;,&quot;link&quot;:&quot;622-usar-o-gate-antes-do-cepstrum&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;6.3 Suaviza\u00e7\u00e3o temporal (EMA) do \u201cpeak\u201d do cepstrum&quot;,&quot;text&quot;:&quot;6.3 Suaviza\u00e7\u00e3o temporal (EMA) do \u201cpeak\u201d do cepstrum&quot;,&quot;link&quot;:&quot;eb-table-content-52&quot;},{&quot;level&quot;:4,&quot;content&quot;:&quot;6.3.1 Aplicando EMA dentro do detector&quot;,&quot;text&quot;:&quot;6.3.1 Aplicando EMA dentro do detector&quot;,&quot;link&quot;:&quot;631-aplicando-ema-dentro-do-detector&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;6.4 Amostragem est\u00e1vel no RP2040 (sem \u201csleep torto\u201d)&quot;,&quot;text&quot;:&quot;6.4 Amostragem est\u00e1vel no RP2040 (sem \u201csleep torto\u201d)&quot;,&quot;link&quot;:&quot;eb-table-content-54&quot;},{&quot;level&quot;:4,&quot;content&quot;:&quot;6.4.1 Callback de amostragem&quot;,&quot;text&quot;:&quot;6.4.1 Callback de amostragem&quot;,&quot;link&quot;:&quot;641-callback-de-amostragem&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;6.5 Inicializa\u00e7\u00e3o do ADC e do LED (Pico SDK)&quot;,&quot;text&quot;:&quot;6.5 Inicializa\u00e7\u00e3o do ADC e do LED (Pico SDK)&quot;,&quot;link&quot;:&quot;eb-table-content-56&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;6.6 Inicializa\u00e7\u00e3o \u201cDSP\u201d: twiddles, janela e buffers&quot;,&quot;text&quot;:&quot;6.6 Inicializa\u00e7\u00e3o \u201cDSP\u201d: twiddles, janela e buffers&quot;,&quot;link&quot;:&quot;eb-table-content-57&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;6.7 Main \u201cquase final\u201d: timer coleta, loop processa frames&quot;,&quot;text&quot;:&quot;6.7 Main \u201cquase final\u201d: timer coleta, loop processa frames&quot;,&quot;link&quot;:&quot;67-main-quase-final-timer-coleta-loop-processa-frames&quot;},{&quot;level&quot;:2,&quot;content&quot;:&quot;7 \u2014 C\u00f3digo completo e funcional (BitDogLab \/ RP2040) \u2014 filtro Taylor + cepstrum + LED&quot;,&quot;text&quot;:&quot;7 \u2014 C\u00f3digo completo e funcional (BitDogLab \/ RP2040) \u2014 filtro Taylor + cepstrum + LED&quot;,&quot;link&quot;:&quot;eb-table-content-59&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;7.1 Como compilar (vis\u00e3o pr\u00e1tica)&quot;,&quot;text&quot;:&quot;7.1 Como compilar (vis\u00e3o pr\u00e1tica)&quot;,&quot;link&quot;:&quot;eb-table-content-60&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;7.2 Ajustes que voc\u00ea provavelmente vai fazer na BitDogLab&quot;,&quot;text&quot;:&quot;7.2 Ajustes que voc\u00ea provavelmente vai fazer na BitDogLab&quot;,&quot;link&quot;:&quot;eb-table-content-61&quot;},{&quot;level&quot;:2,&quot;content&quot;:&quot;8 \u2014 Calibra\u00e7\u00e3o pr\u00e1tica, boas escolhas vs. m\u00e1s escolhas, encerramento e SEO&quot;,&quot;text&quot;:&quot;8 \u2014 Calibra\u00e7\u00e3o pr\u00e1tica, boas escolhas vs. m\u00e1s escolhas, encerramento e SEO&quot;,&quot;link&quot;:&quot;eb-table-content-62&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;8.1 Guia r\u00e1pido de calibra\u00e7\u00e3o (passo a passo)&quot;,&quot;text&quot;:&quot;8.1 Guia r\u00e1pido de calibra\u00e7\u00e3o (passo a passo)&quot;,&quot;link&quot;:&quot;eb-table-content-63&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;8.2 Boas escolhas vs. m\u00e1s escolhas (engenharia real)&quot;,&quot;text&quot;:&quot;8.2 Boas escolhas vs. m\u00e1s escolhas (engenharia real)&quot;,&quot;link&quot;:&quot;eb-table-content-64&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;8.3 Por que essa arquitetura funciona t\u00e3o bem em MCU&quot;,&quot;text&quot;:&quot;8.3 Por que essa arquitetura funciona t\u00e3o bem em MCU&quot;,&quot;link&quot;:&quot;eb-table-content-65&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;8.4 Encerramento&quot;,&quot;text&quot;:&quot;8.4 Encerramento&quot;,&quot;link&quot;:&quot;84-encerramento&quot;}]" data-visible="[true,true,true,true,true,true]" data-delete-headers="[{&quot;label&quot;:&quot;1 \u2014 Motiva\u00e7\u00e3o, Vis\u00e3o Geral do Problema e Arquitetura da Solu\u00e7\u00e3o&quot;,&quot;value&quot;:&quot;1-motiva\u00e7\u00e3o-vis\u00e3o-geral-do-problema-e-arquitetura-da-solu\u00e7\u00e3o&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;1.1 Motiva\u00e7\u00e3o t\u00e9cnica&quot;,&quot;value&quot;:&quot;11-motiva\u00e7\u00e3o-t\u00e9cnica&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;1.2 Problema a ser resolvido&quot;,&quot;value&quot;:&quot;12-problema-a-ser-resolvido&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;1.3 Arquitetura geral do sistema&quot;,&quot;value&quot;:&quot;13-arquitetura-geral-do-sistema&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;1.4 Por que S\u00e9ries de Taylor em filtros digitais?&quot;,&quot;value&quot;:&quot;14-por-que-s\u00e9ries-de-taylor-em-filtros-digitais&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;1.5 O papel do Cepstrum na detec\u00e7\u00e3o do assobio&quot;,&quot;value&quot;:&quot;15-o-papel-do-cepstrum-na-detec\u00e7\u00e3o-do-assobio&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;2 \u2014 Caracter\u00edsticas do Assobio Humano e Modelagem do Sinal&quot;,&quot;value&quot;:&quot;2-caracter\u00edsticas-do-assobio-humano-e-modelagem-do-sinal&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;2.1 O assobio como sinal f\u00edsico&quot;,&quot;value&quot;:&quot;21-o-assobio-como-sinal-f\u00edsico&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;2.2 Faixa t\u00edpica de frequ\u00eancias do assobio humano&quot;,&quot;value&quot;:&quot;22-faixa-t\u00edpica-de-frequ\u00eancias-do-assobio-humano&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;2.3 Sinal amostrado no ADC do RP2040&quot;,&quot;value&quot;:&quot;23-sinal-amostrado-no-adc-do-rp2040&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;2.4 Por que separar fundamental e harm\u00f4nicas?&quot;,&quot;value&quot;:&quot;24-por-que-separar-fundamental-e-harm\u00f4nicas&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;2.5 Introdu\u00e7\u00e3o intuitiva \u00e0s S\u00e9ries de Taylor&quot;,&quot;value&quot;:&quot;25-introdu\u00e7\u00e3o-intuitiva-\u00e0s-s\u00e9ries-de-taylor&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;2.6 Ponte conceitual: derivadas \u2192 filtros&quot;,&quot;value&quot;:&quot;26-ponte-conceitual-derivadas-\u2192-filtros&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;3 \u2014 Constru\u00e7\u00e3o do Filtro Digital usando S\u00e9ries de Taylor (Teoria + Primeira Implementa\u00e7\u00e3o)&quot;,&quot;value&quot;:&quot;3-constru\u00e7\u00e3o-do-filtro-digital-usando-s\u00e9ries-de-taylor-teoria-primeira-implementa\u00e7\u00e3o&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;3.1 Ideia central: Taylor como operador espectral&quot;,&quot;value&quot;:&quot;31-ideia-central-taylor-como-operador-espectral&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;3.2 Derivadas discretas (diferen\u00e7as finitas)&quot;,&quot;value&quot;:&quot;32-derivadas-discretas-diferen\u00e7as-finitas&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;3.3 Filtro passa-faixa baseado em Taylor (modelo)&quot;,&quot;value&quot;:&quot;33-filtro-passa-faixa-baseado-em-taylor-modelo&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;3.4 Estrutura do c\u00f3digo (incremental)&quot;,&quot;value&quot;:&quot;34-estrutura-do-c\u00f3digo-incremental&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;3.4.1 Estrutura de estado do filtro&quot;,&quot;value&quot;:&quot;341-estrutura-de-estado-do-filtro&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;3.5 Implementa\u00e7\u00e3o do filtro em C (primeira vers\u00e3o)&quot;,&quot;value&quot;:&quot;35-implementa\u00e7\u00e3o-do-filtro-em-c-primeira-vers\u00e3o&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;3.6 Integra\u00e7\u00e3o inicial com o ADC (BitDogLab)&quot;,&quot;value&quot;:&quot;36-integra\u00e7\u00e3o-inicial-com-o-adc-bitdoglab&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;3.6.1 Leitura b\u00e1sica do ADC&quot;,&quot;value&quot;:&quot;361-leitura-b\u00e1sica-do-adc&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;3.7 Primeiro loop funcional (sem cepstrum ainda)&quot;,&quot;value&quot;:&quot;37-primeiro-loop-funcional-sem-cepstrum-ainda&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;3.8 Valida\u00e7\u00e3o pr\u00e1tica (o que observar)&quot;,&quot;value&quot;:&quot;38-valida\u00e7\u00e3o-pr\u00e1tica-o-que-observar&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;4 \u2014 Cepstrum para detectar o assobio (conceito + coleta de frames + log via Taylor)&quot;,&quot;value&quot;:&quot;4-cepstrum-para-detectar-o-assobio-conceito-coleta-de-frames-log-via-taylor&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;4.1 O que \u00e9 \u201ccepstrum\u201d e por que ele funciona t\u00e3o bem para assobios&quot;,&quot;value&quot;:&quot;41-o-que-\u00e9-cepstrum-e-por-que-ele-funciona-t\u00e3o-bem-para-assobios&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;4.2 Qual cepstrum vamos implementar no RP2040&quot;,&quot;value&quot;:&quot;42-qual-cepstrum-vamos-implementar-no-rp2040&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;4.3 Coleta de frame (buffer) do sinal j\u00e1 filtrado&quot;,&quot;value&quot;:&quot;43-coleta-de-frame-buffer-do-sinal-j\u00e1-filtrado&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;4.3.1 C\u00f3digo incremental: buffer e coleta&quot;,&quot;value&quot;:&quot;431-c\u00f3digo-incremental-buffer-e-coleta&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;4.4 Logaritmo aproximado com S\u00e9rie de Taylor (sem logf())&quot;,&quot;value&quot;:&quot;44-logaritmo-aproximado-com-s\u00e9rie-de-taylor-sem-logf&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;4.4.1 Implementa\u00e7\u00e3o (Taylor truncada)&quot;,&quot;value&quot;:&quot;441-implementa\u00e7\u00e3o-taylor-truncada&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;4.5 Loop j\u00e1 pronto: filtro + coleta de frame&quot;,&quot;value&quot;:&quot;45-loop-j\u00e1-pronto-filtro-coleta-de-frame&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;5 \u2014 FFT + log-magnitude (com Taylor) + IFFT \u21d2 Cepstrum e detec\u00e7\u00e3o do assobio (j\u00e1 aciona LED)&quot;,&quot;value&quot;:&quot;5-fft-log-magnitude-com-taylor-ifft-\u21d2-cepstrum-e-detec\u00e7\u00e3o-do-assobio-j\u00e1-aciona-led&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;5.1 Estruturas complexas e utilit\u00e1rios m\u00ednimos&quot;,&quot;value&quot;:&quot;51-estruturas-complexas-e-utilit\u00e1rios-m\u00ednimos&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;5.2 FFT radix-2 iterativa (in-place) para N=256&quot;,&quot;value&quot;:&quot;52-fft-radix-2-iterativa-in-place-para-n%3D256&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;5.2.1 Por que radix-2 e N=256&quot;,&quot;value&quot;:&quot;521-por-que-radix-2-e-n%3D256&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;5.2.2 Tabela de twiddles (pr\u00e9-c\u00e1lculo)&quot;,&quot;value&quot;:&quot;522-tabela-de-twiddles-pr\u00e9-c\u00e1lculo&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;5.2.3 Bit-reversal (reordena\u00e7\u00e3o)&quot;,&quot;value&quot;:&quot;523-bit-reversal-reordena\u00e7\u00e3o&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;5.2.4 FFT direta (forward)&quot;,&quot;value&quot;:&quot;524-fft-direta-forward&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;5.2.5 IFFT (inverse)&quot;,&quot;value&quot;:&quot;525-ifft-inverse&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;5.3 Montando o espectro: |X[k]| e log(|X[k]|) usando ln_approx (Taylor)&quot;,&quot;value&quot;:&quot;53-montando-o-espectro-|x[k]|-e-log|x[k]|-usando-ln_approx-taylor&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;5.4 Cepstrum: IFFT do log-magnitude e busca do pico de quefr\u00eancia&quot;,&quot;value&quot;:&quot;54-cepstrum-ifft-do-log-magnitude-e-busca-do-pico-de-quefr\u00eancia&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;5.5 Decis\u00e3o e acionamento do LED com histerese&quot;,&quot;value&quot;:&quot;55-decis\u00e3o-e-acionamento-do-led-com-histerese&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;5.6 Integra\u00e7\u00e3o com o que j\u00e1 temos: processar frame quando encher&quot;,&quot;value&quot;:&quot;56-integra\u00e7\u00e3o-com-o-que-j\u00e1-temos-processar-frame-quando-encher&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;5.7 O que voc\u00ea j\u00e1 consegue testar agora&quot;,&quot;value&quot;:&quot;57-o-que-voc\u00ea-j\u00e1-consegue-testar-agora&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;6 \u2014 Robustez \u201cde produ\u00e7\u00e3o\u201d: janela (Hann), gate de sil\u00eancio, suaviza\u00e7\u00e3o temporal e integra\u00e7\u00e3o de perif\u00e9ricos no RP2040&quot;,&quot;value&quot;:&quot;6-robustez-de-produ\u00e7\u00e3o-janela-hann-gate-de-sil\u00eancio-suaviza\u00e7\u00e3o-temporal-e-integra\u00e7\u00e3o-de-perif\u00e9ricos-no-rp2040&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;6.1 Janela Hann (por que e como)&quot;,&quot;value&quot;:&quot;61-janela-hann-por-que-e-como&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;6.1.1 Tabela da janela (pr\u00e9-calculada)&quot;,&quot;value&quot;:&quot;611-tabela-da-janela-pr\u00e9-calculada&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;6.1.2 Aplicar janela antes da FFT&quot;,&quot;value&quot;:&quot;612-aplicar-janela-antes-da-fft&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;6.2 Gate de sil\u00eancio por energia RMS (para cortar falsos positivos)&quot;,&quot;value&quot;:&quot;62-gate-de-sil\u00eancio-por-energia-rms-para-cortar-falsos-positivos&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;6.2.1 Fun\u00e7\u00e3o de energia do frame&quot;,&quot;value&quot;:&quot;621-fun\u00e7\u00e3o-de-energia-do-frame&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;6.2.2 Usar o gate antes do cepstrum&quot;,&quot;value&quot;:&quot;622-usar-o-gate-antes-do-cepstrum&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;6.3 Suaviza\u00e7\u00e3o temporal (EMA) do \u201cpeak\u201d do cepstrum&quot;,&quot;value&quot;:&quot;63-suaviza\u00e7\u00e3o-temporal-ema-do-peak-do-cepstrum&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;6.3.1 Aplicando EMA dentro do detector&quot;,&quot;value&quot;:&quot;631-aplicando-ema-dentro-do-detector&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;6.4 Amostragem est\u00e1vel no RP2040 (sem \u201csleep torto\u201d)&quot;,&quot;value&quot;:&quot;64-amostragem-est\u00e1vel-no-rp2040-sem-sleep-torto&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;6.4.1 Callback de amostragem&quot;,&quot;value&quot;:&quot;641-callback-de-amostragem&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;6.5 Inicializa\u00e7\u00e3o do ADC e do LED (Pico SDK)&quot;,&quot;value&quot;:&quot;65-inicializa\u00e7\u00e3o-do-adc-e-do-led-pico-sdk&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;6.6 Inicializa\u00e7\u00e3o \u201cDSP\u201d: twiddles, janela e buffers&quot;,&quot;value&quot;:&quot;66-inicializa\u00e7\u00e3o-dsp-twiddles-janela-e-buffers&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;6.7 Main \u201cquase final\u201d: timer coleta, loop processa frames&quot;,&quot;value&quot;:&quot;67-main-quase-final-timer-coleta-loop-processa-frames&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;7 \u2014 C\u00f3digo completo e funcional (BitDogLab \/ RP2040) \u2014 filtro Taylor + cepstrum + LED&quot;,&quot;value&quot;:&quot;7-c\u00f3digo-completo-e-funcional-bitdoglab-rp2040-filtro-taylor-cepstrum-led&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;7.1 Como compilar (vis\u00e3o pr\u00e1tica)&quot;,&quot;value&quot;:&quot;71-como-compilar-vis\u00e3o-pr\u00e1tica&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;7.2 Ajustes que voc\u00ea provavelmente vai fazer na BitDogLab&quot;,&quot;value&quot;:&quot;72-ajustes-que-voc\u00ea-provavelmente-vai-fazer-na-bitdoglab&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;8 \u2014 Calibra\u00e7\u00e3o pr\u00e1tica, boas escolhas vs. m\u00e1s escolhas, encerramento e SEO&quot;,&quot;value&quot;:&quot;8-calibra\u00e7\u00e3o-pr\u00e1tica-boas-escolhas-vs-m\u00e1s-escolhas-encerramento-e-seo&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;8.1 Guia r\u00e1pido de calibra\u00e7\u00e3o (passo a passo)&quot;,&quot;value&quot;:&quot;81-guia-r\u00e1pido-de-calibra\u00e7\u00e3o-passo-a-passo&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;8.2 Boas escolhas vs. m\u00e1s escolhas (engenharia real)&quot;,&quot;value&quot;:&quot;82-boas-escolhas-vs-m\u00e1s-escolhas-engenharia-real&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;8.3 Por que essa arquitetura funciona t\u00e3o bem em MCU&quot;,&quot;value&quot;:&quot;83-por-que-essa-arquitetura-funciona-t\u00e3o-bem-em-mcu&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;8.4 Encerramento&quot;,&quot;value&quot;:&quot;84-encerramento&quot;,&quot;isDelete&quot;:false}]" data-smooth="true" data-top-offset=""><div class="eb-toc__list-wrap"><ul class="eb-toc__list"><li><a href="#eb-table-content-0">1 — Motivação, Visão Geral do Problema e Arquitetura da Solução</a><ul class="eb-toc__list"><li><a href="#eb-table-content-1">1.1 Motivação técnica</a><li><a href="#12-problema-a-ser-resolvido">1.2 Problema a ser resolvido</a><li><a href="#13-arquitetura-geral-do-sistema">1.3 Arquitetura geral do sistema</a><li><a href="#eb-table-content-4">1.4 Por que Séries de Taylor em filtros digitais?</a><li><a href="#eb-table-content-5">1.5 O papel do Cepstrum na detecção do assobio</a></li></ul><li><a href="#eb-table-content-6">2 — Características do Assobio Humano e Modelagem do Sinal</a><ul class="eb-toc__list"><li><a href="#eb-table-content-7">2.1 O assobio como sinal físico</a><li><a href="#eb-table-content-8">2.2 Faixa típica de frequências do assobio humano</a><li><a href="#23-sinal-amostrado-no-adc-do-rp2040">2.3 Sinal amostrado no ADC do RP2040</a><li><a href="#eb-table-content-10">2.4 Por que separar fundamental e harmônicas?</a><li><a href="#eb-table-content-11">2.5 Introdução intuitiva às Séries de Taylor</a><li><a href="#eb-table-content-12">2.6 Ponte conceitual: derivadas → filtros</a></li></ul><li><a href="#eb-table-content-13">3 — Construção do Filtro Digital usando Séries de Taylor (Teoria + Primeira Implementação)</a><ul class="eb-toc__list"><li><a href="#31-ideia-central-taylor-como-operador-espectral">3.1 Ideia central: Taylor como operador espectral</a><li><a href="#eb-table-content-15">3.2 Derivadas discretas (diferenças finitas)</a><li><a href="#33-filtro-passa-faixa-baseado-em-taylor-modelo">3.3 Filtro passa-faixa baseado em Taylor (modelo)</a><li><a href="#eb-table-content-17">3.4 Estrutura do código (incremental)</a><ul class="eb-toc__list"><li><a href="#341-estrutura-de-estado-do-filtro">3.4.1 Estrutura de estado do filtro</a></li></ul><li><a href="#eb-table-content-19">3.5 Implementação do filtro em C (primeira versão)</a><li><a href="#eb-table-content-20">3.6 Integração inicial com o ADC (BitDogLab)</a><ul class="eb-toc__list"><li><a href="#eb-table-content-21">3.6.1 Leitura básica do ADC</a></li></ul><li><a href="#37-primeiro-loop-funcional-sem-cepstrum-ainda">3.7 Primeiro loop funcional (sem cepstrum ainda)</a><li><a href="#eb-table-content-23">3.8 Validação prática (o que observar)</a></li></ul><li><a href="#4-cepstrum-para-detectar-o-assobio-conceito-coleta-de-frames-log-via-taylor">4 — Cepstrum para detectar o assobio (conceito + coleta de frames + log via Taylor)</a><ul class="eb-toc__list"><li><a href="#eb-table-content-25">4.1 O que é “cepstrum” e por que ele funciona tão bem para assobios</a><li><a href="#42-qual-cepstrum-vamos-implementar-no-rp2040">4.2 Qual cepstrum vamos implementar no RP2040</a><li><a href="#eb-table-content-27">4.3 Coleta de frame (buffer) do sinal já filtrado</a><ul class="eb-toc__list"><li><a href="#eb-table-content-28">4.3.1 Código incremental: buffer e coleta</a></li></ul><li><a href="#eb-table-content-29">4.4 Logaritmo aproximado com Série de Taylor (sem logf())</a><ul class="eb-toc__list"><li><a href="#eb-table-content-30">4.4.1 Implementação (Taylor truncada)</a></li></ul><li><a href="#eb-table-content-31">4.5 Loop já pronto: filtro + coleta de frame</a></li></ul><li><a href="#eb-table-content-32">5 — FFT + log-magnitude (com Taylor) + IFFT ⇒ Cepstrum e detecção do assobio (já aciona LED)</a><ul class="eb-toc__list"><li><a href="#eb-table-content-33">5.1 Estruturas complexas e utilitários mínimos</a><li><a href="#eb-table-content-34">5.2 FFT radix-2 iterativa (in-place) para N=256</a><ul class="eb-toc__list"><li><a href="#eb-table-content-35">5.2.1 Por que radix-2 e N=256</a><li><a href="#eb-table-content-36">5.2.2 Tabela de twiddles (pré-cálculo)</a><li><a href="#eb-table-content-37">5.2.3 Bit-reversal (reordenação)</a><li><a href="#524-fft-direta-forward">5.2.4 FFT direta (forward)</a><li><a href="#525-ifft-inverse">5.2.5 IFFT (inverse)</a></li></ul><li><a href="#eb-table-content-40">5.3 Montando o espectro: |X[k]| e log(|X[k]|) usando ln_approx (Taylor)</a><li><a href="#eb-table-content-41">5.4 Cepstrum: IFFT do log-magnitude e busca do pico de quefrência</a><li><a href="#eb-table-content-42">5.5 Decisão e acionamento do LED com histerese</a><li><a href="#eb-table-content-43">5.6 Integração com o que já temos: processar frame quando encher</a><li><a href="#eb-table-content-44">5.7 O que você já consegue testar agora</a></li></ul><li><a href="#eb-table-content-45">6 — Robustez “de produção”: janela (Hann), gate de silêncio, suavização temporal e integração de periféricos no RP2040</a><ul class="eb-toc__list"><li><a href="#61-janela-hann-por-que-e-como">6.1 Janela Hann (por que e como)</a><ul class="eb-toc__list"><li><a href="#eb-table-content-47">6.1.1 Tabela da janela (pré-calculada)</a><li><a href="#612-aplicar-janela-antes-da-fft">6.1.2 Aplicar janela antes da FFT</a></li></ul><li><a href="#eb-table-content-49">6.2 Gate de silêncio por energia RMS (para cortar falsos positivos)</a><ul class="eb-toc__list"><li><a href="#eb-table-content-50">6.2.1 Função de energia do frame</a><li><a href="#622-usar-o-gate-antes-do-cepstrum">6.2.2 Usar o gate antes do cepstrum</a></li></ul><li><a href="#eb-table-content-52">6.3 Suavização temporal (EMA) do “peak” do cepstrum</a><ul class="eb-toc__list"><li><a href="#631-aplicando-ema-dentro-do-detector">6.3.1 Aplicando EMA dentro do detector</a></li></ul><li><a href="#eb-table-content-54">6.4 Amostragem estável no RP2040 (sem “sleep torto”)</a><ul class="eb-toc__list"><li><a href="#641-callback-de-amostragem">6.4.1 Callback de amostragem</a></li></ul><li><a href="#eb-table-content-56">6.5 Inicialização do ADC e do LED (Pico SDK)</a><li><a href="#eb-table-content-57">6.6 Inicialização “DSP”: twiddles, janela e buffers</a><li><a href="#67-main-quase-final-timer-coleta-loop-processa-frames">6.7 Main “quase final”: timer coleta, loop processa frames</a></li></ul><li><a href="#eb-table-content-59">7 — Código completo e funcional (BitDogLab / RP2040) — filtro Taylor + cepstrum + LED</a><ul class="eb-toc__list"><li><a href="#eb-table-content-60">7.1 Como compilar (visão prática)</a><li><a href="#eb-table-content-61">7.2 Ajustes que você provavelmente vai fazer na BitDogLab</a></li></ul><li><a href="#eb-table-content-62">8 — Calibração prática, boas escolhas vs. más escolhas, encerramento e SEO</a><ul class="eb-toc__list"><li><a href="#eb-table-content-63">8.1 Guia rápido de calibração (passo a passo)</a><li><a href="#eb-table-content-64">8.2 Boas escolhas vs. más escolhas (engenharia real)</a><li><a href="#eb-table-content-65">8.3 Por que essa arquitetura funciona tão bem em MCU</a><li><a href="#84-encerramento">8.4 Encerramento</a></li></ul></ul></div></div></div></div></div>


<h2 class="wp-block-heading">1 — Motivação, Visão Geral do Problema e Arquitetura da Solução</h2>



<h3 class="wp-block-heading">1.1 Motivação técnica</h3>



<p class="wp-block-paragraph">Assobios humanos possuem uma característica muito interessante do ponto de vista de <strong>processamento digital de sinais (DSP)</strong>: eles apresentam uma <strong>frequência fundamental bem definida</strong>, normalmente entre <strong>800 Hz e 3 kHz</strong>, acompanhada por <strong>harmônicas</strong> que decrescem em amplitude. Isso os torna excelentes candidatos para estudo de <strong>extração de pitch</strong>, <strong>separação espectral</strong> e <strong>detecção robusta de eventos acústicos</strong> em sistemas embarcados.</p>



<p class="wp-block-paragraph">No contexto de microcontroladores como o <strong>RP2040</strong>, o desafio é duplo:</p>



<ol class="wp-block-list">
<li>Executar algoritmos matematicamente consistentes com <strong>baixo custo computacional</strong>.</li>



<li>Evitar bibliotecas pesadas de DSP, favorecendo implementações <strong>determinísticas</strong>, <strong>explicáveis</strong> e <strong>portáveis</strong>.</li>
</ol>



<p class="wp-block-paragraph">Este artigo foi desenhado exatamente com esse espírito: <strong>mostrar que é possível construir um pipeline de detecção de assobio usando apenas matemática clássica</strong>, séries de Taylor e algoritmos fundamentais de DSP, sem FFTs complexas ou frameworks externos.</p>



<figure class="wp-block-image size-full"><img fetchpriority="high" decoding="async" width="721" height="607" src="https://mcu.tec.br/wp-content/uploads/2026/01/image-5.png" alt="" class="wp-image-1116" srcset="https://mcu.tec.br/wp-content/uploads/2026/01/image-5.png 721w, https://mcu.tec.br/wp-content/uploads/2026/01/image-5-300x253.png 300w" sizes="(max-width: 721px) 100vw, 721px" /></figure>



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



<h3 class="wp-block-heading">1.2 Problema a ser resolvido</h3>



<p class="wp-block-paragraph">O problema central pode ser descrito em três níveis:</p>



<ol class="wp-block-list">
<li><strong>Separação espectral</strong><br>O sinal do microfone contém:<ul><li>Ruído ambiente</li><li>Voz humana</li><li>Sons impulsivos</li><li>O assobio propriamente dito</li></ul>Precisamos <strong>isolar a frequência fundamental do assobio e suas harmônicas</strong>.</li>



<li><strong>Identificação confiável do assobio</strong><br>Apenas detectar energia em uma faixa de frequência <strong>não é suficiente</strong>, pois outros sons podem cair nessa banda.<br>Precisamos identificar <strong>periodicidade</strong> — aqui entra o <strong>cepstrum</strong>, que trabalha no domínio da <em>quefrência</em>.</li>



<li><strong>Ação física</strong><br>Após a detecção confiável:
<ul class="wp-block-list">
<li>Acender um LED quando um assobio é detectado</li>



<li>Apagar o LED quando o assobio desaparece</li>
</ul>
</li>
</ol>



<p class="wp-block-paragraph">Tudo isso deve funcionar <strong>em tempo real</strong>, em um <strong>RP2040</strong>, usando a <strong>BitDogLab</strong> como plataforma de referência.</p>



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



<h3 class="wp-block-heading">1.3 Arquitetura geral do sistema</h3>



<p class="wp-block-paragraph">O pipeline completo que iremos construir ao longo do artigo é o seguinte:</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>Microfone (ADC)
       ↓
Pré-processamento (remoção de DC)
       ↓
Filtro Digital por Séries de Taylor
(separação da fundamental e harmônicas)
       ↓
Cálculo do Cepstrum
(log + autocorrelação simplificada)
       ↓
Detecção de Pitch (assobio)
       ↓
Controle do LED (GPIO)
</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: #88C0D0">Microfone</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">ADC</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">       ↓</span></span>
<span class="line"><span style="color: #D8DEE9">Pré</span><span style="color: #81A1C1">-</span><span style="color: #88C0D0">processamento</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">remoção</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">de</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">DC</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">       ↓</span></span>
<span class="line"><span style="color: #D8DEE9">Filtro</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">Digital</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">por</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">Séries</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">de</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">Taylor</span></span>
<span class="line"><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">separação</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">da</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">fundamental</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">e</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">harmônicas</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">       ↓</span></span>
<span class="line"><span style="color: #D8DEE9">Cálculo</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">do</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">Cepstrum</span></span>
<span class="line"><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">log</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">+</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">autocorrelação</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">simplificada</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">       ↓</span></span>
<span class="line"><span style="color: #D8DEE9">Detecção</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">de</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">Pitch</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">assobio</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">       ↓</span></span>
<span class="line"><span style="color: #D8DEE9">Controle</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">do</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">LED</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">GPIO</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">Cada bloco será implementado <strong>incrementalmente</strong>, de forma que:</p>



<ul class="wp-block-list">
<li>O código compile e funcione a cada etapa</li>



<li>Possamos validar o comportamento do sistema progressivamente</li>



<li>Ao final, teremos <strong>um firmware completo, funcional e didático</strong></li>
</ul>



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



<h3 class="wp-block-heading">1.4 Por que Séries de Taylor em filtros digitais?</h3>



<p class="wp-block-paragraph">Normalmente, filtros digitais são apresentados como:</p>



<ul class="wp-block-list">
<li>IIR (Butterworth, Chebyshev, etc.)</li>



<li>FIR por convolução</li>



<li>FFT + máscara espectral</li>
</ul>



<p class="wp-block-paragraph">Aqui escolhemos <strong>Séries de Taylor</strong> por três razões estratégicas:</p>



<ol class="wp-block-list">
<li><strong>Controle matemático total</strong><br>Um filtro baseado em Taylor é, na prática, uma <strong>aproximação explícita de operadores diferenciais</strong>, o que permite entender exatamente o que está sendo implementado.</li>



<li><strong>Eficiência em microcontroladores</strong><br>Séries truncadas resultam em:
<ul class="wp-block-list">
<li>Poucas multiplicações</li>



<li>Nenhuma função transcendental cara em tempo real</li>
</ul>
</li>



<li><strong>Valor didático elevado</strong><br>Esse método conecta:
<ul class="wp-block-list">
<li>Cálculo diferencial</li>



<li>Sistemas lineares</li>



<li>DSP clássico<br>Em um único algoritmo executável em hardware real.</li>
</ul>
</li>
</ol>



<p class="wp-block-paragraph">Mais adiante, mostraremos como aproximar <strong>respostas passa-faixa</strong> usando expansões de Taylor aplicadas a operadores discretos.</p>



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



<h3 class="wp-block-heading">1.5 O papel do Cepstrum na detecção do assobio</h3>



<p class="wp-block-paragraph">Mesmo após filtrar o sinal, ainda temos um problema:<br><strong>harmônicas também são periódicas</strong>, e ruídos podem enganar um detector simples.</p>



<p class="wp-block-paragraph">O <strong>cepstrum</strong> resolve isso explorando uma ideia elegante:</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">A periodicidade no domínio do tempo vira um pico no domínio da <em>quefrência</em>.</p>
</blockquote>



<p class="wp-block-paragraph">Em termos práticos:</p>



<ul class="wp-block-list">
<li>Um assobio gera um pico claro no cepstrum</li>



<li>Voz humana tende a gerar padrões mais espalhados</li>



<li>Ruído branco praticamente não gera picos estáveis</li>
</ul>



<p class="wp-block-paragraph">Isso torna o cepstrum <strong>extremamente robusto</strong> para identificar assobios reais, mesmo em ambientes ruidosos.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/><p>The post <a href="https://mcu.tec.br/algoritimos/dsp/filtro-digital-com-series-de-taylor-e-cepstrum-para-deteccao-de-assobio-em-rp2040/">Filtro Digital com Séries de Taylor e Cepstrum para Detecção de Assobio em RP2040</a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1115</post-id>	</item>
		<item>
		<title>Filtros para Processamento de Sinais em Sistemas Embarcados: Do Básico ao Avançado</title>
		<link>https://mcu.tec.br/algoritimos/filtros-para-processamento-de-sinais-em-sistemas-embarcados-do-basico-ao-avancado/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=filtros-para-processamento-de-sinais-em-sistemas-embarcados-do-basico-ao-avancado</link>
		
		<dc:creator><![CDATA[Carlos Delfino]]></dc:creator>
		<pubDate>Tue, 06 May 2025 11:38:34 +0000</pubDate>
				<category><![CDATA[Algoritimos]]></category>
		<category><![CDATA[código C]]></category>
		<category><![CDATA[estimativa de estado]]></category>
		<category><![CDATA[filtragem de ruído]]></category>
		<category><![CDATA[filtragem em tempo real]]></category>
		<category><![CDATA[filtro de Kalman]]></category>
		<category><![CDATA[filtro de partículas]]></category>
		<category><![CDATA[filtro de Wiener]]></category>
		<category><![CDATA[filtro digital]]></category>
		<category><![CDATA[filtro exponencial]]></category>
		<category><![CDATA[filtro mediano]]></category>
		<category><![CDATA[média móvel]]></category>
		<category><![CDATA[processamento de sinais]]></category>
		<category><![CDATA[sensores ruidosos]]></category>
		<category><![CDATA[sistemas embarcados]]></category>
		<guid isPermaLink="false">https://mcu.tec.br/?p=485</guid>

					<description><![CDATA[<p>Aprenda como aplicar filtros digitais em sistemas embarcados com exemplos em C: média móvel, Kalman, filtros de partículas e mais.</p>
<p>The post <a href="https://mcu.tec.br/algoritimos/filtros-para-processamento-de-sinais-em-sistemas-embarcados-do-basico-ao-avancado/">Filtros para Processamento de Sinais em Sistemas Embarcados: Do Básico ao Avançado</a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></description>
										<content:encoded><![CDATA[<p class="wp-block-paragraph">Em sistemas embarcados, o processamento de sinais é uma etapa fundamental para extrair informações úteis de sensores ruidosos ou sinais analógicos digitalizados. Um sistema de aquisição de dados, por exemplo, raramente trabalha com sinais puros: leituras de sensores sofrem interferências eletromagnéticas, ruídos térmicos ou distorções causadas por componentes eletrônicos. Filtros digitais são técnicas matemáticas e computacionais aplicadas para atenuar esses ruídos, isolar frequências específicas ou prever valores futuros com base em medições passadas.</p>



<p class="wp-block-paragraph">Este artigo abordará uma variedade de filtros, desde os mais simples e amplamente usados, como a Média Móvel (Moving Average), até técnicas mais sofisticadas como o Filtro de Kalman. Cada técnica será apresentada com sua motivação, estrutura matemática e exemplos de implementação prática em C ou pseudo-C para microcontroladores. O objetivo é tornar o tema acessível mesmo para quem está iniciando no campo do processamento digital de sinais, mas também útil a profissionais buscando soluções eficazes e eficientes para aplicações em tempo real.</p>



<h3 class="wp-block-heading">Filtro de Média Móvel</h3>



<p class="wp-block-paragraph">O filtro de média móvel é uma das técnicas mais simples e intuitivas para suavizar sinais ruidosos. Ele funciona como uma janela deslizante que calcula a média dos últimos N valores de entrada. Por sua simplicidade, é amplamente utilizado em sistemas embarcados com recursos computacionais limitados, como sensores de temperatura, pressão, ou leitura de sinais analógicos via ADC (Conversor Analógico-Digital).</p>



<h4 class="wp-block-heading">Problema Resolvido</h4>



<p class="wp-block-paragraph">Sinais adquiridos por sensores frequentemente contêm flutuações indesejadas — ruídos de alta frequência — que podem dificultar decisões ou controles baseados nesses dados. O filtro de média móvel reduz essas flutuações ao suavizar o sinal, permitindo uma resposta mais estável em aplicações como termostatos, sistemas de controle de motor, ou leitura de biossensores.</p>



<h4 class="wp-block-heading">Estrutura Matemática</h4>



<p class="wp-block-paragraph">A média móvel simples é definida pela fórmula: \[y[n] = \frac{1}{N} \sum_{i=0}^{N-1} x[n-i]\]



<p class="wp-block-paragraph">onde:</p>



<ul class="wp-block-list">
<li>y[n] é o valor filtrado no instante n,</li>



<li>x[n] é a amostra de entrada no instante n,</li>



<li>N é o tamanho da janela de média.</li>
</ul>



<h4 class="wp-block-heading">Exemplo de Código em C</h4>



<pre class="wp-block-preformatted"><code>#include &lt;stdint.h><br><br>#define WINDOW_SIZE 8<br><br>typedef struct {<br>    int16_t buffer[WINDOW_SIZE];<br>    uint8_t index;<br>    int32_t sum;<br>} MovingAverageFilter;<br><br>void initFilter(MovingAverageFilter *filter) {<br>    for (int i = 0; i &lt; WINDOW_SIZE; i++)<br>        filter->buffer[i] = 0;<br>    filter->index = 0;<br>    filter->sum = 0;<br>}<br><br>int16_t updateFilter(MovingAverageFilter *filter, int16_t newValue) {<br>    // Subtrai o valor mais antigo da soma<br>    filter->sum -= filter->buffer[filter->index];<br>    // Armazena o novo valor<br>    filter->buffer[filter->index] = newValue;<br>    // Adiciona o novo valor à soma<br>    filter->sum += newValue;<br>    // Move o índice circular<br>    filter->index = (filter->index + 1) % WINDOW_SIZE;<br>    // Retorna a média<br>    return (int16_t)(filter->sum / WINDOW_SIZE);<br>}<br></code></pre>



<h4 class="wp-block-heading">Análise</h4>



<p class="wp-block-paragraph">Este filtro apresenta desempenho estável e implementação eficiente, sem necessidade de operações complexas como multiplicações ou divisões em ponto flutuante (exceto pela divisão final, que pode ser otimizada via deslocamento quando NNN é potência de 2). Contudo, sua resposta a variações rápidas do sinal é lenta, pois ele tende a &#8220;amortecer&#8221; transientes, tornando-o inadequado para sistemas que exigem alta reatividade.</p>



<h4 class="wp-block-heading">Aplicações Típicas</h4>



<ul class="wp-block-list">
<li>Leitura de sensores analógicos com ruído ambiente</li>



<li>Suavização de variações de corrente em fontes chaveadas</li>



<li>Estabilização de sinais de entrada em filtros digitais mais complexos</li>
</ul>



<h3 class="wp-block-heading">Filtro Exponencial (Média Móvel Exponencial)</h3>



<p class="wp-block-paragraph">O filtro exponencial, também conhecido como <strong>filtro de primeira ordem</strong> ou <strong>filtro IIR de coeficiente simples</strong>, é uma alternativa ao filtro de média móvel que introduz uma ponderação decrescente nas amostras anteriores. Em vez de considerar todos os valores com o mesmo peso, como no filtro de média móvel simples, ele dá mais importância às amostras mais recentes, o que permite uma resposta mais ágil às variações do sinal.</p>



<h4 class="wp-block-heading">Problema Resolvido</h4>



<p class="wp-block-paragraph">O filtro de média móvel tradicional tende a atrasar a resposta do sistema quando a janela é grande. O filtro exponencial resolve esse problema permitindo um controle mais refinado sobre a “inércia” do filtro. Ele é particularmente útil quando é necessário suavizar sinais sem causar atrasos excessivos, como em leitura de sensores em tempo real, entrada de joysticks, ou medições de corrente em fontes chaveadas.</p>



<h4 class="wp-block-heading">Estrutura Matemática</h4>



<p class="wp-block-paragraph">O filtro exponencial é definido pela equação de diferença: \[y[n] = \alpha \cdot x[n] + (1 &#8211; \alpha) \cdot y[n-1]\]



<p class="wp-block-paragraph">onde:</p>



<ul class="wp-block-list">
<li>y[n] é a saída filtrada no tempo nnn,</li>



<li>x[n] é a entrada no tempo nnn,</li>



<li>\(\alpha \in (0, 1)\) é o coeficiente de suavização: quanto mais próximo de 1, mais peso a nova entrada terá (resposta rápida); quanto mais próximo de 0, mais lenta e suave será a resposta.</li>
</ul>



<h4 class="wp-block-heading">Exemplo de Código em C</h4>



<pre class="wp-block-preformatted">cCopiarEditar<code>#include &lt;stdint.h&gt;

typedef struct {
    float alpha;
    float output;
} ExponentialFilter;

void initExponentialFilter(ExponentialFilter *filter, float alpha) {
    filter-&gt;alpha = alpha;
    filter-&gt;output = 0.0f;
}

float updateExponentialFilter(ExponentialFilter *filter, float input) {
    filter-&gt;output = filter-&gt;alpha * input + (1.0f - filter-&gt;alpha) * filter-&gt;output;
    return filter-&gt;output;
}
</code></pre>



<h4 class="wp-block-heading">Versão para Inteiros (sem ponto flutuante)</h4>



<p class="wp-block-paragraph">Para microcontroladores sem FPU (Unidade de Ponto Flutuante), pode-se usar uma versão com inteiros, escalando os valores:</p>



<pre class="wp-block-preformatted">cCopiarEditar<code>#include &lt;stdint.h&gt;

#define ALPHA_FIXED 32  // Ex: 32 representa 0.125 se o fator de escala for 256
#define SCALE 256

typedef struct {
    int32_t output;
} ExpFilterFixed;

int16_t updateExpFilterFixed(ExpFilterFixed *filter, int16_t input) {
    filter-&gt;output = (ALPHA_FIXED * input + (SCALE - ALPHA_FIXED) * filter-&gt;output) / SCALE;
    return (int16_t)filter-&gt;output;
}
</code></pre>



<h4 class="wp-block-heading">Análise</h4>



<p class="wp-block-paragraph">O filtro exponencial possui resposta mais rápida do que a média móvel para o mesmo nível de suavização. Seu atraso de grupo é menor e o consumo de memória é reduzido, pois não é necessário armazenar buffers. Contudo, ele possui &#8220;memória infinita&#8221;, ou seja, o valor passado nunca desaparece completamente — o que pode ser uma desvantagem em alguns casos, como em detecção de transientes.</p>



<h4 class="wp-block-heading">Aplicações Típicas</h4>



<ul class="wp-block-list">
<li>Filtros de ruído para sinais de sensores IMU (Acelerômetro/Giroscópio)</li>



<li>Suavização de sinais de controle em robôs e drones</li>



<li>Filtros de corrente em fontes chaveadas com resposta rápida</li>



<li>Modelagem de resposta térmica em sistemas com controle PID</li>
</ul>



<h3 class="wp-block-heading">Filtro de Média Ponderada (Janela com Pesos Customizados)</h3>



<p class="wp-block-paragraph">O filtro de média ponderada é uma generalização do filtro de média móvel, onde cada amostra na janela recebe um peso diferente. Essa abordagem permite maior controle sobre quais partes do sinal têm maior influência na saída filtrada. O uso de pesos permite ajustar o filtro para atender a diferentes requisitos de resposta, como reduzir o ruído sem atenuar mudanças rápidas relevantes.</p>



<h4 class="wp-block-heading">Problema Resolvido</h4>



<p class="wp-block-paragraph">Sinais que contêm ruídos esporádicos ou picos indesejados (outliers) podem afetar significativamente a média simples. A média ponderada, ao atribuir menos peso a amostras mais antigas (ou potencialmente mais ruidosas), permite que o sistema reaja de forma mais eficiente a mudanças reais sem ser tão suscetível a ruídos momentâneos. É especialmente útil quando o sistema exige suavização, mas sem perder a capacidade de detectar transições.</p>



<h4 class="wp-block-heading">Estrutura Matemática</h4>



<p class="wp-block-paragraph">A média ponderada é definida como: \[y[n] = \frac{\sum_{i=0}^{N-1} w_i \cdot x[n-i]}{\sum_{i=0}^{N-1} w_i}\]



<p class="wp-block-paragraph">onde:</p>



<ul class="wp-block-list">
<li>\(w_i\)​ é o peso atribuído à iii-ésima amostra da janela,</li>



<li>x[n−i] é a iii-ésima amostra mais recente,</li>



<li>N é o tamanho da janela.</li>
</ul>



<p class="wp-block-paragraph">Exemplo de pesos com ênfase nas amostras mais recentes: w={1,2,3,4}w = \{1, 2, 3, 4\}w={1,2,3,4}</p>



<h4 class="wp-block-heading">Exemplo de Código em C</h4>



<pre class="wp-block-preformatted"><code>#include &lt;stdint.h><br><br>#define WINDOW_SIZE 4<br><br>typedef struct {<br>    int16_t buffer[WINDOW_SIZE];<br>    uint8_t index;<br>} WeightedAverageFilter;<br><br>const uint8_t weights[WINDOW_SIZE] = {1, 2, 3, 4}; // pesos: mais recente tem maior peso<br><br>int16_t updateWeightedFilter(WeightedAverageFilter *filter, int16_t newValue) {<br>    filter->buffer[filter->index] = newValue;<br>    filter->index = (filter->index + 1) % WINDOW_SIZE;<br><br>    int32_t weightedSum = 0;<br>    int32_t weightTotal = 0;<br>    uint8_t idx = filter->index;<br><br>    for (uint8_t i = 0; i &lt; WINDOW_SIZE; i++) {<br>        idx = (idx == 0) ? WINDOW_SIZE - 1 : idx - 1;<br>        weightedSum += filter->buffer[idx] * weights[i];<br>        weightTotal += weights[i];<br>    }<br><br>    return (int16_t)(weightedSum / weightTotal);<br>}<br></code></pre>



<h4 class="wp-block-heading">Análise</h4>



<p class="wp-block-paragraph">O filtro de média ponderada oferece maior flexibilidade que a média móvel simples, com custo computacional ligeiramente superior. Ele é eficaz para eliminar ruídos do tipo &#8220;espeto&#8221; (spike noise) e ao mesmo tempo manter a capacidade de rastrear tendências. Sua eficiência depende da escolha apropriada dos pesos — os quais podem ser lineares, exponenciais ou customizados para a aplicação.</p>



<h4 class="wp-block-heading">Aplicações Típicas</h4>



<ul class="wp-block-list">
<li>Suavização de sinais de sensores em ambientes ruidosos</li>



<li>Pré-processamento de sinais em sistemas de classificação (ex: ECG, EMG)</li>



<li>Estabilização de leituras em interfaces homem-máquina (joysticks, sliders, etc.)</li>



<li>Leitura de sinais analógicos sujeitos a distorções temporárias</li>
</ul>



<h3 class="wp-block-heading">Filtro Mediano (Median Filter)</h3>



<p class="wp-block-paragraph">O filtro mediano é uma técnica não linear de processamento de sinais especialmente eficaz na remoção de ruídos impulsivos, como picos isolados (outliers) que podem ocorrer em medições físicas. Diferentemente da média móvel, ele não suaviza gradualmente o sinal, mas substitui o valor central de uma janela de amostras pela mediana — o valor que está no meio quando os dados são ordenados. Isso o torna ideal para preservar bordas e transições bruscas enquanto elimina ruídos esporádicos.</p>



<h4 class="wp-block-heading">Problema Resolvido</h4>



<p class="wp-block-paragraph">Em sistemas embarcados que realizam medições sujeitas a interferências eletromagnéticas, conexões instáveis ou saltos ocasionais de leitura (por exemplo, sensores de distância ultrassônicos, sensores de corrente em ambientes industriais ou dados de visão computacional embarcada), a presença de picos pode prejudicar decisões e controles. O filtro mediano elimina essas perturbações preservando a integridade do sinal real.</p>



<h4 class="wp-block-heading">Estrutura Matemática</h4>



<p class="wp-block-paragraph">Para uma janela de tamanho NNN, o filtro ordena as amostras e seleciona a mediana: \[y[n] = \text{median}(x[n &#8211; (N-1)/2], &#8230;, x[n], &#8230;, x[n + (N-1)/2])\]



<p class="wp-block-paragraph">Onde:</p>



<ul class="wp-block-list">
<li>y[n] é a saída filtrada,</li>



<li>x[n] é a amostra no tempo nnn,</li>



<li>A mediana é o valor central da sequência ordenada.</li>
</ul>



<h4 class="wp-block-heading">Exemplo de Código em C (Janela de 5 Amostras)</h4>



<pre class="wp-block-preformatted"><code>#include &lt;stdint.h><br><br>#define WINDOW_SIZE 5<br><br>typedef struct {<br>    int16_t buffer[WINDOW_SIZE];<br>    uint8_t index;<br>} MedianFilter;<br><br>void insertValue(MedianFilter *filter, int16_t value) {<br>    filter->buffer[filter->index] = value;<br>    filter->index = (filter->index + 1) % WINDOW_SIZE;<br>}<br><br>int compare(const void *a, const void *b) {<br>    return (*(int16_t*)a - *(int16_t*)b);<br>}<br><br>int16_t getMedian(MedianFilter *filter) {<br>    int16_t temp[WINDOW_SIZE];<br>    for (int i = 0; i &lt; WINDOW_SIZE; i++)<br>        temp[i] = filter->buffer[i];<br><br>    qsort(temp, WINDOW_SIZE, sizeof(int16_t), compare);<br>    return temp[WINDOW_SIZE / 2];<br>}<br></code></pre>



<h4 class="wp-block-heading">Uso Típico</h4>



<pre class="wp-block-preformatted">cCopiarEditar<code>MedianFilter filter = {{0}, 0};

void loop() {
    int16_t newSample = read_adc();
    insertValue(&amp;filter, newSample);
    int16_t cleanValue = getMedian(&amp;filter);
    // Use cleanValue no controle ou visualização
}
</code></pre>



<h4 class="wp-block-heading">Análise</h4>



<p class="wp-block-paragraph">Embora seja mais robusto a ruídos extremos, o filtro mediano tem maior custo computacional do que os filtros baseados em média. O uso de <code>qsort()</code> pode ser otimizado com algoritmos específicos para mediana de 3, 5 ou 7 valores, comuns em sistemas embarcados. Ele não distorce o sinal original em regiões com variação suave e é muito eficaz para rejeitar ruídos impulsivos. No entanto, seu uso não é adequado para sistemas que exigem filtragem de ruído gaussiano ou precisão em pequenas variações.</p>



<h4 class="wp-block-heading">Aplicações Típicas</h4>



<ul class="wp-block-list">
<li>Sensores ultrassônicos ou infravermelhos com ruído espúrio</li>



<li>Processamento de imagem (eliminação de pixels corrompidos)</li>



<li>Sensores analógicos de baixo custo (temperatura, corrente, tensão)</li>



<li>Filtragem de sinais biológicos (ex: ECG, EMG) em sistemas embarcados</li>
</ul>



<h3 class="wp-block-heading">Filtro de Kalman</h3>



<p class="wp-block-paragraph">O Filtro de Kalman é um algoritmo matemático sofisticado para estimar o estado de um sistema dinâmico a partir de medições ruidosas. Ele é amplamente utilizado em sistemas embarcados para fusão sensorial (como em IMUs), navegação, robótica e controle adaptativo. Ao contrário dos filtros tradicionais, o Kalman considera não só os valores observados, mas também as incertezas associadas tanto ao modelo quanto às medições, fazendo previsões e correções iterativas.</p>



<h4 class="wp-block-heading">Problema Resolvido</h4>



<p class="wp-block-paragraph">Em muitos sistemas embarcados, as medições de sensores apresentam ruído, e o modelo do sistema também pode ser incerto. O filtro de Kalman resolve esse problema ao estimar o &#8220;verdadeiro estado&#8221; do sistema — mesmo que ele não seja diretamente observável — usando uma abordagem estatística baseada em modelos. É ideal para casos em que múltiplas fontes de dados devem ser integradas (por exemplo, acelerômetro + giroscópio) ou quando o sistema sofre variações lentas mas importantes.</p>



<h4 class="wp-block-heading">Estrutura Matemática (Kalman 1D)</h4>



<p class="wp-block-paragraph">O modelo básico de um sistema linear com ruído aditivo é:</p>



<p class="wp-block-paragraph"><strong>Modelo de estado:</strong> \[\hat{x}_{k|k-1} = \hat{x}_{k-1|k-1}\]



<p class="wp-block-paragraph"><strong>Atualização da incerteza:</strong> \[P_{k|k-1} = P_{k-1|k-1} + Q\]



<p class="wp-block-paragraph"><strong>Ganho de Kalman:</strong> \[K_k = \frac{P_{k|k-1}}{P_{k|k-1} + R}\]



<p class="wp-block-paragraph"><strong>Atualização com medição \(z_k\)​:</strong> \[\hat{x}_{k|k} = \hat{x}_{k|k-1} + K_k (z_k &#8211; \hat{x}_{k|k-1})\]\[P_{k|k} = (1 &#8211; K_k) P_{k|k-1}\]



<p class="wp-block-paragraph">Onde:</p>



<ul class="wp-block-list">
<li>\(\hat{x}\): estimativa do estado</li>



<li>P: incerteza da estimativa</li>



<li>Q: variância do ruído do processo</li>



<li>R: variância do ruído de medição</li>



<li>K: ganho de Kalman</li>
</ul>



<h4 class="wp-block-heading">Exemplo de Código em C (Kalman 1D)</h4>



<pre class="wp-block-preformatted"><code>typedef struct {<br>    float x;     // Estado estimado<br>    float p;     // Incerteza da estimativa<br>    float q;     // Variância do processo<br>    float r;     // Variância da medição<br>    float k;     // Ganho de Kalman<br>} KalmanFilter;<br><br>void initKalman(KalmanFilter *kf, float q, float r, float p, float initial_value) {<br>    kf->q = q;<br>    kf->r = r;<br>    kf->p = p;<br>    kf->x = initial_value;<br>}<br><br>float updateKalman(KalmanFilter *kf, float measurement) {<br>    // Predição<br>    kf->p = kf->p + kf->q;<br><br>    // Atualização<br>    kf->k = kf->p / (kf->p + kf->r);<br>    kf->x = kf->x + kf->k * (measurement - kf->x);<br>    kf->p = (1 - kf->k) * kf->p;<br><br>    return kf->x;<br>}<br></code></pre>



<h4 class="wp-block-heading">Análise</h4>



<p class="wp-block-paragraph">O filtro de Kalman é altamente eficiente, com custo computacional linear, sendo perfeitamente viável em microcontroladores de 32 bits (como Cortex-M). Sua força está em sua capacidade de combinar medições ruidosas com previsões baseadas em modelos, gerando uma estimativa mais precisa do que qualquer medição individual. Ele também pode ser estendido para sistemas multivariados (Kalman Multidimensional) e sistemas não-lineares (Filtro de Kalman Estendido).</p>



<h4 class="wp-block-heading">Aplicações Típicas</h4>



<ul class="wp-block-list">
<li>Fusão de sensores (Ex: acelerômetro + giroscópio + magnetômetro)</li>



<li>Rastreamento de posição e velocidade (GPS com odometria)</li>



<li>Controle de sistemas com estados não diretamente observáveis</li>



<li>Estimativas adaptativas de variáveis físicas em fontes chaveadas (tensão, corrente, temperatura)</li>
</ul>



<h3 class="wp-block-heading">Filtro de Kalman Estendido (Extended Kalman Filter &#8211; EKF)</h3>



<p class="wp-block-paragraph">O Filtro de Kalman Estendido (EKF) é uma extensão do Filtro de Kalman tradicional voltada a sistemas <strong>não-lineares</strong>. Em vez de assumir que o sistema e o modelo de medição são lineares, o EKF utiliza uma aproximação local por meio da linearização com séries de Taylor, aplicando a lógica do Kalman sobre uma versão linearizada do sistema.</p>



<h4 class="wp-block-heading">Problema Resolvido</h4>



<p class="wp-block-paragraph">Muitos sistemas físicos reais possuem comportamentos não-lineares: medição de ângulos, sensores de corrente baseados em campo magnético (como Hall), sistemas com dinâmica de rotação ou filtros para sensores de posição em robótica. O Filtro de Kalman tradicional não pode lidar corretamente com não-linearidades. O EKF permite aplicar as ideias do Kalman em sistemas que possuem modelos descritos por funções arbitrárias.</p>



<h4 class="wp-block-heading">Estrutura Matemática (Resumo)</h4>



<p class="wp-block-paragraph">Dado um sistema modelado por: \[x_k = f(x_{k-1}, u_{k-1}) + w_{k-1}\]\[z_k = h(x_k) + v_k\]



<p class="wp-block-paragraph">Onde:</p>



<ul class="wp-block-list">
<li>\(f(\cdot)\): modelo de transição de estado (não-linear)</li>



<li>\(h(\cdot)\): modelo de observação (não-linear)</li>



<li>w e v: ruídos de processo e medição (gaussianos)</li>
</ul>



<p class="wp-block-paragraph">A linearização é feita por meio das matrizes Jacobianas:</p>



<ul class="wp-block-list">
<li>\(F_k = \frac{\partial f}{\partial x}\)​, avaliada em \(\hat{x}_{k-1}\)</li>



<li>\(H_k = \frac{\partial h}{\partial x}\), avaliada em \(\hat{x}_{k|k-1}\)</li>
</ul>



<h4 class="wp-block-heading">Ciclo do EKF</h4>



<ol class="wp-block-list">
<li><strong>Predição:</strong> \[\hat{x}_{k|k-1} = f(\hat{x}_{k-1}, u_{k-1})\] \[\[P_{k|k-1} = F_k P_{k-1} F_k^T + Q\]</li>



<li><strong>Atualização:</strong> \[K_k = P_{k|k-1} H_k^T (H_k P_{k|k-1} H_k^T + R)^{-1}\]\[\hat{x}_{k} = \hat{x}_{k|k-1} + K_k (z_k &#8211; h(\hat{x}_{k|k-1}))\]\[P_k = (I &#8211; K_k H_k) P_{k|k-1}\]</li>
</ol>



<h4 class="wp-block-heading">Exemplo de Aplicação: Estimativa de Ângulo com Sensor de Giro</h4>



<pre class="wp-block-preformatted"><code>// Modelo simplificado do EKF aplicado a sensor de ângulo com giroscópio<br>float x = 0;   // ângulo estimado<br>float p = 1;<br>float q = 0.01; // ruído do processo<br>float r = 0.1;  // ruído da medição<br><br>float ekf_update(float z, float gyroRate, float dt) {<br>    // Predição<br>    x += gyroRate * dt;      // f(x) = x + w*dt<br>    p += q;<br><br>    // Jacobiano H = 1 para h(x) = x (medição direta)<br>    float k = p / (p + r);   // Kalman Gain<br>    x += k * (z - x);        // Atualização<br>    p = (1 - k) * p;<br><br>    return x;<br>}<br></code></pre>



<h4 class="wp-block-heading">Análise</h4>



<p class="wp-block-paragraph">O EKF é uma solução poderosa, mas exige maior capacidade computacional devido ao cálculo de derivadas (Jacobianas) e multiplicações matriciais. Sua precisão depende fortemente da qualidade das aproximações lineares — erros de modelagem ou suposições ruins podem degradar a estimativa. Ainda assim, o EKF é amplamente usado em sistemas embarcados modernos com suporte matemático básico (por exemplo, ARM Cortex-M4 com FPU).</p>



<h4 class="wp-block-heading">Aplicações Típicas</h4>



<ul class="wp-block-list">
<li>Navegação de robôs móveis (composição entre odometria e GPS)</li>



<li>Estimativa de atitude (roll/pitch/yaw) com IMU em drones</li>



<li>Rastreamento de posição em braços robóticos com sensores não-lineares</li>



<li>Previsão de corrente em inversores com sensores indutivos</li>
</ul>



<h3 class="wp-block-heading">Filtro de Partículas (Particle Filter)</h3>



<p class="wp-block-paragraph">O Filtro de Partículas, também conhecido como <strong>Filtro de Monte Carlo</strong>, é um método de estimação baseado em probabilidade que utiliza <strong>conjuntos de amostras (partículas)</strong> para representar a distribuição de probabilidade de um estado. Ele é especialmente útil para sistemas <strong>altamente não-lineares e não-gaussianos</strong>, onde técnicas como o Filtro de Kalman Estendido se tornam imprecisas ou instáveis.</p>



<h4 class="wp-block-heading">Problema Resolvido</h4>



<p class="wp-block-paragraph">Muitos sistemas embarcados modernos operam em ambientes ruidosos e incertos, com múltiplas fontes de erro e modelos complexos — como mapeamento e localização (SLAM), rastreamento visual ou fusão de sensores com ruídos assimétricos. Nesses casos, não é possível assumir uma única média e variância (como no Kalman), sendo necessário representar a estimativa como uma <strong>distribuição completa</strong>. O filtro de partículas resolve isso ao simular muitas hipóteses (partículas) e atualizá-las com base nas evidências.</p>



<h4 class="wp-block-heading">Princípio de Funcionamento</h4>



<p class="wp-block-paragraph">Cada partícula representa uma possível estimativa do estado. A cada iteração:</p>



<ol class="wp-block-list">
<li><strong>Propagação (Predição):</strong><br>Cada partícula é atualizada segundo o modelo de movimento (com ruído).</li>



<li><strong>Atualização de Peso:</strong><br>Cada partícula é ponderada com base na probabilidade de gerar a medição observada.</li>



<li><strong>Reamostragem:</strong><br>Partículas com maior peso têm mais chances de serem mantidas; partículas com baixo peso são descartadas.</li>
</ol>



<p class="wp-block-paragraph">O estado estimado é a <strong>média ponderada</strong> das partículas.</p>



<h4 class="wp-block-heading">Exemplo Simplificado (1D) em C</h4>



<pre class="wp-block-preformatted"><code>#include &lt;stdlib.h><br>#include &lt;math.h><br><br>#define NUM_PARTICLES 100<br><br>typedef struct {<br>    float x;<br>    float weight;<br>} Particle;<br><br>Particle particles[NUM_PARTICLES];<br><br>void init_particles(float initial_guess) {<br>    for (int i = 0; i &lt; NUM_PARTICLES; i++) {<br>        particles[i].x = initial_guess + ((rand() % 100) / 100.0f - 0.5f);  // ruído inicial<br>        particles[i].weight = 1.0f / NUM_PARTICLES;<br>    }<br>}<br><br>float gaussian(float mu, float sigma, float x) {<br>    float coeff = 1.0f / sqrtf(2.0f * M_PI * sigma * sigma);<br>    float expo = expf(-0.5f * ((x - mu) * (x - mu)) / (sigma * sigma));<br>    return coeff * expo;<br>}<br><br>void update_particles(float control_input, float measurement, float process_noise, float measurement_noise) {<br>    float weight_sum = 0.0f;<br><br>    // Predição e atualização de peso<br>    for (int i = 0; i &lt; NUM_PARTICLES; i++) {<br>        // modelo de movimento: x = x + u + ruído<br>        particles[i].x += control_input + ((rand() % 100) / 100.0f - 0.5f) * process_noise;<br><br>        // probabilidade da medição atual com base na posição da partícula<br>        particles[i].weight = gaussian(particles[i].x, measurement_noise, measurement);<br>        weight_sum += particles[i].weight;<br>    }<br><br>    // Normalização dos pesos<br>    for (int i = 0; i &lt; NUM_PARTICLES; i++) {<br>        particles[i].weight /= weight_sum;<br>    }<br><br>    // Reamostragem (simples)<br>    Particle new_particles[NUM_PARTICLES];<br>    for (int i = 0; i &lt; NUM_PARTICLES; i++) {<br>        float r = (float)rand() / RAND_MAX;<br>        float sum = 0.0f;<br>        for (int j = 0; j &lt; NUM_PARTICLES; j++) {<br>            sum += particles[j].weight;<br>            if (sum >= r) {<br>                new_particles[i] = particles[j];<br>                break;<br>            }<br>        }<br>    }<br><br>    // Atualiza o conjunto<br>    for (int i = 0; i &lt; NUM_PARTICLES; i++) {<br>        particles[i] = new_particles[i];<br>    }<br>}<br><br>float estimate() {<br>    float est = 0.0f;<br>    for (int i = 0; i &lt; NUM_PARTICLES; i++) {<br>        est += particles[i].x * particles[i].weight;<br>    }<br>    return est;<br>}<br></code></pre>



<h4 class="wp-block-heading">Análise</h4>



<p class="wp-block-paragraph">O Filtro de Partículas oferece uma capacidade superior de lidar com múltiplas hipóteses, ruídos não-gaussianos e observações ambíguas. Entretanto, seu custo computacional é elevado, exigindo muitas amostras e operações de reamostragem. Ainda assim, com otimizadores e simplificações, ele pode ser implementado em sistemas embarcados ARM Cortex-M com uso eficiente de memória e tempo. O principal desafio é o ajuste correto da modelagem probabilística.</p>



<h4 class="wp-block-heading">Aplicações Típicas</h4>



<ul class="wp-block-list">
<li>Navegação e Localização (SLAM) em robótica e drones</li>



<li>Rastreamento visual de objetos com câmeras embarcadas</li>



<li>Sistemas biomédicos com sinais altamente ruidosos</li>



<li>Inferência probabilística em dispositivos IoT com múltiplos sensores</li>
</ul>



<h3 class="wp-block-heading">Filtro de Wiener</h3>



<p class="wp-block-paragraph">O Filtro de Wiener é uma técnica de filtragem estatística projetada para produzir uma <strong>estimativa ótima</strong> de um sinal desejado com base em suas correlações com o ruído e com o próprio sinal. É amplamente usado em aplicações que exigem restauração de sinais, como recuperação de áudio, imagem e sinais digitais degradados por canais ruidosos. No contexto embarcado, pode ser aplicado a sinais de sensores em que a estatística do ruído é relativamente conhecida ou estimável.</p>



<h4 class="wp-block-heading">Problema Resolvido</h4>



<p class="wp-block-paragraph">Sinais reais são frequentemente corrompidos por ruído aditivo que pode ser modelado estocasticamente. Enquanto os filtros de média móvel e Kalman trabalham com aproximações pontuais ou suposições simplificadas, o Filtro de Wiener é <strong>ótimo no sentido de minimizar o erro quadrático médio (MSE)</strong> entre o sinal real e a saída filtrada. Ele é ideal para situações onde se conhece ou pode estimar a estatística (auto e cruz-correlações) do sinal e do ruído.</p>



<h4 class="wp-block-heading">Estrutura Matemática (Wiener 1D)</h4>



<p class="wp-block-paragraph">O filtro de Wiener tem como solução ótima (discreta e causal): \[H(\omega) = \frac{S_{xx}(\omega)}{S_{xx}(\omega) + S_{nn}(\omega)}\]



<p class="wp-block-paragraph">onde:</p>



<ul class="wp-block-list">
<li>\(H(\omega)\): resposta em frequência do filtro</li>



<li>\(S_{xx}(\omega)\): densidade espectral de potência do sinal</li>



<li>\(S_{nn}(\omega)\): densidade espectral de potência do ruído</li>
</ul>



<p class="wp-block-paragraph">Na forma discreta e implementável, pode ser expresso como: \[y[n] = \sum_{k=0}^{N-1} h[k] \cdot x[n &#8211; k]\]



<p class="wp-block-paragraph">Os coeficientes h[k] são obtidos resolvendo um sistema de equações baseado nas autocorrelações do sinal e na função cruzada entre entrada e saída desejada.</p>



<h4 class="wp-block-heading">Exemplo de Código em C (Forma simplificada com estimativa empírica)</h4>



<pre class="wp-block-preformatted"><code>#include &lt;stdint.h><br>#include &lt;string.h><br><br>#define N 8 // tamanho do filtro<br><br>void estimate_wiener_coeffs(const float *signal, const float *desired, float *coeffs, int len) {<br>    float R[N][N] = {0}; // matriz de autocorrelação<br>    float P[N] = {0};    // vetor de correlação cruzada<br><br>    // Construir R e P<br>    for (int i = 0; i &lt; len - N; i++) {<br>        for (int j = 0; j &lt; N; j++) {<br>            for (int k = 0; k &lt; N; k++) {<br>                R[j][k] += signal[i + j] * signal[i + k];<br>            }<br>            P[j] += desired[i] * signal[i + j];<br>        }<br>    }<br><br>    // Resolver sistema linear R * h = P (poderia usar Gauss-Jordan ou LU)<br>    // Aqui simplificado como uma solução direta apenas para casos didáticos<br>    for (int i = 0; i &lt; N; i++) {<br>        coeffs[i] = P[i] / (R[i][i] + 1e-6f); // simplificação para exemplo<br>    }<br>}<br><br>float apply_wiener_filter(const float *input, const float *coeffs) {<br>    float output = 0.0f;<br>    for (int i = 0; i &lt; N; i++) {<br>        output += coeffs[i] * input[i];<br>    }<br>    return output;<br>}<br></code></pre>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph"><strong>Nota:</strong> Este exemplo é didático. Em aplicações reais, o sistema R⋅h=PR \cdot h = PR⋅h=P deve ser resolvido com métodos numéricos estáveis (ex: decomposição de Cholesky ou métodos iterativos).</p>
</blockquote>



<h4 class="wp-block-heading">Análise</h4>



<p class="wp-block-paragraph">O Filtro de Wiener é ótimo em contextos onde se conhece a estatística do sinal e ruído, mas é limitado por sua dependência desses parâmetros. Sua implementação completa pode ser pesada para microcontroladores de baixo desempenho, mas versões simplificadas, ou estimativas precomputadas, são perfeitamente viáveis em sistemas embarcados com uso constante de sinais similares.</p>



<h4 class="wp-block-heading">Aplicações Típicas</h4>



<ul class="wp-block-list">
<li>Recuperação de áudio embarcado (remoção de ruído de fundo)</li>



<li>Filtragem de sinais digitais em telecomunicações embarcadas</li>



<li>Processamento de imagem embarcada (ex: remoção de borrões ou granulação)</li>



<li>Detecção de falhas em sensores com comportamento repetitivo (ex: sensores industriais)</li>
</ul>



<p class="wp-block-paragraph">Ao longo dos capítulos anteriores, exploramos uma ampla gama de filtros aplicáveis ao processamento de sinais em sistemas embarcados, desde técnicas simples baseadas em médias até algoritmos probabilísticos e estatísticos avançados. Cada filtro oferece vantagens e limitações, dependendo da natureza do sinal, do ruído presente e dos recursos computacionais disponíveis.</p>



<h4 class="wp-block-heading">Comparação Geral dos Filtros</h4>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Filtro</th><th>Complexidade</th><th>Tipo</th><th>Vantagem Principal</th><th>Limitação Principal</th><th>Aplicação Típica</th></tr></thead><tbody><tr><td>Média Móvel</td><td>Baixa</td><td>Linear</td><td>Simples e fácil de implementar</td><td>Suaviza transientes</td><td>Leitura de sensores analógicos simples</td></tr><tr><td>Exponencial</td><td>Muito baixa</td><td>Linear (IIR)</td><td>Pouco uso de memória, boa resposta</td><td>Menos eficaz com ruídos impulsivos</td><td>Filtragem de sinais em controle de motor</td></tr><tr><td>Média Ponderada</td><td>Baixa</td><td>Linear</td><td>Ajustável ao contexto</td><td>Precisa de cuidado na escolha dos pesos</td><td>Interfaces com usuário (joysticks, etc.)</td></tr><tr><td>Mediano</td><td>Média</td><td>Não-linear</td><td>Robusto a picos e outliers</td><td>Mais pesado, introduz atraso em sinais finos</td><td>Sensores ultrassônicos, visão embarcada</td></tr><tr><td>Kalman</td><td>Média</td><td>Probabilístico</td><td>Otimização estatística com baixo custo</td><td>Exige bom modelo de ruído</td><td>Estimativa de posição, velocidade, IMUs</td></tr><tr><td>Kalman Estendido (EKF)</td><td>Alta</td><td>Não-linear</td><td>Estima estados em sistemas não-lineares</td><td>Custo computacional, sensível a modelagem</td><td>Navegação robótica, fusão sensorial</td></tr><tr><td>Filtro de Partículas</td><td>Muito alta</td><td>Estocástico</td><td>Lida com múltiplas hipóteses e ambiguidade</td><td>Muito pesado computacionalmente</td><td>SLAM, rastreamento em visão embarcada</td></tr><tr><td>Filtro de Wiener</td><td>Alta</td><td>Ótimo estatístico</td><td>Minimiza erro quadrático médio</td><td>Requer estatísticas conhecidas</td><td>Restauração de sinais, áudio, imagem</td></tr></tbody></table></figure>



<h4 class="wp-block-heading">Recomendações Práticas</h4>



<ul class="wp-block-list">
<li><strong>Se o seu sistema embarcado for simples e tiver baixa potência computacional</strong>, comece com filtros como <strong>média móvel</strong>, <strong>exponencial</strong> ou <strong>mediano</strong>.</li>



<li><strong>Se você precisa de suavização adaptativa e preditiva</strong>, e possui sensores com ruído gaussiano, o <strong>Filtro de Kalman</strong> é altamente recomendado.</li>



<li><strong>Em sistemas com modelos não-lineares complexos</strong> (ex: giroscópio + acelerômetro), o <strong>Filtro de Kalman Estendido</strong> é a solução natural.</li>



<li><strong>Quando o sistema apresenta múltiplas hipóteses simultâneas ou incertezas complexas</strong>, como em navegação ou SLAM, o <strong>Filtro de Partículas</strong> se destaca, desde que haja recursos computacionais adequados.</li>



<li><strong>Para aplicações onde você conhece a estatística do ruído e sinal</strong>, e quer obter a melhor estimativa possível com base nessa modelagem, o <strong>Filtro de Wiener</strong> é a escolha teórica ideal.</li>
</ul>



<h4 class="wp-block-heading">Encerramento</h4>



<p class="wp-block-paragraph">Filtros são ferramentas essenciais no arsenal do engenheiro de sistemas embarcados. Dominar seus fundamentos, limitações e aplicações permite construir sistemas mais robustos, confiáveis e eficientes, independentemente da área de atuação — automação, robótica, IoT, biomédica ou aeroespacial.</p><p>The post <a href="https://mcu.tec.br/algoritimos/filtros-para-processamento-de-sinais-em-sistemas-embarcados-do-basico-ao-avancado/">Filtros para Processamento de Sinais em Sistemas Embarcados: Do Básico ao Avançado</a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">485</post-id>	</item>
	</channel>
</rss>
