<?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>microcontrolador - MCU &amp; FPGA</title>
	<atom:link href="https://mcu.tec.br/tags/microcontrolador/feed/" rel="self" type="application/rss+xml" />
	<link>https://mcu.tec.br</link>
	<description>Microcontroladores &#38; FPGA</description>
	<lastBuildDate>Thu, 14 Aug 2025 18:41:34 +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>microcontrolador - MCU &amp; FPGA</title>
	<link>https://mcu.tec.br</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Placa Labrador Caninos Loucos: Desenvolvimento Python e IoT</title>
		<link>https://mcu.tec.br/sbc/placa-labrador-caninos-loucos-desenvolvimento-python-e-iot/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=placa-labrador-caninos-loucos-desenvolvimento-python-e-iot</link>
		
		<dc:creator><![CDATA[Carlos Delfino]]></dc:creator>
		<pubDate>Tue, 19 Aug 2025 18:21:51 +0000</pubDate>
				<category><![CDATA[SBC]]></category>
		<category><![CDATA[ARM Cortex-A7]]></category>
		<category><![CDATA[automação]]></category>
		<category><![CDATA[BLE]]></category>
		<category><![CDATA[Caninos Loucos]]></category>
		<category><![CDATA[caninos-sdk]]></category>
		<category><![CDATA[desenvolvimento Python]]></category>
		<category><![CDATA[gpiod]]></category>
		<category><![CDATA[GPIOs]]></category>
		<category><![CDATA[i2c]]></category>
		<category><![CDATA[IoT]]></category>
		<category><![CDATA[microcontrolador]]></category>
		<category><![CDATA[OpenCV]]></category>
		<category><![CDATA[placa Labrador]]></category>
		<category><![CDATA[robótica]]></category>
		<category><![CDATA[SPI]]></category>
		<category><![CDATA[UART]]></category>
		<guid isPermaLink="false">https://mcu.tec.br/?p=740</guid>

					<description><![CDATA[<p>Aprenda a programar a placa Labrador Caninos Loucos com Python para IoT, explorando GPIOs, comunicação e aplicações práticas</p>
<p>The post <a href="https://mcu.tec.br/sbc/placa-labrador-caninos-loucos-desenvolvimento-python-e-iot/">Placa Labrador Caninos Loucos: Desenvolvimento Python e IoT</a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></description>
										<content:encoded><![CDATA[<p class="wp-block-paragraph">A <strong>Labrador</strong>, desenvolvida pelo projeto <strong>Caninos Loucos</strong>, é um <strong>Single-Board Computer (SBC)</strong> nacional projetado para ser uma plataforma de alto desempenho, aberta e acessível, destinada a aplicações em <strong>IoT (Internet das Coisas)</strong>, automação, robótica e ensino de sistemas embarcados. Seu design compacto esconde um conjunto robusto de recursos, permitindo que tanto iniciantes quanto desenvolvedores experientes explorem ao máximo o potencial do hardware.</p>



<p class="wp-block-paragraph">No núcleo da Labrador encontra-se um <strong>processador ARM Cortex-A7</strong> de baixo consumo e alto desempenho, acompanhado de <strong>512 MB de RAM DDR3</strong> e armazenamento interno <strong>eMMC de 4 GB</strong>, expansível via cartão microSD. A placa oferece conectividade flexível com <strong>Ethernet</strong>, <strong>Wi-Fi</strong> e <strong>Bluetooth</strong>, além de portas <strong>USB</strong> para periféricos e interface HDMI para saída de vídeo.</p>



<p class="wp-block-paragraph">No quesito expansão, a Labrador traz um <strong>header de 40 pinos</strong> compatível com múltiplos protocolos, incluindo <strong>GPIOs</strong>, <strong>UART</strong>, <strong>I²C</strong>, <strong>SPI</strong>, <strong>PWM</strong> e entradas/saídas digitais, permitindo interação direta com sensores, atuadores e outros módulos. Ao todo, são <strong>40 pinos</strong>, dos quais 12 são dedicados à alimentação (8 GND, 2×3,3 V e 2×5 V) e os demais configuráveis para diferentes funções. Os GPIOs seguem um padrão de nomenclatura <strong>letra + número</strong> (ex.: C26), agrupados em blocos gerenciados por chips lógicos individuais (<code>gpiochip0</code>, <code>gpiochip1</code>, etc.), proporcionando flexibilidade e controle refinado.</p>



<p class="wp-block-paragraph">O <strong>Caninos Loucos</strong> é uma iniciativa colaborativa brasileira dedicada a criar soluções de hardware aberto adaptadas à realidade local. A Labrador reflete essa missão ao oferecer um ecossistema de hardware e software que facilita desde a instalação do sistema operacional até o desenvolvimento de projetos avançados, com suporte nativo a <strong>Python</strong> e bibliotecas como <strong>gpiod</strong> e <strong>caninos-sdk</strong>.</p>


<div class="wp-block-image">
<figure class="alignright size-full is-resized"><img fetchpriority="high" decoding="async" width="299" height="169" src="https://mcu.tec.br/wp-content/uploads/2025/08/caninos-loucos-mao-segurando.jpeg" alt="" class="wp-image-742" style="width:433px;height:auto"/></figure>
</div>


<p class="wp-block-paragraph">Este artigo irá explorar a placa Labrador em profundidade, abordando suas especificações técnicas, arquitetura de software e um exemplo prático de desenvolvimento em Python para controle de periféricos. Também serão apresentadas estratégias de otimização SEO para ampliar a visibilidade de projetos e tutoriais relacionados a esta plataforma.</p>



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



<h2 class="wp-block-heading">Arquitetura de Software da Labrador</h2>



<p class="wp-block-paragraph">A <strong>arquitetura de software da placa Labrador</strong> foi projetada para oferecer <strong>flexibilidade</strong>, <strong>facilidade de uso</strong> e <strong>compatibilidade com ferramentas modernas</strong> de desenvolvimento. Baseada em <strong>Linux Debian 11 customizado</strong>, a distribuição oficial da <strong>Caninos Loucos</strong> já vem preparada para o uso educacional e de prototipagem, reduzindo a curva de aprendizado para novos usuários e garantindo robustez para aplicações mais avançadas.</p>



<h3 class="wp-block-heading">Camada de Firmware</h3>



<p class="wp-block-paragraph">O firmware embarcado na Labrador é responsável pela inicialização do hardware, configuração de periféricos e carregamento do sistema operacional. Essa camada interage diretamente com os recursos do <strong>SoC ARM Cortex-A7</strong>, preparando o ambiente para que as bibliotecas de nível mais alto possam controlar <strong>GPIOs, interfaces seriais e módulos de comunicação</strong>.</p>



<h3 class="wp-block-heading">Sistema Operacional e Desenvolvimento</h3>



<p class="wp-block-paragraph">O sistema operacional oficial inclui suporte completo a <strong>Python 3</strong> e <strong>pip3</strong>, permitindo a instalação rápida de bibliotecas essenciais, como:</p>



<ul class="wp-block-list">
<li><strong>gpiod</strong> – Controle de GPIOs em dispositivos Linux com suporte a interfaces digitais genéricas.</li>



<li><strong>caninos-sdk</strong> – Biblioteca oficial da Caninos Loucos, simplificando o acesso aos recursos da Labrador.</li>



<li><strong>OpenCV</strong> – Processamento e análise de imagens em tempo real.</li>



<li><strong>pylibi2c</strong> – Comunicação via barramento I²C de forma simplificada.</li>
</ul>



<p class="wp-block-paragraph">A instalação dessas bibliotecas é feita diretamente no terminal, com comandos simples como:</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>sudo pip3 install gpiod caninos-sdk opencv-python
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9">sudo</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">pip3</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">install</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">gpiod</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">caninos</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9">sdk</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">opencv</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9">python</span></span>
<span class="line"></span></code></pre></div>



<h3 class="wp-block-heading">Protocolos de Comunicação</h3>



<p class="wp-block-paragraph">A Labrador oferece suporte nativo a protocolos amplamente utilizados em sistemas embarcados:</p>



<ul class="wp-block-list">
<li><strong>UART</strong> – Para comunicação serial assíncrona, útil em debug e troca de dados com microcontroladores externos.</li>



<li><strong>I²C</strong> – Para conectar múltiplos sensores e módulos usando apenas dois fios (SDA e SCL).</li>



<li><strong>SPI</strong> – Comunicação síncrona de alta velocidade com displays, memórias flash e outros periféricos.</li>



<li><strong>BLE (Bluetooth Low Energy)</strong> – Comunicação sem fio de baixo consumo, ideal para dispositivos móveis e IoT.</li>
</ul>



<h3 class="wp-block-heading">Estratégia de Controle de Energia</h3>



<p class="wp-block-paragraph">Embora projetada para funcionar continuamente, a Labrador adota práticas de economia de energia inspiradas em dispositivos móveis. O sistema operacional suporta modos de suspensão, desligamento de interfaces inativas e ajustes de frequência do processador conforme a carga de trabalho. Essa abordagem é essencial para projetos IoT alimentados por baterias ou fontes limitadas de energia.</p>



<p class="wp-block-paragraph">Com essa base de software, a Labrador está pronta para receber e executar aplicações de controle, automação e monitoramento, mantendo um equilíbrio entre <strong>desempenho</strong>, <strong>consumo de energia</strong> e <strong>facilidade de programação</strong>.</p>



<p class="wp-block-paragraph">Ótimo, vamos então para a <strong>Seção 4 – Desenvolvimento de um aplicativo Python para a Labrador</strong>.</p>



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



<h2 class="wp-block-heading">Desenvolvimento de um Aplicativo Python para a Labrador</h2>



<p class="wp-block-paragraph">Uma das principais vantagens da <strong>Labrador</strong> é seu suporte nativo a <strong>Python 3</strong>, o que permite o desenvolvimento rápido e direto de aplicações para controle de periféricos, leitura de sensores e integração com sistemas IoT. Nesta seção, vamos criar um exemplo prático que acende e apaga um LED conectado à placa, utilizando tanto a conexão local quanto a possibilidade de adaptação para controle via <strong>Bluetooth Low Energy (BLE)</strong>.</p>



<h3 class="wp-block-heading">Dependências e Ambiente</h3>



<p class="wp-block-paragraph">Antes de iniciar a programação, é necessário garantir que o <strong>Python 3</strong> e o <strong>pip3</strong> estejam atualizados e que as bibliotecas essenciais estejam instaladas:</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>sudo apt update &amp;&amp; sudo apt upgrade
sudo apt install python3 python3-pip
sudo pip3 install gpiod caninos-sdk
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9">sudo</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">apt</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">update</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&amp;&amp;</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">sudo</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">apt</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">upgrade</span></span>
<span class="line"><span style="color: #D8DEE9">sudo</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">apt</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">install</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">python3</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">python3</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9">pip</span></span>
<span class="line"><span style="color: #D8DEE9">sudo</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">pip3</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">install</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">gpiod</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">caninos</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9">sdk</span></span>
<span class="line"></span></code></pre></div>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph"><strong>Dica:</strong> Se a comunicação for via BLE, bibliotecas como <code>bleak</code> podem ser instaladas com <code>pip install bleak</code>.</p>
</blockquote>



<h3 class="wp-block-heading">Estrutura de Diretórios</h3>



<p class="wp-block-paragraph">Para manter a organização, recomenda-se criar um diretório de projeto com a seguinte estrutura:</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>projeto_labrador/
│
├── src/
│   ├── controle_led.py
│
├── assets/          # Imagens, documentação ou diagramas
└── README.md
</textarea></pre><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9">projeto_labrador</span><span style="color: #81A1C1">/</span></span>
<span class="line"><span style="color: #D8DEE9FF">│</span></span>
<span class="line"><span style="color: #D8DEE9FF">├── </span><span style="color: #D8DEE9">src</span><span style="color: #81A1C1">/</span></span>
<span class="line"><span style="color: #D8DEE9FF">│   ├── </span><span style="color: #D8DEE9">controle_led</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">py</span></span>
<span class="line"><span style="color: #D8DEE9FF">│</span></span>
<span class="line"><span style="color: #D8DEE9FF">├── </span><span style="color: #D8DEE9">assets</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9FF">          # </span><span style="color: #D8DEE9">Imagens</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">documentação</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">ou</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">diagramas</span></span>
<span class="line"><span style="color: #D8DEE9FF">└── </span><span style="color: #D8DEE9">README</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">md</span></span>
<span class="line"></span></code></pre></div>



<h3 class="wp-block-heading">Código Exemplo – Controle de LED via GPIO</h3>



<p class="wp-block-paragraph">A seguir, um exemplo completo que acende e apaga um LED conectado ao pino GPIO 17:</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>import gpiod
import time

# Configuração do chip GPIO
chip = gpiod.Chip('gpiochip0')

# Obtém controle sobre o pino 17
led_line = chip.get_line(17)
led_line.request(consumer='led', type=gpiod.LINE_REQ_DIR_OUT)

try:
    while True:
        led_line.set_value(1)  # Liga o LED
        time.sleep(1)
        led_line.set_value(0)  # Desliga o LED
        time.sleep(1)
except KeyboardInterrupt:
    print("\nEncerrando execução e liberando recursos...")
    chip.close()
</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: #81A1C1">import</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">gpiod</span></span>
<span class="line"><span style="color: #8FBCBB">import</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">time</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF"># </span><span style="color: #8FBCBB">Configuração</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">do</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">chip</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">GPIO</span></span>
<span class="line"><span style="color: #8FBCBB">chip</span><span style="color: #D8DEE9FF"> = </span><span style="color: #8FBCBB">gpiod</span><span style="color: #D8DEE9FF">.</span><span style="color: #8FBCBB">Chip</span><span style="color: #D8DEE9FF">(</span><span style="color: #ECEFF4">&#39;</span><span style="color: #A3BE8C">gpiochip0</span><span style="color: #ECEFF4">&#39;</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF"># </span><span style="color: #8FBCBB">Obtém</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">controle</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">sobre</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">o</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">pino</span><span style="color: #D8DEE9FF"> 17</span></span>
<span class="line"><span style="color: #8FBCBB">led_line</span><span style="color: #D8DEE9FF"> = </span><span style="color: #8FBCBB">chip</span><span style="color: #D8DEE9FF">.</span><span style="color: #8FBCBB">get_line</span><span style="color: #D8DEE9FF">(17)</span></span>
<span class="line"><span style="color: #8FBCBB">led_line</span><span style="color: #D8DEE9FF">.</span><span style="color: #8FBCBB">request</span><span style="color: #D8DEE9FF">(</span><span style="color: #8FBCBB">consumer</span><span style="color: #D8DEE9FF">=</span><span style="color: #ECEFF4">&#39;</span><span style="color: #A3BE8C">led</span><span style="color: #ECEFF4">&#39;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">type</span><span style="color: #D8DEE9FF">=</span><span style="color: #8FBCBB">gpiod</span><span style="color: #D8DEE9FF">.</span><span style="color: #8FBCBB">LINE_REQ_DIR_OUT</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #8FBCBB">try</span><span style="color: #D8DEE9FF">:</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #8FBCBB">while</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">True</span><span style="color: #D8DEE9FF">:</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #8FBCBB">led_line</span><span style="color: #D8DEE9FF">.</span><span style="color: #8FBCBB">set_value</span><span style="color: #D8DEE9FF">(1)  # </span><span style="color: #8FBCBB">Liga</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">o</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">LED</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #8FBCBB">time</span><span style="color: #D8DEE9FF">.</span><span style="color: #8FBCBB">sleep</span><span style="color: #D8DEE9FF">(1)</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #8FBCBB">led_line</span><span style="color: #D8DEE9FF">.</span><span style="color: #8FBCBB">set_value</span><span style="color: #D8DEE9FF">(0)  # </span><span style="color: #8FBCBB">Desliga</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">o</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">LED</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #8FBCBB">time</span><span style="color: #D8DEE9FF">.</span><span style="color: #8FBCBB">sleep</span><span style="color: #D8DEE9FF">(1)</span></span>
<span class="line"><span style="color: #8FBCBB">except</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">KeyboardInterrupt</span><span style="color: #D8DEE9FF">:</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #8FBCBB">print</span><span style="color: #D8DEE9FF">(</span><span style="color: #ECEFF4">&quot;</span><span style="color: #EBCB8B">\n</span><span style="color: #A3BE8C">Encerrando execução e liberando recursos...</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #8FBCBB">chip</span><span style="color: #D8DEE9FF">.</span><span style="color: #8FBCBB">close</span><span style="color: #D8DEE9FF">()</span></span>
<span class="line"></span></code></pre></div>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">Esse código acende e apaga o LED em intervalos de 1 segundo. Para adaptar para controle via <strong>BLE</strong>, basta criar uma função de callback que altere o valor do pino conforme os comandos recebidos pelo módulo Bluetooth.</p>
</blockquote>



<h3 class="wp-block-heading">Extensão para Controle via BLE</h3>



<p class="wp-block-paragraph">Com o módulo BLE da Labrador, é possível receber comandos de um aplicativo no celular. Um exemplo de integração seria criar um serviço BLE que, ao receber o valor <code>"on"</code>, acende o LED, e ao receber <code>"off"</code>, apaga. Isso amplia as possibilidades de automação e controle remoto, mantendo a simplicidade do Python.</p>



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



<p class="wp-block-paragraph"></p><p>The post <a href="https://mcu.tec.br/sbc/placa-labrador-caninos-loucos-desenvolvimento-python-e-iot/">Placa Labrador Caninos Loucos: Desenvolvimento Python e IoT</a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">740</post-id>	</item>
		<item>
		<title>Problemas de Deadlock e Starvation em Sistemas Embarcados: O caso dos Filósofos Glutões no FreeRTOS</title>
		<link>https://mcu.tec.br/rtos/problemas-de-deadlock-e-starvation-em-sistemas-embarcados-o-caso-dos-filosofos-glutoes-no-freertos/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=problemas-de-deadlock-e-starvation-em-sistemas-embarcados-o-caso-dos-filosofos-glutoes-no-freertos</link>
		
		<dc:creator><![CDATA[Carlos Delfino]]></dc:creator>
		<pubDate>Fri, 02 May 2025 14:00:00 +0000</pubDate>
				<category><![CDATA[RTOS]]></category>
		<category><![CDATA[concorrência]]></category>
		<category><![CDATA[deadlock]]></category>
		<category><![CDATA[escalonador]]></category>
		<category><![CDATA[filósofos glutões]]></category>
		<category><![CDATA[freertos]]></category>
		<category><![CDATA[herança de prioridade]]></category>
		<category><![CDATA[microcontrolador]]></category>
		<category><![CDATA[mutex]]></category>
		<category><![CDATA[padrões de projeto RTOS]]></category>
		<category><![CDATA[prioridade]]></category>
		<category><![CDATA[priority ceiling]]></category>
		<category><![CDATA[semáforo]]></category>
		<category><![CDATA[sincronização de tarefas]]></category>
		<category><![CDATA[sistemas embarcados]]></category>
		<category><![CDATA[starvation]]></category>
		<guid isPermaLink="false">https://mcu.tec.br/?p=475</guid>

					<description><![CDATA[<p>Aprenda a evitar deadlock e starvation em microcontroladores com FreeRTOS. Veja soluções práticas com mutexes e semáforos no clássico problema dos Filósofos.</p>
<p>The post <a href="https://mcu.tec.br/rtos/problemas-de-deadlock-e-starvation-em-sistemas-embarcados-o-caso-dos-filosofos-glutoes-no-freertos/">Problemas de Deadlock e Starvation em Sistemas Embarcados: O caso dos Filósofos Glutões no FreeRTOS</a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></description>
										<content:encoded><![CDATA[<p class="wp-block-paragraph">O gerenciamento de concorrência em sistemas embarcados de tempo real impõe desafios cruciais para a segurança, desempenho e previsibilidade do sistema. Problemas como <em>deadlock</em> (interbloqueio) e <em>starvation</em> (inanição) surgem quando múltiplas tarefas competem por recursos limitados, podendo comprometer deadlines e a confiabilidade do sistema. Neste artigo, exploramos esses problemas com foco em microcontroladores executando o FreeRTOS, ilustrando os conceitos através do clássico problema dos Filósofos Glutões. Apresentamos os padrões de projeto e estratégias de implementação sugeridas por Bruce Powel Douglass para evitar tais falhas, com exemplos práticos e didáticos.</p>



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



<h3 class="wp-block-heading"><strong>Problema a Ser Resolvido</strong></h3>



<p class="wp-block-paragraph">Sistemas embarcados frequentemente operam em ambientes com recursos escassos e múltiplas tarefas concorrentes, tornando a coordenação entre tarefas crítica para garantir a execução correta. <em>Deadlock</em> ocorre quando duas ou mais tarefas estão esperando indefinidamente por recursos que nunca serão liberados, devido a um ciclo de espera circular. Já a <em>starvation</em> ocorre quando uma tarefa de baixa prioridade é perpetuamente preterida, nunca tendo a chance de acessar os recursos que precisa.</p>



<p class="wp-block-paragraph">Esses problemas são agravados em sistemas de tempo real, pois atrasos não planejados podem resultar em falhas catastróficas. Em contextos como o FreeRTOS, que utiliza escalonamento por prioridade, essas questões se tornam ainda mais relevantes. Entender as condições que causam esses problemas e aplicar padrões de projeto adequados é fundamental para evitar falhas imprevisíveis.</p>



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



<h3 class="wp-block-heading"><strong>Estrutura do Padrão</strong></h3>



<p class="wp-block-paragraph">Um dos exemplos clássicos usados para ilustrar <em>deadlock</em> é o problema dos <strong>Filósofos Glutões</strong>. Nele, cinco filósofos sentam-se à mesa, cada um com um garfo à sua direita e esquerda, e precisam de ambos para comer. Se todos pegam um garfo e esperam o outro, ninguém come — ocorre um <em>deadlock</em>.</p>



<p class="wp-block-paragraph">No contexto do FreeRTOS, esse problema se manifesta quando tarefas compartilham múltiplos recursos (por exemplo, semáforos ou mutexes) e os bloqueiam em ordens diferentes. Bruce Douglass apresenta padrões como <em>Simultaneous Locking</em>, <em>Ordered Locking</em> e <em>Priority Ceiling</em> como soluções. Cada um quebra uma ou mais das quatro condições necessárias para o deadlock:</p>



<ol class="wp-block-list">
<li>Exclusão mútua;</li>



<li>Posse e espera (hold and wait);</li>



<li>Não-preempção;</li>



<li>Espera circularReal-Time Design Patter….</li>
</ol>



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



<h3 class="wp-block-heading"><strong>Papéis de Colaboração (Collaboration Roles)</strong></h3>



<ul class="wp-block-list">
<li><strong>Tarefas (Threads)</strong>: Agentes ativos que requerem acesso a recursos compartilhados.</li>



<li><strong>Scheduler (Escalonador)</strong>: Gerencia as prioridades das tarefas no FreeRTOS.</li>



<li><strong>Mutex/Semáforos</strong>: Controlam o acesso a recursos não-reentrantes.</li>



<li><strong>Shared Resource</strong>: Qualquer dado ou periférico que precise ser protegido.</li>



<li><strong>Task Control Block (TCB)</strong>: Armazena estado, prioridade e contexto de cada tarefa.</li>
</ul>



<h3 class="wp-block-heading"><strong>Consequências</strong></h3>



<p class="wp-block-paragraph">O impacto da ocorrência de <em>deadlock</em> e <em>starvation</em> em sistemas embarcados pode ser catastrófico. Quando tarefas ficam permanentemente bloqueadas, recursos permanecem indisponíveis e o sistema pode parar completamente ou deixar de responder dentro do prazo esperado — o que, em aplicações críticas, como controle industrial ou dispositivos médicos, pode gerar danos materiais ou colocar vidas em risco.</p>



<p class="wp-block-paragraph">No caso do <em>deadlock</em>, a principal consequência é a <strong>paralisação do sistema</strong>, mesmo com o processador ativo. O scheduler do FreeRTOS pode continuar operando, mas as tarefas envolvidas no ciclo de espera nunca prosseguem. Já na <em>starvation</em>, embora o sistema permaneça funcional, uma ou mais tarefas de baixa prioridade <strong>jamais obtêm acesso aos recursos</strong>, resultando em degradação progressiva do desempenho ou falhas intermitentes difíceis de diagnosticar.</p>



<p class="wp-block-paragraph">Outra consequência importante é a dificuldade de <strong>debug e validação de sistemas embarcados</strong> com problemas intermitentes de bloqueio. Tais problemas não são facilmente reproduzíveis, pois dependem da ordem de execução das tarefas, que pode variar conforme as condições de tempo real.</p>



<p class="wp-block-paragraph">Além disso, <em>starvation</em> é frequentemente associada à <strong>inversão de prioridade</strong>, onde uma tarefa de alta prioridade fica bloqueada esperando uma de baixa prioridade liberar um recurso. Isso pode ser agravado em sistemas com escalonamento por prioridade fixa, como o FreeRTOS, a menos que sejam adotados mecanismos como o <strong>herdamento de prioridade (priority inheritance)</strong> ou <strong>teto de prioridade (priority ceiling)</strong>.</p>



<p class="wp-block-paragraph">Portanto, as consequências não são apenas técnicas — elas impactam diretamente os critérios de qualidade e confiabilidade do projeto.</p>



<h3 class="wp-block-heading"><strong>Estratégias de Implementação</strong></h3>



<p class="wp-block-paragraph">Prevenir <em>deadlocks</em> e <em>starvation</em> exige disciplina na coordenação do acesso a recursos e a aplicação de padrões de projeto consolidados. No contexto do FreeRTOS, onde tarefas operam em diferentes níveis de prioridade e disputam semáforos, mutexes ou filas, a implementação correta dos mecanismos de sincronização é essencial.</p>



<h4 class="wp-block-heading"><strong>1. Evitando Deadlock com Ordenação de Locks</strong></h4>



<p class="wp-block-paragraph">A estratégia mais direta para evitar <em>deadlocks</em> é <strong>padronizar a ordem de aquisição de recursos</strong>. Se todas as tarefas adquirirem os recursos sempre na mesma ordem (por exemplo, do recurso A para o B), a condição de espera circular é evitada. Este padrão é conhecido como <strong>Ordered Locking Pattern</strong>, amplamente discutido por Douglass em Real-Time Design Patter.</p>



<pre class="wp-block-preformatted"><code>// Exemplo de ordenação de mutexes no FreeRTOS<br>void Task1(void *pvParameters) {<br>    for (;;) {<br>        xSemaphoreTake(mutexA, portMAX_DELAY);<br>        xSemaphoreTake(mutexB, portMAX_DELAY);<br><br>        // Região crítica usando os dois recursos<br><br>        xSemaphoreGive(mutexB);<br>        xSemaphoreGive(mutexA);<br>    }<br>}<br></code></pre>



<p class="wp-block-paragraph">Todas as tarefas devem respeitar a mesma ordem <code>A -&gt; B</code> ao adquirir múltiplos recursos.</p>



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



<h4 class="wp-block-heading"><strong>2. Evitando Starvation com Herdamento de Prioridade</strong></h4>



<p class="wp-block-paragraph">Quando uma tarefa de alta prioridade espera por um mutex que está com uma tarefa de baixa prioridade, pode haver <em>starvation</em> por inversão de prioridade. O FreeRTOS possui <strong>mutexes com herança de prioridade</strong> (<code>xSemaphoreCreateMutex</code>) justamente para mitigar esse problema.</p>



<pre class="wp-block-preformatted"><code>SemaphoreHandle_t xMutex;<br><br>void vSetup() {<br>    xMutex = xSemaphoreCreateMutex(); // já inclui herança de prioridade<br>}<br></code></pre>



<p class="wp-block-paragraph">Neste mecanismo, a tarefa de baixa prioridade “empresta” sua prioridade para igualar à da tarefa que está bloqueada, impedindo que tarefas intermediárias a impeçam de prosseguir e liberar o recurso.</p>



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



<h4 class="wp-block-heading"><strong>3. Timeout e Deadlock Detectável</strong></h4>



<p class="wp-block-paragraph">Adicionar timeouts ao uso de mutexes pode ajudar a identificar cenários de <em>deadlock</em> em tempo de execução. Embora não evite o problema, permite detectar que algo saiu do esperado.</p>



<pre class="wp-block-preformatted"><code>if (xSemaphoreTake(mutexA, pdMS_TO_TICKS(100)) == pdFALSE) {<br>    // Erro: recurso não obtido — possível deadlock<br>    vHandleDeadlockError();<br>}<br></code></pre>



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



<h4 class="wp-block-heading"><strong>4. Solução Filósofos Glutões com Recurso Central</strong></h4>



<p class="wp-block-paragraph">Um exemplo clássico é substituir os mutexes laterais por um <strong>recurso central</strong> ou um semáforo de contagem (counting semaphore), limitando o número máximo de filósofos que podem pegar os garfos ao mesmo tempo.</p>



<pre class="wp-block-preformatted">SemaphoreHandle_t semGarfos;<br><br>void vInit() {<br>    semGarfos = xSemaphoreCreateCounting(4, 4); // 5 filósofos, 4 permissões<br>}<br><br>void Filosofo(void *pvParameters) {<br>    for (;;) {<br>        pensar();<br><br>        xSemaphoreTake(semGarfos, portMAX_DELAY);<br>        xSemaphoreTake(garfoEsquerda, portMAX_DELAY);<br>        xSemaphoreTake(garfoDireita, portMAX_DELAY);<br><br>        comer();<br><br>        xSemaphoreGive(garfoDireita);<br>        xSemaphoreGive(garfoEsquerda);<br>        xSemaphoreGive(semGarfos);<br>    }<br>}<br></pre>



<p class="wp-block-paragraph">Esse padrão evita <em>deadlock</em> ao garantir que no máximo 4 filósofos estejam tentando pegar dois garfos, sempre sobrando ao menos um.</p>



<h3 class="wp-block-heading"><strong>Padrões Relacionados</strong></h3>



<p class="wp-block-paragraph">A prevenção eficaz de <em>deadlocks</em> e <em>starvation</em> não depende apenas da ordem ou da prioridade, mas também do uso inteligente de padrões complementares que podem ser combinados para diferentes necessidades de sincronização. Bruce Powel Douglass apresenta um conjunto de padrões especialmente aplicáveis a sistemas de tempo real como os que usam o FreeRTOS:</p>



<h4 class="wp-block-heading"><strong>1. Guarded Call Pattern</strong></h4>



<p class="wp-block-paragraph">Esse padrão garante que a chamada a um recurso protegido só ocorra quando sua condição estiver satisfeita, evitando bloqueios desnecessários. Ele frequentemente usa sinais (flags ou semáforos binários) para proteger regiões críticas, reduzindo a chance de deadlocks ao evitar bloqueios longos.</p>



<pre class="wp-block-preformatted"><code>if (xSemaphoreTake(xRecurso, 0) == pdTRUE) {<br>    acessarRecurso();<br>    xSemaphoreGive(xRecurso);<br>} else {<br>    // Recurso indisponível, decide-se agir de outra forma<br>}<br></code></pre>



<h4 class="wp-block-heading"><strong>2. Simultaneous Locking Pattern</strong></h4>



<p class="wp-block-paragraph">Este padrão representa um cenário onde múltiplos recursos são adquiridos simultaneamente — situação comum no problema dos Filósofos Glutões. A solução consiste em sempre adquirir todos os recursos de uma vez (por exemplo, usando semáforo de contagem ou buffers predefinidos), ou falhar imediatamente caso isso não seja possível, evitando a espera bloqueante.</p>



<pre class="wp-block-preformatted"><code>bool lock_all() {<br>    if (xSemaphoreTake(mutexA, 0) == pdTRUE) {<br>        if (xSemaphoreTake(mutexB, 0) == pdTRUE) {<br>            return true;<br>        } else {<br>            xSemaphoreGive(mutexA);<br>        }<br>    }<br>    return false;<br>}<br></code></pre>



<h4 class="wp-block-heading"><strong>3. Priority Ceiling Pattern</strong></h4>



<p class="wp-block-paragraph">Muito eficaz contra <em>inversão de prioridade</em>, esse padrão eleva a prioridade de uma tarefa sempre que ela adquire um recurso compartilhado, ao nível da mais alta prioridade possível que pode usar o recurso. Essa estratégia exige mais controle, mas evita inversões e starvation sem necessidade de herança dinâmica de prioridade.</p>



<p class="wp-block-paragraph">O FreeRTOS não implementa esse padrão nativamente, mas ele pode ser simulado ajustando temporariamente a prioridade da tarefa:</p>



<pre class="wp-block-preformatted"><code>void accessResource() {<br>    UBaseType_t oldPrio = uxTaskPriorityGet(NULL);<br>    vTaskPrioritySet(NULL, PRIORITY_CEILING);<br><br>    usarRecursoCompartilhado();<br><br>    vTaskPrioritySet(NULL, oldPrio);<br>}<br></code></pre>



<h4 class="wp-block-heading"><strong>4. Static Priority Pattern</strong></h4>



<p class="wp-block-paragraph">Este padrão, também documentado por DouglassReal-Time Design Patter…, recomenda que os níveis de prioridade sejam cuidadosamente atribuídos e fixos durante a operação. Isso facilita a verificação de <em>schedulability</em> e evita condições dinâmicas imprevisíveis que podem agravar a starvation.</p>



<h3 class="wp-block-heading"><strong>Modelo de Amostragem: O Problema dos Filósofos Glutões com FreeRTOS</strong></h3>



<p class="wp-block-paragraph">Vamos aplicar os conceitos discutidos em um exemplo prático no FreeRTOS: uma simulação do problema dos <strong>Filósofos Glutões</strong>, ilustrando tanto o problema quanto a solução com semáforo de contagem — uma estratégia segura para evitar <em>deadlock</em>.</p>



<h4 class="wp-block-heading"><strong>Configuração</strong></h4>



<ul class="wp-block-list">
<li><strong>5 tarefas</strong> representando os filósofos.</li>



<li>Cada filósofo precisa pegar dois garfos (mutexes) para comer.</li>



<li>Usa-se um <strong>Counting Semaphore com valor 4</strong>, limitando o número de filósofos com permissão para tentar pegar os garfos ao mesmo tempo.</li>



<li>Cada garfo é um mutex (representando um recurso compartilhado).</li>
</ul>



<pre class="wp-block-preformatted"><code>#include "FreeRTOS.h"<br>#include "task.h"<br>#include "semphr.h"<br><br>#define NUM_FILOSOFOS 5<br><br>SemaphoreHandle_t garfos[NUM_FILOSOFOS];<br>SemaphoreHandle_t semPermissao;<br><br>void pensar(int id) {<br>    printf("Filósofo %d está pensando...\n", id);<br>    vTaskDelay(pdMS_TO_TICKS(500 + id * 100));<br>}<br><br>void comer(int id) {<br>    printf("Filósofo %d está comendo!\n", id);<br>    vTaskDelay(pdMS_TO_TICKS(300));<br>}<br><br>void Filosofo(void *pvParameters) {<br>    int id = (int) pvParameters;<br>    int garfoEsquerda = id;<br>    int garfoDireita = (id + 1) % NUM_FILOSOFOS;<br><br>    for (;;) {<br>        pensar(id);<br><br>        // Espera por permissão para tentar pegar os dois garfos<br>        xSemaphoreTake(semPermissao, portMAX_DELAY);<br><br>        // Pega garfos (ordem fixa: esquerda depois direita)<br>        xSemaphoreTake(garfos[garfoEsquerda], portMAX_DELAY);<br>        xSemaphoreTake(garfos[garfoDireita], portMAX_DELAY);<br><br>        comer(id);<br><br>        // Libera garfos<br>        xSemaphoreGive(garfos[garfoDireita]);<br>        xSemaphoreGive(garfos[garfoEsquerda]);<br><br>        // Libera permissão<br>        xSemaphoreGive(semPermissao);<br>    }<br>}<br><br>void main_app() {<br>    semPermissao = xSemaphoreCreateCounting(NUM_FILOSOFOS - 1, NUM_FILOSOFOS - 1);<br><br>    for (int i = 0; i &lt; NUM_FILOSOFOS; i++) {<br>        garfos[i] = xSemaphoreCreateMutex();<br>    }<br><br>    for (int i = 0; i &lt; NUM_FILOSOFOS; i++) {<br>        char nome[16];<br>        sprintf(nome, "Filosofo%d", i);<br>        xTaskCreate(Filosofo, nome, configMINIMAL_STACK_SIZE, (void *)i, 1, NULL);<br>    }<br><br>    vTaskStartScheduler();<br>}<br></code></pre>



<h4 class="wp-block-heading"><strong>Resultado</strong></h4>



<p class="wp-block-paragraph">Neste modelo, <strong>evitamos o deadlock</strong> limitando o número de filósofos que podem competir por garfos a quatro. Assim, sempre haverá ao menos um garfo disponível, quebrando a condição de espera circular. Ao mesmo tempo, garantimos <em>fairness</em> entre tarefas com prioridade igual, evitando <em>starvation</em> em função da ordem de execução.</p>



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



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



<p class="wp-block-paragraph">Ao trazer os clássicos problemas da ciência da computação como o dos Filósofos Glutões para o contexto de sistemas embarcados com FreeRTOS, reforçamos a importância de padrões de projeto adequados para lidar com concorrência. Evitar <em>deadlock</em> e <em>starvation</em> é essencial para garantir sistemas previsíveis, seguros e eficientes. Estratégias como ordenação de locks, uso de semáforos de contagem, herança de prioridade e padrões como <em>Guarded Call</em> e <em>Priority Ceiling</em> devem fazer parte do repertório de todo engenheiro de firmware.</p><p>The post <a href="https://mcu.tec.br/rtos/problemas-de-deadlock-e-starvation-em-sistemas-embarcados-o-caso-dos-filosofos-glutoes-no-freertos/">Problemas de Deadlock e Starvation em Sistemas Embarcados: O caso dos Filósofos Glutões no FreeRTOS</a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">475</post-id>	</item>
		<item>
		<title>Algoritmos de Controle de Loop Fechado: Guia Completo com PID e Exemplos em C</title>
		<link>https://mcu.tec.br/algoritimos/algoritmos-de-controle-de-loop-fechado-guia-completo-com-pid-e-exemplos-em-c/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=algoritmos-de-controle-de-loop-fechado-guia-completo-com-pid-e-exemplos-em-c</link>
		
		<dc:creator><![CDATA[Carlos Delfino]]></dc:creator>
		<pubDate>Fri, 21 Mar 2025 15:10:44 +0000</pubDate>
				<category><![CDATA[Algoritimos]]></category>
		<category><![CDATA[algoritmo PID em C]]></category>
		<category><![CDATA[controlador PID]]></category>
		<category><![CDATA[controle adaptativo]]></category>
		<category><![CDATA[controle automático]]></category>
		<category><![CDATA[controle Bang-Bang]]></category>
		<category><![CDATA[controle de loop fechado]]></category>
		<category><![CDATA[controle de motor]]></category>
		<category><![CDATA[controle de posição]]></category>
		<category><![CDATA[controle de temperatura]]></category>
		<category><![CDATA[controle de velocidade]]></category>
		<category><![CDATA[controle embarcado]]></category>
		<category><![CDATA[controle H-infinito]]></category>
		<category><![CDATA[controle LQR]]></category>
		<category><![CDATA[controle PD]]></category>
		<category><![CDATA[controle PI]]></category>
		<category><![CDATA[engenharia de controle]]></category>
		<category><![CDATA[exemplo de PID em C]]></category>
		<category><![CDATA[microcontrolador]]></category>
		<category><![CDATA[sistemas de controle digital]]></category>
		<guid isPermaLink="false">https://mcu.tec.br/?p=202</guid>

					<description><![CDATA[<p>Aprenda tudo sobre algoritmos de controle de loop fechado, incluindo PID, PI, PD, Bang-Bang, LQR e H∞. Veja explicações detalhadas, fórmulas matemáticas e exemplos práticos em linguagem C para microcontroladores.</p>
<p>The post <a href="https://mcu.tec.br/algoritimos/algoritmos-de-controle-de-loop-fechado-guia-completo-com-pid-e-exemplos-em-c/">Algoritmos de Controle de Loop Fechado: Guia Completo com PID e Exemplos em C</a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></description>
										<content:encoded><![CDATA[<p class="wp-block-paragraph">Os algoritmos de controle de loop fechado são fundamentais na engenharia de sistemas embarcados, automação industrial e em diversas aplicações onde a estabilidade e o desempenho do sistema precisam ser mantidos diante de variações internas ou externas. Diferentemente dos sistemas de controle de malha aberta, que agem de forma predefinida sem considerar a resposta real do sistema, os sistemas de malha fechada utilizam informações em tempo real de sensores para ajustar continuamente o comportamento do atuador. Este artigo explora os principais tipos de algoritmos de controle de loop fechado, com ênfase nos controladores PID (Proporcional-Integral-Derivativo) e suas variantes. Também serão discutidos controladores como PD, PI, Bang-Bang, controle por modelo (MPC) e controle adaptativo. Para cada tipo, serão apresentadas suas características, equações matemáticas, vantagens, desvantagens, estratégias de implementação e exemplos práticos em linguagem C.</p>



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



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



<h2 class="wp-block-heading">2. Problema a Ser Resolvido</h2>



<p class="wp-block-paragraph">Em sistemas de controle, o objetivo fundamental é garantir que uma determinada variável de interesse (como temperatura, velocidade, posição ou corrente) siga um valor desejado, chamado de referência ou setpoint, mesmo na presença de perturbações e incertezas do ambiente. Em aplicações embarcadas, industriais ou robóticas, por exemplo, controlar com precisão e estabilidade a velocidade de um motor, a posição de um atuador linear ou a pressão em um sistema hidráulico é uma exigência recorrente.</p>



<p class="wp-block-paragraph">O desafio é que muitos sistemas físicos apresentam comportamentos dinâmicos complexos, como atraso de resposta, não linearidades, ruídos de medição ou variações imprevisíveis em sua carga. Além disso, o próprio modelo matemático que descreve o sistema nem sempre é conhecido com exatidão. Esses fatores dificultam a obtenção de um controle confiável apenas por meio de métodos de malha aberta, que operam sem considerar o resultado real das ações de controle. Tais métodos não são capazes de compensar desvios causados por interferências externas ou mudanças na planta controlada.</p>



<p class="wp-block-paragraph">Diante disso, os algoritmos de controle de loop fechado surgem como solução indispensável. Eles utilizam um sensor para medir a saída do sistema, comparam essa medida com o valor de referência e geram automaticamente um sinal de erro. Com base nesse erro, o algoritmo calcula uma nova ação de controle, ajustando dinamicamente o sistema em tempo real. Esse mecanismo de retroalimentação (ou realimentação) é o coração dos sistemas de malha fechada, permitindo que o sistema reaja a distúrbios, compense desvios e mantenha a estabilidade desejada.</p>



<p class="wp-block-paragraph">O problema, portanto, consiste em projetar algoritmos capazes de realizar essa regulação automática de forma eficiente, estável e robusta, mesmo em contextos com recursos computacionais limitados, como nos microcontroladores embarcados. O tipo de controlador ideal dependerá das características do sistema controlado, dos requisitos de desempenho e das limitações práticas do hardware.</p>


<div class="wp-block-image">
<figure class="aligncenter size-full"><img decoding="async" width="700" height="291" src="https://mcu.tec.br/wp-content/uploads/2025/03/image-12.png" alt="" class="wp-image-230" srcset="https://mcu.tec.br/wp-content/uploads/2025/03/image-12.png 700w, https://mcu.tec.br/wp-content/uploads/2025/03/image-12-300x125.png 300w" sizes="(max-width: 700px) 100vw, 700px" /></figure>
</div>


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



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



<h2 class="wp-block-heading">3. Estrutura Geral dos Algoritmos de Controle de Loop Fechado</h2>



<p class="wp-block-paragraph">A estrutura típica de um sistema de controle de loop fechado baseia-se na interação entre três elementos principais: o sensor, o controlador e o atuador, todos conectados em um ciclo contínuo de realimentação. Esse arranjo pode ser descrito pela seguinte sequência funcional:</p>



<ol class="wp-block-list">
<li><strong>Leitura da variável de processo (PV – Process Variable):</strong> um sensor coleta, em tempo real, o valor atual da variável a ser controlada, como a temperatura de um forno ou a velocidade de um motor.</li>



<li><strong>Cálculo do erro:</strong> o controlador recebe o valor atual e o compara com o valor desejado (setpoint ou referência), calculando a diferença entre ambos: \(e(t) = r(t) &#8211; y(t)\) onde:
<ul class="wp-block-list">
<li>e(t) é o erro no instante t,</li>



<li>r(t) é o valor de referência (setpoint),</li>



<li>y(t) é a saída medida do sistema.</li>
</ul>
</li>



<li><strong>Ação de controle:</strong> com base nesse erro, o algoritmo determina o sinal de controle \(u(t)\) a ser aplicado no atuador. A forma como esse cálculo é feito depende do tipo de controlador (PID, Bang-Bang, adaptativo, etc.).</li>



<li><strong>Atualização do sistema:</strong> o atuador aplica o sinal de controle no processo, modificando a variável de interesse. O ciclo se repete periodicamente.</li>
</ol>



<p class="wp-block-paragraph">Essa estrutura é resumida no chamado <strong>diagrama de blocos de controle</strong>, com um laço de realimentação (feedback) que retroalimenta o sistema com a resposta obtida para recalcular o erro continuamente. Em sistemas digitais (como microcontroladores), esse ciclo é discretizado em passos regulares de tempo \(T_s\) (período de amostragem), onde o controle é reavaliado a cada iteração.</p>



<p class="wp-block-paragraph">A implementação computacional desse ciclo envolve uma rotina que é executada em loop infinito ou em um temporizador periódico (timer), garantindo que o sistema responda em tempo real às alterações da planta.</p>



<p class="wp-block-paragraph">A seguir, um esboço simplificado em C para ilustrar a estrutura de controle de malha fechada:</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="#define SAMPLE_TIME_MS 10  // tempo de amostragem em milissegundos

float setpoint = 100.0;    // valor desejado
float process_variable = 0.0;  // valor medido do sensor
float error = 0.0;         // erro entre setpoint e medição
float control_signal = 0.0;  // valor de saída para o atuador

void control_loop(void) {
    process_variable = read_sensor();          // Leitura da PV
    error = setpoint - process_variable;       // Cálculo do erro
    control_signal = compute_control(error);   // Função de controle (PID, etc.)
    write_actuator(control_signal);            // Aplicação no sistema
}
" 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: #616E88">#define SAMPLE_TIME_MS 10  // tempo de amostragem em milissegundos</span></span>
<span class="line"></span>
<span class="line"><span style="color: #88C0D0">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">setpoint</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">100.0</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">//</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">valor</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">desejado</span></span>
<span class="line"><span style="color: #88C0D0">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">process_variable</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0.0</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF">  </span><span style="color: #88C0D0">//</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">valor</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">medido</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">do</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">sensor</span></span>
<span class="line"><span style="color: #88C0D0">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">error</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0.0</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF">         </span><span style="color: #88C0D0">//</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">erro</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">entre</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">setpoint</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">e</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">medição</span></span>
<span class="line"><span style="color: #88C0D0">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">control_signal</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0.0</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF">  </span><span style="color: #88C0D0">//</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">valor</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">de</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">saída</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">para</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">o</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">atuador</span></span>
<span class="line"></span>
<span class="line"><span style="color: #88C0D0">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">control_loop</span><span style="color: #ECEFF4">(</span><span style="color: #88C0D0">void</span><span style="color: #ECEFF4">)</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">process_variable</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">read_sensor</span><span style="color: #ECEFF4">()</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF">          </span><span style="color: #88C0D0">//</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Leitura</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">da</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">PV</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">error</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">setpoint</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">process_variable</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF">       </span><span style="color: #88C0D0">//</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Cálculo</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">do</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">erro</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">control_signal</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">compute_control</span><span style="color: #ECEFF4">(</span><span style="color: #88C0D0">error</span><span style="color: #ECEFF4">)</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF">   </span><span style="color: #88C0D0">//</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Função</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">de</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">controle</span><span style="color: #D8DEE9FF"> (PID, </span><span style="color: #A3BE8C">etc.</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">write_actuator(control_signal</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF">            </span><span style="color: #88C0D0">//</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Aplicação</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">no</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">sistema</span></span>
<span class="line"><span style="color: #D8DEE9FF">}</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">Essa função <code>control_loop()</code> seria chamada periodicamente por um timer, por exemplo a cada 10 ms, mantendo o sistema sob controle constante.</p>



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



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



<h2 class="wp-block-heading">4. Tipos de Algoritmos de Controle de Loop Fechado</h2>



<p class="wp-block-paragraph">Os algoritmos de controle de loop fechado podem assumir diferentes formas, dependendo da natureza da planta, dos requisitos de desempenho e da capacidade de processamento disponível. A seguir, exploramos os tipos mais comuns, destacando suas características fundamentais, equações matemáticas e formas de implementação.</p>



<h3 class="wp-block-heading">4.1 Controlador Proporcional (P)</h3>



<p class="wp-block-paragraph">O controlador proporcional é o mais simples entre os algoritmos clássicos. Ele ajusta o sinal de controle de forma proporcional ao erro presente:</p>



<p class="wp-block-paragraph">\[<br>u(t) = K_p \cdot e(t)<br>\]



<ul class="wp-block-list">
<li>u(t): sinal de controle;</li>



<li>\(K_p\): ganho proporcional;</li>



<li>e(t): erro entre o setpoint e a variável de processo.</li>
</ul>



<p class="wp-block-paragraph">Esse controlador atua de forma rápida, mas nunca zera completamente o erro em sistemas com dinâmica estável. Ele é frequentemente usado quando alguma margem de erro é aceitável ou em combinação com outros termos.</p>



<p class="wp-block-paragraph"><strong>Exemplo em C:</strong></p>



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

float compute_control(float error) {
    return Kp * error;
}
" 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">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Kp</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">2.0</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #88C0D0">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">compute_control</span><span style="color: #ECEFF4">(</span><span style="color: #88C0D0">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">error</span><span style="color: #ECEFF4">)</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">return</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Kp</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">error</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">}</span></span>
<span class="line"></span></code></pre></div>



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



<h3 class="wp-block-heading">4.2 Controlador Proporcional-Integral (PI)</h3>



<p class="wp-block-paragraph">O PI é uma evolução do P e busca eliminar o erro em regime permanente. O termo integral acumula o erro ao longo do tempo: \(u(t) = K_p \cdot e(t) + K_i \cdot \int_0^t e(\tau)\,d\tau\)</p>



<p class="wp-block-paragraph">Em tempo discreto (digital), o termo integral pode ser aproximado por uma soma acumulativa: </p>



<p class="wp-block-paragraph">\[<br>u[k] = K_p \cdot e[k] + K_i \cdot T_s \cdot \sum_{i=0}^k e[i]<br>\]



<p class="wp-block-paragraph"><strong>Exemplo em C:</strong></p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="float Kp = 1.5;
float Ki = 0.8;
float integral = 0.0;
float Ts = 0.01;  // 10 ms

float compute_control(float error) {
    integral += error * Ts;
    return Kp * error + Ki * integral;
}
" 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">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Kp</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">1.5</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #88C0D0">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Ki</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0.8</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #88C0D0">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">integral</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0.0</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #88C0D0">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Ts</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0.01</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF">  </span><span style="color: #88C0D0">//</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">10</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">ms</span></span>
<span class="line"></span>
<span class="line"><span style="color: #88C0D0">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">compute_control</span><span style="color: #ECEFF4">(</span><span style="color: #88C0D0">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">error</span><span style="color: #ECEFF4">)</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">integral</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">+=</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">error</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Ts</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: #A3BE8C">Kp</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">error</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">+</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Ki</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">integral</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">}</span></span>
<span class="line"></span></code></pre></div>



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



<h3 class="wp-block-heading">4.3 Controlador Proporcional-Derivativo (PD)</h3>



<p class="wp-block-paragraph">O controlador PD adiciona um termo que considera a taxa de variação do erro. Isso melhora a resposta dinâmica e reduz o sobretempo: </p>



<p class="wp-block-paragraph">\[<br>u(t) = K_p \cdot e(t) + K_d \cdot \frac{de(t)}{dt}<br>\]



<p class="wp-block-paragraph">Na forma discreta: </p>



<p class="wp-block-paragraph">\[<br>u[k] = K_p \cdot e[k] + K_d \cdot \frac{e[k] &#8211; e[k-1]}{T_s}<br>\]



<p class="wp-block-paragraph"><strong>Exemplo em C:</strong></p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="float Kp = 2.0;
float Kd = 0.5;
float Ts = 0.01;
float previous_error = 0.0;

float compute_control(float error) {
    float derivative = (error - previous_error) / Ts;
    previous_error = error;
    return Kp * error + Kd * derivative;
}
" 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">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Kp</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">2.0</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #88C0D0">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Kd</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0.5</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #88C0D0">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Ts</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0.01</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #88C0D0">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">previous_error</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0.0</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #88C0D0">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">compute_control</span><span style="color: #ECEFF4">(</span><span style="color: #88C0D0">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">error</span><span style="color: #ECEFF4">)</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">derivative</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">=</span><span style="color: #D8DEE9FF"> (error </span><span style="color: #A3BE8C">-</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">previous_error</span><span style="color: #D8DEE9FF">) / Ts</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">previous_error</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">error</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: #A3BE8C">Kp</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">error</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">+</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Kd</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">derivative</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">}</span></span>
<span class="line"></span></code></pre></div>



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



<h3 class="wp-block-heading">4.4 Controlador Proporcional-Integral-Derivativo (PID)</h3>



<p class="wp-block-paragraph">O PID é o controlador mais utilizado em sistemas industriais. Ele combina os efeitos do controle proporcional, integral e derivativo: </p>



<p class="wp-block-paragraph">\[<br>u(t) = K_p \cdot e(t) + K_i \cdot \int_0^t e(\tau)\,d\tau + K_d \cdot \frac{de(t)}{dt}<br>\]



<p class="wp-block-paragraph">Em tempo discreto: </p>



<p class="wp-block-paragraph">\[<br>u[k] = K_p \cdot e[k] + K_i \cdot T_s \cdot \sum e[k] + K_d \cdot \frac{e[k] &#8211; e[k-1]}{T_s}<br>\]



<p class="wp-block-paragraph"><strong>Exemplo em C:</strong></p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="float Kp = 1.5, Ki = 0.4, Kd = 0.2;
float Ts = 0.01;
float integral = 0.0;
float previous_error = 0.0;

float compute_control(float error) {
    integral += error * Ts;
    float derivative = (error - previous_error) / Ts;
    previous_error = error;
    return Kp * error + Ki * integral + Kd * derivative;
}
" 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">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Kp</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">1.5</span><span style="color: #A3BE8C">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Ki</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0.4</span><span style="color: #A3BE8C">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Kd</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0.2</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #88C0D0">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Ts</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0.01</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #88C0D0">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">integral</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0.0</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #88C0D0">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">previous_error</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0.0</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #88C0D0">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">compute_control</span><span style="color: #ECEFF4">(</span><span style="color: #88C0D0">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">error</span><span style="color: #ECEFF4">)</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">integral</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">+=</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">error</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Ts</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">derivative</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">=</span><span style="color: #D8DEE9FF"> (error </span><span style="color: #A3BE8C">-</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">previous_error</span><span style="color: #D8DEE9FF">) / Ts</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">previous_error</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">error</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: #A3BE8C">Kp</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">error</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">+</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Ki</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">integral</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">+</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Kd</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">derivative</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">}</span></span>
<span class="line"></span></code></pre></div>



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



<h3 class="wp-block-heading">4.5 Controlador Bang-Bang (On-Off)</h3>



<p class="wp-block-paragraph">Esse é um controlador de dois estados, com atuação total ou nenhuma. É típico em sistemas térmicos e eletromecânicos simples: u(t)={Umaˊx,se&nbsp;e(t)&gt;εUmıˊn,se&nbsp;e(t)&lt;−εs em&nbsp;ação, caso&nbsp;contrário <br>\[<br>u(t) = \begin{cases} U_{\text{máx}}, &amp; \text{se } e(t) &gt; \varepsilon \\ U_{\text{mín}}, &amp; \text{se } e(t) &lt; -\varepsilon \\ \text{sem ação}, &amp; \text{caso contrário} \end{cases}<br>\]



<p class="wp-block-paragraph"><strong>Exemplo em C:</strong></p>



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

float compute_control(float error) {
    if (error &gt; EPSILON)
        return U_MAX;
    else if (error < -EPSILON)
        return U_MIN;
    else
        return 0.0; // zona morta
}
" 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: #616E88">#define U_MAX 1.0</span></span>
<span class="line"><span style="color: #616E88">#define U_MIN 0.0</span></span>
<span class="line"><span style="color: #616E88">#define EPSILON 0.5</span></span>
<span class="line"></span>
<span class="line"><span style="color: #88C0D0">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">compute_control</span><span style="color: #ECEFF4">(</span><span style="color: #88C0D0">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">error</span><span style="color: #ECEFF4">)</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">(</span><span style="color: #88C0D0">error</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&gt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">EPSILON</span><span style="color: #ECEFF4">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">return</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">U_MAX</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">else</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">(</span><span style="color: #88C0D0">error</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&lt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-EPSILON</span><span style="color: #ECEFF4">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">return</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">U_MIN</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">else</span></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.0</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">//</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">zona</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">morta</span></span>
<span class="line"><span style="color: #D8DEE9FF">}</span></span>
<span class="line"></span></code></pre></div>



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



<h3 class="wp-block-heading">4.6 Controle por Modelo (Model Predictive Control &#8211; MPC)</h3>



<p class="wp-block-paragraph">O <strong>Model Predictive Control (MPC)</strong> é uma técnica de controle avançada que utiliza um <strong>modelo matemático da planta</strong> para prever o comportamento futuro do sistema. O controlador resolve, a cada instante de tempo, um <strong>problema de otimização</strong> que minimiza uma função de custo sobre um horizonte de previsão, respeitando restrições do sistema (como limites de atuação e segurança).</p>



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



<h4 class="wp-block-heading"><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;" /> Conceito Fundamental</h4>



<p class="wp-block-paragraph">Em vez de reagir apenas ao erro atual, o MPC <strong>prevê os futuros estados do sistema</strong> e calcula a sequência ótima de ações de controle para minimizar o erro futuro.</p>



<p class="wp-block-paragraph">A função de custo típica a ser minimizada é:</p>



<p class="wp-block-paragraph">\[<br>J = \sum_{k=0}^{N_p-1} \left[ (x_k &#8211; x_{\text{ref}})^T Q (x_k &#8211; x_{\text{ref}}) + u_k^T R u_k \right]<br>\]



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



<ul class="wp-block-list">
<li>\(x_k\) = estado previsto no instante kk,</li>



<li>\(x_{\text{ref}}\) = valor de referência,</li>



<li>\(u_k\) = controle aplicado no instante kk,</li>



<li>Q e R = matrizes de ponderação de erro e esforço de controle,</li>



<li>\(N_p\) = horizonte de previsão.</li>
</ul>



<p class="wp-block-paragraph">A predição usa um <strong>modelo do sistema</strong> (tipicamente discreto e linear): </p>



<p class="wp-block-paragraph">\[<br>x_{k+1} = A x_k + B u_k<br>\]



<p class="wp-block-paragraph">O MPC então <strong>escolhe a melhor sequência de controles</strong> </p>



<p class="wp-block-paragraph">\[<br>\{u_0, u_1, &#8230;, u_{N_c-1}\}<br>\]



<p class="wp-block-paragraph"> tal que J seja mínimo, e aplica apenas o <strong>primeiro controle da sequência</strong>, recalculando tudo no próximo passo (controle em tempo real, modo receding horizon).</p>



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



<h4 class="wp-block-heading"><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;" /> Vantagens do MPC</h4>



<ul class="wp-block-list">
<li>Considera <strong>dinâmica futura</strong> da planta;</li>



<li>Suporta <strong>restrições explícitas</strong> (por exemplo: saturação de atuadores, limites físicos);</li>



<li>Pode lidar com <strong>sistemas multivariáveis</strong> com facilidade;</li>



<li>É adequado para sistemas lentos ou com atrasos.</li>
</ul>



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



<h4 class="wp-block-heading"><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;" /> Desvantagens</h4>



<ul class="wp-block-list">
<li>Alto custo computacional (resolve um problema de otimização em tempo real);</li>



<li>Exige um <strong>modelo matemático preciso</strong> do sistema;</li>



<li>Mais difícil de implementar em microcontroladores simples (mas viável com Cortex-M7, ESP32, etc.).</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/1f9e9.png" alt="🧩" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Pseudocódigo em C para MPC Linear Simples</h3>



<p class="wp-block-paragraph">Abaixo está uma estrutura simplificada, ilustrando um MPC linear com horizonte de predição curto, sem restrições explícitas:</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="#define N_P 5     // Horizonte de predição
#define N_U 1     // Horizonte de controle (aplicamos só o 1º controle)
#define STATE_DIM 1
#define INPUT_DIM 1

float A = 1.0f;   // Matriz do modelo (simplificado para escalar)
float B = 0.1f;
float Q = 1.0f;   // Peso do erro
float R = 0.01f;  // Peso do esforço
float x = 0.0f;   // Estado atual
float ref = 1.0f; // Referência

// Simula a predição de N_P passos à frente com diferentes valores de u
float simulate_trajectory(float u) {
    float x_pred = x;
    float cost = 0.0f;

    for (int k = 0; k < N_P; k++) {
        x_pred = A * x_pred + B * u;
        float error = x_pred - ref;
        cost += Q * error * error + R * u * u;
    }

    return cost;
}

// Busca o melhor valor de u entre -1.0 e 1.0 (resolução grosseira)
float mpc_control() {
    float best_u = 0.0f;
    float best_cost = 1e9;

    for (float u = -1.0f; u <= 1.0f; u += 0.1f) {
        float cost = simulate_trajectory(u);
        if (cost < best_cost) {
            best_cost = cost;
            best_u = u;
        }
    }

    return best_u;
}

// Loop de controle
void control_loop() {
    float u = mpc_control();
    apply_control(u);           // Envia para o atuador
    x = update_state(x, u);     // Simula planta ou lê via sensor
}
" 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: #616E88">#define N_P 5     // Horizonte de predição</span></span>
<span class="line"><span style="color: #616E88">#define N_U 1     // Horizonte de controle (aplicamos só o 1º controle)</span></span>
<span class="line"><span style="color: #616E88">#define STATE_DIM 1</span></span>
<span class="line"><span style="color: #616E88">#define INPUT_DIM 1</span></span>
<span class="line"></span>
<span class="line"><span style="color: #88C0D0">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">A</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">1.0</span><span style="color: #A3BE8C">f</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF">   </span><span style="color: #88C0D0">//</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Matriz</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">do</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">modelo</span><span style="color: #D8DEE9FF"> (simplificado </span><span style="color: #A3BE8C">para</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">escalar</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #88C0D0">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">B</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0.1</span><span style="color: #A3BE8C">f</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #88C0D0">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Q</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">1.0</span><span style="color: #A3BE8C">f</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF">   </span><span style="color: #88C0D0">//</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Peso</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">do</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">erro</span></span>
<span class="line"><span style="color: #88C0D0">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">R</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0.01</span><span style="color: #A3BE8C">f</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF">  </span><span style="color: #88C0D0">//</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Peso</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">do</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">esforço</span></span>
<span class="line"><span style="color: #88C0D0">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">x</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0.0</span><span style="color: #A3BE8C">f</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF">   </span><span style="color: #88C0D0">//</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Estado</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">atual</span></span>
<span class="line"><span style="color: #88C0D0">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">ref</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">1.0</span><span style="color: #A3BE8C">f</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">//</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Referência</span></span>
<span class="line"></span>
<span class="line"><span style="color: #88C0D0">//</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Simula</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">a</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">predição</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">de</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">N_P</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">passos</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">à</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">frente</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">com</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">diferentes</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">valores</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">de</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">u</span></span>
<span class="line"><span style="color: #88C0D0">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">simulate_trajectory</span><span style="color: #ECEFF4">(</span><span style="color: #88C0D0">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">u</span><span style="color: #ECEFF4">)</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">x_pred</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">x</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">cost</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0.0</span><span style="color: #A3BE8C">f</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">for</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">(</span><span style="color: #88C0D0">int</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">k</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">=</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: #88C0D0">k</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&lt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">N_P</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">k++</span><span style="color: #ECEFF4">)</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">x_pred</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">A</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">x_pred</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">+</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">B</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">u</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">error</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">x_pred</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">ref</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">cost</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">+=</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Q</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">error</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">error</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">+</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">R</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">u</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">u</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #ECEFF4">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">return</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">cost</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #88C0D0">//</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Busca</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">o</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">melhor</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">valor</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">de</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">u</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">entre</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-1.0</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">e</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">1.0</span><span style="color: #D8DEE9FF"> (resolução </span><span style="color: #A3BE8C">grosseira</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #88C0D0">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">mpc_control</span><span style="color: #ECEFF4">()</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">best_u</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0.0</span><span style="color: #A3BE8C">f</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">best_cost</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">1</span><span style="color: #A3BE8C">e9</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">for</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">(</span><span style="color: #88C0D0">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">u</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-1.0f</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">u</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&lt;</span><span style="color: #A3BE8C">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">1.0</span><span style="color: #A3BE8C">f</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">u</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">+=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0.1</span><span style="color: #A3BE8C">f</span><span style="color: #ECEFF4">)</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">cost</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">simulate_trajectory</span><span style="color: #ECEFF4">(</span><span style="color: #88C0D0">u</span><span style="color: #ECEFF4">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">(</span><span style="color: #88C0D0">cost</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&lt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">best_cost</span><span style="color: #ECEFF4">)</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #88C0D0">best_cost</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">cost</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">            </span><span style="color: #88C0D0">best_u</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">u</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>
<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: #A3BE8C">best_u</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #88C0D0">//</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Loop</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">de</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">controle</span></span>
<span class="line"><span style="color: #88C0D0">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">control_loop</span><span style="color: #ECEFF4">()</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">u</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">mpc_control</span><span style="color: #ECEFF4">()</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">apply_control(u</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF">           </span><span style="color: #88C0D0">//</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Envia</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">para</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">o</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">atuador</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">x</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">update_state</span><span style="color: #ECEFF4">(</span><span style="color: #88C0D0">x,</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">u</span><span style="color: #ECEFF4">)</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF">     </span><span style="color: #88C0D0">//</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Simula</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">planta</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">ou</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">lê</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">via</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">sensor</span></span>
<span class="line"><span style="color: #D8DEE9FF">}</span></span>
<span class="line"></span></code></pre></div>



<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/1f9ea.png" alt="🧪" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Explicação do Pseudocódigo</h3>



<ul class="wp-block-list">
<li>O modelo do sistema é: \(x_{k+1} = A x_k + B u_k\).</li>



<li>A função <code>simulate_trajectory(u)</code> calcula o custo total ao aplicar sempre o mesmo uu durante o horizonte de predição.</li>



<li>O controlador testa vários valores de uu e escolhe o que minimiza o custo.</li>



<li>Isso representa um <strong>controle ótimo com base em predições</strong>, mesmo em um sistema com recursos limitados.</li>
</ul>



<figure class="wp-block-image size-large"><img decoding="async" width="1024" height="611" src="https://mcu.tec.br/wp-content/uploads/2025/03/image-14-1024x611.png" alt="" class="wp-image-237" srcset="https://mcu.tec.br/wp-content/uploads/2025/03/image-14-1024x611.png 1024w, https://mcu.tec.br/wp-content/uploads/2025/03/image-14-300x179.png 300w, https://mcu.tec.br/wp-content/uploads/2025/03/image-14-768x458.png 768w, https://mcu.tec.br/wp-content/uploads/2025/03/image-14-1536x916.png 1536w, https://mcu.tec.br/wp-content/uploads/2025/03/image-14.png 1979w" sizes="(max-width: 1024px) 100vw, 1024px" /><figcaption class="wp-element-caption">simulação do controle preditivo por modelo (MPC) aplicado a um sistema simples:<br><strong>Gráfico superior</strong>: mostra a saída do sistema x  ao longo do tempo, convergindo suavemente até a referência (linha tracejada).<br><strong>Gráfico inferior</strong>: mostra o sinal de controle u  ajustado a cada passo para minimizar o erro futuro.</figcaption></figure>



<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/1f6e0.png" alt="🛠" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Melhorias possíveis</h3>



<ul class="wp-block-list">
<li>Resolver o problema de otimização usando algoritmos mais rápidos: <strong>gradiente, Newton, QP</strong>;</li>



<li>Suporte a <strong>restrições de entrada e estado</strong>;</li>



<li>Controle multivariável (com matrizes <code>A</code>, <code>B</code>, <code>Q</code>, <code>R</code>);</li>



<li>Integração com bibliotecas lineares como <strong>Eigen</strong> (C++) ou <strong>CMSIS-DSP</strong> (C para ARM).</li>
</ul>



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



<h3 class="wp-block-heading">4.7 Controle Adaptativo </h3>



<p class="wp-block-paragraph">O <strong>Controle Adaptativo</strong> é uma técnica projetada para sistemas cujas <strong>características dinâmicas mudam ao longo do tempo</strong> ou não são completamente conhecidas. Diferente do PID e do MPC, que pressupõem modelos fixos ou bem definidos, o controle adaptativo <strong>ajusta seus próprios parâmetros automaticamente</strong> com base na resposta do sistema.</p>



<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/1f4cc.png" alt="📌" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Quando usar Controle Adaptativo?</h3>



<ul class="wp-block-list">
<li>Sistemas com grande <strong>variação de carga</strong> (ex: ventiladores, motores, robôs com carga variável);</li>



<li>Plantas com <strong>dinâmica incerta</strong> ou que muda com o tempo (ex: sistemas térmicos, baterias, processos biológicos);</li>



<li>Ambientes que exigem <strong>autocalibração</strong>, como controle remoto sem conhecimento prévio da planta.</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/1f3af.png" alt="🎯" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Objetivo</h3>



<p class="wp-block-paragraph">Projetar um controlador que:</p>



<ul class="wp-block-list">
<li><strong>Estime os parâmetros</strong> do sistema em tempo real;</li>



<li>Ajuste os <strong>parâmetros de controle</strong> com base nessas estimativas;</li>



<li>Mantenha <strong>estabilidade e desempenho</strong> diante de variações.</li>
</ul>



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



<h2 class="wp-block-heading"><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;" /> Tipos Principais de Controle Adaptativo</h2>



<ol class="wp-block-list">
<li><strong>Modelo de Referência (MRAC – Model Reference Adaptive Control):</strong>
<ul class="wp-block-list">
<li>O controlador ajusta seus parâmetros para que o sistema siga a resposta de um <strong>modelo ideal predefinido</strong>.</li>
</ul>
</li>



<li><strong>Self-Tuning Regulator (STR):</strong>
<ul class="wp-block-list">
<li>Primeiro <strong>identifica os parâmetros da planta</strong>, depois <strong>sintetiza o controlador ótimo</strong> com base nesses parâmetros estimados.</li>
</ul>
</li>



<li><strong>Controle com ganho variável (Gain Scheduling):</strong>
<ul class="wp-block-list">
<li>Parâmetros do controlador mudam com base em <strong>condições de operação medidas</strong> (ex: velocidade, temperatura).</li>
</ul>
</li>



<li><strong>Redes neurais ou lógica fuzzy adaptativa:</strong>
<ul class="wp-block-list">
<li>Algoritmos de aprendizado (machine learning) para mapear e ajustar controles não lineares.</li>
</ul>
</li>
</ol>



<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/1f4d0.png" alt="📐" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Exemplo Simples: MRAC com Atualização de Ganhos Online</h3>



<p class="wp-block-paragraph">Dado o sistema: \(x(t)+bu(t)\dot{x}(t) = a x(t) + b u(t)\)</p>



<p class="wp-block-paragraph">Queremos que ele siga o modelo de referência: \(\dot{x}_m(t) = a_m x_m(t) + b_m r(t)\)</p>



<p class="wp-block-paragraph">A lei de controle adaptativa (simplificada) pode ser: \(u(t) = \theta(t) \cdot x(t)\)</p>



<p class="wp-block-paragraph">E os parâmetros θ(t)\theta(t) são ajustados com base no erro de seguimento: \(e(t) = x(t) &#8211; x_m(t)\)</p>



<p class="wp-block-paragraph">A <strong>regra de adaptação</strong> baseada em Lyapunov pode ser: \(\frac{d\theta(t)}{dt} = -\gamma \cdot e(t) \cdot x(t)\)</p>



<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/1f9ee.png" alt="🧮" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Pseudocódigo em C (Versão Discreta)</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" data-code="typedef struct {
    float theta;     // Ganho adaptativo
    float gamma;     // Taxa de aprendizagem
    float a_ref;     // Parâmetro do modelo de referência
    float b_ref;
    float x;         // Estado do sistema real
    float x_ref;     // Estado do modelo de referência
    float Ts;        // Tempo de amostragem
} MRAC_Controller;

void mrac_init(MRAC_Controller* ctrl, float gamma, float a_ref, float b_ref, float Ts) {
    ctrl-&gt;theta = 0.0f;
    ctrl-&gt;gamma = gamma;
    ctrl-&gt;a_ref = a_ref;
    ctrl-&gt;b_ref = b_ref;
    ctrl-&gt;x = 0.0f;
    ctrl-&gt;x_ref = 0.0f;
    ctrl-&gt;Ts = Ts;
}

float mrac_update(MRAC_Controller* ctrl, float reference) {
    // Modelo de referência
    float dx_ref = ctrl-&gt;a_ref * ctrl-&gt;x_ref + ctrl-&gt;b_ref * reference;
    ctrl-&gt;x_ref += dx_ref * ctrl-&gt;Ts;

    // Erro de seguimento
    float error = ctrl-&gt;x - ctrl-&gt;x_ref;

    // Atualização do ganho adaptativo (gradiente descendente)
    ctrl-&gt;theta -= ctrl-&gt;gamma * error * ctrl-&gt;x * ctrl-&gt;Ts;

    // Controle aplicado
    float u = ctrl-&gt;theta * ctrl-&gt;x;

    // Simula a planta real (dinâmica desconhecida, aqui exemplo fixo)
    float a = -0.5f, b = 1.0f;
    float dx = a * ctrl-&gt;x + b * u;
    ctrl-&gt;x += dx * ctrl-&gt;Ts;

    return u;
}
" 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">typedef</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">struct</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">theta</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF">     </span><span style="color: #88C0D0">//</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Ganho</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">adaptativo</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">gamma</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF">     </span><span style="color: #88C0D0">//</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Taxa</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">de</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">aprendizagem</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">a_ref</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF">     </span><span style="color: #88C0D0">//</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Parâmetro</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">do</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">modelo</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">de</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">referência</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">b_ref</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">x</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF">         </span><span style="color: #88C0D0">//</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Estado</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">do</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">sistema</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">real</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">x_ref</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF">     </span><span style="color: #88C0D0">//</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Estado</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">do</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">modelo</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">de</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">referência</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Ts</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">//</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Tempo</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">de</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">amostragem</span></span>
<span class="line"><span style="color: #D8DEE9FF">} MRAC_Controller;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #88C0D0">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">mrac_init</span><span style="color: #ECEFF4">(</span><span style="color: #88C0D0">MRAC_Controller*</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">ctrl,</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">gamma,</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">a_ref,</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">b_ref,</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Ts</span><span style="color: #ECEFF4">)</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">ctrl-&gt;theta</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0.0</span><span style="color: #A3BE8C">f</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">ctrl-&gt;gamma</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">gamma</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">ctrl-&gt;a_ref</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">a_ref</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">ctrl-&gt;b_ref</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">b_ref</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">ctrl-&gt;x</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0.0</span><span style="color: #A3BE8C">f</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">ctrl-&gt;x_ref</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0.0</span><span style="color: #A3BE8C">f</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">ctrl-&gt;Ts</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Ts</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #88C0D0">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">mrac_update</span><span style="color: #ECEFF4">(</span><span style="color: #88C0D0">MRAC_Controller*</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">ctrl,</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">reference</span><span style="color: #ECEFF4">)</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">//</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Modelo</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">de</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">referência</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">dx_ref</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">ctrl</span><span style="color: #D8DEE9FF">-</span><span style="color: #81A1C1">&gt;</span><span style="color: #A3BE8C">a_ref</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">ctrl</span><span style="color: #D8DEE9FF">-</span><span style="color: #81A1C1">&gt;</span><span style="color: #A3BE8C">x_ref</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">+</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">ctrl</span><span style="color: #D8DEE9FF">-</span><span style="color: #81A1C1">&gt;</span><span style="color: #A3BE8C">b_ref</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">reference</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">ctrl-&gt;x_ref</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">+=</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">dx_ref</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">ctrl</span><span style="color: #D8DEE9FF">-</span><span style="color: #81A1C1">&gt;</span><span style="color: #A3BE8C">Ts</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">//</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Erro</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">de</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">seguimento</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">error</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">ctrl</span><span style="color: #D8DEE9FF">-</span><span style="color: #81A1C1">&gt;</span><span style="color: #A3BE8C">x</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">ctrl</span><span style="color: #D8DEE9FF">-</span><span style="color: #81A1C1">&gt;</span><span style="color: #A3BE8C">x_ref</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">//</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Atualização</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">do</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">ganho</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">adaptativo</span><span style="color: #D8DEE9FF"> (gradiente </span><span style="color: #A3BE8C">descendente</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">ctrl-&gt;theta</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-=</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">ctrl</span><span style="color: #D8DEE9FF">-</span><span style="color: #81A1C1">&gt;</span><span style="color: #A3BE8C">gamma</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">error</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">ctrl</span><span style="color: #D8DEE9FF">-</span><span style="color: #81A1C1">&gt;</span><span style="color: #A3BE8C">x</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">ctrl</span><span style="color: #D8DEE9FF">-</span><span style="color: #81A1C1">&gt;</span><span style="color: #A3BE8C">Ts</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">//</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Controle</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">aplicado</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">u</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">ctrl</span><span style="color: #D8DEE9FF">-</span><span style="color: #81A1C1">&gt;</span><span style="color: #A3BE8C">theta</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">ctrl</span><span style="color: #D8DEE9FF">-</span><span style="color: #81A1C1">&gt;</span><span style="color: #A3BE8C">x</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">//</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Simula</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">a</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">planta</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">real</span><span style="color: #D8DEE9FF"> (dinâmica </span><span style="color: #A3BE8C">desconhecida,</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">aqui</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">exemplo</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">fixo</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">a</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-0.5f,</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">b</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">1.0</span><span style="color: #A3BE8C">f</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">dx</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">a</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">ctrl</span><span style="color: #D8DEE9FF">-</span><span style="color: #81A1C1">&gt;</span><span style="color: #A3BE8C">x</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">+</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">b</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">u</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">ctrl-&gt;x</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">+=</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">dx</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">ctrl</span><span style="color: #D8DEE9FF">-</span><span style="color: #81A1C1">&gt;</span><span style="color: #A3BE8C">Ts</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">return</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">u</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">}</span></span>
<span class="line"></span></code></pre></div>



<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/1f4ca.png" alt="📊" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Comportamento Esperado</h3>



<ul class="wp-block-list">
<li>A cada passo, o parâmetro θ é ajustado de forma a minimizar o erro entre o sistema real e o modelo de referência;</li>



<li>Ao longo do tempo, o sistema &#8220;aprende&#8221; a resposta desejada;</li>



<li>A estabilidade é garantida se a taxa de adaptação γ for bem escolhida.</li>
</ul>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="826" src="https://mcu.tec.br/wp-content/uploads/2025/03/image-15-1024x826.png" alt="" class="wp-image-242" srcset="https://mcu.tec.br/wp-content/uploads/2025/03/image-15-1024x826.png 1024w, https://mcu.tec.br/wp-content/uploads/2025/03/image-15-300x242.png 300w, https://mcu.tec.br/wp-content/uploads/2025/03/image-15-768x620.png 768w, https://mcu.tec.br/wp-content/uploads/2025/03/image-15-1536x1239.png 1536w, https://mcu.tec.br/wp-content/uploads/2025/03/image-15.png 1958w" sizes="(max-width: 1024px) 100vw, 1024px" /><figcaption class="wp-element-caption">gráficos da simulação do controlador adaptativo MRAC:<br><strong>Gráfico superior:</strong> mostra como a saída do sistema real (linha contínua) converge ao longo do tempo para a trajetória do modelo de referência (linha tracejada), mesmo sem conhecimento prévio dos parâmetros da planta.<br><strong>Gráfico do meio:</strong> representa o erro de seguimento entre o sistema real e o modelo ideal. O erro tende a zero à medida que o controlador se ajusta.<br><strong>Gráfico inferior:</strong> mostra a evolução do ganho adaptativo θ(t), que é ajustado dinamicamente para manter o controle ideal.</figcaption></figure>



<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/1f9f0.png" alt="🧰" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Vantagens do Controle Adaptativo</h3>



<ul class="wp-block-list">
<li><strong>Alta flexibilidade</strong> frente a incertezas e variações;</li>



<li>Requer <strong>menos conhecimento prévio</strong> da planta;</li>



<li>Potencial de <strong>autoajuste contínuo</strong> durante a operação.</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/26a0.png" alt="⚠" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Desvantagens</h3>



<ul class="wp-block-list">
<li>Mais difícil de <strong>analisar e validar formalmente</strong>;</li>



<li>Pode ser sensível a ruídos, atrasos ou saturações;</li>



<li>Requer <strong>cuidados com estabilidade</strong> (sobretudo em sistemas rápidos).</li>
</ul>



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



<h3 class="wp-block-heading">4.8 Controle Ótimo Linear Quadrático (LQR – Linear Quadratic Regulator)</h3>



<p class="wp-block-paragraph">O LQR é um algoritmo de controle ótimo que busca minimizar uma função de custo quadrática, considerando simultaneamente a resposta do sistema e o esforço de controle. Ele se baseia em um modelo de estado da planta (forma matricial) e é projetado para sistemas lineares com tempo contínuo ou discreto.</p>



<p class="wp-block-paragraph">A função de custo a ser minimizada é: </p>



<p class="wp-block-paragraph">\[<br>J = \int_0^\infty (x^T Q x + u^T R u)\,dt<br>\]



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



<ul class="wp-block-list">
<li>x: vetor de estados do sistema;</li>



<li>u: vetor de controle;</li>



<li>Q: matriz de ponderação dos estados (penaliza desvios);</li>



<li>R: matriz de ponderação do esforço de controle.</li>
</ul>



<p class="wp-block-paragraph">O controlador LQR calcula o vetor de controle como: \(\(u(t) = -K \cdot x(t)\)\)</p>



<p class="wp-block-paragraph">onde K é a matriz de ganhos ótima obtida pela resolução da equação de Riccati.</p>



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



<ul class="wp-block-list">
<li>Otimização rigorosa de desempenho e energia;</li>



<li>Estável por construção;</li>



<li>Fácil de estender para sistemas multivariáveis.</li>
</ul>



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



<ul class="wp-block-list">
<li>Exige conhecimento preciso do modelo matemático;</li>



<li>Pouco robusto a variações bruscas na planta.</li>
</ul>



<p class="wp-block-paragraph"><strong>Aplicações típicas:</strong></p>



<ul class="wp-block-list">
<li>Controle de veículos autônomos (tração e frenagem);</li>



<li>Estabilização de drones;</li>



<li>Robótica de precisão.</li>
</ul>



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



<h3 class="wp-block-heading">4.9 Controle Robusto H∞ (H-infinito)</h3>



<p class="wp-block-paragraph">O controle H∞H_\infty é uma técnica voltada para garantir <strong>robustez</strong> contra incertezas no modelo da planta e rejeição de perturbações externas. Em vez de minimizar um custo específico (como no LQR), o objetivo é minimizar o <strong>ganho máximo</strong> da função de transferência sensibilidade do sistema, assegurando desempenho mesmo sob as piores condições.</p>



<p class="wp-block-paragraph">Ele é formulado como um problema de otimização de normas matriciais, buscando um controlador \(K(s)\) tal que: </p>



<p class="wp-block-paragraph">\[<br>\| T_{zw}(s) \|_{\infty} &lt; \gamma<br>\]



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



<ul class="wp-block-list">
<li>\(T_{zw}(s)\): função de transferência entre perturbações w e saídas z;</li>



<li>\(γ\gamma\): ganho máximo admissível.</li>
</ul>



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



<ul class="wp-block-list">
<li>Garante robustez explícita contra incertezas modeladas;</li>



<li>Adequado para sistemas sujeitos a perturbações e ruído.</li>
</ul>



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



<ul class="wp-block-list">
<li>Complexidade matemática e computacional elevada;</li>



<li>Requer métodos de síntese numérica (como LMI – Linear Matrix Inequalities).</li>
</ul>



<p class="wp-block-paragraph"><strong>Aplicações típicas:</strong></p>



<ul class="wp-block-list">
<li>Controle de sistemas aeroespaciais;</li>



<li>Estabilização de sistemas instáveis com ruído;</li>



<li>Sistemas com requisitos de segurança rigorosos.</li>
</ul>



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



<p class="wp-block-paragraph">Esses dois métodos — LQR e \(H_\infty\) — fazem parte do campo do <strong>controle moderno</strong>, no qual se representa o sistema na forma de estado e se explora otimização, robustez e propriedades matemáticas formais.</p>



<p class="wp-block-paragraph">Ambos requerem modelagem precisa e ferramentas de cálculo avançado, como MATLAB, Scilab, Octave ou bibliotecas científicas específicas em C/C++ (por exemplo, Armadillo ou Eigen).</p>



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



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



<h2 class="wp-block-heading">5. Consequências e Comparação Entre os Métodos de Controle de Loop Fechado</h2>



<p class="wp-block-paragraph">Cada algoritmo de controle de loop fechado traz consigo um conjunto distinto de características, implicações práticas e limitações. A escolha adequada do controlador não depende apenas do desempenho teórico, mas também do ambiente de aplicação, do custo computacional e da robustez exigida. Abaixo, discutimos as principais consequências de adotar cada tipo de controlador.</p>



<h3 class="wp-block-heading">5.1 Controladores Clássicos (P, PI, PD, PID)</h3>



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



<ul class="wp-block-list">
<li>Simples de implementar e ajustar;</li>



<li>Amplamente utilizados em sistemas industriais e embarcados;</li>



<li>PID pode ser implementado mesmo em microcontroladores simples.</li>
</ul>



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



<ul class="wp-block-list">
<li>Não oferecem robustez explícita;</li>



<li>Não consideram restrições do sistema (saturação, limites físicos);</li>



<li>Não têm otimização formal de desempenho.</li>
</ul>



<p class="wp-block-paragraph"><strong>Aplicações Típicas:</strong></p>



<ul class="wp-block-list">
<li>Controle de temperatura, velocidade, pressão;</li>



<li>Motores DC e servo motores;</li>



<li>Fontes chaveadas, HVAC, automação básica.</li>
</ul>



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



<h3 class="wp-block-heading">5.2 Bang-Bang (On-Off)</h3>



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



<ul class="wp-block-list">
<li>Simplicidade extrema (usa apenas decisões binárias);</li>



<li>Alta robustez em aplicações com grande histerese.</li>
</ul>



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



<ul class="wp-block-list">
<li>Pode gerar oscilação e desgaste mecânico;</li>



<li>Pouco preciso;</li>



<li>Inadequado para sistemas dinâmicos rápidos.</li>
</ul>



<p class="wp-block-paragraph"><strong>Aplicações Típicas:</strong></p>



<ul class="wp-block-list">
<li>Termostatos, acionamento de relés, controle hidráulico básico;</li>



<li>Controle de bombas e aquecedores simples.</li>
</ul>



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



<h3 class="wp-block-heading">5.3 Controle Ótimo (LQR)</h3>



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



<ul class="wp-block-list">
<li>Otimiza a estabilidade e o esforço de controle;</li>



<li>Excelente para sistemas com múltiplos estados;</li>



<li>Garante desempenho suave e previsível.</li>
</ul>



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



<ul class="wp-block-list">
<li>Requer modelo matemático preciso;</li>



<li>Complexidade de projeto e cálculo da matriz de ganhos KK;</li>



<li>Dificuldade de adaptação em tempo real.</li>
</ul>



<p class="wp-block-paragraph"><strong>Aplicações Típicas:</strong></p>



<ul class="wp-block-list">
<li>Drones, veículos autônomos, sistemas inerciais;</li>



<li>Robôs manipuladores e estabilizadores de câmera.</li>
</ul>



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



<h3 class="wp-block-heading">5.4 Controle Robusto \(H_\infty\)</h3>



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



<ul class="wp-block-list">
<li>Forte resistência a incertezas na planta;</li>



<li>Ideal para sistemas críticos e inseguros;</li>



<li>Considera perturbações explícitas e desempenho em condições extremas.</li>
</ul>



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



<ul class="wp-block-list">
<li>Projeto matematicamente complexo;</li>



<li>Elevado custo computacional;</li>



<li>Pouco utilizado em sistemas embarcados com recursos limitados.</li>
</ul>



<p class="wp-block-paragraph"><strong>Aplicações Típicas:</strong></p>



<ul class="wp-block-list">
<li>Controle aeroespacial, defesa, sistemas navais;</li>



<li>Equipamentos de missão crítica ou ambientes hostis.</li>
</ul>



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



<h3 class="wp-block-heading">5.5 Controle Adaptativo</h3>



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



<ul class="wp-block-list">
<li>Ajusta-se automaticamente às mudanças da planta;</li>



<li>Ideal para sistemas com comportamento não estacionário;</li>



<li>Pode manter desempenho mesmo em casos imprevistos.</li>
</ul>



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



<ul class="wp-block-list">
<li>Maior complexidade computacional e teórica;</li>



<li>Pode ter instabilidades se mal projetado;</li>



<li>Difícil de validar com testes formais.</li>
</ul>



<p class="wp-block-paragraph"><strong>Aplicações Típicas:</strong></p>



<ul class="wp-block-list">
<li>Máquinas CNC com variação de carga;</li>



<li>Controle inteligente de motores;</li>



<li>Sistemas embarcados em ambientes variáveis.</li>
</ul>



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



<h3 class="wp-block-heading">5.6 Comparação Geral</h3>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Algoritmo</th><th>Fácil de Implementar</th><th>Robusto</th><th>Otimizado</th><th>Exige Modelo</th><th>Baixo Custo Computacional</th></tr></thead><tbody><tr><td>P</td><td>Sim</td><td>Baixo</td><td>Não</td><td>Não</td><td>Sim</td></tr><tr><td>PI</td><td>Sim</td><td>Médio</td><td>Parcial</td><td>Não</td><td>Sim</td></tr><tr><td>PID</td><td>Sim</td><td>Médio</td><td>Parcial</td><td>Não</td><td>Sim</td></tr><tr><td>Bang-Bang</td><td>Sim</td><td>Alto</td><td>Não</td><td>Não</td><td>Sim</td></tr><tr><td>LQR</td><td>Não</td><td>Médio</td><td>Sim</td><td>Sim</td><td>Médio</td></tr><tr><td>H∞</td><td>Não</td><td>Muito Alto</td><td>Sim</td><td>Sim</td><td>Alto</td></tr><tr><td>Adaptativo</td><td>Não</td><td>Alto</td><td>Sim</td><td>Não Necessário</td><td>Médio-Alto</td></tr></tbody></table></figure>



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



<p class="wp-block-paragraph">Em resumo, <strong>controladores clássicos</strong> continuam sendo a melhor escolha para aplicações <strong>simples e eficientes</strong>, enquanto <strong>controladores ótimos e robustos</strong> são ideais para <strong>sistemas complexos</strong>, com <strong>grandes incertezas</strong> ou que requerem <strong>máxima confiabilidade</strong>.</p>



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



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



<h2 class="wp-block-heading">6. Estratégias de Implementação em Sistemas Embarcados</h2>



<p class="wp-block-paragraph">Implementar algoritmos de controle de loop fechado em sistemas embarcados exige atenção a diversos fatores práticos: uso eficiente do tempo de CPU, precisão numérica, uso de interrupções e recursos periféricos como ADCs, timers e PWMs. Esta seção apresenta estratégias eficazes para tornar os algoritmos aplicáveis em microcontroladores como STM32, AVR, ESP32, entre outros.</p>



<h3 class="wp-block-heading">6.1 Amostragem Periódica</h3>



<p class="wp-block-paragraph">A base do controle digital é o cálculo periódico do sinal de controle. Para isso, o ideal é configurar um <strong>timer de hardware</strong> que dispare uma <strong>interrupção periódica</strong> a cada TsT_s milissegundos. Essa interrupção deve chamar a função do controlador.</p>



<p class="wp-block-paragraph"><strong>Exemplo (pseudocódigo para STM32 HAL):</strong></p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) {
    if (htim-&gt;Instance == TIM3) { // Timer configurado para 10 ms
        control_loop();           // Executa o PID
    }
}
" 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">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">HAL_TIM_PeriodElapsedCallback</span><span style="color: #ECEFF4">(</span><span style="color: #88C0D0">TIM_HandleTypeDef</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #A3BE8C">htim</span><span style="color: #ECEFF4">)</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">(</span><span style="color: #88C0D0">htim-&gt;Instance</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">==</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">TIM3</span><span style="color: #ECEFF4">)</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">//</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Timer</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">configurado</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">para</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">10</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">ms</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">control_loop</span><span style="color: #ECEFF4">()</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF">           </span><span style="color: #88C0D0">//</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Executa</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">o</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">PID</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>
<span class="line"></span></code></pre></div>



<h3 class="wp-block-heading">6.2 Leitura de Sensores (ADC)</h3>



<p class="wp-block-paragraph">A maioria das variáveis de processo (como corrente, temperatura ou velocidade) é medida via <strong>ADC</strong> (Conversor Analógico-Digital). A leitura deve ser feita no início do loop de controle.</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="float read_sensor() {
    HAL_ADC_Start(&amp;hadc1);
    HAL_ADC_PollForConversion(&amp;hadc1, 10);
    uint32_t raw = HAL_ADC_GetValue(&amp;hadc1);
    return (float)raw * SCALE_FACTOR;  // converter para unidade real
}
" 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">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">read_sensor</span><span style="color: #ECEFF4">()</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">HAL_ADC_Start(</span><span style="color: #ECEFF4">&amp;</span><span style="color: #88C0D0">hadc1</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">HAL_ADC_PollForConversion(</span><span style="color: #ECEFF4">&amp;</span><span style="color: #88C0D0">hadc1,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">10</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">uint32_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">raw</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">HAL_ADC_GetValue</span><span style="color: #ECEFF4">(&amp;</span><span style="color: #88C0D0">hadc1</span><span style="color: #ECEFF4">)</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"> (float)raw </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> SCALE_FACTOR</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF">  </span><span style="color: #88C0D0">//</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">converter</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">para</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">unidade</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">real</span></span>
<span class="line"><span style="color: #D8DEE9FF">}</span></span>
<span class="line"></span></code></pre></div>



<h3 class="wp-block-heading">6.3 Escrita no Atuador (PWM ou DAC)</h3>



<p class="wp-block-paragraph">O sinal de controle calculado deve ser convertido em uma ação física. Nos sistemas embarcados, isso é feito tipicamente via:</p>



<ul class="wp-block-list">
<li><strong>PWM</strong> (modulação por largura de pulso), para controlar motores, aquecedores, etc.</li>



<li><strong>DAC</strong> (Conversor Digital-Analógico), para gerar tensões analógicas em sistemas de controle contínuo.</li>
</ul>



<p class="wp-block-paragraph"><strong>Exemplo com PWM:</strong></p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="void write_actuator(float control) {
    if (control < 0) control = 0;
    if (control &gt; 100) control = 100;
    __HAL_TIM_SET_COMPARE(&amp;htim2, TIM_CHANNEL_1, control);  // Duty cycle (%)
}
" 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">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">write_actuator</span><span style="color: #ECEFF4">(</span><span style="color: #88C0D0">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">control</span><span style="color: #ECEFF4">)</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">(</span><span style="color: #88C0D0">control</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&lt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0</span><span style="color: #ECEFF4">)</span><span style="color: #D8DEE9FF"> control = 0</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">(</span><span style="color: #88C0D0">control</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&gt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">100</span><span style="color: #ECEFF4">)</span><span style="color: #D8DEE9FF"> control = 100</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">__HAL_TIM_SET_COMPARE(</span><span style="color: #ECEFF4">&amp;</span><span style="color: #88C0D0">htim2,</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">TIM_CHANNEL_1,</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">control</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF">  </span><span style="color: #88C0D0">//</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Duty</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">cycle</span><span style="color: #D8DEE9FF"> (%)</span></span>
<span class="line"><span style="color: #D8DEE9FF">}</span></span>
<span class="line"></span></code></pre></div>



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



<h3 class="wp-block-heading">6.4 Cálculo Seguro do Controle</h3>



<ul class="wp-block-list">
<li>Use <strong>variáveis <code>float</code> ou <code>fixed-point</code></strong> dependendo da arquitetura e necessidade de precisão.</li>



<li>Implemente <strong>limites no integrador (anti-windup)</strong> para evitar saturações.</li>



<li>Proteja o cálculo com <strong>&#8220;clipping&#8221;</strong> de entrada e saída.</li>
</ul>



<pre class="wp-block-code"><code>if (integral &gt; INTEGRAL_MAX) integral = INTEGRAL_MAX;
if (integral &lt; INTEGRAL_MIN) integral = INTEGRAL_MIN;
</code></pre>



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



<h3 class="wp-block-heading">6.5 Filtros para Derivada</h3>



<p class="wp-block-paragraph">O termo derivativo do PID é sensível a ruído de medição. Para suavizá-lo, use <strong>filtros digitais</strong>: </p>



<p class="wp-block-paragraph">\[<br>D(t) = K_d \cdot \frac{d}{dt} \left( y_{\text{filtrado}}(t) \right)<br>\]



<p class="wp-block-paragraph">Um filtro passa-baixa simples pode ser usado para suavizar a variável medida:</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="float low_pass_filter(float current, float previous, float alpha) {
    return alpha * current + (1 - alpha) * previous;
}
" 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">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">low_pass_filter</span><span style="color: #ECEFF4">(</span><span style="color: #88C0D0">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">current,</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">previous,</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">alpha</span><span style="color: #ECEFF4">)</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">return</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">alpha</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">current</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">+</span><span style="color: #D8DEE9FF"> (1 </span><span style="color: #A3BE8C">-</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">alpha</span><span style="color: #D8DEE9FF">) </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> previous</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">}</span></span>
<span class="line"></span></code></pre></div>



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



<h3 class="wp-block-heading">6.6 Estrutura Modular</h3>



<p class="wp-block-paragraph">Divida o controle em três blocos principais:</p>



<ol class="wp-block-list">
<li><strong>Amostragem da variável (sensor)</strong></li>



<li><strong>Cálculo do controle</strong></li>



<li><strong>Aplicação da saída (atuador)</strong></li>
</ol>



<p class="wp-block-paragraph">Isso facilita manutenção, testes e mudanças de controlador. Também permite reaproveitar o mesmo &#8220;esqueleto&#8221; para múltiplos tipos de controlador (PID, LQR, etc.).</p>



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



<h3 class="wp-block-heading">6.7 Considerações para Controladores Avançados</h3>



<p class="wp-block-paragraph">Para algoritmos como <strong>LQR, MPC ou Adaptativo</strong>, é necessário:</p>



<ul class="wp-block-list">
<li>Estruturas de matriz (como arrays bidimensionais);</li>



<li>Uso de bibliotecas como <a href="https://arm-software.github.io/CMSIS_5/DSP/html/index.html">CMSIS-DSP</a> (para ARM Cortex-M);</li>



<li>Alocação estática de memória (evitar <code>malloc</code>);</li>



<li>Processamento fora da interrupção (por ex., em tarefa de RTOS).</li>
</ul>



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



<p class="wp-block-paragraph">Essas estratégias visam garantir <strong>baixa latência</strong>, <strong>alta precisão</strong>, <strong>tempo real garantido</strong> e <strong>robustez frente a falhas</strong> – requisitos essenciais em controle embarcado.</p>



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



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



<h2 class="wp-block-heading">7. Padrões Relacionados e Modelos de Projeto</h2>



<p class="wp-block-paragraph">A implementação de algoritmos de controle em sistemas embarcados pode se beneficiar enormemente do uso de <strong>padrões de projeto (design patterns)</strong>. Esses padrões ajudam a estruturar o código de forma clara, reutilizável e extensível, permitindo manutenção mais fácil e maior confiabilidade, especialmente em sistemas de tempo real.</p>



<p class="wp-block-paragraph">Abaixo, listamos os principais padrões relacionados ao desenvolvimento de controladores de loop fechado:</p>



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



<h3 class="wp-block-heading">7.1 Strategy Pattern (Padrão Estratégia)</h3>



<p class="wp-block-paragraph">Esse é um dos mais diretamente aplicáveis ao controle. O Strategy Pattern permite que diferentes algoritmos de controle (PID, Bang-Bang, LQR, etc.) sejam intercambiáveis em tempo de execução, desde que implementem uma interface comum.</p>



<p class="wp-block-paragraph"><strong>Aplicação:</strong> Você define uma interface <code>ControlAlgorithm</code> com a função <code>compute(float error)</code>. Cada algoritmo implementa essa função de forma diferente.</p>



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



<ul class="wp-block-list">
<li>Facilita a troca dinâmica do controlador;</li>



<li>Permite testes A/B de algoritmos com a mesma infraestrutura de hardware;</li>



<li>Reutilização de código.</li>
</ul>



<p class="wp-block-paragraph"><strong>Exemplo em C:</strong></p>



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

typedef struct {
    control_function_t compute;
} ControlStrategy;

ControlStrategy pid_controller = { .compute = pid_compute };
ControlStrategy bangbang_controller = { .compute = bangbang_compute };

// No loop de controle:
float u = controller.compute(error);
" 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">typedef</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">float</span><span style="color: #D8DEE9FF"> (*control_function_t)</span><span style="color: #ECEFF4">(</span><span style="color: #88C0D0">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">error</span><span style="color: #ECEFF4">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #88C0D0">typedef</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">struct</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">control_function_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">compute</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">} ControlStrategy;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #88C0D0">ControlStrategy</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">pid_controller</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">{</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">.compute</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">pid_compute</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">}</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #88C0D0">ControlStrategy</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">bangbang_controller</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">{</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">.compute</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">bangbang_compute</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">}</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #88C0D0">//</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">No</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">loop</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">de</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">controle:</span></span>
<span class="line"><span style="color: #88C0D0">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">u</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">controller.compute</span><span style="color: #ECEFF4">(</span><span style="color: #88C0D0">error</span><span style="color: #ECEFF4">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span></code></pre></div>



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



<h3 class="wp-block-heading">7.2 State Pattern (Padrão de Estado)</h3>



<p class="wp-block-paragraph">Útil em sistemas com diferentes <strong>modos operacionais</strong>, como controle ativo, standby, segurança, etc. Cada estado pode usar um algoritmo de controle diferente, ou configurar parâmetros do PID de forma distinta.</p>



<p class="wp-block-paragraph"><strong>Aplicação:</strong> Você modela o sistema como uma <strong>máquina de estados</strong>, e cada estado contém um algoritmo ou conjunto de parâmetros.</p>



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



<ul class="wp-block-list">
<li>Estado “Aquecendo” usa PID.</li>



<li>Estado “Manutenção” usa Bang-Bang.</li>



<li>Estado “Falha” desliga a saída.</li>
</ul>



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



<h3 class="wp-block-heading">7.3 Singleton Pattern</h3>



<p class="wp-block-paragraph">Em muitos sistemas embarcados, o controlador é um único recurso global. O padrão Singleton garante que apenas uma instância do controlador esteja ativa e acessível globalmente (com cuidado em sistemas com multitarefa).</p>



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



<h3 class="wp-block-heading">7.4 Observer Pattern</h3>



<p class="wp-block-paragraph">Ideal para desacoplar o controlador dos sensores e atuadores. O controlador pode ser notificado quando um novo valor de sensor é lido (por exemplo, em RTOS ou eventos baseados em filas).</p>



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



<h3 class="wp-block-heading">7.5 Command Pattern</h3>



<p class="wp-block-paragraph">Útil quando se deseja encapsular comandos de controle, por exemplo para registrar comandos enviados, desfazer ações (undo), ou aplicar sequências de controle programadas.</p>



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



<h3 class="wp-block-heading">7.6 Aplicação Combinada com RTOS</h3>



<p class="wp-block-paragraph">Em sistemas com sistemas operacionais de tempo real (como FreeRTOS, Zephyr ou ThreadX), o controlador pode ser implementado como uma <strong>tarefa</strong> que bloqueia esperando um semáforo ou notificação de timer. Os padrões citados ajudam a estruturar essa tarefa:</p>



<ul class="wp-block-list">
<li>O Strategy define a lógica de controle;</li>



<li>O Observer permite que a tarefa reaja a eventos;</li>



<li>O State define modos de operação com diferentes estratégias.</li>
</ul>



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



<h3 class="wp-block-heading">Exemplo Integrado:</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" data-code="// Estrutura do controlador com Strategy
typedef struct {
    control_function_t compute;
    float Kp, Ki, Kd;
} PIDController;

float pid_compute(PIDController* pid, float error) {
    // implementação PID com base nos parâmetros
}
" 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">//</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Estrutura</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">do</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">controlador</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">com</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Strategy</span></span>
<span class="line"><span style="color: #88C0D0">typedef</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">struct</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">control_function_t</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">compute</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Kp,</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Ki,</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Kd</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">} PIDController;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #88C0D0">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">pid_compute</span><span style="color: #ECEFF4">(</span><span style="color: #88C0D0">PIDController*</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">pid,</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">error</span><span style="color: #ECEFF4">)</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">//</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">implementação</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">PID</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">com</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">base</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">nos</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">parâmetros</span></span>
<span class="line"><span style="color: #D8DEE9FF">}</span></span>
<span class="line"></span></code></pre></div>



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



<p class="wp-block-paragraph"><strong>Benefícios de usar padrões de projeto no controle:</strong></p>



<ul class="wp-block-list">
<li><strong>Clareza</strong>: separa claramente responsabilidades (cálculo, interface, hardware);</li>



<li><strong>Escalabilidade</strong>: facilita a evolução do sistema com novos algoritmos ou estados;</li>



<li><strong>Testabilidade</strong>: permite testes unitários isolados para cada componente;</li>



<li><strong>Reutilização</strong>: mesmo controlador pode ser usado em vários projetos.</li>
</ul>



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



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



<h2 class="wp-block-heading">8. Modelo de Amostragem: Exemplo Completo de Implementação PID em C</h2>



<p class="wp-block-paragraph">A seguir está um modelo funcional e modularizado de controlador PID em C. Ele pode ser adaptado facilmente para microcontroladores como STM32, AVR, ESP32 ou outros, e segue as boas práticas discutidas nas seções anteriores, incluindo encapsulamento, separação de responsabilidades e proteção contra saturações.</p>



<h3 class="wp-block-heading">8.1 Arquivo de Cabeçalho – <code>pid.h</code></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" data-code="#ifndef PID_H
#define PID_H

typedef struct {
    float Kp;
    float Ki;
    float Kd;
    float Ts;             // Tempo de amostragem em segundos
    float integral;
    float prev_error;
    float output_min;
    float output_max;
} PIDController;

// Inicializa os parâmetros do PID
void pid_init(PIDController* pid, float Kp, float Ki, float Kd, float Ts, float min, float max);

// Executa o cálculo do PID
float pid_compute(PIDController* pid, float setpoint, float measurement);

#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: #616E88">#ifndef PID_H</span></span>
<span class="line"><span style="color: #616E88">#define PID_H</span></span>
<span class="line"></span>
<span class="line"><span style="color: #88C0D0">typedef</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">struct</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Kp</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Ki</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Kd</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Ts</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF">             </span><span style="color: #88C0D0">//</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Tempo</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">de</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">amostragem</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">em</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">segundos</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">integral</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">prev_error</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">output_min</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">output_max</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">} PIDController;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #88C0D0">//</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Inicializa</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">os</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">parâmetros</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">do</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">PID</span></span>
<span class="line"><span style="color: #88C0D0">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">pid_init</span><span style="color: #ECEFF4">(</span><span style="color: #88C0D0">PIDController*</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">pid,</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Kp,</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Ki,</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Kd,</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Ts,</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">min,</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">max</span><span style="color: #ECEFF4">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #88C0D0">//</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Executa</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">o</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">cálculo</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">do</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">PID</span></span>
<span class="line"><span style="color: #88C0D0">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">pid_compute</span><span style="color: #ECEFF4">(</span><span style="color: #88C0D0">PIDController*</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">pid,</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">setpoint,</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">measurement</span><span style="color: #ECEFF4">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #616E88">#endif</span></span>
<span class="line"></span></code></pre></div>



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



<h3 class="wp-block-heading">8.2 Arquivo de Implementação – <code>pid.c</code></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" data-code="#include &quot;pid.h&quot;

void pid_init(PIDController* pid, float Kp, float Ki, float Kd, float Ts, float min, float max) {
    pid-&gt;Kp = Kp;
    pid-&gt;Ki = Ki;
    pid-&gt;Kd = Kd;
    pid-&gt;Ts = Ts;
    pid-&gt;integral = 0.0f;
    pid-&gt;prev_error = 0.0f;
    pid-&gt;output_min = min;
    pid-&gt;output_max = max;
}

float pid_compute(PIDController* pid, float setpoint, float measurement) {
    float error = setpoint - measurement;
    pid-&gt;integral += error * pid-&gt;Ts;

    // Anti-windup
    if (pid-&gt;integral &gt; pid-&gt;output_max) pid-&gt;integral = pid-&gt;output_max;
    if (pid-&gt;integral < pid-&gt;output_min) pid-&gt;integral = pid-&gt;output_min;

    float derivative = (error - pid-&gt;prev_error) / pid-&gt;Ts;
    pid-&gt;prev_error = error;

    float output = pid-&gt;Kp * error + pid-&gt;Ki * pid-&gt;integral + pid-&gt;Kd * derivative;

    // Saturação da saída
    if (output &gt; pid-&gt;output_max) output = pid-&gt;output_max;
    if (output < pid-&gt;output_min) output = pid-&gt;output_min;

    return output;
}
" 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: #616E88">#include &quot;pid.h&quot;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #88C0D0">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">pid_init</span><span style="color: #ECEFF4">(</span><span style="color: #88C0D0">PIDController*</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">pid,</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Kp,</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Ki,</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Kd,</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Ts,</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">min,</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">max</span><span style="color: #ECEFF4">)</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">pid-&gt;Kp</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Kp</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">pid-&gt;Ki</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Ki</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">pid-&gt;Kd</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Kd</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">pid-&gt;Ts</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Ts</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">pid-&gt;integral</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0.0</span><span style="color: #A3BE8C">f</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">pid-&gt;prev_error</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0.0</span><span style="color: #A3BE8C">f</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">pid-&gt;output_min</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">min</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">pid-&gt;output_max</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">max</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #88C0D0">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">pid_compute</span><span style="color: #ECEFF4">(</span><span style="color: #88C0D0">PIDController*</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">pid,</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">setpoint,</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">measurement</span><span style="color: #ECEFF4">)</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">error</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">setpoint</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">-</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">measurement</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">pid-&gt;integral</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">+=</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">error</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">pid</span><span style="color: #D8DEE9FF">-</span><span style="color: #81A1C1">&gt;</span><span style="color: #A3BE8C">Ts</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">//</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Anti-windup</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">(</span><span style="color: #88C0D0">pid-&gt;integral</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&gt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">pid</span><span style="color: #D8DEE9FF">-</span><span style="color: #81A1C1">&gt;</span><span style="color: #A3BE8C">output_max</span><span style="color: #ECEFF4">)</span><span style="color: #D8DEE9FF"> pid-</span><span style="color: #81A1C1">&gt;</span><span style="color: #D8DEE9FF">integral = pid-</span><span style="color: #81A1C1">&gt;</span><span style="color: #D8DEE9FF">output_max</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">(</span><span style="color: #88C0D0">pid-&gt;integral</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&lt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">pid</span><span style="color: #D8DEE9FF">-</span><span style="color: #81A1C1">&gt;</span><span style="color: #A3BE8C">output_min</span><span style="color: #ECEFF4">)</span><span style="color: #D8DEE9FF"> pid-</span><span style="color: #81A1C1">&gt;</span><span style="color: #D8DEE9FF">integral = pid-</span><span style="color: #81A1C1">&gt;</span><span style="color: #D8DEE9FF">output_min</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">derivative</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">=</span><span style="color: #D8DEE9FF"> (error </span><span style="color: #A3BE8C">-</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">pid</span><span style="color: #D8DEE9FF">-</span><span style="color: #81A1C1">&gt;</span><span style="color: #A3BE8C">prev_error</span><span style="color: #D8DEE9FF">) / pid-</span><span style="color: #81A1C1">&gt;</span><span style="color: #D8DEE9FF">Ts</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">pid-&gt;prev_error</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">error</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">output</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">pid</span><span style="color: #D8DEE9FF">-</span><span style="color: #81A1C1">&gt;</span><span style="color: #A3BE8C">Kp</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">error</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">+</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">pid</span><span style="color: #D8DEE9FF">-</span><span style="color: #81A1C1">&gt;</span><span style="color: #A3BE8C">Ki</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">pid</span><span style="color: #D8DEE9FF">-</span><span style="color: #81A1C1">&gt;</span><span style="color: #A3BE8C">integral</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">+</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">pid</span><span style="color: #D8DEE9FF">-</span><span style="color: #81A1C1">&gt;</span><span style="color: #A3BE8C">Kd</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">derivative</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">//</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Saturação</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">da</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">saída</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">(</span><span style="color: #88C0D0">output</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&gt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">pid</span><span style="color: #D8DEE9FF">-</span><span style="color: #81A1C1">&gt;</span><span style="color: #A3BE8C">output_max</span><span style="color: #ECEFF4">)</span><span style="color: #D8DEE9FF"> output = pid-</span><span style="color: #81A1C1">&gt;</span><span style="color: #D8DEE9FF">output_max</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">if</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">(</span><span style="color: #88C0D0">output</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&lt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">pid</span><span style="color: #D8DEE9FF">-</span><span style="color: #81A1C1">&gt;</span><span style="color: #A3BE8C">output_min</span><span style="color: #ECEFF4">)</span><span style="color: #D8DEE9FF"> output = pid-</span><span style="color: #81A1C1">&gt;</span><span style="color: #D8DEE9FF">output_min</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">return</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">output</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">}</span></span>
<span class="line"></span></code></pre></div>



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



<h3 class="wp-block-heading">8.3 Exemplo de Uso – <code>main.c</code></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" data-code="#include <stdio.h&gt;
#include &quot;pid.h&quot;

// Simulação de sensor e atuador
float read_sensor() {
    static float y = 0.0f;
    return y;
}

void write_actuator(float control_signal) {
    printf(&quot;Controle aplicado: %.2f\n&quot;, control_signal);
}

int main() {
    PIDController pid;
    pid_init(&amp;pid, 2.0f, 1.0f, 0.5f, 0.01f, 0.0f, 100.0f);  // Kp, Ki, Kd, Ts, min, max

    float setpoint = 50.0f;  // Valor desejado
    float process_value = 0.0f;

    for (int i = 0; i < 100; i++) {
        process_value = read_sensor();  // Aqui pode ser ADC
        float u = pid_compute(&amp;pid, setpoint, process_value);
        write_actuator(u);              // Aqui pode ser PWM
        // Simula atualização da variável controlada (pode incluir dinâmica)
    }

    return 0;
}
" 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: #616E88">#include &lt;stdio.h&gt;</span></span>
<span class="line"><span style="color: #616E88">#include &quot;pid.h&quot;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #88C0D0">//</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Simulação</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">de</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">sensor</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">e</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">atuador</span></span>
<span class="line"><span style="color: #88C0D0">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">read_sensor</span><span style="color: #ECEFF4">()</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">static</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">y</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0.0</span><span style="color: #A3BE8C">f</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: #A3BE8C">y</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #88C0D0">void</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">write_actuator</span><span style="color: #ECEFF4">(</span><span style="color: #88C0D0">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">control_signal</span><span style="color: #ECEFF4">)</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">printf</span><span style="color: #D8DEE9FF">(</span><span style="color: #88C0D0">&quot;Controle aplicado: %.2f\n&quot;</span><span style="color: #88C0D0">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">control_signal</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #88C0D0">int</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">main</span><span style="color: #ECEFF4">()</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">PIDController</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">pid</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">pid_init(</span><span style="color: #ECEFF4">&amp;</span><span style="color: #88C0D0">pid,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">2.0</span><span style="color: #A3BE8C">f,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">1.0</span><span style="color: #A3BE8C">f,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0.5</span><span style="color: #A3BE8C">f,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0.01</span><span style="color: #A3BE8C">f,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0.0</span><span style="color: #A3BE8C">f,</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">100.0</span><span style="color: #A3BE8C">f</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF">  </span><span style="color: #88C0D0">//</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Kp,</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Ki,</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Kd,</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Ts,</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">min,</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">max</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">setpoint</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">50.0</span><span style="color: #A3BE8C">f</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF">  </span><span style="color: #88C0D0">//</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Valor</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">desejado</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">process_value</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">0.0</span><span style="color: #A3BE8C">f</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">for</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">(</span><span style="color: #88C0D0">int</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">i</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">=</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: #88C0D0">i</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">&lt;</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">100</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF"> </span><span style="color: #88C0D0">i++</span><span style="color: #ECEFF4">)</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">{</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">process_value</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">read_sensor</span><span style="color: #ECEFF4">()</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF">  </span><span style="color: #88C0D0">//</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Aqui</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">pode</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">ser</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">ADC</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">u</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">pid_compute</span><span style="color: #ECEFF4">(&amp;</span><span style="color: #88C0D0">pid,</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">setpoint,</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">process_value</span><span style="color: #ECEFF4">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">write_actuator(u</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span><span style="color: #D8DEE9FF">              </span><span style="color: #88C0D0">//</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Aqui</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">pode</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">ser</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">PWM</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #88C0D0">//</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Simula</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">atualização</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">da</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">variável</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">controlada</span><span style="color: #D8DEE9FF"> (pode </span><span style="color: #A3BE8C">incluir</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">dinâmica</span><span style="color: #D8DEE9FF">)</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: #D8DEE9FF">}</span></span>
<span class="line"></span></code></pre></div>



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



<h3 class="wp-block-heading">8.4 Como Adaptar</h3>



<ul class="wp-block-list">
<li><strong>Em tempo real:</strong> coloque <code>pid_compute()</code> em uma ISR de timer (ex: a cada 10 ms).</li>



<li><strong>Leitura real:</strong> substitua <code>read_sensor()</code> por leitura via ADC (HAL ou bare-metal).</li>



<li><strong>Saída real:</strong> use <code>write_actuator()</code> com PWM, DAC ou GPIO para ativar o atuador.</li>



<li><strong>RTOS:</strong> execute o controle em uma tarefa periódica com prioridade adequada.</li>
</ul>



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



<h3 class="wp-block-heading">8.5 Extensões Possíveis</h3>



<ul class="wp-block-list">
<li>Adicionar <strong>limites de velocidade</strong> na saída (<code>du/dt</code>);</li>



<li>Incorporar <strong>filtro na entrada</strong> (sensor ruidoso);</li>



<li>Suporte a <strong>estratégias de controle alternativas</strong> (via ponteiro de função ou enum);</li>



<li>Log de dados e interface de monitoramento serial.</li>
</ul>



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



<h3 class="wp-block-heading">Conclusão do Modelo</h3>



<p class="wp-block-paragraph">Este exemplo serve como base robusta para <strong>qualquer aplicação embarcada com controle de malha fechada</strong>. Com pequenas alterações, pode ser usado para sistemas de corrente, temperatura, velocidade, posição, entre outros — tanto em aplicações industriais quanto acadêmicas ou hobby.</p>



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



<p class="wp-block-paragraph">Se você conhece ou desenvolveu um algoritmo de controle de loop fechado alternativo — seja uma variação do PID, um controlador adaptativo ou mesmo uma abordagem inovadora baseada em inteligência artificial — convidamos você a colaborar com este conteúdo! Compartilhe sua ideia e o código explicando sua lógica por meio de um <a href="https://gist.github.com/">GitHub Gist</a>, e envie o link nos comentários ou entre em contato. Sua contribuição poderá enriquecer ainda mais este guia e ajudar outros desenvolvedores e engenheiros na criação de sistemas de controle mais eficientes e criativos.</p><p>The post <a href="https://mcu.tec.br/algoritimos/algoritmos-de-controle-de-loop-fechado-guia-completo-com-pid-e-exemplos-em-c/">Algoritmos de Controle de Loop Fechado: Guia Completo com PID e Exemplos em C</a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">202</post-id>	</item>
	</channel>
</rss>
