<?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>projeto robótico - MCU &amp; FPGA</title>
	<atom:link href="https://mcu.tec.br/tags/projeto-robotico/feed/" rel="self" type="application/rss+xml" />
	<link>https://mcu.tec.br</link>
	<description>Microcontroladores &#38; FPGA</description>
	<lastBuildDate>Fri, 28 Mar 2025 19:21:12 +0000</lastBuildDate>
	<language>pt-BR</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=7.1</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>projeto robótico - MCU &amp; FPGA</title>
	<link>https://mcu.tec.br</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>O Desafio de Equilibrar um Equipamento com Duas Rodas</title>
		<link>https://mcu.tec.br/algoritimos/o-desafio-de-equilibrar-um-equipamento-com-duas-rodas/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=o-desafio-de-equilibrar-um-equipamento-com-duas-rodas</link>
		
		<dc:creator><![CDATA[Carlos Delfino]]></dc:creator>
		<pubDate>Mon, 31 Mar 2025 18:57:26 +0000</pubDate>
				<category><![CDATA[Algoritimos]]></category>
		<category><![CDATA[algoritmo de controle]]></category>
		<category><![CDATA[código C para robótica]]></category>
		<category><![CDATA[controle em tempo real]]></category>
		<category><![CDATA[controle PID]]></category>
		<category><![CDATA[equilíbrio dinâmico]]></category>
		<category><![CDATA[filtro complementar]]></category>
		<category><![CDATA[IMU]]></category>
		<category><![CDATA[motor DC]]></category>
		<category><![CDATA[MPU6050]]></category>
		<category><![CDATA[pêndulo invertido]]></category>
		<category><![CDATA[projeto robótico]]></category>
		<category><![CDATA[robô autoequilibrante]]></category>
		<category><![CDATA[robô de duas rodas]]></category>
		<category><![CDATA[robô equilibrado]]></category>
		<category><![CDATA[sensores inerciais]]></category>
		<guid isPermaLink="false">https://mcu.tec.br/?p=276</guid>

					<description><![CDATA[<p>Aprenda como funciona um robô autoequilibrante com duas rodas. Este tutorial completo explica os sensores utilizados, o algoritmo PID com filtro complementar e apresenta código C detalhado com fórmulas físicas e controle em tempo real.</p>
<p>The post <a href="https://mcu.tec.br/algoritimos/o-desafio-de-equilibrar-um-equipamento-com-duas-rodas/">O Desafio de Equilibrar um Equipamento com Duas Rodas</a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></description>
										<content:encoded><![CDATA[<p class="wp-block-paragraph">Equilibrar um equipamento sobre duas rodas, como um robô autoestabilizante (inspirado no famoso Segway), é uma tarefa complexa e instigante dentro do universo da robótica móvel. Ao contrário de veículos com três ou quatro rodas, que possuem estabilidade estática, um sistema com apenas duas rodas exige controle dinâmico contínuo para se manter na vertical. Isso ocorre porque seu centro de massa está acima do ponto de apoio (as rodas), formando um sistema inerentemente instável que se comporta como um pêndulo invertido.</p>



<p class="wp-block-paragraph">Esse desafio é abordado utilizando sensores para medir o estado atual do sistema (como inclinação e velocidade angular), atuadores para aplicar forças corretivas (como motores DC ou brushless com controle PWM), e um algoritmo de controle de loop fechado que ajusta continuamente os comandos para manter o equilíbrio. O objetivo é detectar desvios do equilíbrio vertical e aplicar correções na direção e intensidade adequadas para restaurar o alinhamento.</p>



<h4 class="wp-block-heading"><strong>Sensores Comuns Utilizados</strong></h4>



<ul class="wp-block-list">
<li><strong>IMU (Unidade de Medição Inercial)</strong>: Contém acelerômetro (mede aceleração linear) e giroscópio (mede velocidade angular). Alguns modelos também incluem magnetômetro.</li>



<li><strong>Encoder nos Motores</strong>: Para medir a rotação das rodas e estimar a velocidade do deslocamento.</li>



<li><strong>Sensor de Ultrassom ou ToF (opcional)</strong>: Pode ser usado para evitar obstáculos ou medir distância do chão, mas não é necessário para o equilíbrio.</li>
</ul>



<h4 class="wp-block-heading"><strong>Atuadores Comuns Utilizados</strong></h4>



<ul class="wp-block-list">
<li><strong>Motores DC ou Brushless com controle PWM</strong>: Conectados a um driver de potência, como L298N, VNH5019, ou drivers MOSFETs.</li>



<li><strong>Placa de controle (microcontrolador)</strong>: Tipicamente um STM32, ESP32, Arduino ou Raspberry Pi.</li>
</ul>



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



<p class="wp-block-paragraph">Equipamentos de duas rodas autoequilibrantes podem ser usados em:</p>



<ul class="wp-block-list">
<li>Robôs de entrega ou vigilância.</li>



<li>Cadeiras de rodas inteligentes.</li>



<li>Plataformas móveis autônomas.</li>



<li>Brinquedos ou dispositivos educacionais.</li>
</ul>



<p class="wp-block-paragraph">O domínio deste controle é um excelente exercício para estudar sistemas de controle de tempo real, fusão de sensores e algoritmos matemáticos aplicados a sistemas físicos.</p>



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



<h3 class="wp-block-heading"><strong>Fundamentos Teóricos e Algoritmo de Controle</strong></h3>



<h4 class="wp-block-heading"><strong>1. O Pêndulo Invertido: Modelagem Física</strong></h4>



<p class="wp-block-paragraph">O comportamento de um robô de duas rodas é matematicamente semelhante a um pêndulo invertido. Quando a estrutura do robô se inclina para frente ou para trás, a gravidade gera um torque que o faz cair, exigindo uma ação ativa do motor para restaurar o equilíbrio.</p>



<p class="wp-block-paragraph">A equação que governa o pêndulo invertido com base em torque é derivada das leis de Newton e pode ser escrita como:</p>



<p class="wp-block-paragraph">\[<br>\tau = I \cdot \alpha = m \cdot g \cdot l \cdot \sin(\theta)<br>\]



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



<ul class="wp-block-list">
<li>τ = torque aplicado</li>



<li>I = momento de inércia do sistema</li>



<li>α = aceleração angular</li>



<li>m = massa da estrutura</li>



<li>g = aceleração da gravidade</li>



<li>ll = distância do centro de massa ao ponto de rotação</li>



<li>θ = ângulo de inclinação em relação à vertical</li>
</ul>



<p class="wp-block-paragraph">Para manter o equilíbrio, o sistema precisa aplicar torque (via motor) em resposta ao desvio angular θ, de forma a gerar uma aceleração que compense a tendência de queda.</p>



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



<h4 class="wp-block-heading"><strong>2. Fusão Sensorial: Filtro Complementar</strong></h4>



<p class="wp-block-paragraph">Sensores IMU fornecem dois tipos de medidas:</p>



<ul class="wp-block-list">
<li>O <strong>acelerômetro</strong> detecta o ângulo de inclinação, mas é sensível a ruído e vibrações.</li>



<li>O <strong>giroscópio</strong> detecta a velocidade angular com boa precisão, mas sofre de <em>drift</em> (desvio acumulado com o tempo).</li>
</ul>



<p class="wp-block-paragraph">O <strong>filtro complementar</strong> combina os dois sensores para obter um ângulo mais estável: </p>



<p class="wp-block-paragraph">\[<br>\theta_{\text{estimado}} = \alpha \cdot (\theta_{\text{anterior}} + \omega \cdot \Delta t) + (1 &#8211; \alpha) \cdot \theta_{\text{acc}}<br>\]



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



<ul class="wp-block-list">
<li>ω = velocidade angular do giroscópio</li>



<li>θacc = ângulo estimado pelo acelerômetro</li>



<li>α = coeficiente de mistura (tipicamente entre 0.90 e 0.98)</li>



<li>Δt = tempo entre amostras</li>
</ul>



<p class="wp-block-paragraph">Esse filtro suaviza os dados e mantém uma estimativa confiável da inclinação.</p>



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



<h4 class="wp-block-heading"><strong>3. Controle PID: Algoritmo de Feedback</strong></h4>



<p class="wp-block-paragraph">O PID é um controlador de malha fechada que calcula a força de correção com base em três componentes:</p>



<ul class="wp-block-list">
<li><strong>Proporcional (P):</strong> Corrige proporcionalmente ao erro atual.</li>



<li><strong>Integral (I):</strong> Corrige erros acumulados ao longo do tempo.</li>



<li><strong>Derivativo (D):</strong> Reage à taxa de variação do erro.</li>
</ul>



<p class="wp-block-paragraph">A equação do PID contínuo é: </p>



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



<p class="wp-block-paragraph">Na forma discreta, para ser usada em código C:</p>



<p class="wp-block-paragraph">\[<br>\begin{align*} e[k] &amp;= \theta_{\text{ref}} &#8211; \theta[k] \\ \text{erro\_integral} &amp;= \text{erro\_integral} + e[k] \cdot \Delta t \\ \text{erro\_derivada} &amp;= \frac{e[k] &#8211; e[k-1]}{\Delta t} \\ u[k] &amp;= K_p \cdot e[k] + K_i \cdot \text{erro\_integral} + K_d \cdot \text{erro\_derivada} \end{align*}<br>\]



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



<ul class="wp-block-list">
<li>u[k] = sinal de controle (PWM do motor)</li>



<li>θref = posição desejada (em geral 0°, ou vertical)</li>



<li>e[k] = erro no instante atual</li>



<li>Δt = tempo entre atualizações (período da amostragem)</li>
</ul>



<p class="wp-block-paragraph">A saída do PID é então convertida em um comando PWM aplicado ao motor, movimentando o robô para corrigir a inclinação.</p>



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



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



<h3 class="wp-block-heading"><strong>Código de Implementação</strong></h3>



<p class="wp-block-paragraph">A seguir está uma versão simplificada do controlador de equilíbrio para um robô de duas rodas. O código assume que já há uma função para ler os dados da IMU e enviar sinais PWM para os motores.</p>



<h4 class="wp-block-heading"><strong>1. Definições e Variáveis Globais</strong></h4>



<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 DT 0.01  // Intervalo de amostragem em segundos (10ms)
#define ALPHA 0.98  // Coeficiente do filtro complementar

// Constantes do PID
float Kp = 35.0;
float Ki = 0.5;
float Kd = 0.8;

// Variáveis do PID
float error = 0, previous_error = 0;
float integral = 0, derivative = 0;
float control_signal = 0;

// Variáveis do filtro complementar
float angle_gyro = 0;
float angle_acc = 0;
float angle = 0;  // Ângulo estimado final
" 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 DT 0.01  // Intervalo de amostragem em segundos (10ms)</span></span>
<span class="line"><span style="color: #616E88">#define ALPHA 0.98  // Coeficiente do filtro complementar</span></span>
<span class="line"></span>
<span class="line"><span style="color: #88C0D0">//</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Constantes</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">Kp</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">35.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">Ki</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">Kd</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>
<span class="line"><span style="color: #88C0D0">//</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Variáveis</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">error</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: #A3BE8C">,</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</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</span><span style="color: #A3BE8C">,</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"> </span><span style="color: #B48EAD">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">control_signal</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>
<span class="line"></span>
<span class="line"><span style="color: #88C0D0">//</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Variáveis</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">do</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">filtro</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">complementar</span></span>
<span class="line"><span style="color: #88C0D0">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">angle_gyro</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>
<span class="line"><span style="color: #88C0D0">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">angle_acc</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>
<span class="line"><span style="color: #88C0D0">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">angle</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">//</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Ângulo</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">estimado</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">final</span></span>
<span class="line"></span></code></pre></div>



<h4 class="wp-block-heading"><strong>2. Função para Atualização do Ângulo com Filtro Complementar</strong></h4>



<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 atualizar_angulo(float acc_y, float acc_z, float gyro_x) {
    // Estimativa de inclinação a partir do acelerômetro (em graus)
    angle_acc = atan2(acc_y, acc_z) * 180 / 3.14159;

    // Integração da velocidade angular do giroscópio
    angle_gyro += gyro_x * DT;

    // Fusão dos sensores
    angle = ALPHA * angle_gyro + (1 - ALPHA) * angle_acc;
}
" 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">atualizar_angulo</span><span style="color: #ECEFF4">(</span><span style="color: #88C0D0">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">acc_y,</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">acc_z,</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">gyro_x</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">Estimativa</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">de</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">inclinação</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">a</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">partir</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">do</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">acelerômetro</span><span style="color: #D8DEE9FF"> (em </span><span style="color: #A3BE8C">graus</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">angle_acc</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">=</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">atan2</span><span style="color: #ECEFF4">(</span><span style="color: #88C0D0">acc_y,</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">acc_z</span><span style="color: #ECEFF4">)</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">180</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">/</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">3.14159</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">Integração</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">da</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">velocidade</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">angular</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">do</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">giroscópio</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">angle_gyro</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">+=</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">gyro_x</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">DT</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">Fusão</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">dos</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">sensores</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">angle</span><span style="color: #D8DEE9FF"> </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"> </span><span style="color: #A3BE8C">angle_gyro</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"> angle_acc</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">}</span></span>
<span class="line"></span></code></pre></div>



<h4 class="wp-block-heading"><strong>3. Função de Controle PID</strong></h4>



<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 controle_PID(float setpoint) {
    error = setpoint - angle;
    integral += error * DT;
    derivative = (error - previous_error) / DT;

    control_signal = Kp * error + Ki * integral + Kd * derivative;

    previous_error = error;

    aplicar_PWM(control_signal);  // Envia o sinal para os motores
}
" 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">controle_PID</span><span style="color: #ECEFF4">(</span><span style="color: #88C0D0">float</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">setpoint</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">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">angle</span><span style="color: #81A1C1">;</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">DT</span><span style="color: #81A1C1">;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">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">) / DT</span><span style="color: #81A1C1">;</span></span>
<span class="line"></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">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>
<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>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">aplicar_PWM(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">Envia</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">o</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">sinal</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">para</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">os</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">motores</span></span>
<span class="line"><span style="color: #D8DEE9FF">}</span></span>
<span class="line"></span></code></pre></div>



<h4 class="wp-block-heading"><strong>4. Laço Principal de Controle</strong></h4>



<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 loop_de_controle() {
    float acc_y, acc_z, gyro_x;

    // 1. Ler sensores da IMU
    ler_IMU(&amp;acc_y, &amp;acc_z, &amp;gyro_x);  // Função hipotética de leitura

    // 2. Atualizar ângulo estimado
    atualizar_angulo(acc_y, acc_z, gyro_x);

    // 3. Controlar com PID para manter posição vertical (0 graus)
    controle_PID(0.0);

    // 4. Esperar próximo ciclo
    delay_ms(DT * 1000);
}
" 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">loop_de_controle</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">acc_y,</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">acc_z,</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">gyro_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: #B48EAD">1</span><span style="color: #A3BE8C">.</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Ler</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">sensores</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">da</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">IMU</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">ler_IMU(</span><span style="color: #ECEFF4">&amp;</span><span style="color: #88C0D0">acc_y,</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&amp;</span><span style="color: #88C0D0">acc_z,</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&amp;</span><span style="color: #88C0D0">gyro_x</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">Função</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">hipotética</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">de</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">leitura</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: #B48EAD">2</span><span style="color: #A3BE8C">.</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Atualizar</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">ângulo</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">estimado</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">atualizar_angulo(acc_y,</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">acc_z,</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">gyro_x</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">//</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">3</span><span style="color: #A3BE8C">.</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Controlar</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">com</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">PID</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">para</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">manter</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">posição</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">vertical</span><span style="color: #D8DEE9FF"> (0 </span><span style="color: #A3BE8C">graus</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">controle_PID(0.0</span><span style="color: #D8DEE9FF">)</span><span style="color: #81A1C1">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">//</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">4</span><span style="color: #A3BE8C">.</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">Esperar</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">próximo</span><span style="color: #D8DEE9FF"> </span><span style="color: #A3BE8C">ciclo</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #88C0D0">delay_ms(DT</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">*</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">1000</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></code></pre></div>



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



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



<ul class="wp-block-list">
<li><strong>Leitura da IMU:</strong> a função <code>ler_IMU()</code> deve ser adaptada ao seu hardware. A maioria dos sensores como MPU6050 usam I2C.</li>



<li><strong>Saturação do PWM:</strong> é importante limitar o valor de <code>control_signal</code> para evitar sobrecarga nos motores (ex: clamp entre -255 e +255).</li>



<li><strong>Direção dos motores:</strong> valores positivos e negativos devem acionar os motores em sentidos opostos.</li>



<li><strong>Calibração:</strong> os valores de Kp, Ki, Kd devem ser ajustados empiricamente (tuning) para cada robô, podendo-se usar técnicas como Ziegler–Nichols ou tentativa e erro.</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/><p>The post <a href="https://mcu.tec.br/algoritimos/o-desafio-de-equilibrar-um-equipamento-com-duas-rodas/">O Desafio de Equilibrar um Equipamento com Duas Rodas</a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">276</post-id>	</item>
	</channel>
</rss>
