Trilha de aprendizado · Nível 13 · Tutorial 6

Controlador PI em tempo discreto

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.

  • Nível: Avançado
  • Duração: 20 min
  • 8 passos
Controlador PI em tempo discreto

O que você vai percorrer

  1. 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
  2. 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
  3. 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
  4. 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
  5. 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
  6. 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
  7. 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
  8. 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

O que você vai aprender

  • Calcular as parcelas proporcional e integral para uma sequência de erros.
  • Escolher unidades consistentes para K_p, K_i e T_s.
  • Implementar o estado integral sem reinicializá-lo a cada chamada.
  • Verificar a influência correta do período de atualização sobre a acumulação.

Antes de começar

  • Controle proporcional de uma saída RC
  • Funções com parâmetros e retorno
  • Período de atualização e orçamento de execução

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.

Integral é memória temporal

Erro instantâneo e memória

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.

Duas formas de responder ao erro

Comparação entre uma amostra instantânea de erro e vários retângulos de área acumulada ao longo do tempo.

A proporcional acompanha a amostra atual; a integral conserva o efeito do histórico.

O que cada intervalo deixa na memória

Somar áreas discretas

Sem usar cálculo integral, estime a acumulação com retângulos:

  • erro positivo durante um intervalo: área positiva;
  • erro nulo: área zero;
  • erro negativo: área negativa;
  • erro de maior magnitude ou que dura mais tempo: área de maior módulo.

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

Exemplo: sinais opostos

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.

Área depende de sinal e duração

Dois históricos de erro em retângulos: um com três áreas positivas e outro com duas positivas e uma negativa.

Áreas de sinais opostos se compensam parcialmente.

Compare antes de concluir

Atenção

Memória não é garantia

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

Compare as áreas

Dois históricos usam o mesmo período Tₛ:

  • A: erro +1 por 6 atualizações.
  • B: erro +3 por 2 atualizações e erro 0 por 4 atualizações.

Qual histórico produz a maior acumulação positiva de área?

Verificação

Qual conclusão é correta para os históricos apresentados?

Condições para reduzir o erro

Qual afirmação descreve corretamente o limite da ação integral diante de um erro constante?

Passo 2 de 8

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.

Identifique os três resultados

Dois ramos, um comando

Um PI na forma paralela recebe o mesmo erro atual, e[k], em dois ramos:

  • Proporcional: responde ao erro desta amostra: P[k] = K_p × e[k].
  • Integral: parte do estado guardado e acrescenta a contribuição da amostra: I[k] = I[k − 1] + K_i × T_s × e[k].

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.

Estrutura do PI paralelo

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].

O ramo proporcional usa o erro atual; o integral atualiza um estado que vem da amostra anterior.

Atualize primeiro, some depois

Ordem da atualização

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:

  1. Calcule P[k] usando e[k].
  2. Calcule o incremento integral K_i × T_s × e[k].
  3. Some o incremento a I[k − 1] para obter I[k].
  4. Some P[k] ao I[k] recém-atualizado para obter u*[k].

Não some P[k] ao estado antigo I[k − 1]. E não acumule u*: somente o estado I é acumulado.

Exemplo

Exemplo na primeira amostra

Considere, somente para este exemplo, K_p = 2, K_i × T_s = 0,5, e[0] = 3 e I[−1] = 1.

  1. P[0] = 2 × 3 = 6
  2. Incremento integral = 0,5 × 3 = 1,5
  3. I[0] = 1 + 1,5 = 2,5
  4. u*[0] = 6 + 2,5 = 8,5

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.

Verifique os papéis

Papéis das expressões

Associe cada expressão ao seu papel no PI paralelo.

Toque em um item e depois no par correspondente.

Pratique a ordem correta

Sequência de cálculo

Organize uma atualização do PI. Considere que P[k] e o incremento já podem ser calculados a partir de e[k].

  1. Atualizar I[k] = I[k − 1] + incremento
  2. Calcular u*[k] = P[k] + I[k]
  3. Calcular P[k] = K_p × e[k] e o incremento K_i × T_s × e[k]

Passo 3 de 8

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.

Unidades que fecham a equação

Uma unidade para cada parcela

A recorrência já conhecida é:

  • P[k] = K_p × e[k]
  • I[k] = I[k − 1] + K_i × T_s × e[k]
  • u*[k] = P[k] + I[k]

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.

Fluxo dimensional do PI

Diagrama mostrando que os ramos proporcional e integral convertem erro em volts para um comando sem unidade.

Nos dois ramos, o resultado deve ter a unidade do comando.

Exemplo

Cheque as dimensões

Para esse caso:

  • K_p: comando por volt → 1/V
  • K_i: comando por volt por segundo → 1/(V·s)
  • T_s: segundo → s

