
Passo 1 de 8
Ação integral: acumular erro ao longo do tempo
Entenda a ação integral como a memória das áreas de erro acumuladas no tempo e reconheça seus limites práticos.
Trilha de aprendizado · Nível 13 · Tutorial 6
Implementar a atualização numérica de um controlador PI e verificar suas parcelas em testes locais, antes de conectá-lo à atuação física.
Ação integral: acumular erro ao longo do tempo
Entenda a ação integral como a memória das áreas de erro acumuladas no tempo e reconheça seus limites práticos. 2 min
Separar as parcelas do PI paralelo
Separe as parcelas proporcional e integral de um PI paralelo e use o estado integral recém-atualizado para calcular o comando. 3 min
Conferir unidades e converter o período
Use análise dimensional e conversão explícita para manter as parcelas do PI coerentes com o período de atualização. 2 min
Rastrear uma sequência de erros
Calcule as parcelas proporcional e integral ao longo de uma sequência curta, preservando o estado entre atualizações. 3 min
Implementar o estado persistente em C/C++
Implemente a atualização discreta de um PI em C/C++, preservando o estado integral entre chamadas. 3 min
Verificar as parcelas em um teste local
Execute um teste de console autossuficiente para conferir as parcelas P, I e u* de uma rotina PI antes de qualquer conexão física. 3 min
Verificar a consistência temporal
Compare dois ensaios com o mesmo tempo total para verificar se a acumulação integral respeita o período de atualização. 3 min
Aplicação final: validar o núcleo PI
Concluir a validação de uma rotina PI identificando seus resultados esperados e os limites do que foi testado. 2 min

Passo 1 de 8
Entenda a ação integral como a memória das áreas de erro acumuladas no tempo e reconheça seus limites práticos.
A ação proporcional usa o erro agora: se e[k] muda, sua contribuição muda naquele instante. A ação integral acrescenta memória: ela reúne o erro que persistiu ao longo das atualizações.
Pense em cada intervalo como uma pequena área: altura igual ao erro e largura igual ao período de atualização Tₛ. A ação integral cresce ou diminui conforme a soma dessas áreas — não conforme uma única amostra isolada.

A proporcional acompanha a amostra atual; a integral conserva o efeito do histórico.
Sem usar cálculo integral, estime a acumulação com retângulos:
Com o mesmo Tₛ, quatro amostras de erro +2 acumulam o dobro da área de quatro amostras de erro +1. Se Tₛ for maior, cada retângulo também será mais largo.
Exemplo
Considere períodos iguais de 0,1 s.
Histórico A: erro +2 durante 3 atualizações
Área acumulada ≈ 3 × (+2) × 0,1 = +0,6
Histórico B: erro +2 por 2 atualizações e depois −2 por 1 atualização
Área acumulada ≈ 2 × (+2) × 0,1 + 1 × (−2) × 0,1 = +0,2
O erro negativo não apaga a memória “por mágica”: ele contribui com área de sinal oposto e reduz o acumulado.

Áreas de sinais opostos se compensam parcialmente.
Atenção
A ação integral pode ajudar a reduzir um erro constante, mas isso depende do sistema inteiro. Ela não garante que todo erro será eliminado.
Para essa redução ser possível, a malha precisa permanecer estável, a referência precisa ser alcançável e o atuador precisa ter margem para aplicar o comando necessário. Se a referência exigir mais do que a atuação disponível, ou se a malha se tornar instável, a memória integral não resolve a limitação.
Nesta etapa, trate a integral como uma parcela numérica a ser compreendida e testada; os limites de saída e a proteção contra acúmulo excessivo serão abordados adiante.
Exemplo
Dois históricos usam o mesmo período Tₛ:
Qual histórico produz a maior acumulação positiva de área?
Qual conclusão é correta para os históricos apresentados?
Qual afirmação descreve corretamente o limite da ação integral diante de um erro constante?

