PID Library in Portuguese

/**********************************************************************************************

  • Arduino PID Biblioteca
  • Por Nathanyel Sandi - Handrey Emanuel Galon - Vinicius Goulert
  • Colaborador : Fábio Rocha - UFSC
  • UTFPR - Campus Pato Branco
    **********************************************************************************************/
    //Dependendo da versão do Arduino é configurado uma biblioteca específica para os padrões de linguagem
    #if ARDUINO >= 100
    #include “Arduino.h”
    #else
    #include “WProgram.h”
    #endif
    //------------------------------------------------------------------------------------------------------
    #include <PID_v1.h> //Carrega biblioteca com declarações de variáveis

/Contstrutor da função PID*************************************************

  • Os parâmetros especificados nesta função não tem um padrão “confiável”
  • sendo assim, há a necessidade de um usuário configurá-los
  • com base em simulações
    ************************************************************************/
    PID::PID(double
    Input, double
    Output, double
    Setpoint,
    double Kp, double Ki, double Kd, int ControllerDirection)
    {

myOutput = Output; //Saída do sistema - Ajuste da velocidade do Cooler
myInput = Input; //Entrada do sistema - Leitura dos sensores de temperatura
mySetpoint = Setpoint; //SetPoint - Referência - Temperatura que desejamos manter
inAuto = false; //Modo PId Automático (Que será setado na função main()

PID::SetOutputLimits(0, 255); //Seta os limites - Saturação

SampleTime = 100; //Tempo de amostragen de 0.1 segundos

PID::SetControllerDirection(ControllerDirection); //Direção da ação de controle (Pode ser reversa, ou direta)
PID::SetTunings(Kp, Ki, Kd); //Seta parâmetros de Ganho Proporciona, Integrador e Derivativo

lastTime = millis()-SampleTime; //Pega o último tempo amostrado, Tempo Atual - Tempo de Amostragem
}

/* Função - Cálculo PID*************************************************************

  • Essa função deve ser chamada toda vez que a função void loop() do main()
  • a função decide por si mesmo se a saída do PID deve ser calculada
  • e retorna True quando a saída é calculada e False quando não for calculada
    **********************************************************************************/
    bool PID::Compute()
    {
    if(!inAuto) return false; //Se o modo não for automático (MF) retorna falso
    unsigned long now = millis(); //Caso não seja → Medição de tempo do primeiro ciclo (usando millis)
    unsigned long timeChange = (now - lastTime);
    if(timeChange>=SampleTime)
    {
    /Calcular todas as variáveis de erro/
    double input = *myInput; //Ponteiro para a variável de temperatura (declarado anteriormente no método construtor)
    double error = *mySetpoint - input; //Calcula o erro - Entrada (Referência) - Saída;
    ITerm+= (ki * error); //Ação de controle Integradora = Constante integrador vezes o erro
    if(ITerm > outMax) ITerm= outMax; //Se Integrador saturou - Vai para 255
    else if(ITerm < outMin) ITerm= outMin;//Se Saturou (menor que 0 ) -Vai para zero
    double dInput = (input - lastInput); //Ação Derivativa - Saída atual menos Saída anterior

/saída do PID/
double output = kp * error + ITerm- kd * dInput; //Soma das ações de Controle
//Adaptada para GANHO PROPORCIONAL MENOS ERRO + TERMO DE AÇÃO DE CONTROLE INTEGRADORA - GANHO DERIVATIVO*TERMO DE AÇÃO DE CONTROLE DERIVATIVO

if(output > outMax) output = outMax; //Se saída calculada for maior que o limite definido, saída passa ser máxima
else if(output < outMin) output = outMin; //Caso contrário mínima
*myOutput = output; //Ponteiro para saída recebe saída

/Recupera variáveis para próxima amostra/
lastInput = input;
lastTime = now;
return true; //Retorna verdadeiro pois foi necessário calcular o PID
}
else return false; //Caso contrário retorna falso
}