Logo:

  • P = (1/V) × V = 1
  • incremento de I = [1/(V·s)] × s × V = 1

Como I começa com unidade de comando e recebe incrementos de mesma unidade, I e u* permanecem adimensionais.

Tempo em segundos, uma vez só

Converta o período explicitamente

Use sempre T_s em segundos na atualização integral. Converta o período antes de multiplicar por K_i.

  • 25 ms = 25 ÷ 1000 s = 0,025 s
  • 400 µs = 400 ÷ 1 000 000 s = 0,0004 s

Não arredonde para zero: a parte fracionária representa o tempo decorrido entre atualizações.

Conversões frequentes

Exemplos de períodos e sua forma adequada para a equação integral.

T_s usado em K_i × T_s × e
Período informadoCálculoT_s em segundos
5 ms5 ÷ 10000,005 s
20 ms20 ÷ 10000,020 s
250 µs250 ÷ 1 000 0000,000250 s
1,5 ms1,5 ÷ 10000,0015 s

Dica

K_i não é K_i × T_s

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;.

Pratique as conversões

Unidade da ação integral

Para erro em volts e comando normalizado, qual unidade deve ter K_i?

Escreva pelo menos 3 caracteres (0/3).

Conversão de período

Converta 750 µs para segundos e preencha o valor numérico.

Escreva pelo menos 5 caracteres (0/5).

Detecte o período duplicado

Cheque a expressão

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

Regra de conferência

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

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.

Acompanhe os dois comportamentos

O estado segue de uma amostra para a próxima

Use a mesma atualização em cada amostra:

  • P[k] = K_p × e[k]
  • ΔI[k] = K_i × T_s × e[k]
  • I[k] = I[k − 1] + ΔI[k]
  • u*[k] = P[k] + I[k]

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.

P acompanha; I conserva histórico

Gráfico conceitual com a parcela proporcional variando junto com o erro e o estado integral mantendo parte de seu valor entre amostras.

A parcela proporcional muda imediatamente com o erro. O estado integral só muda quando há incremento integral.

Rastreie a sequência completa

Exemplo

Exemplo resolvido

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.

Cálculo amostra a amostra

Rastreamento completo da sequência.

Em k = 1, o erro é zero: P e ΔI são zero, mas I mantém o valor acumulado anteriormente.
ke[k]P[k]ΔI[k]I[k]u*[k]
010,20,10,50,7
100,00,00,50,5
2−0,5−0,1−0,050,450,35

Leia a última linha

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.

Pratique um rastreamento inédito

Novo ensaio para calcular

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.

Calcule o primeiro incremento

No novo ensaio, qual é o incremento integral ΔI[0]? Use vírgula ou ponto decimal.

Preserve o estado com erro nulo

No novo ensaio, qual é o estado integral I[1], após processar e[1] = 0? Use vírgula ou ponto decimal.

Some as parcelas na última amostra

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

Implementar o estado persistente em C/C++

Implemente a atualização discreta de um PI em C/C++, preservando o estado integral entre chamadas.

Separar estado de cálculos temporários

Memória integral

Estado que continua 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:

  1. calcule P = Kp × erro;
  2. calcule incremento = Ki × Ts × erro;
  3. atualize I com o incremento;
  4. retorne P + I já atualizado.

P e incremento são temporários; I é o estado persistente.

O que permanece e o que é temporário

Diagrama de chamadas sucessivas de uma função PI: o acumulador integral permanece entre chamadas, enquanto os cálculos proporcional e incremento são temporários.

O estado integral atravessa as chamadas; as variáveis locais de cálculo não precisam atravessá-las.

Codificar a recorrência

Rotina PI mínima

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*.

cpp
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

Inicialização é diferente de atualização

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.

Evitar a reinicialização indevida

Atenção

Erro que apaga a memória

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.

Exemplo incorreto

Esta versão parece parecida, mas está incorreta: integral é criada novamente com zero em toda chamada. Assim, nenhum erro anterior é retido.

cpp
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;
}

Por que a versão falha

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.

Praticar a ordem correta

Complete a atualização do PI

Complete a rotina preservando a ordem de atualização adotada.

cpp
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

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.

O que o teste verifica

Ensaio numérico isolado

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 estado atravessa o ensaio

Diagrama de três amostras de erro passando por ramos proporcional e integral com memória, gerando linhas de resultados.

O teste processa uma amostra por vez: a integral atualizada em uma linha é o estado de partida da linha seguinte.

Programa reproduzível

Copie e execute localmente

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.

Programa de teste

Arquivo completo: teste_pi.cpp

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";
  }
}
Saída esperada
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 e diagnostique

Referência para comparação

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.

Tabela de referência