Passo 2 de 8
Separe as parcelas proporcional e integral de um PI paralelo e use o estado integral recém-atualizado para calcular o comando.
Um PI na forma paralela recebe o mesmo erro atual, e[k], em dois ramos:
Os ramos se reencontram no comando calculado:
u*[k] = P[k] + I[k]
Assim, P[k] não guarda histórico; I[k] é a memória acumulada; e u*[k] é a soma das duas parcelas. O asterisco indica que este é o comando calculado, antes de qualquer limitação de saída, que será tratada adiante.
![Diagrama do erro e[k] dividido em ramo proporcional e ramo integral com memória I[k − 1], reunidos na soma que produz u*[k].](https://cursa-json-routes.s3.amazonaws.com/learning-paths/pt/eletronica/bfb33b443480/level-13/tutorial-06/step-02/screen-01/item-02.webp)
O ramo proporcional usa o erro atual; o integral atualiza um estado que vem da amostra anterior.
A notação I[−1] é uma convenção para declarar o estado integral existente antes da primeira atualização, quando k = 0. Por exemplo, se o ensaio começa com I[−1] = 1, esse valor é o ponto de partida da atualização de I[0].
Em cada amostra, adote esta ordem:
Não some P[k] ao estado antigo I[k − 1]. E não acumule u*: somente o estado I é acumulado.
Exemplo
Considere, somente para este exemplo, K_p = 2, K_i × T_s = 0,5, e[0] = 3 e I[−1] = 1.
O comando usa I[0], não o valor inicial 1. Note também que 8,5 não é guardado como novo estado: o estado a preservar para a próxima atualização é I[0] = 2,5.
Associe cada expressão ao seu papel no PI paralelo.
Toque em um item e depois no par correspondente.
Organize uma atualização do PI. Considere que P[k] e o incremento já podem ser calculados a partir de e[k].

Passo 3 de 8
Use análise dimensional e conversão explícita para manter as parcelas do PI coerentes com o período de atualização.
A recorrência já conhecida é:
As unidades funcionam como uma checagem da equação. Se o erro e[k] está em volts (V) e o comando u* é normalizado, isto é, sem unidade, então P, I e o incremento integral também precisam ser adimensionais.

Nos dois ramos, o resultado deve ter a unidade do comando.
Exemplo
Para esse caso:
Logo:
Como I começa com unidade de comando e recebe incrementos de mesma unidade, I e u* permanecem adimensionais.
Use sempre T_s em segundos na atualização integral. Converta o período antes de multiplicar por K_i.
Não arredonde para zero: a parte fracionária representa o tempo decorrido entre atualizações.
Exemplos de períodos e sua forma adequada para a equação integral.
| Período informado | Cálculo | T_s em segundos |
|---|---|---|
| 5 ms | 5 ÷ 1000 | 0,005 s |
| 20 ms | 20 ÷ 1000 | 0,020 s |
| 250 µs | 250 ÷ 1 000 000 | 0,000250 s |
| 1,5 ms | 1,5 ÷ 1000 | 0,0015 s |
Dica
O período aparece uma única vez. K_i é um ganho por segundo; já o produto K_i × T_s é o coeficiente integral específico daquela atualização.
Se você definiu coefIntegral = K_i * T_s, use:
incremento = coefIntegral * e;
Não multiplique por T_s novamente. Da mesma forma, se usar K_i diretamente, calcule incremento = K_i * T_s * e;.
Para erro em volts e comando normalizado, qual unidade deve ter K_i?
Escreva pelo menos 3 caracteres (0/3).
Converta 750 µs para segundos e preencha o valor numérico.
Escreva pelo menos 5 caracteres (0/5).
Qual expressão calcula um incremento integral dimensionalmente correto quando erro está em V, Ki está em 1/(V·s) e Ts está em s?
Escreva pelo menos 10 caracteres (0/10).
Dica
Uma forma equivalente é guardar coefIntegral = Ki × Ts. Nesse caso, o incremento é coefIntegral × erro: T_s já está incorporado no coeficiente e não deve ser aplicado outra vez.

Passo 4 de 8
Calcule as parcelas proporcional e integral ao longo de uma sequência curta, preservando o estado entre atualizações.
Use a mesma atualização em cada amostra:
Nesta sequência, use K_p = 0,2, K_i = 0,2, T_s = 0,5 s e estado inicial I[−1] = 0,4. Os erros serão 1, 0 e −0,5.
A cada linha, calcule P e ΔI; atualize I com o valor vindo da linha anterior; por fim, calcule u usando o I já atualizado*. Os comandos calculados deste exemplo ficam entre 0 e 1.

A parcela proporcional muda imediatamente com o erro. O estado integral só muda quando há incremento integral.
Exemplo
Comece pelo estado declarado I[−1] = 0,4. Os valores desta atividade são apenas resultados numéricos de teste; o comando calculado permanece entre 0 e 1.
Rastreamento completo da sequência.
| k | e[k] | P[k] | ΔI[k] | I[k] | u*[k] |
|---|---|---|---|---|---|
| 0 | 1 | 0,2 | 0,1 | 0,5 | 0,7 |
| 1 | 0 | 0,0 | 0,0 | 0,5 | 0,5 |
| 2 | −0,5 | −0,1 | −0,05 | 0,45 | 0,35 |
Em k = 2, o erro negativo reduz I de 0,5 para 0,45. Ele não precisa tornar I negativo: isso depende do histórico acumulado e da magnitude dos incrementos.
Também note que I[2] = 0,45, enquanto u*[2] = 0,35. Integral e comando total são grandezas diferentes: o comando inclui também P[2] = −0,1.
Agora faça um rastreamento novo, sem consultar valores prontos. Use K_p = 0,2, K_i = 0,2, T_s = 0,5 s e I[−1] = 0,3. A sequência é e[0] = 0,5, e[1] = 0 e e[2] = −0,5.
Mantenha o estado de uma linha para a seguinte. Os comandos totais desse ensaio também ficam entre 0 e 1.
No novo ensaio, qual é o incremento integral ΔI[0]? Use vírgula ou ponto decimal.
No novo ensaio, qual é o estado integral I[1], após processar e[1] = 0? Use vírgula ou ponto decimal.
No novo ensaio, qual é o comando calculado u*[2], após processar e[2] = −0,5? Use vírgula ou ponto decimal.

Passo 5 de 8
Implemente a atualização discreta de um PI em C/C++, preservando o estado integral entre chamadas.
A rotina PI recebe a amostra atual erro, os ganhos e Ts em segundos. Porém, I não pode nascer de novo a cada chamada: ele guarda o histórico acumulado.
Defina-o fora da função, com valor inicial explícito. Em cada atualização:
P = Kp × erro;incremento = Ki × Ts × erro;I com o incremento;P + I já atualizado.P e incremento são temporários; I é o estado persistente.

O estado integral atravessa as chamadas; as variáveis locais de cálculo não precisam atravessá-las.
A variável global integral representa o estado I[k − 1] na entrada da função e passa a representar I[k] após a atualização. A função não lê sensor nem escreve PWM: ela apenas calcula o comando solicitado u*.
float integral = 0.0f; // estado inicial, antes do ensaio
float atualizarPI(float erro, float Kp, float Ki, float Ts) {
float P = Kp * erro;
float incremento = Ki * Ts * erro;
integral = integral + incremento;
float uCalculado = P + integral;
return uCalculado;
}Dica
Use float para não perder incrementos fracionários. Antes de iniciar um novo ensaio independente, inicialize explicitamente integral = 0.0f; — ou outro estado inicial definido pelo teste.
Dentro de um mesmo ensaio, cada chamada deve receber o valor deixado pela chamada anterior.
Atenção
Não declare nem zere o acumulador dentro de atualizarPI. Isso faria toda chamada começar em zero, convertendo a parcela integral em apenas mais um cálculo instantâneo.
Esta versão parece parecida, mas está incorreta: integral é criada novamente com zero em toda chamada. Assim, nenhum erro anterior é retido.
float atualizarPI(float erro, float Kp, float Ki, float Ts) {
float integral = 0.0f; // ERRADO: reinicia a cada chamada
float P = Kp * erro;
integral = integral + Ki * Ts * erro;
return P + integral;
}A variável local integral só existe durante uma execução da função. Ao retornar, ela deixa de existir; na chamada seguinte, volta a valer 0.0f.
Mantenha o estado fora da função nesta versão simples. Classes e estruturas podem organizar controladores mais tarde, mas não são necessárias para implementar a recorrência.
Complete a rotina preservando a ordem de atualização adotada.
float integral = 0.0f;
float atualizarPI(float erro, float Kp, float Ki, float Ts) {
float P = Kp * erro;
float incremento = ;
integral = ;
return ;
}
Passo 6 de 8
Execute um teste de console autossuficiente para conferir as parcelas P, I e u* de uma rotina PI antes de qualquer conexão física.
Use um programa de console local para testar somente a aritmética do PI: nenhuma placa, leitura de sensor ou saída PWM é necessária. Os ganhos e a sequência são dados de teste, não uma sugestão de sintonia.
Este ensaio reproduz a sequência não saturante calculada no step anterior: Kp = 0,2, Ki = 0,2, Ts = 0,5 s, estado inicial I[-1] = 0,3 e erros 0,5, 0 e -0,5. A cada amostra, registre P, o estado integral atualizado I e o comando calculado u*.

O teste processa uma amostra por vez: a integral atualizada em uma linha é o estado de partida da linha seguinte.
Crie no seu computador um arquivo chamado teste_pi.cpp, copie o programa completo e execute-o com seu editor e compilador. A variável global integral é definida uma vez antes do ensaio e reinicializada explicitamente apenas antes deste caso de teste.
Com g++, compile com:g++ -std=c++11 teste_pi.cpp -o teste_pi
Depois execute ./teste_pi no Linux/macOS ou teste_pi.exe no Windows. O programa não controla hardware; ele apenas imprime resultados numéricos.
Arquivo completo: teste_pi.cpp
#include <iomanip>
#include <iostream>
float integral = 0.0f;
float atualizarPI(float erro, float Kp, float Ki, float Ts) {
float P = Kp * erro;
float incremento = Ki * Ts * erro;
integral = integral + incremento;
return P + integral;
}
int main() {
const float Kp = 0.2f;
const float Ki = 0.2f;
const float Ts = 0.5f;
const float erros[] = {0.5f, 0.0f, -0.5f};
const int n = sizeof(erros) / sizeof(erros[0]);
integral = 0.3f;
std::cout << std::fixed << std::setprecision(3);
for (int k = 0; k < n; ++k) {
float P = Kp * erros[k];
float u = atualizarPI(erros[k], Kp, Ki, Ts);
std::cout << k << " P=" << P
<< " I=" << integral
<< " u*=" << u << "\n";
}
}0 P=0.100 I=0.350 u*=0.450 1 P=0.000 I=0.350 u*=0.350 2 P=-0.100 I=0.300 u*=0.200
Compare os valores numéricos. A impressão usa três casas decimais; internamente, a comparação de referência adotada é de 0,0001.
Compare cada parcela com a referência. Adote tolerância absoluta de 0,0001: dois valores a e b concordam quando |a - b| ≤ 0,0001. Como a saída é mostrada com três casas decimais, os valores abaixo devem também coincidir visualmente.
A coluna I[k] já inclui o incremento produzido pelo erro da própria linha. Todos os comandos deste ensaio ficam entre 0 e 1; isso apenas mantém o exemplo numérico dentro da faixa normalizada, sem testar limites de atuação.
Resultados após cada atualização, com Kp = 0,2, Ki = 0,2, Ts = 0,5 s e I inicial = 0,3.
| k | e[k] | P[k] | I[k] | u*[k] |
|---|---|---|---|---|
| 0 | 0,5 | 0,100 | 0,350 | 0,450 |
| 1 | 0,0 | 0,000 | 0,350 | 0,350 |
| 2 | -0,5 | -0,100 | 0,300 | 0,200 |
Complete a chamada usada dentro do laço de teste.
float u = atualizarPI(erros[], , , );Execute o programa e registre a linha k = 2: informe P, I e u* e diga se concordam com a referência dentro de 0,0001. Se observar divergência, compare também as linhas anteriores.
Pista de diagnóstico: se I for reiniciada em cada chamada, a última linha tende a mostrar I = -0,050 e u* = -0,150. Se o comando for somado ao estado anterior em vez do atualizado, a divergência aparece desde a primeira linha. A ausência de Ts altera os incrementos, mesmo que alguns valores possam coincidir por acaso em uma linha isolada.
Escreva pelo menos 30 caracteres (0/30).

Passo 7 de 8
Compare dois ensaios com o mesmo tempo total para verificar se a acumulação integral respeita o período de atualização.
Considere dois ensaios independentes da mesma rotina integral. Em ambos, mantenha Kᵢ = 0,5, e = 2,0, I inicial = 0,1 e duração total de 1,0 s.
O estado inicial é apenas o ponto de partida: ele não corresponde a uma atualização extra. Em cada ensaio, N atualizações representam exatamente N × Tₛ segundos de acumulação.

Com erro constante, diminuir Tₛ reduz a largura — e o incremento — de cada retângulo, mas aumenta a quantidade de atualizações no mesmo tempo.
Dica
Os valores previstos são obtidos sem simular amostra a amostra:
I final = I inicial + Kᵢ × e × N × Tₛ
Como N × Tₛ vale 1,0 s nos dois casos, ambos devem terminar em:
I final = 0,1 + 0,5 × 2,0 × 1,0 = 1,1
Isso verifica especificamente a acumulação integral. Não conclua, por isso, que duas malhas fechadas com períodos diferentes terão a mesma estabilidade ou resposta: essa análise exige outros critérios.
Compare o tamanho de cada passo e a quantidade de passos. O produto entre eles permanece igual.
| Ensaio | Tₛ (s) | N | Incremento por atualização | I final previsto |
|---|---|---|---|---|
| A | 0,100 | 10 | 0,5 × 0,100 × 2,0 = 0,100 | 1,100 |
| B | 0,025 | 40 | 0,5 × 0,025 × 2,0 = 0,025 | 1,100 |
A contagem correta começa na primeira atualização e termina na N-ésima. Por exemplo, no ensaio A há 10 incrementos de 0,100; não há um 11º incremento associado ao valor inicial I = 0,1.
Se uma implementação produz resultados muito diferentes nesses dois ensaios, confira se ela multiplica por Tₛ em cada incremento e se executa exatamente N atualizações.
No seu computador, crie um arquivo chamado consistencia_pi.cpp, cole o programa e execute-o com um compilador C++ local. Por exemplo, em um terminal com g++:
g++ -std=c++11 consistencia_pi.cpp -o consistencia_pi
Depois execute ./consistencia_pi no Linux/macOS ou consistencia_pi.exe no Windows. Os dois resultados devem ser iguais dentro da tolerância declarada.
Programa completo para comparar dois períodos de atualização.
#include <cmath>
#include <iomanip>
#include <iostream>
double acumular(double i_inicial, double ki, double erro,
double ts, int n) {
double i = i_inicial;
for (int k = 0; k < n; ++k) {
i += ki * ts * erro;
}
return i;
}
int main() {
const double ki = 0.5;
const double erro = 2.0;
const double i_inicial = 0.1;
double i_a = acumular(i_inicial, ki, erro, 0.100, 10);
double i_b = acumular(i_inicial, ki, erro, 0.025, 40);
std::cout << std::fixed << std::setprecision(6);
std::cout << "Ensaio A: " << i_a << "\n";
std::cout << "Ensaio B: " << i_b << "\n";
std::cout << "Diferenca: " << std::fabs(i_a - i_b) << "\n";
std::cout << "Consistente: "
<< (std::fabs(i_a - i_b) < 1e-6 ? "sim" : "nao")
<< "\n";
}Ensaio A: 1.100000 Ensaio B: 1.100000 Diferenca: 0.000000 Consistente: sim
A última casa exibida pode variar ligeiramente entre compiladores por ponto flutuante. O critério do programa é a diferença menor que 1e-6.
Complete a expressão que relaciona atualizações, período e acumulação para erro constante.
double tempo_total = * ;
double i_final = i_inicial + ki * erro * N * ;Uma rotina atualiza i += ki * erro; e omite Tₛ. Com o mesmo erro durante 1 segundo, ela resulta em valores diferentes para Tₛ = 0,100 s e Tₛ = 0,025 s. Qual é o defeito principal?

Passo 8 de 8
Concluir a validação de uma rotina PI identificando seus resultados esperados e os limites do que foi testado.
Antes de considerar qualquer uso fora do teste local, revise o núcleo numérico. Em cada atualização:
P = Kp * erro.Ki * Ts * erro.integral já existente.P + integral, usando a integral recém-atualizada.Nesta revisão, Ts deve estar em segundos e aparecer uma única vez no incremento. O estado inicial precisa ser explícito antes do ensaio e não pode ser reinicializado entre amostras do mesmo ensaio.

O ramo integral recebe o estado anterior, é atualizado uma vez por amostra e só então compõe o comando calculado.
Dica
Checklist final:
Ts foi convertido para segundos.Ki * Ts * erro, sem omitir nem duplicar Ts.integral recebeu um valor inicial declarado antes do ensaio.P + integral após a atualização.Essa lista valida a aritmética e a ordem da rotina. Ela não testa planta, sensor, atuador, limites de saída nem comportamento em malha fechada.
Complete a rotina. Considere erro em volts, comando normalizado e Ts já expresso em segundos.
float integral = 0.40f; // estado inicial, antes do ensaio
float atualizarPI(float erro, float Kp, float Ki, float Ts) {
float P = * erro;
integral = integral + * Ts * erro;
return P + ;
}Faça um novo ensaio numérico local, sem conectar hardware. Use:
Kp = 0,20 1/VKi = 0,40 1/(V·s)Ts = 0,050 sI[-1] = 0,40e[0] = 1,0 V, e[1] = 0 V e e[2] = -0,5 VPreserve integral de uma atualização para a seguinte. Este caso foi escolhido para que os três comandos calculados permaneçam entre 0 e 1: ele valida apenas a aritmética na região não saturada.
Após processar e[2] = -0,5 V, informe a linha final: P[2], I[2] e u*[2].
Escreva pelo menos 20 caracteres (0/20).
Em um ensaio independente, mantenha erro = 1,0 V durante 0,150 s, com Ki = 0,40 1/(V·s) e I inicial = 0,40. Se Ts = 0,025 s, são 6 atualizações. Qual será o valor final de I?
Resumo
Atenção
Uma rotina aprovada nesses testes ainda não está autorizada a comandar uma saída física. Ela não foi verificada diante de saturação, referência inalcançável, dinâmica da planta, ruído, atrasos ou perda de prazo.
No próximo tutorial, você tratará o anti-windup por integração condicional antes dos ensaios de ajuste no circuito RC.
Parabéns! Você concluiu: Controlador PI em tempo discreto
Milhares de cursos online em vídeo, ebooks e áudiobooks.
Para testar seus conhecimentos no decorrer dos cursos online
Gerado diretamente na galeria de fotos do seu celular e enviado ao seu e-mail
Baixe nosso aplicativo pelo QR Code ou pelos links abaixo:.
+ de 10 milhões
de alunos
Certificado grátis e
válido em todo o Brasil
60 mil exercícios
gratuitos
4,8/5 classificação
nas lojas de apps
Cursos gratuitos em
vídeo, ebooks e audiobooks