programação de loops PID em C

11

Eu sou um engenheiro elétrico que foi empurrado para o mundo digital e aprendendo à medida que passo. Estou programando um processador de TI para fazer um loop PID (proporcional-integral-derivado) , ilustrado por este diagrama:

Imagem de loop PID da Wikipedia

Também vou descrevê-lo:

Op-amp de feedback negativo, com o terminal não inversor aterrado. Entrada através do terminal negativo. O circuito de realimentação é um circuito da série RE em paralelo com um resistor e tudo isso em paralelo com uma tampa.

Alguém tem alguma idéia de como converter esse circuito em código C? Estou um pouco fora do meu elemento sobre isso e poderia usar a ajuda.

Engenheiro Jedi
fonte
Você pode vincular a uma imagem e alguém converterá esse link em uma imagem real para você.
Joachim Sauer
2
O link que você publicou fornece um pseudocódigo básico para isso. Se você não se importa com C #, aqui está um exemplo de um loop pid em C # .
Neil
1
Neil está certo. Eu implementei quase exatamente esse loop em C na TI. Uma dica: use um loop de tempo constante e fatore o fixo dtnas constantes, em vez de fazer divisões e multiplicações extras no loop.
ASHelly #
1
@ Neil que foi um link que eu adicionei na revisão 2 porque não sabia o que era um loop PID e suspeitei que muitos outros também não.
@ MichaelT, ah minhas desculpas então.
Neil

Respostas:

18

O circuito

Ok, acabei de criar uma conta aqui quando vi essa pergunta. Não consigo editar sua pergunta para que eu possa corrigir o erro de digitação que você fez. Eu acredito que você quis dizer circuito da série RC em paralelo, em vez de RE (se for, não tenho uma única pista do que isso significa)

Parece que o circuito analógico que você deseja simular usando C se parece com isso

                         Ci
                  |------| |--------------|
                  |           Rp          |
                  |----/\/\/\/\-----------|
                  |          Rd    Cd     |
           Rf     |----/\/\/\---| |-------|
Vin o----/\/\/\---|                       |
                  |    |\                 |
                  |    | \                |
                  |----|- \               | 
                       |   \              |
                       |    \-------------|---------o  Vout
                       |    /
                       |   /
                       |+ /
                   ----| /
                  |    |/
                  |
                  |
               ___|___ GND
                _____
                 ___
                  _

LEGEND:
  Vin is the input signal.
  Vout is the Output.
  Rp controls the propotional term ( P in PID) 
  Ci controls the Integral term ( I id PID)
  Rd and Cd controls the differential term ( D in PID)
  Rf is the gain control, which is common to all of the above controllers.

(Eu não pude resistir ao meu desejo de desenhar isso, pois queria dizer como os engenheiros eletroeletrônicos costumavam se comunicar em fóruns e e-mails sem imagens ... e por que adoramos courier, fonte de largura fixa)

Devo confessar que o circuito que você está usando é simples de configurar, mas é muito complexo matematicamente, quando se trata de ajustar as constantes Propocional, Integral e Derivada do sistema para um valor desejado individualmente, não é possível.

Eu sugiro fortemente que você use o circuito desta fonte para estudar.

Embora seja um pouco tedioso de configurar, matematicamente é muito mais simples de analisar, pois você pode relacioná-lo diretamente à forma matemática padrão em vez da forma ideal.

Por fim, o Vout vai controlar um motor ou o que precisar ser controlado. E Vin é a tensão variável do processo.

Antes de molhar os pés em C (mar?)

Suponho que você esteja lendo os sinais de algum tipo de conversor analógico para digital. Caso contrário, você teria que simular o sinal como uma entrada.

Se usando o formulário Padrão, temos,

Supondo que o tempo de execução do loop seja pequeno o suficiente (um processo lento), podemos usar a seguinte função para calcular a saída,

output = Kp * err + (Ki * int * dt) + (Kd * der /dt);

Onde

Kp = Proptional Constant.
Ki = Integral Constant.
Kd = Derivative Constant.
err = Expected Output - Actual Output ie. error;
int  = int from previous loop + err; ( i.e. integral error )
der  = err - err from previous loop; ( i.e. differential error)
dt = execution time of loop.

onde inicialmente 'der' e 'int' seriam zero. Se você usar uma função de atraso no código para sintonizar a frequência do loop para dizer 1 KHz, seu dt seria 0,001 segundos.

Drawning em C

Eu encontrei esse excelente código para PID em C, embora ele não cubra todos os aspectos, é bom mesmo assim.

//get value of setpoint from user
while(1){
  // reset Timer
  // write code to escape loop on receiving a keyboard interrupt.
  // read the value of Vin from ADC ( Analogue to digital converter).
  // Calculate the output using the formula discussed previously.
  // Apply the calculated outpout to DAC ( digital to analogue converter).
  // wait till the Timer reach 'dt' seconds.
}

Se tomarmos um processo lento, poderemos usar uma frequência mais baixa, de modo que o tempo de execução do código dt >>> para o loop único (muito maior que). Nesses casos, podemos acabar com o timer e usar uma função de atraso.

D34dman
fonte
6
O diagrama ASCII me surpreendeu. 1
l46kok
1
link "esta fonte" não está funcionando
Ccr
Ah, desculpe-me por ouvir isso, um bom recurso se perdeu :(. Bem, o conceito foi explicado no código de exemplo do loop while que eu havia compartilhado. Não tenho experiência em como lidar com essa situação, talvez alguns editores possam corrigi-lo com mensagem adequada (o link morto).
D34dman
2
A falta "esta fonte" pode estar disponível aqui: educypedia.karadimov.info/library/piddocs.pdf
David Suarez