/* Ajuste dos Paramêtros*************************************************************

  • Essa função permite que o desempenho dinâmico do controlador possa ser ajustado.
  • é chamado automatiacmente a partir do método construtor, alguns ajustes podem ser
  • feitos durante a operação
    ******************************************************************************/
    void PID::SetTunings(double Kp, double Ki, double Kd)
    {
    if (Kp<0 || Ki<0 || Kd<0) return;

dispKp = Kp; dispKi = Ki; dispKd = Kd;

double SampleTimeInSec = ((double)SampleTime)/1000; //Tempo de Amostragem em Segundos
kp = Kp; //Kp = Kp
ki = Ki * SampleTimeInSec; //Ki recebe ganho integrador vezes o tempo de amostragem em segundos
kd = Kd / SampleTimeInSec; //Kd recebe ganho derivativo dividido tempo de amostragem em segundos
if(controllerDirection ==REVERSE) //Apenas altera os sinais se a ação de controle for reversa
{
kp = (0 - kp);
ki = (0 - ki);
kd = (0 - kd);
}
}

/* Tempo de amostragem*********************************************************

  • Define o período em milissegundos em que o cálculo é realizado
    ******************************************************************************/
    void PID::SetSampleTime(int NewSampleTime)
    {
    if (NewSampleTime > 0)
    {
    double ratio = (double)NewSampleTime
    / (double)SampleTime;
    ki *= ratio;
    kd /= ratio;
    SampleTime = (unsigned long)NewSampleTime;
    }
    }

/* SetOutputLimits(…)****************************************************

  • Define o minimo e máximo da saída do Arduino
    **************************************************************************/
    void PID::SetOutputLimits(double Min, double Max)
    {
    if(Min >= Max) return; //Se minimo for maior igual maximo
    outMin = Min; //Saídas recebe seus respectivos valores
    outMax = Max;

if(inAuto) //Se ele está no modo automático
{
if(*myOutput > outMax) *myOutput = outMax; //Verifica se a saída atual é maior que a máxima, se for saída atual recebe máxima
else if(*myOutput < outMin) *myOutput = outMin; //Ainda é realizado a verificação da mínima se for menor recebe 0

if(ITerm > outMax) ITerm= outMax; //Mesmo ocorre para ação de controle do INTEGRADOR!
else if(ITerm < outMin) ITerm= outMin;
}
}

/* Seta o modo de controle***************************************************************

  • Permite que o modo de controlador possa ser definido manualmente ou automaticamente
  • no caso foi usado ele automaticamente, em questão da inicialização, parâmetros, etc…
    ******************************************************************************/
    void PID::SetMode(int Mode)
    {
    bool newAuto = (Mode == AUTOMATIC);
    if(newAuto == !inAuto)
    {
    PID::Initialize();
    }
    inAuto = newAuto;
    }

/* Função de inciialização******************************************************

  • Faz todas as coisas que precisam acontecer para garantir uma transferência
  • uniforme de manual para o modo automático
    ******************************************************************************/
    void PID::Initialize()
    {
    ITerm = *myOutput; //Ponteiro para a variável de temperatura (declarado anteriormente no método construtor)
    lastInput = *myInput; //lastInput passa ser a útlima saída obtida no modo manual
    if(ITerm > outMax) ITerm = outMax; //Se Integrador saturou - Vai para 255
    else if(ITerm < outMin) ITerm = outMin; //Se Saturou (menor que 0 ) -Vai para zero
    }

/* Seta direção de ação de controle*************************************************

  • O PID é ligado por default um processo onde a saída + leva a uma entrada +
  • ou no caso de uma ação reversa uma saída + leva a uma entrada - (fazendo uma
    analogia com o projeto Cooler mais rápido leva a uma temperatura menor)
    ******************************************************************************/
    void PID::SetControllerDirection(int Direction)
    {
    if(inAuto && Direction !=controllerDirection)
    {
    kp = (0 - kp);
    ki = (0 - ki);
    kd = (0 - kd);
    }
    controllerDirection = Direction;
    }

/* Função de retorno dos status*************************************************************
*/
double PID::GetKp(){ return dispKp; }
double PID::GetKi(){ return dispKi;}
double PID::GetKd(){ return dispKd;}
int PID::GetMode(){ return inAuto ? AUTOMATIC : MANUAL;}
int PID::GetDirection(){ return controllerDirection;}

Estás a fornecer o código ou tens alguma dúvida?