<?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>RP2040 - MCU &amp; FPGA</title>
	<atom:link href="https://mcu.tec.br/tags/rp2040/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.0</generator>

<image>
	<url>https://mcu.tec.br/wp-content/uploads/2025/02/Robo-para-o-site-MCU.tec_.br-512x512-1-150x150.png</url>
	<title>RP2040 - 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>Detecção de Assobio com Goertzel e Aprendizado Estatístico no RP2040</title>
		<link>https://mcu.tec.br/algoritimos/dsp/deteccao-de-assobio-com-goertzel-e-aprendizado-estatistico-no-rp2040/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=deteccao-de-assobio-com-goertzel-e-aprendizado-estatistico-no-rp2040</link>
		
		<dc:creator><![CDATA[Carlos Delfino]]></dc:creator>
		<pubDate>Thu, 12 Feb 2026 11:36:50 +0000</pubDate>
				<category><![CDATA[DSP]]></category>
		<category><![CDATA[aprendizado estatístico]]></category>
		<category><![CDATA[BitDogLab]]></category>
		<category><![CDATA[classificação estatística]]></category>
		<category><![CDATA[detecção de assobio]]></category>
		<category><![CDATA[DSP embarcado]]></category>
		<category><![CDATA[firmware em c]]></category>
		<category><![CDATA[Goertzel]]></category>
		<category><![CDATA[processamento de áudio]]></category>
		<category><![CDATA[RP2040]]></category>
		<category><![CDATA[sistemas adaptativos]]></category>
		<guid isPermaLink="false">https://mcu.tec.br/?p=1127</guid>

					<description><![CDATA[<p>Este artigo apresenta uma abordagem avançada e didática para detecção de assobio humano em microcontroladores RP2040 utilizando o algoritmo de Goertzel combinado com aprendizado estatístico adaptativo. Como continuação direta de uma série sobre DSP embarcado, o conteúdo mostra como transformar medições espectrais determinísticas em vetores de características robustos e como aplicar modelos estatísticos leves — baseados em média, variância e distância probabilística — para tomada de decisão confiável em ambientes variáveis. Toda a solução é implementada integralmente em linguagem C, sem bibliotecas externas, executando em tempo real na BitDogLab. O artigo é voltado a engenheiros, estudantes e desenvolvedores que desejam compreender, projetar e aplicar sistemas de processamento digital de sinais adaptativos em microcontroladores de recursos limitados.</p>
<p>The post <a href="https://mcu.tec.br/algoritimos/dsp/deteccao-de-assobio-com-goertzel-e-aprendizado-estatistico-no-rp2040/">Detecção de Assobio com Goertzel e Aprendizado Estatístico no RP2040</a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></description>
										<content:encoded><![CDATA[<p class="wp-block-paragraph">Continuação da série: </p>



<ul class="wp-block-list">
<li><a href="https://mcu.tec.br/?p=1115" title="">Filtragem Digital, Cepstrum e Detecção Acústica em MCU</a></li>



<li><a href="https://mcu.tec.br/?p=1125" title="detecção de assobio">Detecção de Assobio Humano com o Algoritmo de Goertzel no RP2040</a></li>
</ul>


<div class="root-eb-toc-tjnly wp-block-essential-blocks-table-of-contents"><div class="eb-parent-wrapper eb-parent-eb-toc-tjnly "><div class="eb-toc-container eb-toc-tjnly  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. Introdu\u00e7\u00e3o \u2014 Por que combinar Goertzel com aprendizado estat\u00edstico?&quot;,&quot;text&quot;:&quot;1. Introdu\u00e7\u00e3o \u2014 Por que combinar Goertzel com aprendizado estat\u00edstico?&quot;,&quot;link&quot;:&quot;eb-table-content-0&quot;},{&quot;level&quot;:2,&quot;content&quot;:&quot;1.1 O papel do Goertzel nesta nova arquitetura&quot;,&quot;text&quot;:&quot;1.1 O papel do Goertzel nesta nova arquitetura&quot;,&quot;link&quot;:&quot;11-o-papel-do-goertzel-nesta-nova-arquitetura&quot;},{&quot;level&quot;:2,&quot;content&quot;:&quot;1.2 O que entendemos aqui por \u201caprendizado estat\u00edstico\u201d&quot;,&quot;text&quot;:&quot;1.2 O que entendemos aqui por \u201caprendizado estat\u00edstico\u201d&quot;,&quot;link&quot;:&quot;eb-table-content-2&quot;},{&quot;level&quot;:2,&quot;content&quot;:&quot;1.3 Por que limiares fixos falham em campo&quot;,&quot;text&quot;:&quot;1.3 Por que limiares fixos falham em campo&quot;,&quot;link&quot;:&quot;13-por-que-limiares-fixos-falham-em-campo&quot;},{&quot;level&quot;:2,&quot;content&quot;:&quot;1.4 Vis\u00e3o geral da nova arquitetura&quot;,&quot;text&quot;:&quot;1.4 Vis\u00e3o geral da nova arquitetura&quot;,&quot;link&quot;:&quot;eb-table-content-4&quot;},{&quot;level&quot;:2,&quot;content&quot;:&quot;1.5 O que voc\u00ea ter\u00e1 ao final deste artigo&quot;,&quot;text&quot;:&quot;1.5 O que voc\u00ea ter\u00e1 ao final deste artigo&quot;,&quot;link&quot;:&quot;eb-table-content-5&quot;},{&quot;level&quot;:2,&quot;content&quot;:&quot;2 \u2014 Do sinal ao vetor de caracter\u00edsticas: extraindo features estat\u00edsticas a partir do Goertzel&quot;,&quot;text&quot;:&quot;2 \u2014 Do sinal ao vetor de caracter\u00edsticas: extraindo features estat\u00edsticas a partir do Goertzel&quot;,&quot;link&quot;:&quot;eb-table-content-6&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;2.1 Por que \u201cfeatures\u201d s\u00e3o mais importantes que o algoritmo de decis\u00e3o&quot;,&quot;text&quot;:&quot;2.1 Por que \u201cfeatures\u201d s\u00e3o mais importantes que o algoritmo de decis\u00e3o&quot;,&quot;link&quot;:&quot;eb-table-content-7&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;2.2 O que N\u00c3O usar como feature (e por qu\u00ea)&quot;,&quot;text&quot;:&quot;2.2 O que N\u00c3O usar como feature (e por qu\u00ea)&quot;,&quot;link&quot;:&quot;eb-table-content-8&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;2.3 Princ\u00edpio fundamental: normaliza\u00e7\u00e3o e rela\u00e7\u00f5es&quot;,&quot;text&quot;:&quot;2.3 Princ\u00edpio fundamental: normaliza\u00e7\u00e3o e rela\u00e7\u00f5es&quot;,&quot;link&quot;:&quot;eb-table-content-9&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;2.4 Feature 1 \u2014 Energia normalizada da fundamental&quot;,&quot;text&quot;:&quot;2.4 Feature 1 \u2014 Energia normalizada da fundamental&quot;,&quot;link&quot;:&quot;24-feature-1-energia-normalizada-da-fundamental&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;2.5 Feature 2 \u2014 Rela\u00e7\u00e3o do 2\u00ba harm\u00f4nico&quot;,&quot;text&quot;:&quot;2.5 Feature 2 \u2014 Rela\u00e7\u00e3o do 2\u00ba harm\u00f4nico&quot;,&quot;link&quot;:&quot;eb-table-content-11&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;2.6 Feature 3 \u2014 Rela\u00e7\u00e3o do 3\u00ba harm\u00f4nico (opcional, mas valiosa)&quot;,&quot;text&quot;:&quot;2.6 Feature 3 \u2014 Rela\u00e7\u00e3o do 3\u00ba harm\u00f4nico (opcional, mas valiosa)&quot;,&quot;link&quot;:&quot;eb-table-content-12&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;2.7 Feature 4 \u2014 Estabilidade temporal da frequ\u00eancia&quot;,&quot;text&quot;:&quot;2.7 Feature 4 \u2014 Estabilidade temporal da frequ\u00eancia&quot;,&quot;link&quot;:&quot;eb-table-content-13&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;2.8 Montando o vetor de caracter\u00edsticas&quot;,&quot;text&quot;:&quot;2.8 Montando o vetor de caracter\u00edsticas&quot;,&quot;link&quot;:&quot;eb-table-content-14&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;2.9 Feature engineering \u00e9 engenharia, n\u00e3o tentativa&quot;,&quot;text&quot;:&quot;2.9 Feature engineering \u00e9 engenharia, n\u00e3o tentativa&quot;,&quot;link&quot;:&quot;eb-table-content-15&quot;},{&quot;level&quot;:2,&quot;content&quot;:&quot;3 \u2014 Modelo estat\u00edstico adaptativo: m\u00e9dia, vari\u00e2ncia e decis\u00e3o probabil\u00edstica (online, leve e interpret\u00e1vel)&quot;,&quot;text&quot;:&quot;3 \u2014 Modelo estat\u00edstico adaptativo: m\u00e9dia, vari\u00e2ncia e decis\u00e3o probabil\u00edstica (online, leve e interpret\u00e1vel)&quot;,&quot;link&quot;:&quot;eb-table-content-16&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;3.1 Princ\u00edpio do modelo: aprender o \u201cnormal\u201d e medir desvio&quot;,&quot;text&quot;:&quot;3.1 Princ\u00edpio do modelo: aprender o \u201cnormal\u201d e medir desvio&quot;,&quot;link&quot;:&quot;eb-table-content-17&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;3.2 Modelo estat\u00edstico por feature (independente)&quot;,&quot;text&quot;:&quot;3.2 Modelo estat\u00edstico por feature (independente)&quot;,&quot;link&quot;:&quot;eb-table-content-18&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;3.3 Atualiza\u00e7\u00e3o online da m\u00e9dia (EMA)&quot;,&quot;text&quot;:&quot;3.3 Atualiza\u00e7\u00e3o online da m\u00e9dia (EMA)&quot;,&quot;link&quot;:&quot;eb-table-content-19&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;3.4 Atualiza\u00e7\u00e3o online da vari\u00e2ncia (forma est\u00e1vel)&quot;,&quot;text&quot;:&quot;3.4 Atualiza\u00e7\u00e3o online da vari\u00e2ncia (forma est\u00e1vel)&quot;,&quot;link&quot;:&quot;eb-table-content-20&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;3.5 Inicializa\u00e7\u00e3o segura do modelo&quot;,&quot;text&quot;:&quot;3.5 Inicializa\u00e7\u00e3o segura do modelo&quot;,&quot;link&quot;:&quot;eb-table-content-21&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;3.6 Medida de desvio: Z-score por feature&quot;,&quot;text&quot;:&quot;3.6 Medida de desvio: Z-score por feature&quot;,&quot;link&quot;:&quot;36-medida-de-desvio-z-score-por-feature&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;3.7 Dist\u00e2ncia estat\u00edstica simplificada (score global)&quot;,&quot;text&quot;:&quot;3.7 Dist\u00e2ncia estat\u00edstica simplificada (score global)&quot;,&quot;link&quot;:&quot;eb-table-content-23&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;3.8 Regra de decis\u00e3o probabil\u00edstica simples&quot;,&quot;text&quot;:&quot;3.8 Regra de decis\u00e3o probabil\u00edstica simples&quot;,&quot;link&quot;:&quot;eb-table-content-24&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;3.9 Aprendizado controlado (n\u00e3o aprender ru\u00eddo)&quot;,&quot;text&quot;:&quot;3.9 Aprendizado controlado (n\u00e3o aprender ru\u00eddo)&quot;,&quot;link&quot;:&quot;eb-table-content-25&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;3.10 O que conquistamos at\u00e9 aqui&quot;,&quot;text&quot;:&quot;3.10 O que conquistamos at\u00e9 aqui&quot;,&quot;link&quot;:&quot;eb-table-content-26&quot;},{&quot;level&quot;:2,&quot;content&quot;:&quot;4 \u2014 Integra\u00e7\u00e3o completa em tempo real: Goertzel + features + modelo estat\u00edstico + LED no RP2040&quot;,&quot;text&quot;:&quot;4 \u2014 Integra\u00e7\u00e3o completa em tempo real: Goertzel + features + modelo estat\u00edstico + LED no RP2040&quot;,&quot;link&quot;:&quot;eb-table-content-27&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;4.1 Vis\u00e3o geral do fluxo em tempo real&quot;,&quot;text&quot;:&quot;4.1 Vis\u00e3o geral do fluxo em tempo real&quot;,&quot;link&quot;:&quot;eb-table-content-28&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;4.2 Estruturas globais de estado&quot;,&quot;text&quot;:&quot;4.2 Estruturas globais de estado&quot;,&quot;link&quot;:&quot;42-estruturas-globais-de-estado&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;4.3 Constru\u00e7\u00e3o do vetor de features em tempo real&quot;,&quot;text&quot;:&quot;4.3 Constru\u00e7\u00e3o do vetor de features em tempo real&quot;,&quot;link&quot;:&quot;eb-table-content-30&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;4.4 Avalia\u00e7\u00e3o estat\u00edstica e decis\u00e3o&quot;,&quot;text&quot;:&quot;4.4 Avalia\u00e7\u00e3o estat\u00edstica e decis\u00e3o&quot;,&quot;link&quot;:&quot;eb-table-content-31&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;4.5 Atualiza\u00e7\u00e3o do modelo (aprendizado online controlado)&quot;,&quot;text&quot;:&quot;4.5 Atualiza\u00e7\u00e3o do modelo (aprendizado online controlado)&quot;,&quot;link&quot;:&quot;eb-table-content-32&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;4.6 Acionamento do LED (sem l\u00f3gica escondida)&quot;,&quot;text&quot;:&quot;4.6 Acionamento do LED (sem l\u00f3gica escondida)&quot;,&quot;link&quot;:&quot;eb-table-content-33&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;4.7 Loop principal: simples, limpo e determin\u00edstico&quot;,&quot;text&quot;:&quot;4.7 Loop principal: simples, limpo e determin\u00edstico&quot;,&quot;link&quot;:&quot;eb-table-content-34&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;4.8 O que temos agora (antes do c\u00f3digo final)&quot;,&quot;text&quot;:&quot;4.8 O que temos agora (antes do c\u00f3digo final)&quot;,&quot;link&quot;:&quot;eb-table-content-35&quot;},{&quot;level&quot;:2,&quot;content&quot;:&quot;5 \u2014 C\u00f3digo completo e funcional (Goertzel + aprendizado estat\u00edstico) para BitDogLab \/ RP2040&quot;,&quot;text&quot;:&quot;5 \u2014 C\u00f3digo completo e funcional (Goertzel + aprendizado estat\u00edstico) para BitDogLab \/ RP2040&quot;,&quot;link&quot;:&quot;eb-table-content-36&quot;},{&quot;level&quot;:2,&quot;content&quot;:&quot;6 \u2014 Calibra\u00e7\u00e3o pr\u00e1tica, boas escolhas vs. m\u00e1s escolhas, compara\u00e7\u00e3o entre estrat\u00e9gias, encerramento e SEO&quot;,&quot;text&quot;:&quot;6 \u2014 Calibra\u00e7\u00e3o pr\u00e1tica, boas escolhas vs. m\u00e1s escolhas, compara\u00e7\u00e3o entre estrat\u00e9gias, encerramento e SEO&quot;,&quot;link&quot;:&quot;eb-table-content-37&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;6.1 Calibra\u00e7\u00e3o pr\u00e1tica do modelo estat\u00edstico (como fazer funcionar em campo)&quot;,&quot;text&quot;:&quot;6.1 Calibra\u00e7\u00e3o pr\u00e1tica do modelo estat\u00edstico (como fazer funcionar em campo)&quot;,&quot;link&quot;:&quot;eb-table-content-38&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;6.2 Boas escolhas vs. m\u00e1s escolhas (aprendizado estat\u00edstico em MCU)&quot;,&quot;text&quot;:&quot;6.2 Boas escolhas vs. m\u00e1s escolhas (aprendizado estat\u00edstico em MCU)&quot;,&quot;link&quot;:&quot;eb-table-content-39&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;6.3 Compara\u00e7\u00e3o final entre os tr\u00eas artigos da s\u00e9rie&quot;,&quot;text&quot;:&quot;6.3 Compara\u00e7\u00e3o final entre os tr\u00eas artigos da s\u00e9rie&quot;,&quot;link&quot;:&quot;eb-table-content-40&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;6.4 Encerramento conceitual&quot;,&quot;text&quot;:&quot;6.4 Encerramento conceitual&quot;,&quot;link&quot;:&quot;64-encerramento-conceitual&quot;}]" data-visible="[true,true,true,true,true,true]" data-delete-headers="[{&quot;label&quot;:&quot;1. Introdu\u00e7\u00e3o \u2014 Por que combinar Goertzel com aprendizado estat\u00edstico?&quot;,&quot;value&quot;:&quot;1-introdu\u00e7\u00e3o-por-que-combinar-goertzel-com-aprendizado-estat\u00edstico&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;1.1 O papel do Goertzel nesta nova arquitetura&quot;,&quot;value&quot;:&quot;11-o-papel-do-goertzel-nesta-nova-arquitetura&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;1.2 O que entendemos aqui por \u201caprendizado estat\u00edstico\u201d&quot;,&quot;value&quot;:&quot;12-o-que-entendemos-aqui-por-aprendizado-estat\u00edstico&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;1.3 Por que limiares fixos falham em campo&quot;,&quot;value&quot;:&quot;13-por-que-limiares-fixos-falham-em-campo&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;1.4 Vis\u00e3o geral da nova arquitetura&quot;,&quot;value&quot;:&quot;14-vis\u00e3o-geral-da-nova-arquitetura&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;1.5 O que voc\u00ea ter\u00e1 ao final deste artigo&quot;,&quot;value&quot;:&quot;15-o-que-voc\u00ea-ter\u00e1-ao-final-deste-artigo&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;2 \u2014 Do sinal ao vetor de caracter\u00edsticas: extraindo features estat\u00edsticas a partir do Goertzel&quot;,&quot;value&quot;:&quot;2-do-sinal-ao-vetor-de-caracter\u00edsticas-extraindo-features-estat\u00edsticas-a-partir-do-goertzel&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;2.1 Por que \u201cfeatures\u201d s\u00e3o mais importantes que o algoritmo de decis\u00e3o&quot;,&quot;value&quot;:&quot;21-por-que-features-s\u00e3o-mais-importantes-que-o-algoritmo-de-decis\u00e3o&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;2.2 O que N\u00c3O usar como feature (e por qu\u00ea)&quot;,&quot;value&quot;:&quot;22-o-que-n\u00e3o-usar-como-feature-e-por-qu\u00ea&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;2.3 Princ\u00edpio fundamental: normaliza\u00e7\u00e3o e rela\u00e7\u00f5es&quot;,&quot;value&quot;:&quot;23-princ\u00edpio-fundamental-normaliza\u00e7\u00e3o-e-rela\u00e7\u00f5es&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;2.4 Feature 1 \u2014 Energia normalizada da fundamental&quot;,&quot;value&quot;:&quot;24-feature-1-energia-normalizada-da-fundamental&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;2.5 Feature 2 \u2014 Rela\u00e7\u00e3o do 2\u00ba harm\u00f4nico&quot;,&quot;value&quot;:&quot;25-feature-2-rela\u00e7\u00e3o-do-2\u00ba-harm\u00f4nico&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;2.6 Feature 3 \u2014 Rela\u00e7\u00e3o do 3\u00ba harm\u00f4nico (opcional, mas valiosa)&quot;,&quot;value&quot;:&quot;26-feature-3-rela\u00e7\u00e3o-do-3\u00ba-harm\u00f4nico-opcional-mas-valiosa&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;2.7 Feature 4 \u2014 Estabilidade temporal da frequ\u00eancia&quot;,&quot;value&quot;:&quot;27-feature-4-estabilidade-temporal-da-frequ\u00eancia&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;2.8 Montando o vetor de caracter\u00edsticas&quot;,&quot;value&quot;:&quot;28-montando-o-vetor-de-caracter\u00edsticas&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;2.9 Feature engineering \u00e9 engenharia, n\u00e3o tentativa&quot;,&quot;value&quot;:&quot;29-feature-engineering-\u00e9-engenharia-n\u00e3o-tentativa&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;3 \u2014 Modelo estat\u00edstico adaptativo: m\u00e9dia, vari\u00e2ncia e decis\u00e3o probabil\u00edstica (online, leve e interpret\u00e1vel)&quot;,&quot;value&quot;:&quot;3-modelo-estat\u00edstico-adaptativo-m\u00e9dia-vari\u00e2ncia-e-decis\u00e3o-probabil\u00edstica-online-leve-e-interpret\u00e1vel&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;3.1 Princ\u00edpio do modelo: aprender o \u201cnormal\u201d e medir desvio&quot;,&quot;value&quot;:&quot;31-princ\u00edpio-do-modelo-aprender-o-normal-e-medir-desvio&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;3.2 Modelo estat\u00edstico por feature (independente)&quot;,&quot;value&quot;:&quot;32-modelo-estat\u00edstico-por-feature-independente&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;3.3 Atualiza\u00e7\u00e3o online da m\u00e9dia (EMA)&quot;,&quot;value&quot;:&quot;33-atualiza\u00e7\u00e3o-online-da-m\u00e9dia-ema&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;3.4 Atualiza\u00e7\u00e3o online da vari\u00e2ncia (forma est\u00e1vel)&quot;,&quot;value&quot;:&quot;34-atualiza\u00e7\u00e3o-online-da-vari\u00e2ncia-forma-est\u00e1vel&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;3.5 Inicializa\u00e7\u00e3o segura do modelo&quot;,&quot;value&quot;:&quot;35-inicializa\u00e7\u00e3o-segura-do-modelo&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;3.6 Medida de desvio: Z-score por feature&quot;,&quot;value&quot;:&quot;36-medida-de-desvio-z-score-por-feature&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;3.7 Dist\u00e2ncia estat\u00edstica simplificada (score global)&quot;,&quot;value&quot;:&quot;37-dist\u00e2ncia-estat\u00edstica-simplificada-score-global&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;3.8 Regra de decis\u00e3o probabil\u00edstica simples&quot;,&quot;value&quot;:&quot;38-regra-de-decis\u00e3o-probabil\u00edstica-simples&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;3.9 Aprendizado controlado (n\u00e3o aprender ru\u00eddo)&quot;,&quot;value&quot;:&quot;39-aprendizado-controlado-n\u00e3o-aprender-ru\u00eddo&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;3.10 O que conquistamos at\u00e9 aqui&quot;,&quot;value&quot;:&quot;310-o-que-conquistamos-at\u00e9-aqui&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;4 \u2014 Integra\u00e7\u00e3o completa em tempo real: Goertzel + features + modelo estat\u00edstico + LED no RP2040&quot;,&quot;value&quot;:&quot;4-integra\u00e7\u00e3o-completa-em-tempo-real-goertzel-features-modelo-estat\u00edstico-led-no-rp2040&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;4.1 Vis\u00e3o geral do fluxo em tempo real&quot;,&quot;value&quot;:&quot;41-vis\u00e3o-geral-do-fluxo-em-tempo-real&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;4.2 Estruturas globais de estado&quot;,&quot;value&quot;:&quot;42-estruturas-globais-de-estado&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;4.3 Constru\u00e7\u00e3o do vetor de features em tempo real&quot;,&quot;value&quot;:&quot;43-constru\u00e7\u00e3o-do-vetor-de-features-em-tempo-real&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;4.4 Avalia\u00e7\u00e3o estat\u00edstica e decis\u00e3o&quot;,&quot;value&quot;:&quot;44-avalia\u00e7\u00e3o-estat\u00edstica-e-decis\u00e3o&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;4.5 Atualiza\u00e7\u00e3o do modelo (aprendizado online controlado)&quot;,&quot;value&quot;:&quot;45-atualiza\u00e7\u00e3o-do-modelo-aprendizado-online-controlado&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;4.6 Acionamento do LED (sem l\u00f3gica escondida)&quot;,&quot;value&quot;:&quot;46-acionamento-do-led-sem-l\u00f3gica-escondida&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;4.7 Loop principal: simples, limpo e determin\u00edstico&quot;,&quot;value&quot;:&quot;47-loop-principal-simples-limpo-e-determin\u00edstico&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;4.8 O que temos agora (antes do c\u00f3digo final)&quot;,&quot;value&quot;:&quot;48-o-que-temos-agora-antes-do-c\u00f3digo-final&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;5 \u2014 C\u00f3digo completo e funcional (Goertzel + aprendizado estat\u00edstico) para BitDogLab \/ RP2040&quot;,&quot;value&quot;:&quot;5-c\u00f3digo-completo-e-funcional-goertzel-aprendizado-estat\u00edstico-para-bitdoglab-rp2040&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;6 \u2014 Calibra\u00e7\u00e3o pr\u00e1tica, boas escolhas vs. m\u00e1s escolhas, compara\u00e7\u00e3o entre estrat\u00e9gias, encerramento e SEO&quot;,&quot;value&quot;:&quot;6-calibra\u00e7\u00e3o-pr\u00e1tica-boas-escolhas-vs-m\u00e1s-escolhas-compara\u00e7\u00e3o-entre-estrat\u00e9gias-encerramento-e-seo&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;6.1 Calibra\u00e7\u00e3o pr\u00e1tica do modelo estat\u00edstico (como fazer funcionar em campo)&quot;,&quot;value&quot;:&quot;61-calibra\u00e7\u00e3o-pr\u00e1tica-do-modelo-estat\u00edstico-como-fazer-funcionar-em-campo&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;6.2 Boas escolhas vs. m\u00e1s escolhas (aprendizado estat\u00edstico em MCU)&quot;,&quot;value&quot;:&quot;62-boas-escolhas-vs-m\u00e1s-escolhas-aprendizado-estat\u00edstico-em-mcu&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;6.3 Compara\u00e7\u00e3o final entre os tr\u00eas artigos da s\u00e9rie&quot;,&quot;value&quot;:&quot;63-compara\u00e7\u00e3o-final-entre-os-tr\u00eas-artigos-da-s\u00e9rie&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;6.4 Encerramento conceitual&quot;,&quot;value&quot;:&quot;64-encerramento-conceitual&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. Introdução — Por que combinar Goertzel com aprendizado estatístico?</a><li><a href="#11-o-papel-do-goertzel-nesta-nova-arquitetura">1.1 O papel do Goertzel nesta nova arquitetura</a><li><a href="#eb-table-content-2">1.2 O que entendemos aqui por “aprendizado estatístico”</a><li><a href="#13-por-que-limiares-fixos-falham-em-campo">1.3 Por que limiares fixos falham em campo</a><li><a href="#eb-table-content-4">1.4 Visão geral da nova arquitetura</a><li><a href="#eb-table-content-5">1.5 O que você terá ao final deste artigo</a><li><a href="#eb-table-content-6">2 — Do sinal ao vetor de características: extraindo features estatísticas a partir do Goertzel</a><ul class="eb-toc__list"><li><a href="#eb-table-content-7">2.1 Por que “features” são mais importantes que o algoritmo de decisão</a><li><a href="#eb-table-content-8">2.2 O que NÃO usar como feature (e por quê)</a><li><a href="#eb-table-content-9">2.3 Princípio fundamental: normalização e relações</a><li><a href="#24-feature-1-energia-normalizada-da-fundamental">2.4 Feature 1 — Energia normalizada da fundamental</a><li><a href="#eb-table-content-11">2.5 Feature 2 — Relação do 2º harmônico</a><li><a href="#eb-table-content-12">2.6 Feature 3 — Relação do 3º harmônico (opcional, mas valiosa)</a><li><a href="#eb-table-content-13">2.7 Feature 4 — Estabilidade temporal da frequência</a><li><a href="#eb-table-content-14">2.8 Montando o vetor de características</a><li><a href="#eb-table-content-15">2.9 Feature engineering é engenharia, não tentativa</a></li></ul><li><a href="#eb-table-content-16">3 — Modelo estatístico adaptativo: média, variância e decisão probabilística (online, leve e interpretável)</a><ul class="eb-toc__list"><li><a href="#eb-table-content-17">3.1 Princípio do modelo: aprender o “normal” e medir desvio</a><li><a href="#eb-table-content-18">3.2 Modelo estatístico por feature (independente)</a><li><a href="#eb-table-content-19">3.3 Atualização online da média (EMA)</a><li><a href="#eb-table-content-20">3.4 Atualização online da variância (forma estável)</a><li><a href="#eb-table-content-21">3.5 Inicialização segura do modelo</a><li><a href="#36-medida-de-desvio-z-score-por-feature">3.6 Medida de desvio: Z-score por feature</a><li><a href="#eb-table-content-23">3.7 Distância estatística simplificada (score global)</a><li><a href="#eb-table-content-24">3.8 Regra de decisão probabilística simples</a><li><a href="#eb-table-content-25">3.9 Aprendizado controlado (não aprender ruído)</a><li><a href="#eb-table-content-26">3.10 O que conquistamos até aqui</a></li></ul><li><a href="#eb-table-content-27">4 — Integração completa em tempo real: Goertzel + features + modelo estatístico + LED no RP2040</a><ul class="eb-toc__list"><li><a href="#eb-table-content-28">4.1 Visão geral do fluxo em tempo real</a><li><a href="#42-estruturas-globais-de-estado">4.2 Estruturas globais de estado</a><li><a href="#eb-table-content-30">4.3 Construção do vetor de features em tempo real</a><li><a href="#eb-table-content-31">4.4 Avaliação estatística e decisão</a><li><a href="#eb-table-content-32">4.5 Atualização do modelo (aprendizado online controlado)</a><li><a href="#eb-table-content-33">4.6 Acionamento do LED (sem lógica escondida)</a><li><a href="#eb-table-content-34">4.7 Loop principal: simples, limpo e determinístico</a><li><a href="#eb-table-content-35">4.8 O que temos agora (antes do código final)</a></li></ul><li><a href="#eb-table-content-36">5 — Código completo e funcional (Goertzel + aprendizado estatístico) para BitDogLab / RP2040</a><li><a href="#eb-table-content-37">6 — Calibração prática, boas escolhas vs. más escolhas, comparação entre estratégias, encerramento e SEO</a><ul class="eb-toc__list"><li><a href="#eb-table-content-38">6.1 Calibração prática do modelo estatístico (como fazer funcionar em campo)</a><li><a href="#eb-table-content-39">6.2 Boas escolhas vs. más escolhas (aprendizado estatístico em MCU)</a><li><a href="#eb-table-content-40">6.3 Comparação final entre os três artigos da série</a><li><a href="#64-encerramento-conceitual">6.4 Encerramento conceitual</a></li></ul></ul></div></div></div></div></div>


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



<h2 class="wp-block-heading">1. Introdução — Por que combinar Goertzel com aprendizado estatístico?</h2>



<p class="wp-block-paragraph">Nos dois artigos anteriores desta série, exploramos <strong>duas estratégias clássicas e complementares</strong> de processamento digital de sinais em microcontroladores:</p>



<ol class="wp-block-list">
<li><strong>Séries de Taylor + Cepstrum</strong> → análise estrutural e harmônica do sinal</li>



<li><strong>Algoritmo de Goertzel</strong> → detecção espectral dirigida e altamente eficiente</li>
</ol>



<p class="wp-block-paragraph">Ambas funcionam muito bem, mas compartilham uma característica importante:<br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f449.png" alt="👉" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>a decisão final é baseada em limiares fixos</strong>.</p>



<p class="wp-block-paragraph">Neste terceiro artigo, damos um passo conceitual além, mantendo o Goertzel como <strong>extrator de características espectrais</strong>, mas substituindo o decisor rígido por um <strong>modelo de aprendizado estatístico leve</strong>, adequado a MCUs como o RP2040.</p>



<p class="wp-block-paragraph">O objetivo não é “colocar inteligência artificial por marketing”, mas sim responder a um problema real:</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph"><em>Como tornar a detecção mais robusta quando o ambiente muda, o usuário muda ou o ruído não é previsível?</em></p>
</blockquote>



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



<h2 class="wp-block-heading">1.1 O papel do Goertzel nesta nova arquitetura</h2>



<p class="wp-block-paragraph">É importante deixar claro desde o início:</p>



<ul class="wp-block-list">
<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Goertzel <strong>não será substituído</strong></li>



<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Não vamos rodar FFT gigante</li>



<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Não vamos usar redes neurais profundas</li>



<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Goertzel continua sendo o <strong>sensor espectral</strong></li>
</ul>



<p class="wp-block-paragraph">Nesta arquitetura, o Goertzel atua como um <strong>extrator determinístico de características (features)</strong>:</p>



<ul class="wp-block-list">
<li>Energia na frequência fundamental</li>



<li>Relação entre harmônicos</li>



<li>Estabilidade espectral ao longo do tempo</li>
</ul>



<p class="wp-block-paragraph">Esses valores passam a ser <strong>dados de entrada</strong> para um bloco estatístico que decide se o padrão observado <strong>se parece ou não com um assobio humano real</strong>.</p>



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



<h2 class="wp-block-heading">1.2 O que entendemos aqui por “aprendizado estatístico”</h2>



<p class="wp-block-paragraph">Neste artigo, <strong>aprendizado estatístico não significa deep learning</strong>.</p>



<p class="wp-block-paragraph">Vamos trabalhar com modelos:</p>



<ul class="wp-block-list">
<li>Interpretáveis</li>



<li>Leves</li>



<li>Computacionalmente previsíveis</li>



<li>Treináveis com poucos dados</li>
</ul>



<p class="wp-block-paragraph">Exemplos que abordaremos ao longo do artigo:</p>



<ul class="wp-block-list">
<li>Média e variância adaptativas</li>



<li>Distância estatística (z-score, Mahalanobis simplificada)</li>



<li>Classificador linear simples</li>



<li>Modelo incremental (online learning)</li>
</ul>



<p class="wp-block-paragraph">Tudo isso é:</p>



<ul class="wp-block-list">
<li>Executável em ponto flutuante simples</li>



<li>Compatível com firmware bare-metal</li>



<li>Determinístico em tempo real</li>
</ul>



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



<h2 class="wp-block-heading">1.3 Por que limiares fixos falham em campo</h2>



<p class="wp-block-paragraph">Nos artigos anteriores, usamos decisões do tipo:</p>



<ul class="wp-block-list">
<li><code>score &gt; S_ON</code></li>



<li><code>score &lt; S_OFF</code></li>
</ul>



<p class="wp-block-paragraph">Isso funciona bem quando:</p>



<ul class="wp-block-list">
<li>O ambiente é estável</li>



<li>O microfone é sempre o mesmo</li>



<li>O usuário assobia sempre da mesma forma</li>
</ul>



<p class="wp-block-paragraph">Mas em campo real:</p>



<ul class="wp-block-list">
<li>Pessoas assobiam diferente</li>



<li>Distância ao microfone muda</li>



<li>Ruído de fundo varia</li>



<li>Ganho analógico muda com temperatura e alimentação</li>
</ul>



<p class="wp-block-paragraph">Resultado:<br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f449.png" alt="👉" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>limiar bom hoje, ruim amanhã</strong>.</p>



<p class="wp-block-paragraph">O aprendizado estatístico resolve exatamente isso:</p>



<ul class="wp-block-list">
<li>Ele <strong>aprende o padrão típico</strong></li>



<li>Ele <strong>tolera variações naturais</strong></li>



<li>Ele <strong>se adapta lentamente ao ambiente</strong></li>
</ul>



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



<h2 class="wp-block-heading">1.4 Visão geral da nova arquitetura</h2>



<p class="wp-block-paragraph">A nova cadeia de processamento será:</p>



<pre class="wp-block-code"><code>ADC
 └── DC-block
     └── Frame (256 amostras)
         └── Goertzel (fundamental + harmônicos)
             └── Vetor de características
                 └── Modelo estatístico adaptativo
                     └── Decisão (assobio / não assobio)
                         └── LED / evento
</code></pre>



<p class="wp-block-paragraph">Comparando com o artigo anterior:</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Artigo</th><th>Decisão</th></tr></thead><tbody><tr><td>Taylor + Cepstrum</td><td>Limiar estrutural</td></tr><tr><td>Goertzel clássico</td><td>Score com limiar</td></tr><tr><td><strong>Goertzel + Estatística</strong></td><td><strong>Classificação adaptativa</strong></td></tr></tbody></table></figure>



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



<h2 class="wp-block-heading">1.5 O que você terá ao final deste artigo</h2>



<p class="wp-block-paragraph">Ao final deste terceiro artigo da série, você terá:</p>



<ul class="wp-block-list">
<li>Um <strong>detector de assobio adaptativo</strong></li>



<li>Baseado em <strong>Goertzel + estatística</strong></li>



<li>Código <strong>100% em C</strong></li>



<li>Executando em <strong>tempo real no RP2040</strong></li>



<li>Sem dependência de bibliotecas externas</li>



<li>Com arquitetura reutilizável para:
<ul class="wp-block-list">
<li>Detecção de padrões acústicos</li>



<li>Sensores inteligentes</li>



<li>Interfaces por som</li>



<li>Pré-processamento para tinyML</li>
</ul>
</li>
</ul>



<p class="wp-block-paragraph">Mais importante:<br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f449.png" alt="👉" class="wp-smiley" style="height: 1em; max-height: 1em;" /> você entenderá <strong>como transformar DSP em dados</strong> e <strong>dados em decisão</strong>, de forma técnica.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/><p>The post <a href="https://mcu.tec.br/algoritimos/dsp/deteccao-de-assobio-com-goertzel-e-aprendizado-estatistico-no-rp2040/">Detecção de Assobio com Goertzel e Aprendizado Estatístico no 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">1127</post-id>	</item>
		<item>
		<title>Comparativo Técnico de Microcontroladores: ESP32, STM32, Arduino, RP2040 e nRF52</title>
		<link>https://mcu.tec.br/microcontroladores/comparativo-tecnico-de-microcontroladores-esp32-stm32-arduino-rp2040-e-nrf52/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=comparativo-tecnico-de-microcontroladores-esp32-stm32-arduino-rp2040-e-nrf52</link>
		
		<dc:creator><![CDATA[Carlos Delfino]]></dc:creator>
		<pubDate>Tue, 10 Feb 2026 10:59:31 +0000</pubDate>
				<category><![CDATA[microcontroladores]]></category>
		<category><![CDATA[Arduino AVR]]></category>
		<category><![CDATA[baixo consumo]]></category>
		<category><![CDATA[bluetooth low energy]]></category>
		<category><![CDATA[controle industrial]]></category>
		<category><![CDATA[engenharia eletrônica]]></category>
		<category><![CDATA[esp32]]></category>
		<category><![CDATA[firmware embarcado]]></category>
		<category><![CDATA[IoT]]></category>
		<category><![CDATA[nRF52]]></category>
		<category><![CDATA[RP2040]]></category>
		<category><![CDATA[sistemas embarcados]]></category>
		<category><![CDATA[stm32]]></category>
		<category><![CDATA[wi-fi embarcado]]></category>
		<guid isPermaLink="false">https://mcu.tec.br/?p=1291</guid>

					<description><![CDATA[<p>Este artigo apresenta uma análise comparativa e didática entre os principais microcontroladores do mercado — ESP32, STM32, Arduino (AVR), RP2040 e nRF52. O texto explora arquitetura, desempenho, consumo energético, conectividade e contexto de uso de cada família, ajudando engenheiros, estudantes e desenvolvedores a escolherem a plataforma mais adequada para projetos de IoT, sistemas industriais, dispositivos embarcados de baixo consumo e aplicações educacionais. O conteúdo é técnico, claro e orientado à tomada de decisão consciente em engenharia de sistemas embarcado</p>
<p>The post <a href="https://mcu.tec.br/microcontroladores/comparativo-tecnico-de-microcontroladores-esp32-stm32-arduino-rp2040-e-nrf52/">Comparativo Técnico de Microcontroladores: ESP32, STM32, Arduino, RP2040 e nRF52</a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></description>
										<content:encoded><![CDATA[<div class="root-eb-toc-poauy wp-block-essential-blocks-table-of-contents"><div class="eb-parent-wrapper eb-parent-eb-toc-poauy "><div class="eb-toc-container eb-toc-poauy  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;Introdu\u00e7\u00e3o&quot;,&quot;text&quot;:&quot;Introdu\u00e7\u00e3o&quot;,&quot;link&quot;:&quot;eb-table-content-0&quot;},{&quot;level&quot;:2,&quot;content&quot;:&quot;ESP32 \u2013 Conectividade Integrada e Foco em IoT&quot;,&quot;text&quot;:&quot;ESP32 \u2013 Conectividade Integrada e Foco em IoT&quot;,&quot;link&quot;:&quot;esp32-conectividade-integrada-e-foco-em-iot&quot;},{&quot;level&quot;:2,&quot;content&quot;:&quot;STM32 \u2013 Desempenho, Escalabilidade e Foco Industrial&quot;,&quot;text&quot;:&quot;STM32 \u2013 Desempenho, Escalabilidade e Foco Industrial&quot;,&quot;link&quot;:&quot;stm32-desempenho-escalabilidade-e-foco-industrial&quot;},{&quot;level&quot;:2,&quot;content&quot;:&quot;Arduino (AVR) \u2013 Simplicidade, Acesso e Limita\u00e7\u00f5es Arquiteturais&quot;,&quot;text&quot;:&quot;Arduino (AVR) \u2013 Simplicidade, Acesso e Limita\u00e7\u00f5es Arquiteturais&quot;,&quot;link&quot;:&quot;eb-table-content-3&quot;},{&quot;level&quot;:2,&quot;content&quot;:&quot;RP2040 \u2013 Arquitetura Moderna, PIO e Flexibilidade a Baixo Custo&quot;,&quot;text&quot;:&quot;RP2040 \u2013 Arquitetura Moderna, PIO e Flexibilidade a Baixo Custo&quot;,&quot;link&quot;:&quot;rp2040-arquitetura-moderna-pio-e-flexibilidade-a-baixo-custo&quot;},{&quot;level&quot;:2,&quot;content&quot;:&quot;nRF52 \u2013 Ultra Baixo Consumo e Comunica\u00e7\u00e3o Bluetooth Low Energy&quot;,&quot;text&quot;:&quot;nRF52 \u2013 Ultra Baixo Consumo e Comunica\u00e7\u00e3o Bluetooth Low Energy&quot;,&quot;link&quot;:&quot;eb-table-content-5&quot;},{&quot;level&quot;:2,&quot;content&quot;:&quot;Tabela Comparativa T\u00e9cnica entre as Plataformas&quot;,&quot;text&quot;:&quot;Tabela Comparativa T\u00e9cnica entre as Plataformas&quot;,&quot;link&quot;:&quot;eb-table-content-6&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;Leitura cr\u00edtica da tabela&quot;,&quot;text&quot;:&quot;Leitura cr\u00edtica da tabela&quot;,&quot;link&quot;:&quot;eb-table-content-7&quot;}]" data-visible="[true,true,true,true,true,true]" data-delete-headers="[{&quot;label&quot;:&quot;Introdu\u00e7\u00e3o&quot;,&quot;value&quot;:&quot;introdu\u00e7\u00e3o&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;ESP32 \u2013 Conectividade Integrada e Foco em IoT&quot;,&quot;value&quot;:&quot;esp32-conectividade-integrada-e-foco-em-iot&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;STM32 \u2013 Desempenho, Escalabilidade e Foco Industrial&quot;,&quot;value&quot;:&quot;stm32-desempenho-escalabilidade-e-foco-industrial&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Arduino (AVR) \u2013 Simplicidade, Acesso e Limita\u00e7\u00f5es Arquiteturais&quot;,&quot;value&quot;:&quot;arduino-avr-simplicidade-acesso-e-limita\u00e7\u00f5es-arquiteturais&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;RP2040 \u2013 Arquitetura Moderna, PIO e Flexibilidade a Baixo Custo&quot;,&quot;value&quot;:&quot;rp2040-arquitetura-moderna-pio-e-flexibilidade-a-baixo-custo&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;nRF52 \u2013 Ultra Baixo Consumo e Comunica\u00e7\u00e3o Bluetooth Low Energy&quot;,&quot;value&quot;:&quot;nrf52-ultra-baixo-consumo-e-comunica\u00e7\u00e3o-bluetooth-low-energy&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Tabela Comparativa T\u00e9cnica entre as Plataformas&quot;,&quot;value&quot;:&quot;tabela-comparativa-t\u00e9cnica-entre-as-plataformas&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;Leitura cr\u00edtica da tabela&quot;,&quot;value&quot;:&quot;leitura-cr\u00edtica-da-tabela&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">Introdução</a><li><a href="#esp32-conectividade-integrada-e-foco-em-iot">ESP32 – Conectividade Integrada e Foco em IoT</a><li><a href="#stm32-desempenho-escalabilidade-e-foco-industrial">STM32 – Desempenho, Escalabilidade e Foco Industrial</a><li><a href="#eb-table-content-3">Arduino (AVR) – Simplicidade, Acesso e Limitações Arquiteturais</a><li><a href="#rp2040-arquitetura-moderna-pio-e-flexibilidade-a-baixo-custo">RP2040 – Arquitetura Moderna, PIO e Flexibilidade a Baixo Custo</a><li><a href="#eb-table-content-5">nRF52 – Ultra Baixo Consumo e Comunicação Bluetooth Low Energy</a><li><a href="#eb-table-content-6">Tabela Comparativa Técnica entre as Plataformas</a><ul class="eb-toc__list"><li><a href="#eb-table-content-7">Leitura crítica da tabela</a></li></ul></ul></div></div></div></div></div>


<h2 class="wp-block-heading">Introdução</h2>



<p class="wp-block-paragraph">A escolha de um microcontrolador é uma das decisões mais críticas no desenvolvimento de sistemas embarcados, pois impacta diretamente o custo, o consumo de energia, a complexidade do firmware, a conectividade disponível e até mesmo a viabilidade do produto final. Nos últimos anos, o mercado passou a oferecer famílias extremamente distintas, que atendem desde projetos educacionais e protótipos rápidos até aplicações industriais, IoT em larga escala e dispositivos vestíveis de ultra-baixo consumo.</p>



<p class="wp-block-paragraph">Neste artigo comparativo, analisamos cinco plataformas amplamente utilizadas — <strong>ESP32</strong>, <strong>STM32</strong>, <strong>Arduino (AVR)</strong>, <strong>RP2040</strong> e <strong>nRF52</strong> — destacando suas arquiteturas, capacidades de processamento, conectividade, consumo energético e contextos de uso. O objetivo não é eleger um “melhor” microcontrolador, mas fornecer critérios técnicos claros para que o engenheiro ou desenvolvedor escolha a solução mais adequada ao seu projeto.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/><p>The post <a href="https://mcu.tec.br/microcontroladores/comparativo-tecnico-de-microcontroladores-esp32-stm32-arduino-rp2040-e-nrf52/">Comparativo Técnico de Microcontroladores: ESP32, STM32, Arduino, RP2040 e nRF52</a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1291</post-id>	</item>
		<item>
		<title>Detecção de Assobio Humano com o Algoritmo de Goertzel no RP2040</title>
		<link>https://mcu.tec.br/algoritimos/dsp/deteccao-de-assobio-humano-com-o-algoritmo-de-goertzel-no-rp2040/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=deteccao-de-assobio-humano-com-o-algoritmo-de-goertzel-no-rp2040</link>
		
		<dc:creator><![CDATA[Carlos Delfino]]></dc:creator>
		<pubDate>Thu, 29 Jan 2026 22:37:21 +0000</pubDate>
				<category><![CDATA[DSP]]></category>
		<category><![CDATA[algoritmo goertzel]]></category>
		<category><![CDATA[análise espectral]]></category>
		<category><![CDATA[áudio embarcado]]></category>
		<category><![CDATA[BitDogLab]]></category>
		<category><![CDATA[detecção de assobio]]></category>
		<category><![CDATA[DSP embarcado]]></category>
		<category><![CDATA[firmware em c]]></category>
		<category><![CDATA[microcontroladores]]></category>
		<category><![CDATA[processamento digital de sinais]]></category>
		<category><![CDATA[RP2040]]></category>
		<guid isPermaLink="false">https://mcu.tec.br/?p=1125</guid>

					<description><![CDATA[<p>Este artigo apresenta uma implementação completa e didática do algoritmo de Goertzel para detecção de assobio humano em microcontroladores RP2040, dando continuidade à série de processamento digital de sinais iniciada com filtros baseados em Séries de Taylor e cepstrum. O conteúdo explora os fundamentos matemáticos do Goertzel, sua interpretação como um filtro ressonante discreto e sua aplicação prática em tempo real usando ADC, temporização estável, remoção de offset DC e análise espectral pontual. O projeto é implementado integralmente em linguagem C, sem bibliotecas externas de DSP, e demonstra como detectar a frequência fundamental e harmônicos de um assobio, gerar um score robusto e acionar um LED de forma confiável. Ideal para engenheiros e estudantes que desejam aprofundar conhecimentos em DSP embarcado, otimização de firmware e detecção acústica em sistemas de recursos limitados.</p>
<p>The post <a href="https://mcu.tec.br/algoritimos/dsp/deteccao-de-assobio-humano-com-o-algoritmo-de-goertzel-no-rp2040/">Detecção de Assobio Humano com o Algoritmo de Goertzel no RP2040</a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></description>
										<content:encoded><![CDATA[<h3 class="wp-block-heading">Continuação da série: <a href="https://mcu.tec.br/?p=1115" title="">Filtragem Digital, Cepstrum e Detecção Acústica em MCU</a></h3>


<div class="root-eb-toc-84t2n wp-block-essential-blocks-table-of-contents"><div class="eb-parent-wrapper eb-parent-eb-toc-84t2n "><div class="eb-toc-container eb-toc-84t2n  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;:3,&quot;content&quot;:&quot;Continua\u00e7\u00e3o da s\u00e9rie: Filtragem Digital, Cepstrum e Detec\u00e7\u00e3o Ac\u00fastica em MCU&quot;,&quot;text&quot;:&quot;Continua\u00e7\u00e3o da s\u00e9rie: Filtragem Digital, Cepstrum e Detec\u00e7\u00e3o Ac\u00fastica em MCU&quot;,&quot;link&quot;:&quot;eb-table-content-0&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;1. Introdu\u00e7\u00e3o \u2014 Por que Goertzel?&quot;,&quot;text&quot;:&quot;1. Introdu\u00e7\u00e3o \u2014 Por que Goertzel?&quot;,&quot;link&quot;:&quot;eb-table-content-1&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;1.1 Estrat\u00e9gia geral adotada neste artigo&quot;,&quot;text&quot;:&quot;1.1 Estrat\u00e9gia geral adotada neste artigo&quot;,&quot;link&quot;:&quot;eb-table-content-2&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;1.2 Quando Goertzel \u00e9 a escolha correta (e quando n\u00e3o \u00e9)&quot;,&quot;text&quot;:&quot;1.2 Quando Goertzel \u00e9 a escolha correta (e quando n\u00e3o \u00e9)&quot;,&quot;link&quot;:&quot;eb-table-content-3&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;1.3 Rela\u00e7\u00e3o direta com o artigo anterior&quot;,&quot;text&quot;:&quot;1.3 Rela\u00e7\u00e3o direta com o artigo anterior&quot;,&quot;link&quot;:&quot;eb-table-content-4&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;1.4 O que voc\u00ea ter\u00e1 ao final deste artigo&quot;,&quot;text&quot;:&quot;1.4 O que voc\u00ea ter\u00e1 ao final deste artigo&quot;,&quot;link&quot;:&quot;eb-table-content-5&quot;},{&quot;level&quot;:2,&quot;content&quot;:&quot;2 \u2014 Fundamentos matem\u00e1ticos do algoritmo de Goertzel (do zero, passo a passo)&quot;,&quot;text&quot;:&quot;2 \u2014 Fundamentos matem\u00e1ticos do algoritmo de Goertzel (do zero, passo a passo)&quot;,&quot;link&quot;:&quot;eb-table-content-6&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;2.1 Onde o Goertzel se encaixa no DSP cl\u00e1ssico&quot;,&quot;text&quot;:&quot;2.1 Onde o Goertzel se encaixa no DSP cl\u00e1ssico&quot;,&quot;link&quot;:&quot;eb-table-content-7&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;2.2 A DFT vista como um \u00fanico bin&quot;,&quot;text&quot;:&quot;2.2 A DFT vista como um \u00fanico bin&quot;,&quot;link&quot;:&quot;eb-table-content-8&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;2.3 A ideia-chave: um oscilador ressonante discreto&quot;,&quot;text&quot;:&quot;2.3 A ideia-chave: um oscilador ressonante discreto&quot;,&quot;link&quot;:&quot;23-a-ideia-chave-um-oscilador-ressonante-discreto&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;2.4 Extraindo a energia da frequ\u00eancia&quot;,&quot;text&quot;:&quot;2.4 Extraindo a energia da frequ\u00eancia&quot;,&quot;link&quot;:&quot;eb-table-content-10&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;2.5 Rela\u00e7\u00e3o com filtros IIR de segunda ordem&quot;,&quot;text&quot;:&quot;2.5 Rela\u00e7\u00e3o com filtros IIR de segunda ordem&quot;,&quot;link&quot;:&quot;eb-table-content-11&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;2.6 Escolha de (N) e resolu\u00e7\u00e3o em frequ\u00eancia&quot;,&quot;text&quot;:&quot;2.6 Escolha de (N) e resolu\u00e7\u00e3o em frequ\u00eancia&quot;,&quot;link&quot;:&quot;eb-table-content-12&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;2.7 Como mapeamos frequ\u00eancia real \u2192 \u00edndice (k)&quot;,&quot;text&quot;:&quot;2.7 Como mapeamos frequ\u00eancia real \u2192 \u00edndice (k)&quot;,&quot;link&quot;:&quot;eb-table-content-13&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;2.8 O que vamos detectar no assobio&quot;,&quot;text&quot;:&quot;2.8 O que vamos detectar no assobio&quot;,&quot;link&quot;:&quot;28-o-que-vamos-detectar-no-assobio&quot;},{&quot;level&quot;:2,&quot;content&quot;:&quot;3 \u2014 Implementa\u00e7\u00e3o b\u00e1sica do algoritmo de Goertzel em C (isolado, incremental e test\u00e1vel)&quot;,&quot;text&quot;:&quot;3 \u2014 Implementa\u00e7\u00e3o b\u00e1sica do algoritmo de Goertzel em C (isolado, incremental e test\u00e1vel)&quot;,&quot;link&quot;:&quot;eb-table-content-15&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;3.1 Estrutura de estado do Goertzel&quot;,&quot;text&quot;:&quot;3.1 Estrutura de estado do Goertzel&quot;,&quot;link&quot;:&quot;31-estrutura-de-estado-do-goertzel&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;3.2 Inicializa\u00e7\u00e3o do detector Goertzel&quot;,&quot;text&quot;:&quot;3.2 Inicializa\u00e7\u00e3o do detector Goertzel&quot;,&quot;link&quot;:&quot;eb-table-content-17&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;3.3 Passo recursivo do Goertzel (n\u00facleo do algoritmo)&quot;,&quot;text&quot;:&quot;3.3 Passo recursivo do Goertzel (n\u00facleo do algoritmo)&quot;,&quot;link&quot;:&quot;eb-table-content-18&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;3.4 C\u00e1lculo da energia da frequ\u00eancia&quot;,&quot;text&quot;:&quot;3.4 C\u00e1lculo da energia da frequ\u00eancia&quot;,&quot;link&quot;:&quot;eb-table-content-19&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;3.5 Reset do estado (para novo frame)&quot;,&quot;text&quot;:&quot;3.5 Reset do estado (para novo frame)&quot;,&quot;link&quot;:&quot;35-reset-do-estado-para-novo-frame&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;3.6 Teste isolado com sinal sint\u00e9tico (valida\u00e7\u00e3o conceitual)&quot;,&quot;text&quot;:&quot;3.6 Teste isolado com sinal sint\u00e9tico (valida\u00e7\u00e3o conceitual)&quot;,&quot;link&quot;:&quot;eb-table-content-21&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;3.7 O que aprendemos at\u00e9 aqui&quot;,&quot;text&quot;:&quot;3.7 O que aprendemos at\u00e9 aqui&quot;,&quot;link&quot;:&quot;eb-table-content-22&quot;},{&quot;level&quot;:2,&quot;content&quot;:&quot;4 \u2014 Goertzel em tempo real no RP2040: ADC + frames + m\u00faltiplas frequ\u00eancias (fundamental e harm\u00f4nicos)&quot;,&quot;text&quot;:&quot;4 \u2014 Goertzel em tempo real no RP2040: ADC + frames + m\u00faltiplas frequ\u00eancias (fundamental e harm\u00f4nicos)&quot;,&quot;link&quot;:&quot;eb-table-content-23&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;4.1 Definindo o frame e a taxa de amostragem&quot;,&quot;text&quot;:&quot;4.1 Definindo o frame e a taxa de amostragem&quot;,&quot;link&quot;:&quot;41-definindo-o-frame-e-a-taxa-de-amostragem&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;4.2 Estrat\u00e9gia \u201cGoertzel multibanda\u201d&quot;,&quot;text&quot;:&quot;4.2 Estrat\u00e9gia \u201cGoertzel multibanda\u201d&quot;,&quot;link&quot;:&quot;eb-table-content-25&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;4.3 Aquisi\u00e7\u00e3o em tempo real (ADC + timer), igual ao artigo anterior&quot;,&quot;text&quot;:&quot;4.3 Aquisi\u00e7\u00e3o em tempo real (ADC + timer), igual ao artigo anterior&quot;,&quot;link&quot;:&quot;eb-table-content-26&quot;},{&quot;level&quot;:4,&quot;content&quot;:&quot;4.3.1 Buffer de frame (o mesmo padr\u00e3o)&quot;,&quot;text&quot;:&quot;4.3.1 Buffer de frame (o mesmo padr\u00e3o)&quot;,&quot;link&quot;:&quot;eb-table-content-27&quot;},{&quot;level&quot;:4,&quot;content&quot;:&quot;4.3.2 Leitura ADC normalizada&quot;,&quot;text&quot;:&quot;4.3.2 Leitura ADC normalizada&quot;,&quot;link&quot;:&quot;432-leitura-adc-normalizada&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;4.4 Pr\u00e9-processamento m\u00ednimo: remo\u00e7\u00e3o de DC por m\u00e9dia m\u00f3vel (mais robusto)&quot;,&quot;text&quot;:&quot;4.4 Pr\u00e9-processamento m\u00ednimo: remo\u00e7\u00e3o de DC por m\u00e9dia m\u00f3vel (mais robusto)&quot;,&quot;link&quot;:&quot;eb-table-content-29&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;4.5 Varredura com Goertzel (faixa 800\u20133000 Hz)&quot;,&quot;text&quot;:&quot;4.5 Varredura com Goertzel (faixa 800\u20133000 Hz)&quot;,&quot;link&quot;:&quot;45-varredura-com-goertzel-faixa-8003000-hz&quot;},{&quot;level&quot;:4,&quot;content&quot;:&quot;4.5.1 Fun\u00e7\u00e3o: pot\u00eancia Goertzel para uma frequ\u00eancia f0 em um frame&quot;,&quot;text&quot;:&quot;4.5.1 Fun\u00e7\u00e3o: pot\u00eancia Goertzel para uma frequ\u00eancia f0 em um frame&quot;,&quot;link&quot;:&quot;eb-table-content-31&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;4.6 Encontrando o candidato de fundamental (pico na faixa)&quot;,&quot;text&quot;:&quot;4.6 Encontrando o candidato de fundamental (pico na faixa)&quot;,&quot;link&quot;:&quot;46-encontrando-o-candidato-de-fundamental-pico-na-faixa&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;4.7 Confirma\u00e7\u00e3o por harm\u00f4nicos (2f0 e 3f0)&quot;,&quot;text&quot;:&quot;4.7 Confirma\u00e7\u00e3o por harm\u00f4nicos (2f0 e 3f0)&quot;,&quot;link&quot;:&quot;eb-table-content-33&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;4.8 Integra\u00e7\u00e3o: montar o \u201cprocessador de frame\u201d (ainda sem LED)&quot;,&quot;text&quot;:&quot;4.8 Integra\u00e7\u00e3o: montar o \u201cprocessador de frame\u201d (ainda sem LED)&quot;,&quot;link&quot;:&quot;eb-table-content-34&quot;},{&quot;level&quot;:2,&quot;content&quot;:&quot;5 \u2014 Decisor completo + LED + otimiza\u00e7\u00f5es (coeficientes pr\u00e9-computados, EMA, histerese) e integra\u00e7\u00e3o no RP2040&quot;,&quot;text&quot;:&quot;5 \u2014 Decisor completo + LED + otimiza\u00e7\u00f5es (coeficientes pr\u00e9-computados, EMA, histerese) e integra\u00e7\u00e3o no RP2040&quot;,&quot;link&quot;:&quot;eb-table-content-35&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;5.1 Otimiza\u00e7\u00e3o essencial: pr\u00e9-computar os detectores da varredura&quot;,&quot;text&quot;:&quot;5.1 Otimiza\u00e7\u00e3o essencial: pr\u00e9-computar os detectores da varredura&quot;,&quot;link&quot;:&quot;eb-table-content-36&quot;},{&quot;level&quot;:4,&quot;content&quot;:&quot;5.1.1 Estrutura do \u201cdetector preparado\u201d&quot;,&quot;text&quot;:&quot;5.1.1 Estrutura do \u201cdetector preparado\u201d&quot;,&quot;link&quot;:&quot;511-estrutura-do-detector-preparado&quot;},{&quot;level&quot;:4,&quot;content&quot;:&quot;5.1.2 Construindo a lista de bins (800\u20133000 Hz, passo 2 bins)&quot;,&quot;text&quot;:&quot;5.1.2 Construindo a lista de bins (800\u20133000 Hz, passo 2 bins)&quot;,&quot;link&quot;:&quot;512-construindo-a-lista-de-bins-8003000-hz-passo-2-bins&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;5.2 Goertzel \u201cr\u00e1pido\u201d usando coeff pr\u00e9-calculado&quot;,&quot;text&quot;:&quot;5.2 Goertzel \u201cr\u00e1pido\u201d usando coeff pr\u00e9-calculado&quot;,&quot;link&quot;:&quot;eb-table-content-39&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;5.3 Encontrar o melhor candidato f0 (varredura)&quot;,&quot;text&quot;:&quot;5.3 Encontrar o melhor candidato f0 (varredura)&quot;,&quot;link&quot;:&quot;53-encontrar-o-melhor-candidato-f0-varredura&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;5.4 Harm\u00f4nicos com c\u00e1lculo \u201con demand\u201d&quot;,&quot;text&quot;:&quot;5.4 Harm\u00f4nicos com c\u00e1lculo \u201con demand\u201d&quot;,&quot;link&quot;:&quot;eb-table-content-41&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;5.5 Crit\u00e9rio espectral composto (score)&quot;,&quot;text&quot;:&quot;5.5 Crit\u00e9rio espectral composto (score)&quot;,&quot;link&quot;:&quot;eb-table-content-42&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;5.6 Decis\u00e3o robusta com EMA + histerese&quot;,&quot;text&quot;:&quot;5.6 Decis\u00e3o robusta com EMA + histerese&quot;,&quot;link&quot;:&quot;eb-table-content-43&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;5.7 Integra\u00e7\u00e3o de tempo real (ADC + DC-block + frame)&quot;,&quot;text&quot;:&quot;5.7 Integra\u00e7\u00e3o de tempo real (ADC + DC-block + frame)&quot;,&quot;link&quot;:&quot;eb-table-content-44&quot;},{&quot;level&quot;:4,&quot;content&quot;:&quot;5.7.1 DC-block&quot;,&quot;text&quot;:&quot;5.7.1 DC-block&quot;,&quot;link&quot;:&quot;571-dc-block&quot;},{&quot;level&quot;:4,&quot;content&quot;:&quot;5.7.2 Estado global e callback de amostragem&quot;,&quot;text&quot;:&quot;5.7.2 Estado global e callback de amostragem&quot;,&quot;link&quot;:&quot;572-estado-global-e-callback-de-amostragem&quot;},{&quot;level&quot;:4,&quot;content&quot;:&quot;5.7.3 Loop processa frame e atualiza LED&quot;,&quot;text&quot;:&quot;5.7.3 Loop processa frame e atualiza LED&quot;,&quot;link&quot;:&quot;573-loop-processa-frame-e-atualiza-led&quot;},{&quot;level&quot;:2,&quot;content&quot;:&quot;5 \u2014 Decisor completo + LED + otimiza\u00e7\u00f5es (coeficientes pr\u00e9-computados, EMA, histerese) e integra\u00e7\u00e3o no RP2040&quot;,&quot;text&quot;:&quot;5 \u2014 Decisor completo + LED + otimiza\u00e7\u00f5es (coeficientes pr\u00e9-computados, EMA, histerese) e integra\u00e7\u00e3o no RP2040&quot;,&quot;link&quot;:&quot;eb-table-content-48&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;5.1 Otimiza\u00e7\u00e3o essencial: pr\u00e9-computar os detectores da varredura&quot;,&quot;text&quot;:&quot;5.1 Otimiza\u00e7\u00e3o essencial: pr\u00e9-computar os detectores da varredura&quot;,&quot;link&quot;:&quot;eb-table-content-49&quot;},{&quot;level&quot;:4,&quot;content&quot;:&quot;5.1.1 Estrutura do \u201cdetector preparado\u201d&quot;,&quot;text&quot;:&quot;5.1.1 Estrutura do \u201cdetector preparado\u201d&quot;,&quot;link&quot;:&quot;511-estrutura-do-detector-preparado&quot;},{&quot;level&quot;:4,&quot;content&quot;:&quot;5.1.2 Construindo a lista de bins (800\u20133000 Hz, passo 2 bins)&quot;,&quot;text&quot;:&quot;5.1.2 Construindo a lista de bins (800\u20133000 Hz, passo 2 bins)&quot;,&quot;link&quot;:&quot;512-construindo-a-lista-de-bins-8003000-hz-passo-2-bins&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;5.2 Goertzel \u201cr\u00e1pido\u201d usando coeff pr\u00e9-calculado&quot;,&quot;text&quot;:&quot;5.2 Goertzel \u201cr\u00e1pido\u201d usando coeff pr\u00e9-calculado&quot;,&quot;link&quot;:&quot;eb-table-content-52&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;5.3 Encontrar o melhor candidato f0 (varredura)&quot;,&quot;text&quot;:&quot;5.3 Encontrar o melhor candidato f0 (varredura)&quot;,&quot;link&quot;:&quot;53-encontrar-o-melhor-candidato-f0-varredura&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;5.4 Harm\u00f4nicos com c\u00e1lculo \u201con demand\u201d&quot;,&quot;text&quot;:&quot;5.4 Harm\u00f4nicos com c\u00e1lculo \u201con demand\u201d&quot;,&quot;link&quot;:&quot;eb-table-content-54&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;5.5 Crit\u00e9rio espectral composto (score)&quot;,&quot;text&quot;:&quot;5.5 Crit\u00e9rio espectral composto (score)&quot;,&quot;link&quot;:&quot;eb-table-content-55&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;5.6 Decis\u00e3o robusta com EMA + histerese&quot;,&quot;text&quot;:&quot;5.6 Decis\u00e3o robusta com EMA + histerese&quot;,&quot;link&quot;:&quot;eb-table-content-56&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;5.7 Integra\u00e7\u00e3o de tempo real (ADC + DC-block + frame)&quot;,&quot;text&quot;:&quot;5.7 Integra\u00e7\u00e3o de tempo real (ADC + DC-block + frame)&quot;,&quot;link&quot;:&quot;eb-table-content-57&quot;},{&quot;level&quot;:4,&quot;content&quot;:&quot;5.7.1 DC-block&quot;,&quot;text&quot;:&quot;5.7.1 DC-block&quot;,&quot;link&quot;:&quot;571-dc-block&quot;},{&quot;level&quot;:4,&quot;content&quot;:&quot;5.7.2 Estado global e callback de amostragem&quot;,&quot;text&quot;:&quot;5.7.2 Estado global e callback de amostragem&quot;,&quot;link&quot;:&quot;572-estado-global-e-callback-de-amostragem&quot;},{&quot;level&quot;:4,&quot;content&quot;:&quot;5.7.3 Loop processa frame e atualiza LED&quot;,&quot;text&quot;:&quot;5.7.3 Loop processa frame e atualiza LED&quot;,&quot;link&quot;:&quot;573-loop-processa-frame-e-atualiza-led&quot;},{&quot;level&quot;:2,&quot;content&quot;:&quot;6 \u2014 C\u00f3digo completo e funcional (BitDogLab \/ RP2040) com Goertzel: detec\u00e7\u00e3o de assobio + LED&quot;,&quot;text&quot;:&quot;6 \u2014 C\u00f3digo completo e funcional (BitDogLab \/ RP2040) com Goertzel: detec\u00e7\u00e3o de assobio + LED&quot;,&quot;link&quot;:&quot;eb-table-content-61&quot;},{&quot;level&quot;:2,&quot;content&quot;:&quot;7 \u2014 Calibra\u00e7\u00e3o pr\u00e1tica, compara\u00e7\u00e3o com o artigo anterior, encerramento e SEO&quot;,&quot;text&quot;:&quot;7 \u2014 Calibra\u00e7\u00e3o pr\u00e1tica, compara\u00e7\u00e3o com o artigo anterior, encerramento e SEO&quot;,&quot;link&quot;:&quot;eb-table-content-62&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;7.1 Calibra\u00e7\u00e3o pr\u00e1tica (engenharia de campo, n\u00e3o de laborat\u00f3rio)&quot;,&quot;text&quot;:&quot;7.1 Calibra\u00e7\u00e3o pr\u00e1tica (engenharia de campo, n\u00e3o de laborat\u00f3rio)&quot;,&quot;link&quot;:&quot;eb-table-content-63&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;7.2 Boas escolhas vs. m\u00e1s escolhas (espec\u00edfico do Goertzel)&quot;,&quot;text&quot;:&quot;7.2 Boas escolhas vs. m\u00e1s escolhas (espec\u00edfico do Goertzel)&quot;,&quot;link&quot;:&quot;eb-table-content-64&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;7.3 Compara\u00e7\u00e3o direta com o artigo anterior (Taylor + Cepstrum)&quot;,&quot;text&quot;:&quot;7.3 Compara\u00e7\u00e3o direta com o artigo anterior (Taylor + Cepstrum)&quot;,&quot;link&quot;:&quot;eb-table-content-65&quot;},{&quot;level&quot;:3,&quot;content&quot;:&quot;7.4 Encerramento&quot;,&quot;text&quot;:&quot;7.4 Encerramento&quot;,&quot;link&quot;:&quot;74-encerramento&quot;}]" data-visible="[true,true,true,true,true,true]" data-delete-headers="[{&quot;label&quot;:&quot;Continua\u00e7\u00e3o da s\u00e9rie: Filtragem Digital, Cepstrum e Detec\u00e7\u00e3o Ac\u00fastica em MCU&quot;,&quot;value&quot;:&quot;continua\u00e7\u00e3o-da-s\u00e9rie-filtragem-digital-cepstrum-e-detec\u00e7\u00e3o-ac\u00fastica-em-mcu&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;1. Introdu\u00e7\u00e3o \u2014 Por que Goertzel?&quot;,&quot;value&quot;:&quot;1-introdu\u00e7\u00e3o-por-que-goertzel&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;1.1 Estrat\u00e9gia geral adotada neste artigo&quot;,&quot;value&quot;:&quot;11-estrat\u00e9gia-geral-adotada-neste-artigo&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;1.2 Quando Goertzel \u00e9 a escolha correta (e quando n\u00e3o \u00e9)&quot;,&quot;value&quot;:&quot;12-quando-goertzel-\u00e9-a-escolha-correta-e-quando-n\u00e3o-\u00e9&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;1.3 Rela\u00e7\u00e3o direta com o artigo anterior&quot;,&quot;value&quot;:&quot;13-rela\u00e7\u00e3o-direta-com-o-artigo-anterior&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;1.4 O que voc\u00ea ter\u00e1 ao final deste artigo&quot;,&quot;value&quot;:&quot;14-o-que-voc\u00ea-ter\u00e1-ao-final-deste-artigo&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;2 \u2014 Fundamentos matem\u00e1ticos do algoritmo de Goertzel (do zero, passo a passo)&quot;,&quot;value&quot;:&quot;2-fundamentos-matem\u00e1ticos-do-algoritmo-de-goertzel-do-zero-passo-a-passo&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;2.1 Onde o Goertzel se encaixa no DSP cl\u00e1ssico&quot;,&quot;value&quot;:&quot;21-onde-o-goertzel-se-encaixa-no-dsp-cl\u00e1ssico&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;2.2 A DFT vista como um \u00fanico bin&quot;,&quot;value&quot;:&quot;22-a-dft-vista-como-um-\u00fanico-bin&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;2.3 A ideia-chave: um oscilador ressonante discreto&quot;,&quot;value&quot;:&quot;23-a-ideia-chave-um-oscilador-ressonante-discreto&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;2.4 Extraindo a energia da frequ\u00eancia&quot;,&quot;value&quot;:&quot;24-extraindo-a-energia-da-frequ\u00eancia&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;2.5 Rela\u00e7\u00e3o com filtros IIR de segunda ordem&quot;,&quot;value&quot;:&quot;25-rela\u00e7\u00e3o-com-filtros-iir-de-segunda-ordem&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;2.6 Escolha de (N) e resolu\u00e7\u00e3o em frequ\u00eancia&quot;,&quot;value&quot;:&quot;26-escolha-de-n-e-resolu\u00e7\u00e3o-em-frequ\u00eancia&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;2.7 Como mapeamos frequ\u00eancia real \u2192 \u00edndice (k)&quot;,&quot;value&quot;:&quot;27-como-mapeamos-frequ\u00eancia-real-\u2192-\u00edndice-k&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;2.8 O que vamos detectar no assobio&quot;,&quot;value&quot;:&quot;28-o-que-vamos-detectar-no-assobio&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;3 \u2014 Implementa\u00e7\u00e3o b\u00e1sica do algoritmo de Goertzel em C (isolado, incremental e test\u00e1vel)&quot;,&quot;value&quot;:&quot;3-implementa\u00e7\u00e3o-b\u00e1sica-do-algoritmo-de-goertzel-em-c-isolado-incremental-e-test\u00e1vel&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;3.1 Estrutura de estado do Goertzel&quot;,&quot;value&quot;:&quot;31-estrutura-de-estado-do-goertzel&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;3.2 Inicializa\u00e7\u00e3o do detector Goertzel&quot;,&quot;value&quot;:&quot;32-inicializa\u00e7\u00e3o-do-detector-goertzel&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;3.3 Passo recursivo do Goertzel (n\u00facleo do algoritmo)&quot;,&quot;value&quot;:&quot;33-passo-recursivo-do-goertzel-n\u00facleo-do-algoritmo&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;3.4 C\u00e1lculo da energia da frequ\u00eancia&quot;,&quot;value&quot;:&quot;34-c\u00e1lculo-da-energia-da-frequ\u00eancia&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;3.5 Reset do estado (para novo frame)&quot;,&quot;value&quot;:&quot;35-reset-do-estado-para-novo-frame&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;3.6 Teste isolado com sinal sint\u00e9tico (valida\u00e7\u00e3o conceitual)&quot;,&quot;value&quot;:&quot;36-teste-isolado-com-sinal-sint\u00e9tico-valida\u00e7\u00e3o-conceitual&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;3.7 O que aprendemos at\u00e9 aqui&quot;,&quot;value&quot;:&quot;37-o-que-aprendemos-at\u00e9-aqui&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;4 \u2014 Goertzel em tempo real no RP2040: ADC + frames + m\u00faltiplas frequ\u00eancias (fundamental e harm\u00f4nicos)&quot;,&quot;value&quot;:&quot;4-goertzel-em-tempo-real-no-rp2040-adc-frames-m\u00faltiplas-frequ\u00eancias-fundamental-e-harm\u00f4nicos&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;4.1 Definindo o frame e a taxa de amostragem&quot;,&quot;value&quot;:&quot;41-definindo-o-frame-e-a-taxa-de-amostragem&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;4.2 Estrat\u00e9gia \u201cGoertzel multibanda\u201d&quot;,&quot;value&quot;:&quot;42-estrat\u00e9gia-goertzel-multibanda&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;4.3 Aquisi\u00e7\u00e3o em tempo real (ADC + timer), igual ao artigo anterior&quot;,&quot;value&quot;:&quot;43-aquisi\u00e7\u00e3o-em-tempo-real-adc-timer-igual-ao-artigo-anterior&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;4.3.1 Buffer de frame (o mesmo padr\u00e3o)&quot;,&quot;value&quot;:&quot;431-buffer-de-frame-o-mesmo-padr\u00e3o&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;4.3.2 Leitura ADC normalizada&quot;,&quot;value&quot;:&quot;432-leitura-adc-normalizada&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;4.4 Pr\u00e9-processamento m\u00ednimo: remo\u00e7\u00e3o de DC por m\u00e9dia m\u00f3vel (mais robusto)&quot;,&quot;value&quot;:&quot;44-pr\u00e9-processamento-m\u00ednimo-remo\u00e7\u00e3o-de-dc-por-m\u00e9dia-m\u00f3vel-mais-robusto&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;4.5 Varredura com Goertzel (faixa 800\u20133000 Hz)&quot;,&quot;value&quot;:&quot;45-varredura-com-goertzel-faixa-8003000-hz&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;4.5.1 Fun\u00e7\u00e3o: pot\u00eancia Goertzel para uma frequ\u00eancia f0 em um frame&quot;,&quot;value&quot;:&quot;451-fun\u00e7\u00e3o-pot\u00eancia-goertzel-para-uma-frequ\u00eancia-f0-em-um-frame&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;4.6 Encontrando o candidato de fundamental (pico na faixa)&quot;,&quot;value&quot;:&quot;46-encontrando-o-candidato-de-fundamental-pico-na-faixa&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;4.7 Confirma\u00e7\u00e3o por harm\u00f4nicos (2f0 e 3f0)&quot;,&quot;value&quot;:&quot;47-confirma\u00e7\u00e3o-por-harm\u00f4nicos-2f0-e-3f0&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;4.8 Integra\u00e7\u00e3o: montar o \u201cprocessador de frame\u201d (ainda sem LED)&quot;,&quot;value&quot;:&quot;48-integra\u00e7\u00e3o-montar-o-processador-de-frame-ainda-sem-led&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;5 \u2014 Decisor completo + LED + otimiza\u00e7\u00f5es (coeficientes pr\u00e9-computados, EMA, histerese) e integra\u00e7\u00e3o no RP2040&quot;,&quot;value&quot;:&quot;5-decisor-completo-led-otimiza\u00e7\u00f5es-coeficientes-pr\u00e9-computados-ema-histerese-e-integra\u00e7\u00e3o-no-rp2040&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;5.1 Otimiza\u00e7\u00e3o essencial: pr\u00e9-computar os detectores da varredura&quot;,&quot;value&quot;:&quot;51-otimiza\u00e7\u00e3o-essencial-pr\u00e9-computar-os-detectores-da-varredura&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;5.1.1 Estrutura do \u201cdetector preparado\u201d&quot;,&quot;value&quot;:&quot;511-estrutura-do-detector-preparado&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;5.1.2 Construindo a lista de bins (800\u20133000 Hz, passo 2 bins)&quot;,&quot;value&quot;:&quot;512-construindo-a-lista-de-bins-8003000-hz-passo-2-bins&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;5.2 Goertzel \u201cr\u00e1pido\u201d usando coeff pr\u00e9-calculado&quot;,&quot;value&quot;:&quot;52-goertzel-r\u00e1pido-usando-coeff-pr\u00e9-calculado&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;5.3 Encontrar o melhor candidato f0 (varredura)&quot;,&quot;value&quot;:&quot;53-encontrar-o-melhor-candidato-f0-varredura&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;5.4 Harm\u00f4nicos com c\u00e1lculo \u201con demand\u201d&quot;,&quot;value&quot;:&quot;54-harm\u00f4nicos-com-c\u00e1lculo-on-demand&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;5.5 Crit\u00e9rio espectral composto (score)&quot;,&quot;value&quot;:&quot;55-crit\u00e9rio-espectral-composto-score&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;5.6 Decis\u00e3o robusta com EMA + histerese&quot;,&quot;value&quot;:&quot;56-decis\u00e3o-robusta-com-ema-histerese&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;5.7 Integra\u00e7\u00e3o de tempo real (ADC + DC-block + frame)&quot;,&quot;value&quot;:&quot;57-integra\u00e7\u00e3o-de-tempo-real-adc-dc-block-frame&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;5.7.1 DC-block&quot;,&quot;value&quot;:&quot;571-dc-block&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;5.7.2 Estado global e callback de amostragem&quot;,&quot;value&quot;:&quot;572-estado-global-e-callback-de-amostragem&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;5.7.3 Loop processa frame e atualiza LED&quot;,&quot;value&quot;:&quot;573-loop-processa-frame-e-atualiza-led&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;5 \u2014 Decisor completo + LED + otimiza\u00e7\u00f5es (coeficientes pr\u00e9-computados, EMA, histerese) e integra\u00e7\u00e3o no RP2040&quot;,&quot;value&quot;:&quot;5-decisor-completo-led-otimiza\u00e7\u00f5es-coeficientes-pr\u00e9-computados-ema-histerese-e-integra\u00e7\u00e3o-no-rp2040&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;5.1 Otimiza\u00e7\u00e3o essencial: pr\u00e9-computar os detectores da varredura&quot;,&quot;value&quot;:&quot;51-otimiza\u00e7\u00e3o-essencial-pr\u00e9-computar-os-detectores-da-varredura&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;5.1.1 Estrutura do \u201cdetector preparado\u201d&quot;,&quot;value&quot;:&quot;511-estrutura-do-detector-preparado&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;5.1.2 Construindo a lista de bins (800\u20133000 Hz, passo 2 bins)&quot;,&quot;value&quot;:&quot;512-construindo-a-lista-de-bins-8003000-hz-passo-2-bins&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;5.2 Goertzel \u201cr\u00e1pido\u201d usando coeff pr\u00e9-calculado&quot;,&quot;value&quot;:&quot;52-goertzel-r\u00e1pido-usando-coeff-pr\u00e9-calculado&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;5.3 Encontrar o melhor candidato f0 (varredura)&quot;,&quot;value&quot;:&quot;53-encontrar-o-melhor-candidato-f0-varredura&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;5.4 Harm\u00f4nicos com c\u00e1lculo \u201con demand\u201d&quot;,&quot;value&quot;:&quot;54-harm\u00f4nicos-com-c\u00e1lculo-on-demand&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;5.5 Crit\u00e9rio espectral composto (score)&quot;,&quot;value&quot;:&quot;55-crit\u00e9rio-espectral-composto-score&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;5.6 Decis\u00e3o robusta com EMA + histerese&quot;,&quot;value&quot;:&quot;56-decis\u00e3o-robusta-com-ema-histerese&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;5.7 Integra\u00e7\u00e3o de tempo real (ADC + DC-block + frame)&quot;,&quot;value&quot;:&quot;57-integra\u00e7\u00e3o-de-tempo-real-adc-dc-block-frame&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;5.7.1 DC-block&quot;,&quot;value&quot;:&quot;571-dc-block&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;5.7.2 Estado global e callback de amostragem&quot;,&quot;value&quot;:&quot;572-estado-global-e-callback-de-amostragem&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;5.7.3 Loop processa frame e atualiza LED&quot;,&quot;value&quot;:&quot;573-loop-processa-frame-e-atualiza-led&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;6 \u2014 C\u00f3digo completo e funcional (BitDogLab \/ RP2040) com Goertzel: detec\u00e7\u00e3o de assobio + LED&quot;,&quot;value&quot;:&quot;6-c\u00f3digo-completo-e-funcional-bitdoglab-rp2040-com-goertzel-detec\u00e7\u00e3o-de-assobio-led&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;7 \u2014 Calibra\u00e7\u00e3o pr\u00e1tica, compara\u00e7\u00e3o com o artigo anterior, encerramento e SEO&quot;,&quot;value&quot;:&quot;7-calibra\u00e7\u00e3o-pr\u00e1tica-compara\u00e7\u00e3o-com-o-artigo-anterior-encerramento-e-seo&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;7.1 Calibra\u00e7\u00e3o pr\u00e1tica (engenharia de campo, n\u00e3o de laborat\u00f3rio)&quot;,&quot;value&quot;:&quot;71-calibra\u00e7\u00e3o-pr\u00e1tica-engenharia-de-campo-n\u00e3o-de-laborat\u00f3rio&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;7.2 Boas escolhas vs. m\u00e1s escolhas (espec\u00edfico do Goertzel)&quot;,&quot;value&quot;:&quot;72-boas-escolhas-vs-m\u00e1s-escolhas-espec\u00edfico-do-goertzel&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;7.3 Compara\u00e7\u00e3o direta com o artigo anterior (Taylor + Cepstrum)&quot;,&quot;value&quot;:&quot;73-compara\u00e7\u00e3o-direta-com-o-artigo-anterior-taylor-cepstrum&quot;,&quot;isDelete&quot;:false},{&quot;label&quot;:&quot;7.4 Encerramento&quot;,&quot;value&quot;:&quot;74-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">Continuação da série: Filtragem Digital, Cepstrum e Detecção Acústica em MCU</a><li><a href="#eb-table-content-1">1. Introdução — Por que Goertzel?</a><li><a href="#eb-table-content-2">1.1 Estratégia geral adotada neste artigo</a><li><a href="#eb-table-content-3">1.2 Quando Goertzel é a escolha correta (e quando não é)</a><li><a href="#eb-table-content-4">1.3 Relação direta com o artigo anterior</a><li><a href="#eb-table-content-5">1.4 O que você terá ao final deste artigo</a><li><a href="#eb-table-content-6">2 — Fundamentos matemáticos do algoritmo de Goertzel (do zero, passo a passo)</a><ul class="eb-toc__list"><li><a href="#eb-table-content-7">2.1 Onde o Goertzel se encaixa no DSP clássico</a><li><a href="#eb-table-content-8">2.2 A DFT vista como um único bin</a><li><a href="#23-a-ideia-chave-um-oscilador-ressonante-discreto">2.3 A ideia-chave: um oscilador ressonante discreto</a><li><a href="#eb-table-content-10">2.4 Extraindo a energia da frequência</a><li><a href="#eb-table-content-11">2.5 Relação com filtros IIR de segunda ordem</a><li><a href="#eb-table-content-12">2.6 Escolha de (N) e resolução em frequência</a><li><a href="#eb-table-content-13">2.7 Como mapeamos frequência real → índice (k)</a><li><a href="#28-o-que-vamos-detectar-no-assobio">2.8 O que vamos detectar no assobio</a></li></ul><li><a href="#eb-table-content-15">3 — Implementação básica do algoritmo de Goertzel em C (isolado, incremental e testável)</a><ul class="eb-toc__list"><li><a href="#31-estrutura-de-estado-do-goertzel">3.1 Estrutura de estado do Goertzel</a><li><a href="#eb-table-content-17">3.2 Inicialização do detector Goertzel</a><li><a href="#eb-table-content-18">3.3 Passo recursivo do Goertzel (núcleo do algoritmo)</a><li><a href="#eb-table-content-19">3.4 Cálculo da energia da frequência</a><li><a href="#35-reset-do-estado-para-novo-frame">3.5 Reset do estado (para novo frame)</a><li><a href="#eb-table-content-21">3.6 Teste isolado com sinal sintético (validação conceitual)</a><li><a href="#eb-table-content-22">3.7 O que aprendemos até aqui</a></li></ul><li><a href="#eb-table-content-23">4 — Goertzel em tempo real no RP2040: ADC + frames + múltiplas frequências (fundamental e harmônicos)</a><ul class="eb-toc__list"><li><a href="#41-definindo-o-frame-e-a-taxa-de-amostragem">4.1 Definindo o frame e a taxa de amostragem</a><li><a href="#eb-table-content-25">4.2 Estratégia “Goertzel multibanda”</a><li><a href="#eb-table-content-26">4.3 Aquisição em tempo real (ADC + timer), igual ao artigo anterior</a><ul class="eb-toc__list"><li><a href="#eb-table-content-27">4.3.1 Buffer de frame (o mesmo padrão)</a><li><a href="#432-leitura-adc-normalizada">4.3.2 Leitura ADC normalizada</a></li></ul><li><a href="#eb-table-content-29">4.4 Pré-processamento mínimo: remoção de DC por média móvel (mais robusto)</a><li><a href="#45-varredura-com-goertzel-faixa-8003000-hz">4.5 Varredura com Goertzel (faixa 800–3000 Hz)</a><ul class="eb-toc__list"><li><a href="#eb-table-content-31">4.5.1 Função: potência Goertzel para uma frequência f0 em um frame</a></li></ul><li><a href="#46-encontrando-o-candidato-de-fundamental-pico-na-faixa">4.6 Encontrando o candidato de fundamental (pico na faixa)</a><li><a href="#eb-table-content-33">4.7 Confirmação por harmônicos (2f0 e 3f0)</a><li><a href="#eb-table-content-34">4.8 Integração: montar o “processador de frame” (ainda sem LED)</a></li></ul><li><a href="#eb-table-content-35">5 — Decisor completo + LED + otimizações (coeficientes pré-computados, EMA, histerese) e integração no RP2040</a><ul class="eb-toc__list"><li><a href="#eb-table-content-36">5.1 Otimização essencial: pré-computar os detectores da varredura</a><ul class="eb-toc__list"><li><a href="#511-estrutura-do-detector-preparado">5.1.1 Estrutura do “detector preparado”</a><li><a href="#512-construindo-a-lista-de-bins-8003000-hz-passo-2-bins">5.1.2 Construindo a lista de bins (800–3000 Hz, passo 2 bins)</a></li></ul><li><a href="#eb-table-content-39">5.2 Goertzel “rápido” usando coeff pré-calculado</a><li><a href="#53-encontrar-o-melhor-candidato-f0-varredura">5.3 Encontrar o melhor candidato f0 (varredura)</a><li><a href="#eb-table-content-41">5.4 Harmônicos com cálculo “on demand”</a><li><a href="#eb-table-content-42">5.5 Critério espectral composto (score)</a><li><a href="#eb-table-content-43">5.6 Decisão robusta com EMA + histerese</a><li><a href="#eb-table-content-44">5.7 Integração de tempo real (ADC + DC-block + frame)</a><ul class="eb-toc__list"><li><a href="#571-dc-block">5.7.1 DC-block</a><li><a href="#572-estado-global-e-callback-de-amostragem">5.7.2 Estado global e callback de amostragem</a><li><a href="#573-loop-processa-frame-e-atualiza-led">5.7.3 Loop processa frame e atualiza LED</a></li></ul></li></ul><li><a href="#eb-table-content-48">5 — Decisor completo + LED + otimizações (coeficientes pré-computados, EMA, histerese) e integração no RP2040</a><ul class="eb-toc__list"><li><a href="#eb-table-content-49">5.1 Otimização essencial: pré-computar os detectores da varredura</a><ul class="eb-toc__list"><li><a href="#511-estrutura-do-detector-preparado">5.1.1 Estrutura do “detector preparado”</a><li><a href="#512-construindo-a-lista-de-bins-8003000-hz-passo-2-bins">5.1.2 Construindo a lista de bins (800–3000 Hz, passo 2 bins)</a></li></ul><li><a href="#eb-table-content-52">5.2 Goertzel “rápido” usando coeff pré-calculado</a><li><a href="#53-encontrar-o-melhor-candidato-f0-varredura">5.3 Encontrar o melhor candidato f0 (varredura)</a><li><a href="#eb-table-content-54">5.4 Harmônicos com cálculo “on demand”</a><li><a href="#eb-table-content-55">5.5 Critério espectral composto (score)</a><li><a href="#eb-table-content-56">5.6 Decisão robusta com EMA + histerese</a><li><a href="#eb-table-content-57">5.7 Integração de tempo real (ADC + DC-block + frame)</a><ul class="eb-toc__list"><li><a href="#571-dc-block">5.7.1 DC-block</a><li><a href="#572-estado-global-e-callback-de-amostragem">5.7.2 Estado global e callback de amostragem</a><li><a href="#573-loop-processa-frame-e-atualiza-led">5.7.3 Loop processa frame e atualiza LED</a></li></ul></li></ul><li><a href="#eb-table-content-61">6 — Código completo e funcional (BitDogLab / RP2040) com Goertzel: detecção de assobio + LED</a><li><a href="#eb-table-content-62">7 — Calibração prática, comparação com o artigo anterior, encerramento e SEO</a><ul class="eb-toc__list"><li><a href="#eb-table-content-63">7.1 Calibração prática (engenharia de campo, não de laboratório)</a><li><a href="#eb-table-content-64">7.2 Boas escolhas vs. más escolhas (específico do Goertzel)</a><li><a href="#eb-table-content-65">7.3 Comparação direta com o artigo anterior (Taylor + Cepstrum)</a><li><a href="#74-encerramento">7.4 Encerramento</a></li></ul></ul></div></div></div></div></div>


<h3 class="wp-block-heading">1. Introdução — Por que Goertzel?</h3>



<p class="wp-block-paragraph">No artigo anterior desta série, exploramos uma abordagem baseada em <strong>filtragem digital construída com Séries de Taylor</strong>, seguida pelo <strong>cálculo do cepstrum</strong>, para identificar a periodicidade característica de um assobio humano. Aquela estratégia privilegiou uma análise <strong>global do espectro</strong>, permitindo identificar a estrutura harmônica do sinal de forma robusta, mesmo em ambientes com ruído.</p>



<p class="wp-block-paragraph">Neste novo artigo, damos continuidade direta a essa série, adotando <strong>uma estratégia complementar e mais enxuta</strong>: o <strong>algoritmo de Goertzel</strong>. Em vez de calcular todo o espectro via FFT, o Goertzel permite <strong>extrair seletivamente a energia de frequências específicas</strong>, tornando-o ideal para microcontroladores com recursos limitados — como o RP2040 — quando o interesse está restrito a <strong>faixas bem definidas</strong>.</p>



<p class="wp-block-paragraph">O assobio humano típico apresenta uma frequência fundamental relativamente estável, geralmente entre <strong>800 Hz e 3000 Hz</strong>, com harmônicos previsíveis. O algoritmo de Goertzel explora exatamente esse cenário:</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph"><em>“Eu sei qual frequência quero detectar — e só ela importa.”</em></p>
</blockquote>



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



<h3 class="wp-block-heading">1.1 Estratégia geral adotada neste artigo</h3>



<p class="wp-block-paragraph">A arquitetura de processamento deste artigo será:</p>



<ol class="wp-block-list">
<li><strong>Aquisição do sinal acústico</strong> (ADC do RP2040)</li>



<li><strong>Pré-processamento simples</strong> (remoção de DC e normalização)</li>



<li><strong>Aplicação do algoritmo de Goertzel</strong> para:
<ul class="wp-block-list">
<li>Frequência fundamental</li>



<li>Harmônicos selecionados</li>
</ul>
</li>



<li><strong>Construção de um critério de decisão espectral</strong></li>



<li><strong>Confirmação temporal</strong> (evitar falsos positivos)</li>



<li><strong>Acionamento de um LED</strong> quando o assobio é detectado</li>
</ol>



<p class="wp-block-paragraph">Diferentemente do artigo anterior:</p>



<ul class="wp-block-list">
<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Não calcularemos FFT</li>



<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Não calcularemos cepstrum</li>



<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Usaremos <strong>análise espectral pontual</strong></li>



<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Menor uso de RAM e CPU</li>



<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Menor latência</li>
</ul>



<p class="wp-block-paragraph">Isso permite uma comparação clara entre duas filosofias de DSP embarcado:</p>



<ul class="wp-block-list">
<li><strong>FFT + Cepstrum → análise estrutural</strong></li>



<li><strong>Goertzel → análise dirigida por frequência</strong></li>
</ul>



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



<h3 class="wp-block-heading">1.2 Quando Goertzel é a escolha correta (e quando não é)</h3>



<p class="wp-block-paragraph"><strong>Goertzel é uma excelente escolha quando:</strong></p>



<ul class="wp-block-list">
<li>Você conhece as frequências de interesse</li>



<li>O número de frequências é pequeno</li>



<li>O MCU possui RAM limitada</li>



<li>A latência precisa ser baixa</li>



<li>O sistema é reativo (event-driven)</li>
</ul>



<p class="wp-block-paragraph"><strong>Goertzel NÃO é a melhor escolha quando:</strong></p>



<ul class="wp-block-list">
<li>A frequência fundamental varia muito</li>



<li>Você precisa analisar o espectro completo</li>



<li>O sinal tem múltiplas fontes concorrentes</li>



<li>A estrutura harmônica é desconhecida</li>
</ul>



<p class="wp-block-paragraph">Este artigo assume explicitamente o <strong>caso ideal para Goertzel</strong>:<br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f449.png" alt="👉" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <em>detectar um fenômeno acústico específico e conhecido</em>.</p>



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



<h3 class="wp-block-heading">1.3 Relação direta com o artigo anterior</h3>



<p class="wp-block-paragraph">Este artigo <strong>não substitui</strong> o anterior — ele o <strong>complementa</strong>.</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Artigo anterior</th><th>Este artigo</th></tr></thead><tbody><tr><td>Séries de Taylor</td><td>Goertzel</td></tr><tr><td>FFT + Cepstrum</td><td>Análise pontual</td></tr><tr><td>Estrutura harmônica global</td><td>Frequência-alvo</td></tr><tr><td>Mais matemática</td><td>Mais eficiência</td></tr><tr><td>Mais flexível</td><td>Mais determinístico</td></tr></tbody></table></figure>



<p class="wp-block-paragraph">A ideia da série é exatamente essa: <strong>mostrar estratégias diferentes para o mesmo problema</strong>, permitindo ao engenheiro escolher conscientemente.</p>



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



<h3 class="wp-block-heading">1.4 O que você terá ao final deste artigo</h3>



<p class="wp-block-paragraph">Ao final deste artigo, você terá:</p>



<ul class="wp-block-list">
<li>Um <strong>detector de assobio funcional</strong></li>



<li>Código <strong>100% em C</strong>, portátil</li>



<li>Execução em <strong>tempo real no RP2040</strong></li>



<li>Arquitetura reutilizável para:
<ul class="wp-block-list">
<li>DTMF</li>



<li>Tons de controle</li>



<li>Alarmes acústicos</li>



<li>Interfaces sonoras simples</li>
</ul>
</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/><p>The post <a href="https://mcu.tec.br/algoritimos/dsp/deteccao-de-assobio-humano-com-o-algoritmo-de-goertzel-no-rp2040/">Detecção de Assobio Humano com o Algoritmo de Goertzel no 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">1125</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>Como Estruturar um Projeto Profissional com CMake para o RP2040: Guia Didático Passo a Passo</title>
		<link>https://mcu.tec.br/linguagem/builds/como-estruturar-um-projeto-profissional-com-cmake-para-o-rp2040-guia-didatico-passo-a-passo/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=como-estruturar-um-projeto-profissional-com-cmake-para-o-rp2040-guia-didatico-passo-a-passo</link>
		
		<dc:creator><![CDATA[Carlos Delfino]]></dc:creator>
		<pubDate>Fri, 01 Aug 2025 01:06:42 +0000</pubDate>
				<category><![CDATA[Builds]]></category>
		<category><![CDATA[build system CMake]]></category>
		<category><![CDATA[CMake]]></category>
		<category><![CDATA[CMakeLists.txt]]></category>
		<category><![CDATA[compile_commands.json]]></category>
		<category><![CDATA[env.cmake]]></category>
		<category><![CDATA[firmware embarcado]]></category>
		<category><![CDATA[lwIP MQTT]]></category>
		<category><![CDATA[microcontrolador com Wi-Fi]]></category>
		<category><![CDATA[MQTT embedded]]></category>
		<category><![CDATA[projeto embarcado]]></category>
		<category><![CDATA[projeto RP2040]]></category>
		<category><![CDATA[Raspberry Pi Pico]]></category>
		<category><![CDATA[RP2040]]></category>
		<category><![CDATA[SDK Pico]]></category>
		<category><![CDATA[stdio UART]]></category>
		<category><![CDATA[stdio USB]]></category>
		<category><![CDATA[toolchain para RP2040]]></category>
		<category><![CDATA[variável de ambiente]]></category>
		<category><![CDATA[Wi-Fi no RP2040]]></category>
		<guid isPermaLink="false">https://mcu.tec.br/?p=635</guid>

					<description><![CDATA[<p>Aprenda a estruturar corretamente um projeto para o microcontrolador RP2040 utilizando CMake. Este guia didático passo a passo explica cada linha do CMakeLists.txt, desde variáveis de ambiente até a geração do firmware .uf2, com foco em boas práticas e clareza para iniciantes.</p>
<p>The post <a href="https://mcu.tec.br/linguagem/builds/como-estruturar-um-projeto-profissional-com-cmake-para-o-rp2040-guia-didatico-passo-a-passo/">Como Estruturar um Projeto Profissional com CMake para o RP2040: Guia Didático Passo a Passo</a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></description>
										<content:encoded><![CDATA[<p class="wp-block-paragraph">No universo do desenvolvimento embarcado, a jornada do iniciante pode parecer repleta de barreiras invisíveis. Uma das mais frequentes – e subestimadas – está na <strong>estruturação correta do projeto</strong>, especialmente quando se trata de plataformas modernas como o <strong>RP2040</strong>, o microcontrolador da Raspberry Pi Foundation. Antes mesmo de escrever a primeira linha de código C, é essencial compreender como preparar o ambiente de compilação, como organizar os arquivos e como garantir que tudo esteja pronto para transformar ideias em firmware funcional.</p>



<p class="wp-block-paragraph">Neste contexto, o sistema de build <strong>CMake</strong> se torna uma ferramenta central. Apesar de sua aparência intimidadora para quem está começando, o CMake é uma ponte poderosa entre o código-fonte e o binário que rodará no seu dispositivo. Ele permite organizar dependências, configurar variáveis, compilar múltiplos arquivos e até mesmo lidar com diferentes toolchains de forma automatizada. E quando combinamos o CMake com o ecossistema do RP2040, especialmente com o <strong>Pico SDK</strong>, temos um ambiente robusto, escalável e flexível — desde projetos educacionais até aplicações industriais.</p>



<p class="wp-block-paragraph">Por isso, este artigo tem como objetivo guiar o leitor iniciante <strong>passo a passo</strong> pela análise de um projeto real baseado no RP2040, explicando detalhadamente cada trecho do arquivo <code>CMakeLists.txt</code> e os scripts auxiliares que compõem a infraestrutura de build. Vamos abordar o papel de cada linha, o porquê das decisões adotadas, e quais boas práticas estão sendo aplicadas — além de sugerir melhorias e comparações com abordagens de outras plataformas.</p>



<p class="wp-block-paragraph">Este não é apenas um guia técnico: é também um convite à compreensão. Ao final desta leitura, você não apenas será capaz de compilar um projeto com confiança, mas também entenderá <strong>por que cada etapa é importante</strong>. Assim, poderá adaptar seus projetos futuros com segurança e domínio técnico, explorando todo o potencial do RP2040.</p>



<p class="wp-block-paragraph">Prepare seu editor de texto e acompanhe cada seção com atenção — pois cada linha que vamos explorar é um pequeno degrau em direção à maestria no desenvolvimento embarcado moderno.</p>



<p class="wp-block-paragraph">Para este artigo foi usado os seguintes arquivos CMakeLists.txt:</p>



<ul class="wp-block-list">
<li><a href="https://github.com/carlosdelfino/embarcatech_etapa_2_cap_2_Tarefa-Pr-tica-IOT-3/blob/main/rp2040_mqtt_server_example/CMakeLists.txt">https://github.com/carlosdelfino/embarcatech_etapa_2_cap_2_Tarefa-Pr-tica-IOT-3/blob/main/rp2040_mqtt_server_example/CMakeLists.txt</a> </li>



<li><a href="https://github.com/carlosdelfino/embarcatech_etapa_2_cap_2_Tarefa-Pr-tica-IOT-3/blob/main/rp2040_mqtt_client_example/CMakeLists.txt ">https://github.com/carlosdelfino/embarcatech_etapa_2_cap_2_Tarefa-Pr-tica-IOT-3/blob/main/rp2040_mqtt_client_example/CMakeLists.txt </a></li>
</ul>



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



<h2 class="wp-block-heading"><strong>1. Configuração Inicial do CMake: Definindo Versão e Padrões do Projeto</strong></h2>



<p class="wp-block-paragraph">Logo no início do arquivo <code>CMakeLists.txt</code>, temos um trecho essencial para garantir a compatibilidade e padronização do ambiente de compilação. Veja abaixo:</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" data-code="cmake_minimum_required(VERSION 3.13)

set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><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">cmake_minimum_required</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">VERSION</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">3.13</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #88C0D0">set</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">CMAKE_C_STANDARD</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">11</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #88C0D0">set</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">CMAKE_CXX_STANDARD</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">17</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #88C0D0">set</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">CMAKE_EXPORT_COMPILE_COMMANDS</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">ON</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"></span></code></pre></div>



<h3 class="wp-block-heading"><strong>Explicação Didática</strong></h3>



<ol class="wp-block-list">
<li><strong><code>cmake_minimum_required(VERSION 3.13)</code></strong><br>Esta linha define a <strong>versão mínima do CMake</strong> exigida para processar corretamente este projeto. O valor <code>3.13</code> é uma escolha segura para projetos com RP2040, pois é compatível com as versões mais estáveis do SDK da Raspberry Pi e da extensão para VSCode. Se o desenvolvedor tentar compilar o projeto com uma versão mais antiga do CMake, ele receberá uma mensagem de erro clara, evitando comportamento indefinido ou suporte incompleto a recursos.</li>



<li><strong><code>set(CMAKE_C_STANDARD 11)</code></strong><br>Define que o código C será compilado segundo o <strong>padrão C11</strong>, uma versão estável e moderna da linguagem C, que inclui melhorias importantes como <em>atomics</em>, <em>static assertions</em> e melhor suporte a multithreading.</li>



<li><strong><code>set(CMAKE_CXX_STANDARD 17)</code></strong><br>Determina que, caso o projeto inclua arquivos em C++, eles devem seguir o padrão <strong>C++17</strong>. Este padrão oferece recursos como <em>structured bindings</em>, <em>if constexpr</em>, e <em>std::optional</em>, que podem ser úteis em aplicações mais complexas.</li>



<li><strong><code>set(CMAKE_EXPORT_COMPILE_COMMANDS ON)</code></strong><br>Esta opção gera o arquivo <code>compile_commands.json</code>, que descreve os comandos de compilação de cada fonte no projeto. Ele é extremamente útil para ferramentas externas como <strong>servidores de linguagem (LSPs)</strong>, <strong>linters</strong> e <strong>analisadores estáticos</strong>, como o <code>clangd</code>.</li>
</ol>



<h3 class="wp-block-heading"><strong>Análise Crítica</strong></h3>



<ul class="wp-block-list">
<li>A escolha de <strong>C11 e C++17</strong> é apropriada: garante modernidade sem sacrificar a compatibilidade com a maioria dos toolchains usados no mundo embarcado.</li>



<li>A inclusão de <code>CMAKE_EXPORT_COMPILE_COMMANDS</code> mostra preocupação com a <strong>qualidade do desenvolvimento</strong>, pois favorece a integração com IDEs modernas e ferramentas de verificação de código.</li>



<li>Poderia ser interessante tornar os padrões configuráveis via variável de cache (<code>CACHE STRING</code>), permitindo ao usuário customizar sem alterar diretamente o CMakeLists.txt.</li>
</ul>



<h3 class="wp-block-heading"><strong>Observações Didáticas</strong></h3>



<ul class="wp-block-list">
<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f530.png" alt="🔰" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Para iniciantes:</strong> Pense nesta seção como o &#8220;acordo inicial&#8221; entre você e o compilador. Aqui você diz: “vamos trabalhar com a linguagem C moderna, C++ moderno e quero um ambiente que me ajude a detectar erros logo no começo”.</li>



<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f6e0.png" alt="🛠" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Boas práticas:</strong> Sempre explicite o padrão da linguagem em projetos embarcados. Evita surpresas e garante consistência entre diferentes ambientes de build.</li>



<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f9e0.png" alt="🧠" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Dica extra:</strong> O <code>compile_commands.json</code> pode ser usado por ferramentas como o <strong>clang-tidy</strong> ou <strong>cppcheck</strong> para inspeções profundas do seu código.</li>
</ul>



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



<h2 class="wp-block-heading"><strong>2. Configuração da Extensão VSCode e Inclusão do SDK</strong></h2>



<p class="wp-block-paragraph">Após definir os padrões iniciais de compilação, o projeto introduz uma etapa importante para integração com o ambiente de desenvolvimento e o SDK do RP2040. Veja o trecho a seguir:</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" data-code="# == DO NOT EDIT THE FOLLOWING LINES for the Raspberry Pi Pico VS Code Extension to work ==
if(WIN32)
    set(USERHOME $ENV{USERPROFILE})
else()
    set(USERHOME $ENV{HOME})
endif()
set(sdkVersion 2.1.1)
set(toolchainVersion 14_2_Rel1)
set(picotoolVersion 2.1.1)
set(picoVscode ${USERHOME}/.pico-sdk/cmake/pico-vscode.cmake)
if (EXISTS ${picoVscode})
    include(${picoVscode})
endif()
# ====================================================================================
" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><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: #81A1C1">==</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">DO</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">NOT</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">EDIT</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">THE</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">FOLLOWING</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">LINES</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">for</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">the</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">Raspberry</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">Pi</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">Pico</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">VS</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">Code</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">Extension</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">to</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">work</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">==</span></span>
<span class="line"><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">WIN32</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">set</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">USERHOME</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">$ENV</span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9">USERPROFILE</span><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #81A1C1">else</span><span style="color: #D8DEE9FF">()</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">set</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">USERHOME</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">$ENV</span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9">HOME</span><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #88C0D0">endif</span><span style="color: #D8DEE9FF">()</span></span>
<span class="line"><span style="color: #88C0D0">set</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">sdkVersion</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">2.1</span><span style="color: #ECEFF4">.</span><span style="color: #B48EAD">1</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #88C0D0">set</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">toolchainVersion</span><span style="color: #D8DEE9FF"> 14</span><span style="color: #D8DEE9">_2_Rel1</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #88C0D0">set</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">picotoolVersion</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">2.1</span><span style="color: #ECEFF4">.</span><span style="color: #B48EAD">1</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #88C0D0">set</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">picoVscode</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">$</span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9">USERHOME</span><span style="color: #ECEFF4">}</span><span style="color: #81A1C1">/</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">pico</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9">sdk</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9">cmake</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9">pico</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9">vscode</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">cmake</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">EXISTS</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">$</span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9">picoVscode</span><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">include</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">$</span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9">picoVscode</span><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #88C0D0">endif</span><span style="color: #D8DEE9FF">()</span></span>
<span class="line"><span style="color: #D8DEE9FF"># </span><span style="color: #81A1C1">====================================================================================</span></span>
<span class="line"></span></code></pre></div>



<h3 class="wp-block-heading"><strong>Explicação Didática</strong></h3>



<ol class="wp-block-list">
<li><strong>Bloco condicional <code>if(WIN32)</code>&#8230;</strong><br>Aqui é verificado se o sistema operacional é Windows (<code>WIN32</code>). Se for, define a variável <code>USERHOME</code> como o caminho da variável de ambiente <code>USERPROFILE</code>. Caso contrário (Linux/macOS), usa <code>HOME</code>.<br>Isso garante <strong>portabilidade do projeto entre sistemas operacionais</strong>, o que é essencial para ambientes colaborativos e didáticos.</li>



<li><strong><code>set(sdkVersion ...)</code>, <code>toolchainVersion ...</code>, <code>picotoolVersion ...)</code></strong><br>Essas linhas servem como <strong>metadados informativos</strong> que descrevem as versões usadas no ambiente de desenvolvimento. Embora não sejam diretamente utilizadas pelo CMake nesta etapa, são úteis para documentação, scripts externos ou para controle de consistência do ambiente de build.</li>



<li><strong><code>set(picoVscode ...)</code> e <code>include(...)</code></strong><br>Essa etapa tenta localizar o arquivo <code>pico-vscode.cmake</code>, que é utilizado pela extensão oficial da Raspberry Pi no VSCode para configurar corretamente o ambiente.<br>Se o arquivo existir, ele é incluído, permitindo que recursos como <strong>auto-complete</strong>, <strong>debug remoto</strong>, e <strong>templates automáticos</strong> funcionem adequadamente.</li>
</ol>



<h3 class="wp-block-heading"><strong>Análise Crítica</strong></h3>



<ul class="wp-block-list">
<li>O uso de <code>EXISTS</code> para checar a presença do arquivo evita erros e torna o projeto mais robusto.</li>



<li>Esta seção é essencial para <strong>ambientes com suporte a IDEs modernas</strong>, mas pode ser <strong>omitida com segurança</strong> se o projeto for construído apenas via terminal.</li>



<li>A presença dos comentários <code>DO NOT EDIT</code> é uma prática comum para marcar blocos sensíveis que são exigidos por ferramentas externas.</li>
</ul>



<h3 class="wp-block-heading"><strong>Observações Didáticas</strong></h3>



<ul class="wp-block-list">
<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f9f0.png" alt="🧰" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Para iniciantes:</strong> Essa parte pode parecer obscura à primeira vista, mas pense nela como a “ponte” entre o CMake e o seu editor (VSCode). Se ela estiver funcionando, você terá suporte a <strong>atalhos, intellisense e debug facilitado</strong>.</li>



<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f30d.png" alt="🌍" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Dica de compatibilidade:</strong> Quando você compartilha seu projeto com colegas usando Windows e você usa Linux (ou vice-versa), esse bloco ajuda a manter tudo funcionando sem dor de cabeça.</li>



<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4e6.png" alt="📦" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Importante saber:</strong> Se o arquivo <code>pico-vscode.cmake</code> não estiver instalado, o build ainda funcionará — mas <strong>você perderá integração com o VSCode</strong>.</li>
</ul>



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



<h2 class="wp-block-heading"><strong>3. Parametrização por Ambiente: Importando o <code>env.cmake</code></strong></h2>



<p class="wp-block-paragraph">Este bloco mostra como carregar configurações externas e definir valores padrão para variáveis críticas de conexão, como Wi-Fi e MQTT. Veja o trecho abaixo:</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" data-code="if(EXISTS &quot;${CMAKE_SOURCE_DIR}/env.cmake&quot;)
    include(&quot;${CMAKE_SOURCE_DIR}/env.cmake&quot;)
    message(STATUS &quot;Arquivo env.cmake carregado com sucesso.&quot;)
else()
    message(FATAL_ERROR &quot;Arquivo env.cmake não encontrado!&quot;)
endif()
" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><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: #81A1C1">if</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">EXISTS</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">${CMAKE_SOURCE_DIR}/env.cmake</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">include</span><span style="color: #D8DEE9FF">(</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">${CMAKE_SOURCE_DIR}/env.cmake</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">message</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">STATUS</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Arquivo env.cmake carregado com sucesso.</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #81A1C1">else</span><span style="color: #D8DEE9FF">()</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">message</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">FATAL_ERROR</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Arquivo env.cmake não encontrado!</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #88C0D0">endif</span><span style="color: #D8DEE9FF">()</span></span>
<span class="line"></span></code></pre></div>



<h3 class="wp-block-heading"><strong>Explicação Didática</strong></h3>



<ol class="wp-block-list">
<li><strong><code>if(EXISTS "${CMAKE_SOURCE_DIR}/env.cmake")</code></strong><br>Verifica se o arquivo <code>env.cmake</code> existe no diretório raiz do projeto. Essa verificação é crucial para não interromper o processo de configuração se o arquivo estiver ausente ou mal posicionado.</li>



<li><strong><code>include(...)</code></strong><br>Se o arquivo existir, ele é carregado e suas variáveis passam a ser conhecidas no escopo do CMake. Isso permite separar a <strong>configuração sensível ou personalizada</strong> (como senhas e tópicos MQTT) do corpo principal do projeto.</li>



<li><strong><code>message(STATUS "...")</code> e <code>message(FATAL_ERROR "...")</code></strong><br>Usadas para informar claramente ao usuário o sucesso ou falha dessa etapa. Um erro fatal é gerado se o <code>env.cmake</code> estiver ausente, forçando o desenvolvedor a corrigi-lo antes de prosseguir — uma forma de evitar builds incompletos ou configurações erradas.</li>
</ol>



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



<p class="wp-block-paragraph">A seguir, são aplicadas validações adicionais:</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" data-code="if(NOT DEFINED ENV{WIFI_SSID})
    message(WARNING &quot;Variável WIFI_SSID não definida no .env.&quot;)
    set(ENV{WIFI_SSID} &quot;ArvoreDosSaberes&quot;)
endif()
# ... outros blocos semelhantes para WIFI_PASSWORD, MQTT_BROKER, etc.
" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><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: #81A1C1">if</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">NOT</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">DEFINED</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">ENV</span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9">WIFI_SSID</span><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">message</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">WARNING</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">Variável WIFI_SSID não definida no .env.</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">set</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">ENV</span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9">WIFI_SSID</span><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">ArvoreDosSaberes</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #88C0D0">endif</span><span style="color: #D8DEE9FF">()</span></span>
<span class="line"><span style="color: #D8DEE9FF"># </span><span style="color: #81A1C1">...</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">outros</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">blocos</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">semelhantes</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">para</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">WIFI_PASSWORD</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">MQTT_BROKER</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">etc</span><span style="color: #ECEFF4">.</span></span>
<span class="line"></span></code></pre></div>



<h3 class="wp-block-heading"><strong>Explicação Didática</strong></h3>



<p class="wp-block-paragraph">Cada bloco verifica se uma variável de ambiente essencial está definida (<code>ENV{VARIAVEL}</code>). Se não estiver, ele:</p>



<ul class="wp-block-list">
<li>Emite um <strong>aviso não fatal</strong>, alertando o usuário;</li>



<li>Define um valor <strong>padrão razoável</strong> para que o build continue.</li>
</ul>



<p class="wp-block-paragraph">Ao final, todas as variáveis são capturadas explicitamente para o escopo interno do CMake:</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" data-code="set(WIFI_SSID &quot;$ENV{WIFI_SSID}&quot;)
set(WIFI_PASSWORD &quot;$ENV{WIFI_PASSWORD}&quot;)
set(MQTT_BROKER &quot;$ENV{MQTT_BROKER}&quot;)
set(MQTT_BASE_TOPIC &quot;$ENV{MQTT_BASE_TOPIC}&quot;)
set(MQTT_RACK_NUMBER &quot;$ENV{MQTT_RACK_NUMBER}&quot;)
" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><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">set</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">WIFI_SSID</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">$ENV{WIFI_SSID}</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #88C0D0">set</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">WIFI_PASSWORD</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">$ENV{WIFI_PASSWORD}</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #88C0D0">set</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">MQTT_BROKER</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">$ENV{MQTT_BROKER}</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #88C0D0">set</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">MQTT_BASE_TOPIC</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">$ENV{MQTT_BASE_TOPIC}</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #88C0D0">set</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">MQTT_RACK_NUMBER</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">$ENV{MQTT_RACK_NUMBER}</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"></span></code></pre></div>



<h3 class="wp-block-heading"><strong>Análise Crítica</strong></h3>



<ul class="wp-block-list">
<li>O uso do <code>env.cmake</code> permite separar configuração de ambiente do código — uma excelente prática que segue os princípios da engenharia de software moderna.</li>



<li>Fornecer valores padrão facilita testes e uso didático, mas o ideal seria mover os valores <strong>sensíveis (como senhas)</strong> para fora do controle de versão (usando, por exemplo, <code>.gitignore</code>).</li>



<li>Poderia haver uma variável global ou opção no CMake para <strong>desativar temporariamente os erros fatais</strong>, facilitando builds rápidos durante o desenvolvimento.</li>
</ul>



<h3 class="wp-block-heading"><strong>Observações Didáticas</strong></h3>



<ul class="wp-block-list">
<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f9ea.png" alt="🧪" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Analogia simples:</strong> Pense no <code>env.cmake</code> como um “cartão de visita” que você entrega ao projeto, dizendo quem você é (SSID, senha, broker). Assim, ele sabe com quem falar e como se comportar.</li>



<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4c1.png" alt="📁" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Organização é tudo:</strong> Ao manter essas variáveis fora do <code>CMakeLists.txt</code>, você pode trocar de rede ou broker sem reconfigurar o projeto inteiro — basta editar ou substituir o <code>env.cmake</code>.</li>



<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f6ab.png" alt="🚫" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Cuidado comum:</strong> Não deixar o <code>env.cmake</code> com credenciais sensíveis visíveis em repositórios públicos. Para isso, use <code>.gitignore</code>.</li>
</ul>



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



<h2 class="wp-block-heading"><strong>4. Inicialização do SDK e Definição do Executável</strong></h2>



<p class="wp-block-paragraph">Com todas as variáveis e configurações preparadas, o próximo passo é estruturar o projeto de forma que o SDK da Raspberry Pi Pico possa ser utilizado corretamente, e o firmware final seja construído como um <strong>executável nomeado</strong>. O trecho em destaque é 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" data-code="# Pull in Raspberry Pi Pico SDK (must be before project)
include(pico_sdk_import.cmake)

project(firmware_client_mqtt C CXX ASM)

# Initialise the Raspberry Pi Pico SDK
pico_sdk_init()
" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><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">Pull</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">in</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">Raspberry</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">Pi</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">Pico</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">SDK</span><span style="color: #D8DEE9FF"> (</span><span style="color: #D8DEE9">must</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">be</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">before</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">project</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #88C0D0">include</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">pico_sdk_import</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">cmake</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #88C0D0">project</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">firmware_client_mqtt</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">C</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">CXX</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">ASM</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF"># </span><span style="color: #D8DEE9">Initialise</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">the</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">Raspberry</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">Pi</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">Pico</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">SDK</span></span>
<span class="line"><span style="color: #88C0D0">pico_sdk_init</span><span style="color: #D8DEE9FF">()</span></span>
<span class="line"></span></code></pre></div>



<h3 class="wp-block-heading"><strong>Explicação Didática</strong></h3>



<ol class="wp-block-list">
<li><strong><code>include(pico_sdk_import.cmake)</code></strong><br>Este comando inclui o script <code>pico_sdk_import.cmake</code>, normalmente localizado na raiz do SDK da Raspberry Pi. Ele é responsável por <strong>carregar as bibliotecas, drivers e configurações internas</strong> que fazem parte do Pico SDK.<br>É essencial que esta linha venha <strong>antes do comando <code>project(...)</code></strong>, pois o SDK precisa estar carregado para que o CMake reconheça suas funções auxiliares como <code>pico_sdk_init()</code> ou <code>pico_enable_stdio_usb()</code>.</li>



<li><strong><code>project(firmware_client_mqtt C CXX ASM)</code></strong><br>Define oficialmente o nome do projeto, bem como os tipos de código que ele conterá:
<ul class="wp-block-list">
<li><code>C</code>: código C (linguagem base do projeto);</li>



<li><code>CXX</code>: suporte a C++, mesmo que opcional;</li>



<li><code>ASM</code>: suporte à linguagem Assembly, caso você deseje manipular diretamente registradores ou realizar otimizações de baixo nível.</li>
</ul>
</li>



<li><strong><code>pico_sdk_init()</code></strong><br>Esta função é uma <strong>macro do Pico SDK</strong> que realiza a configuração padrão do ambiente, ativando funcionalidades como drivers de hardware (<code>hardware_gpio</code>, <code>hardware_adc</code>, etc.), bibliotecas utilitárias e integração com o sistema de build.</li>
</ol>



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



<p class="wp-block-paragraph">Em seguida, o projeto define o binário principal:</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" data-code="add_executable(firmware_client_mqtt
    firmware_client_mqtt.c
)
" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><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">add_executable</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">firmware_client_mqtt</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">firmware_client_mqtt</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">c</span></span>
<span class="line"><span style="color: #D8DEE9FF">)</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">E depois configura nome e versão para fins de organização:</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" data-code="pico_set_program_name(firmware_client_mqtt &quot;firmware_client_mqtt&quot;)
pico_set_program_version(firmware_client_mqtt &quot;0.1&quot;)
" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><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">pico_set_program_name</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">firmware_client_mqtt</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">firmware_client_mqtt</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #88C0D0">pico_set_program_version</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">firmware_client_mqtt</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">0.1</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"></span></code></pre></div>



<h3 class="wp-block-heading"><strong>Explicação Didática</strong></h3>



<ol start="4" class="wp-block-list">
<li><strong><code>add_executable(...)</code></strong><br>Esta linha define o <strong>arquivo principal a ser compilado</strong>, neste caso, <code>firmware_client_mqtt.c</code>. O nome dado ao executável será usado como base para gerar o binário <code>.uf2</code> (formato de firmware usado pelo RP2040).<br>Também é possível incluir múltiplos arquivos <code>.c</code>, <code>.cpp</code> ou <code>.s</code> (Assembly) se o projeto for modularizado.</li>



<li><strong><code>pico_set_program_name</code> e <code>pico_set_program_version</code></strong><br>Estes comandos definem metadados do projeto, como nome e versão, que podem ser usados por ferramentas de depuração ou sistemas de versionamento. Embora opcionais, são úteis em ambientes colaborativos ou industriais.</li>
</ol>



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



<h3 class="wp-block-heading"><strong>Análise Crítica</strong></h3>



<ul class="wp-block-list">
<li>Esta seção está <strong>tecnicamente correta</strong> e bem estruturada, seguindo as recomendações do Pico SDK.</li>



<li>O uso explícito de <code>C</code>, <code>CXX</code> e <code>ASM</code> torna o projeto mais <strong>versátil</strong> e pronto para escalar em complexidade.</li>



<li>O nome do projeto (<code>firmware_client_mqtt</code>) é repetido em vários pontos. Poderia ser definido via uma variável (<code>set(PROJECT_NAME firmware_client_mqtt)</code>) para facilitar manutenção futura.</li>
</ul>



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



<h3 class="wp-block-heading"><strong>Observações Didáticas</strong></h3>



<ul class="wp-block-list">
<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f680.png" alt="🚀" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Analogia prática:</strong> Essa parte é como “ligar a tomada” do seu projeto. Você diz ao sistema: “meu projeto se chama X, usa essas linguagens, e quero usar as bibliotecas do SDK da Raspberry Pi”.</li>



<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4e6.png" alt="📦" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Dica extra:</strong> Ao compilar, o CMake vai gerar automaticamente arquivos <code>.elf</code>, <code>.bin</code> e <code>.uf2</code>, prontos para serem gravados na flash do RP2040.</li>



<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f5c3.png" alt="🗃" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Boas práticas:</strong> Sempre modularize seu código desde o começo. Mesmo que só tenha um arquivo <code>.c</code>, mantenha espaço para crescer (ex: <code>src/</code>, <code>include/</code>).</li>
</ul>



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



<h2 class="wp-block-heading"><strong>5. Ativando Entradas/Saídas e Ligando Bibliotecas Essenciais</strong></h2>



<p class="wp-block-paragraph">Depois de declarar o executável e configurar seu nome e versão, o projeto define como o firmware irá se comunicar com o mundo externo — por portas seriais ou USB — e quais bibliotecas devem ser incluídas na hora da linkagem. Veja o trecho:</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" data-code="pico_enable_stdio_uart(firmware_client_mqtt 0)
pico_enable_stdio_usb(firmware_client_mqtt 1)
" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><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">pico_enable_stdio_uart</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">firmware_client_mqtt</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #88C0D0">pico_enable_stdio_usb</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">firmware_client_mqtt</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">1</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"></span></code></pre></div>



<h3 class="wp-block-heading"><strong>Explicação Didática</strong></h3>



<ol class="wp-block-list">
<li><strong><code>pico_enable_stdio_uart(&lt;target> &lt;boolean>)</code></strong><br>Define se a <strong>UART (porta serial física)</strong> será usada como saída padrão (<code>stdout</code>) do programa. No exemplo acima, o valor <code>0</code> desativa a UART. Isso pode ser útil se o projeto não utilizar os pinos GPIO dedicados à UART, ou se estiver usando USB para comunicação com o PC.</li>



<li><strong><code>pico_enable_stdio_usb(&lt;target> &lt;boolean>)</code></strong><br>Ativa a comunicação serial via <strong>USB virtual (CDC)</strong>. Com <code>1</code>, o firmware pode imprimir mensagens no terminal conectado via cabo USB — muito útil para debug com ferramentas como <code>minicom</code>, <code>PuTTY</code>, <code>Thonny</code> ou o console do VSCode.</li>
</ol>



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



<p class="wp-block-paragraph">Em seguida, são declaradas as bibliotecas necessárias à aplicação:</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" data-code="target_link_libraries(firmware_client_mqtt
    pico_stdlib
    pico_cyw43_arch_lwip_threadsafe_background
    pico_lwip_mqtt
)
" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><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">target_link_libraries</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">firmware_client_mqtt</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">pico_stdlib</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">pico_cyw43_arch_lwip_threadsafe_background</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">pico_lwip_mqtt</span></span>
<span class="line"><span style="color: #D8DEE9FF">)</span></span>
<span class="line"></span></code></pre></div>



<h3 class="wp-block-heading"><strong>Explicação Didática</strong></h3>



<ol start="3" class="wp-block-list">
<li><strong><code>target_link_libraries(...)</code></strong><br>Essa linha especifica quais bibliotecas serão <strong>ligadas (linkadas)</strong> ao firmware durante a compilação.
<ul class="wp-block-list">
<li><code>pico_stdlib</code>: a <strong>biblioteca padrão</strong> do SDK, que fornece funções básicas como <code>printf</code>, controle de pinos, delays, etc.</li>



<li><code>pico_cyw43_arch_lwip_threadsafe_background</code>: fornece <strong>acesso ao chip Wi-Fi CYW43</strong> (usado no RP2040 W) em modo cooperativo com a pilha TCP/IP lwIP.</li>



<li><code>pico_lwip_mqtt</code>: adiciona suporte ao <strong>protocolo MQTT</strong> com base na biblioteca lwIP, permitindo que o firmware se comunique com brokers MQTT como o Mosquitto, HiveMQ, etc.</li>
</ul>
</li>
</ol>



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



<h3 class="wp-block-heading"><strong>Análise Crítica</strong></h3>



<ul class="wp-block-list">
<li>Desativar UART e ativar apenas USB (como neste projeto) é uma escolha moderna e prática, já que a maioria dos computadores não possui porta serial física.</li>



<li>O uso de <code>pico_lwip_mqtt</code> demonstra um foco em <strong>conectividade IoT</strong>. Esta biblioteca ainda é pouco documentada fora dos exemplos oficiais, então usar os exemplos do SDK como base é uma boa prática.</li>



<li>Poderia ser interessante encapsular as bibliotecas adicionais em uma função auxiliar (<code>add_custom_dependencies()</code>), principalmente em projetos maiores.</li>
</ul>



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



<h3 class="wp-block-heading"><strong>Observações Didáticas</strong></h3>



<ul class="wp-block-list">
<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f50c.png" alt="🔌" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Para iniciantes:</strong> Pense na UART e na USB como “canais de conversa” entre o RP2040 e o mundo externo. Você pode escolher usar um, ambos, ou nenhum.</li>



<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f9f0.png" alt="🧰" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Boas práticas:</strong> Se for usar UART, lembre-se de configurar os pinos no firmware (<code>gpio_set_function(...)</code>). Se usar USB, não esqueça que a comunicação começa <strong>após a USB ser enumerada pelo host</strong> — o que leva alguns milissegundos após reset.</li>



<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f310.png" alt="🌐" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Importante saber:</strong> A biblioteca <code>pico_cyw43_arch_lwip_threadsafe_background</code> executa tarefas de rede em segundo plano, sem precisar de um RTOS. Ideal para projetos simples mas que precisam de conectividade Wi-Fi confiável.</li>
</ul>



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



<h2 class="wp-block-heading"><strong>6. Inclusão de Diretórios e Definição de Macros de Conexão</strong></h2>



<p class="wp-block-paragraph">Com a estrutura principal pronta e as bibliotecas já ligadas, o projeto agora configura o acesso aos diretórios de cabeçalhos e exporta as variáveis de ambiente para uso direto no código C:</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" data-code="target_include_directories(firmware_client_mqtt PRIVATE ${CMAKE_CURRENT_LIST_DIR})
" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><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">target_include_directories</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">firmware_client_mqtt</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">PRIVATE</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">$</span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9">CMAKE_CURRENT_LIST_DIR</span><span style="color: #ECEFF4">}</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"></span></code></pre></div>



<h3 class="wp-block-heading"><strong>Explicação Didática</strong></h3>



<ol class="wp-block-list">
<li><strong><code>target_include_directories(...)</code></strong><br>Especifica para o compilador onde ele deve procurar os arquivos <code>.h</code> durante a compilação.
<ul class="wp-block-list">
<li><code>firmware_client_mqtt</code>: é o alvo (o executável).</li>



<li><code>PRIVATE</code>: significa que esses diretórios são usados <strong>apenas internamente</strong> para este alvo (e não propagados a outras dependências).</li>



<li><code>${CMAKE_CURRENT_LIST_DIR}</code>: refere-se ao diretório atual onde está o <code>CMakeLists.txt</code>. Isso permite que o <code>main.c</code> e outros arquivos no mesmo diretório acessem os headers locais diretamente.</li>
</ul>
</li>
</ol>



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



<p class="wp-block-paragraph">Agora, as variáveis de ambiente definidas anteriormente são “injetadas” no código-fonte como macros com <code>#define</code>, utilizando o comando:</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" data-code="target_compile_definitions(firmware_client_mqtt PRIVATE 
    WIFI_SSID=\&quot;${WIFI_SSID}\&quot; 
    WIFI_PASSWORD=\&quot;${WIFI_PASSWORD}\&quot; 
    MQTT_BROKER=\&quot;${MQTT_BROKER}\&quot; 
    MQTT_BASE_TOPIC=\&quot;${MQTT_BASE_TOPIC}\&quot;
    MQTT_RACK_NUMBER=\&quot;${MQTT_RACK_NUMBER}\&quot;
)
" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><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">target_compile_definitions</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">firmware_client_mqtt</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">PRIVATE</span><span style="color: #D8DEE9FF"> </span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">WIFI_SSID</span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF">\</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">${WIFI_SSID}</span><span style="color: #EBCB8B">\&quot;</span><span style="color: #D8DEE9"> </span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">WIFI_PASSWORD</span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF">\</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">${WIFI_PASSWORD}</span><span style="color: #EBCB8B">\&quot;</span><span style="color: #D8DEE9"> </span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">MQTT_BROKER</span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF">\</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">${MQTT_BROKER}</span><span style="color: #EBCB8B">\&quot;</span><span style="color: #D8DEE9"> </span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">MQTT_BASE_TOPIC</span><span style="color: #81A1C1">=</span><span style="color: #D8DEE9FF">\</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">${MQTT_BASE_TOPIC}</span><span style="color: #EBCB8B">\&quot;</span></span>
<span class="line"><span style="color: #A3BE8C">    MQTT_RACK_NUMBER=</span><span style="color: #EBCB8B">\&quot;</span><span style="color: #A3BE8C">${MQTT_RACK_NUMBER}</span><span style="color: #EBCB8B">\&quot;</span></span>
<span class="line"><span style="color: #D8DEE9">)</span></span>
<span class="line"></span></code></pre></div>



<h3 class="wp-block-heading"><strong>Explicação Didática</strong></h3>



<ol start="2" class="wp-block-list">
<li><strong><code>target_compile_definitions(...)</code></strong><br>Insere <strong>macros de pré-processador</strong> no projeto. Na prática, é como se o CMake escrevesse automaticamente estas linhas no seu código: <code>#define WIFI_SSID "ArvoreDosSaberes" #define WIFI_PASSWORD "Arduino2022" #define MQTT_BROKER "mqtt.rapport.tec.br" #define MQTT_BASE_TOPIC "rack_inteligente" #define MQTT_RACK_NUMBER "3"</code> Isso permite que o código-fonte seja <strong>genérico e portátil</strong>, pegando os dados do ambiente e não de strings fixas.</li>
</ol>



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



<h3 class="wp-block-heading"><strong>Análise Crítica</strong></h3>



<ul class="wp-block-list">
<li>O uso de <code>target_compile_definitions</code> é <strong>altamente recomendável</strong>, pois centraliza a configuração no CMake em vez de espalhar definições pelo código-fonte.</li>



<li>A sintaxe de escape com <code>\"...\"</code> garante que as strings sejam corretamente interpretadas como literais no código C. Uma falha comum de iniciantes é esquecer essas aspas.</li>



<li>Em projetos maiores, pode-se usar arquivos <code>.h</code> autogerados a partir do CMake para organizar essas definições (ex: <code>config.h.in</code> com <code>configure_file()</code>).</li>
</ul>



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



<h3 class="wp-block-heading"><strong>Observações Didáticas</strong></h3>



<ul class="wp-block-list">
<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f9e0.png" alt="🧠" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Para iniciantes:</strong> Pense que você está mandando um bilhete do CMake para o seu código C. Esse bilhete diz: “ei, aqui está o nome da sua rede Wi-Fi e os dados do MQTT”.</li>



<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/26a0.png" alt="⚠" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Erros comuns:</strong> Se você esquecer de escapar as aspas (<code>\"</code>), o compilador vai entender errado a definição e gerar erros como “expected identifier”.</li>



<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f6e1.png" alt="🛡" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Boas práticas:</strong> Nunca inclua senhas reais ou dados sensíveis diretamente no <code>main.c</code>. Use sempre esse método de parametrização, ou proteja via arquivos ignorados no Git.</li>
</ul>



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



<h2 class="wp-block-heading"><strong>7. Geração dos Arquivos de Saída: <code>pico_add_extra_outputs</code></strong></h2>



<p class="wp-block-paragraph">No final do arquivo, encontramos a seguinte linha:</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" data-code="pico_add_extra_outputs(firmware_client_mqtt)
" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><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">pico_add_extra_outputs</span><span style="color: #D8DEE9FF">(</span><span style="color: #D8DEE9">firmware_client_mqtt</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"></span></code></pre></div>



<h3 class="wp-block-heading"><strong>Explicação Didática</strong></h3>



<p class="wp-block-paragraph">Este comando é uma <strong>macro fornecida pelo Pico SDK</strong> que automatiza a criação de diferentes formatos de saída do firmware. A partir do executável gerado (<code>firmware_client_mqtt.elf</code>), ela cuida de produzir também:</p>



<ul class="wp-block-list">
<li><code>firmware_client_mqtt.bin</code>: imagem binária “crua”, usada em alguns programadores.</li>



<li><code>firmware_client_mqtt.uf2</code>: formato específico do RP2040, utilizado para arrastar e soltar o firmware diretamente na unidade USB visível quando o RP2040 está em modo de bootloader.</li>



<li>Arquivos <code>.map</code>, <code>.hex</code>, <code>.dis</code> ou <code>.lst</code> também podem ser gerados, dependendo das opções do CMake.</li>
</ul>



<p class="wp-block-paragraph">Tudo isso acontece de forma automática, dispensando a escrita manual de comandos extras.</p>



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



<h3 class="wp-block-heading"><strong>Análise Crítica</strong></h3>



<ul class="wp-block-list">
<li>O uso de <code>pico_add_extra_outputs</code> é <strong>obrigatório</strong> em projetos com RP2040 se você quiser gerar arquivos <code>.uf2</code>, que são os mais práticos para upload via USB.</li>



<li>Essa macro também <strong>facilita o debug</strong>, já que o <code>.elf</code> gerado pode ser carregado diretamente por ferramentas como GDB, OpenOCD ou o depurador do VSCode.</li>



<li>Poderia ser complementada com scripts de pós-build para, por exemplo, copiar o <code>.uf2</code> para um diretório específico ou ativar gravação automática via <code>picotool</code>.</li>
</ul>



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



<h3 class="wp-block-heading"><strong>Observações Didáticas</strong></h3>



<ul class="wp-block-list">
<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f9fe.png" alt="🧾" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Para iniciantes:</strong> Essa etapa é como pedir ao compilador: “não me dê só o resultado final, me dê também outras versões do programa — uma para o bootloader, outra para depurar, outra para backup”.</li>



<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4be.png" alt="💾" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Boas práticas:</strong> Após cada build, confira a pasta <code>build/</code> — os arquivos <code>.uf2</code>, <code>.elf</code> e <code>.bin</code> estarão lá. O <code>.uf2</code> é o que você deve <strong>arrastar e soltar</strong> no RP2040 quando ele estiver em modo boot (pressionando o botão BOOTSEL).</li>



<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f6a6.png" alt="🚦" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Dica de produtividade:</strong> Se você estiver usando VSCode com a extensão oficial, essa macro garante que o botão “Build” funcione corretamente e gere o <code>.uf2</code> automaticamente.</li>
</ul>



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



<h3 class="wp-block-heading"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Finalização da Análise Técnica</h3>



<p class="wp-block-paragraph">Com essa última linha, fechamos a análise completa e detalhada do arquivo <code>CMakeLists.txt</code>. Todas as etapas — desde configuração básica, carregamento do SDK, definição do executável, inclusão de bibliotecas, parâmetros de ambiente até a geração dos arquivos finais — foram explicadas com clareza e espírito didático.</p>



<p class="wp-block-paragraph">Perfeito! Vamos então à conclusão geral do artigo, amarrando todo o conteúdo de forma coesa e didática.</p>



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



<h2 class="wp-block-heading"><strong>Conclusão</strong></h2>



<p class="wp-block-paragraph">Ao longo deste artigo, percorremos — linha por linha — a estrutura de um <code>CMakeLists.txt</code> real utilizado em um projeto baseado no microcontrolador <strong>RP2040</strong>, com foco em conectividade Wi-Fi e MQTT. O objetivo foi mais do que explicar comandos: buscamos desenvolver no leitor a compreensão do <strong>porquê</strong> de cada configuração, tornando-o capaz de <strong>analisar, adaptar e evoluir seus próprios projetos</strong>.</p>



<p class="wp-block-paragraph">Iniciamos com a definição dos padrões de compilação e seguimos pela configuração do ambiente de desenvolvimento, mostrando como tornar o projeto compatível com ferramentas modernas como o VSCode. Depois, vimos como separar parâmetros de configuração em arquivos auxiliares (<code>env.cmake</code>) e como capturar variáveis de ambiente de forma segura e elegante. Em seguida, exploramos a inicialização do SDK, a declaração do executável, a ativação dos canais de comunicação via USB e UART, a ligação com bibliotecas críticas como <code>pico_lwip_mqtt</code>, e, por fim, a geração dos arquivos <code>.uf2</code> e <code>.elf</code> prontos para gravação.</p>



<p class="wp-block-paragraph">Além do conteúdo técnico, discutimos <strong>boas práticas</strong> como:</p>



<ul class="wp-block-list">
<li>Separar configuração do código-fonte com <code>env.cmake</code>;</li>



<li>Utilizar <code>target_compile_definitions</code> para injetar parâmetros no pré-processador;</li>



<li>Escapar corretamente strings definidas no CMake;</li>



<li>Manter o projeto modular e escalável com <code>target_include_directories</code> e <code>target_link_libraries</code>;</li>



<li>Evitar hardcoding de dados sensíveis e trabalhar com variáveis de ambiente.</li>
</ul>



<p class="wp-block-paragraph">Esse conhecimento é <strong>fundamental para qualquer desenvolvedor embarcado que deseje usar o RP2040 de forma profissional e segura</strong>. A compreensão profunda da infraestrutura de build é o que separa um programador iniciante de um desenvolvedor capaz de integrar sistemas complexos, automatizar tarefas, e resolver problemas de forma elegante.</p>



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



<h2 class="wp-block-heading"><strong>Próximos Passos</strong></h2>



<p class="wp-block-paragraph">Se você chegou até aqui, parabéns! Seu próximo passo pode ser:</p>



<ul class="wp-block-list">
<li>Explorar o conteúdo do arquivo <code>env.cmake</code> em detalhes;</li>



<li>Modularizar seu projeto criando subdiretórios como <code>src/</code> e <code>include/</code>;</li>



<li>Automatizar tarefas de pós-build, como upload via <code>picotool</code>;</li>



<li>Adicionar testes unitários usando CMocka ou Unity em conjunto com CMake;</li>



<li>Criar templates de projetos reutilizáveis com base nessa estrutura.</li>
</ul>



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



<h2 class="wp-block-heading"><strong>Indicações de Leitura Complementar</strong></h2>



<ul class="wp-block-list">
<li><a href="https://datasheets.raspberrypi.com/pico/raspberry-pi-pico-c-sdk.pdf">Documentação oficial do Pico SDK</a></li>



<li><a href="https://www.jetbrains.com/help/clion/quick-cmake-tutorial.html">Tutorial CMake da JetBrains</a></li>



<li><a href="https://interrupt.memfault.com/blog/firmware-build-systems">CMake para Embedded (platformIO-style)</a></li>
</ul>



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



<p class="wp-block-paragraph"></p><p>The post <a href="https://mcu.tec.br/linguagem/builds/como-estruturar-um-projeto-profissional-com-cmake-para-o-rp2040-guia-didatico-passo-a-passo/">Como Estruturar um Projeto Profissional com CMake para o RP2040: Guia Didático Passo a Passo</a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">635</post-id>	</item>
	</channel>
</rss>