Resultados após cada atualização, com Kp = 0,2, Ki = 0,2, Ts = 0,5 s e I inicial = 0,3.

A integral é preservada entre as linhas e atualizada antes do cálculo de u*.
ke[k]P[k]I[k]u*[k]
00,50,1000,3500,450
10,00,0000,3500,350
2-0,5-0,1000,3000,200

Monte a chamada de atualização

Complete a chamada usada dentro do laço de teste.

cpp
float u = atualizarPI(erros[], , , );

Registre sua verificação

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

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.

Preservar o tempo acumulado

Dois períodos, um mesmo tempo

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.

  • Ensaio A: Tₛ = 0,100 s; portanto, N = 10 atualizações.
  • Ensaio B: Tₛ = 0,025 s; portanto, N = 40 atualizações.

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.

Mesma área acumulada

Comparação visual entre dez retângulos largos e quarenta retângulos estreitos, ambos ocupando o mesmo intervalo total e formando a mesma área.

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

Previsão da integral final

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.

Ler a equivalência numérica

Referência numérica

Compare o tamanho de cada passo e a quantidade de passos. O produto entre eles permanece igual.

Os dois ensaios acumulam o mesmo valor porque o tempo total N × Tₛ é igual.
EnsaioTₛ (s)NIncremento por atualizaçãoI final previsto
A0,100100,5 × 0,100 × 2,0 = 0,1001,100
B0,025400,5 × 0,025 × 2,0 = 0,0251,100

Contagem sem atualização extra

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.

Executar a comparação

Teste local reproduzível

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.

consistencia_pi.cpp

Programa completo para comparar dois períodos de atualização.

cpp
#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";
}
Saída esperada
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.

Checar a implementação

Completar a relação temporal

Complete a expressão que relaciona atualizações, período e acumulação para erro constante.

cpp
double tempo_total =  * ;
double i_final = i_inicial + ki * erro * N * ;

Diagnosticar uma divergência

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

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.

Revisão do núcleo numérico

Critério de validação

Antes de considerar qualquer uso fora do teste local, revise o núcleo numérico. Em cada atualização:

  1. Calcule P = Kp * erro.
  2. Calcule o incremento Ki * Ts * erro.
  3. Some o incremento ao estado integral já existente.
  4. Retorne 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 que a revisão deve confirmar

Diagrama do erro seguindo por ramos proporcional e integral com memória, que se unem no comando calculado e são conferidos em um console.

O ramo integral recebe o estado anterior, é atualizado uma vez por amostra e só então compõe o comando calculado.

Dica

Checklist do núcleo PI

Checklist final:

  • Ts foi convertido para segundos.
  • O incremento é Ki * Ts * erro, sem omitir nem duplicar Ts.
  • integral recebeu um valor inicial declarado antes do ensaio.
  • O estado integral foi preservado entre chamadas.
  • O retorno usa 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.

Implementação revisada

Complete a atualização PI

Complete a rotina. Considere erro em volts, comando normalizado e Ts já expresso em segundos.

cpp
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 + ;
}

Aplicação numérica final

Caso final de validação

Faça um novo ensaio numérico local, sem conectar hardware. Use:

  • Kp = 0,20 1/V
  • Ki = 0,40 1/(V·s)
  • Ts = 0,050 s
  • I[-1] = 0,40
  • erros: e[0] = 1,0 V, e[1] = 0 V e e[2] = -0,5 V

Preserve 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.

Calcule a última atualização

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).

Preveja a integral com outro período

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?

Encerramento

Resumo

Núcleo PI validado

  • A rotina PI calcula P[k] = Kp × e[k], atualiza I[k] = I[k−1] + Ki × Ts × e[k] e retorna u*[k] = P[k] + I[k].
  • Ts deve estar em segundos e entrar uma única vez no incremento integral.
  • O estado integral precisa ter valor inicial explícito e permanecer entre chamadas do mesmo ensaio.
  • Testes por sequência e por tempo total validam a aritmética do núcleo, não o comportamento completo de uma malha física.

Atenção

Limite da validação atual

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.

Baixe o Aplicativo agora para ter acesso a + de 5000 cursos gratuitos, exercícios, certificado e muito conteúdo sem pagar nada!

  • Cursos online 100% gratuitos do início ao fim

    Milhares de cursos online em vídeo, ebooks e áudiobooks.

  • Mais de 60 mil exercícios gratuitos

    Para testar seus conhecimentos no decorrer dos cursos online

  • Certificado Digital gratuito válido em todo o Brasil

    Gerado diretamente na galeria de fotos do seu celular e enviado ao seu e-mail

Aplicativo Cursa na tela de ebook, na tela de curso em vídeo e na tela de exercícios do curso, mais o certificado de conclusão de curso