Commit 7f0f212e authored by Bernardo Quaresma Dias's avatar Bernardo Quaresma Dias
Browse files

Inclusão de lib-wellbot

INSTMPA-1288
parent 5dfb06f7
This source diff could not be displayed because it is too large. You can view the blob instead.
class{ id = "NMPC_MPA_REAL_POINT", name = "Ponto Real NMPC/MPA", group = "WellBot",
isPoint = true,
bases = { "REAL_POINT" },
simulationValue = 0,
description = "Classe de ponto real que converte valores com fator no MPA para acesso do NMPC.",
attributes = {
{ id = "ponto_mpa", name = "Ponto MPA", type = "REAL_POINT", access = "rw",
description =[[Ponto com o valor a ser lido pelo NMPC.]] ,
},
{ id = "modo", name = "Modo", type = "STRING", access = "g",
description =[[Modo de atualização do tag MPA.]],
},
},
methods = {
{ id = "atualizar", name = "Atualizar",
description = [[Atualiza o valor do ponto disponível para NMPC com o valor atual do SDCD de acordo com o modo.
Se o ]],
parameters = {
},
results = {
},
code = [===[ function(self)
if self.modo == "r" then
local valor = self.ponto_mpa:read()
self:write(valor)
end
if self.modo == "w" then
local valor = self:read()
if self.__lastwritten ~= valor then
self.ponto_mpa:write(valor)
self.__lastwritten = valor
end
end
if self.modo == "rw" then
local valor = self.ponto_mpa:read()
if self.__lastwritten ~= valor then
self:write(valor)
else
valor = self:read()
if self.__lastwritten ~= valor then
self.ponto_mpa:write(valor)
end
end
self.__lastwritten = valor
end
end ]===],
},
},
code = [[
]],
}
class{ id = "mod_wellbot", name = "Módulo WellBot", group = "WellBot",
bases = {},
description = [[Classe com parametros para execucao de Algoritmo de NMPC do controle de Golfadas.]],
attributes = {
{ id = "pt_habilita", name = "Habilita", type = "BOOLEAN_POINT", access = "rw",
description = [[Habilita o WellBot.]],
},
{ id = "m_antigolf", name = "Módulo Anti-Golfadas", type = "mod_antigolf", access = "g",
description = [[Módulo Anti-Golfadas utilizado pelo WellBot.]],
},
{ id = "controlador", name = "Controlador NMPC", type = "pid_velocidade", access = "g",
description = [[Algoritmo NMPC que calcula variacao na abertura a partir de PDG.]],
},
{ id = "filtro_pv",
name = "Filtro PV",
type = "bloco_filtro",
access = "g",
description =[[Filtro PDG.]],
},
{ id = "filtro_SP",
name = "Filtro SP",
type = "bloco_filtro",
access = "g",
description =[[Filtro SP para teste sem BRNMPC.]],
},
{ id = "T_filtro_SP",
name = "T filtro SP",
type = "REAL",
access = "gs",
description =[[Constante de tempo do filtro de primeira ordem do SP, para testes sem BRNMPC.]],
},
{ id = "usar_BRNMPC",
name = "Usar BRNMPC",
type = "BOOLEAN",
access = "gs",
description = [[Define a estrategia de controle, com ou sem BRNMPC.]],
},
{ id = "SP_NMPC",
name = "SP do NMPC",
type = "REAL_POINT",
access = "rw",
description = [[Valor de pressao objetivo para o NMPC.]],
},
{ id = "SP_IHM",
name = "SP da IHM",
type = "REAL_POINT",
access = "rw",
description = [[Valor de pressao objetivo inserido via IHM para o NMPC.]],
},
{ id = "PRED_MA",
name = "PREDIÇÃO PDG",
type = "REAL_POINT",
access = "rw",
description = [[Valor da predicao da pressao do PDG em malha aberta.]],
},
{ id = "WATCHDOG_BRNMPC",
name = "Watchdog do controlador preditivo",
type = "BOOLEAN_POINT",
access = "rw",
description = [[Indica o status da comunicacao do controlador preditivo (0=sem comunicacao, 1=comunicando).]],
},
{ id = "ALARME_WDOG_BRNMPC",
name = "Alarme_wdog",
type = "BOOLEAN",
access = "gs",
description = [[Alarme da comunicacao do controlador preditivo.]],
},
{ id = "ACIONAMENTO_REMOTO_CONTROLADA",
name = "Acionamento remoto NMPC - Controlada",
type = "INTEGER_POINT",
access = "rw",
description = [[Indica a condicao de acionamento remoto da malha da variavel controlada do controlador preditivo (1 = Malha Fechada, 2 = Malha Aberta.)]],
},
{ id = "ACIONAMENTO_REMOTO_MANIPULADA",
name = "Acionamento remoto NMPC - Manipulada",
type = "INTEGER_POINT",
access = "rw",
description = [[Indica a condicao de acionamento remoto da malha da variavel manipulada do controlador preditivo (3 = Malha Fechada, 4 = Malha Aberta.)]],
},
{ id = "Auto_Settling",
name = "Auto Settling",
type = "mod_wellbot_AutoSettling",
access = "g",
description = [[Parametrização do Algoritmo do Auto Settling para descida automática do SP do Controlador de Golfadas.]],
},
{ id = "CHOKE_REFERENCIA",
name = "Abertura de referencia da Choke",
type = "REAL_POINT",
access = "rw",
description = [[Indica abertura de seguranca da choke quando o controlador preditivo perde comunicacao.]],
},
{ id = "bias",
name = "BIAS",
type = "REAL_POINT",
access = "rw",
description = [[Valor calculado pelo controlador preditivo para abertura da choke.]],
},
{ id = "Dbias",
name = "DBIAS",
type = "REAL_POINT",
access = "rw",
description = [[Delta de abertura da choke calculado pelo controlador preditivo.]],
},
{ id = "Dcontrole",
name = "DControle",
type = "REAL_POINT",
access = "rw",
description = [[Delta do PID + Delta bias do controlador preditivo.]],
},
{ id = "MEDIA_CHOKE",
name = "Media Movel da Choke",
type = "bloco_media",
access = "g",
description = [[Calcula a media movel de abertura da choke]],
},
{ id = "Kp_INICIAL",
name = "Kp_INICIAL",
type = "REAL",
access = "gs",
description = [[Indica o Kp inical do Algoritmo NMPC.]],
},
{ id = "t",
name = "Tempo para atingir o Kp",
type = "REAL",
access = "gs",
description = [[Indica o tempo, em segundos, da rampa para atingir o Kp final.]],
},
{ id = "CA_GS",
name = "Coeficiente angular gain scheduling",
type = "REAL",
access = "gs",
description = [[Coeficiente angular da curva de gain scheduling.]],
},
{ id = "CL_GS",
name = "Coeficiente linear gain scheduling",
type = "REAL",
access = "gs",
description = [[Coeficiente linear da curva de gain scheduling.]],
},
{ id = "Fator_GS",
name = "Fator gain scheduling",
type = "REAL_POINT",
access = "rw",
description = [[Indica o fator multiplicativo da curva de gain scheduling.]],
},
{ id = "Kp_min",
name = "Limite minimo do Kp",
type = "REAL",
access = "gs",
description = [[Limite minimo do Kp.]],
},
{ id = "Kp_max",
name = "Limite maximo do Kp",
type = "REAL",
access = "gs",
description = [[Limite maximo do Kp.]],
},
{ id = "STATUS",
name = "Status",
type = "INTEGER_POINT",
access = "rw",
description = [[Exibe o Status do Algoritmo NMPC.]],
},
{ id = "alarme_choke",
name = "Alarme Choke",
type = "BOOLEAN_POINT",
access = "gw",
description =[[Ponto usado para indicar problemas no acionamento da válvula choke do poço, desabilitando o controlador.]],
},
},
methods = {
},
}
class{ id = "pid_velocidade", name = "PID Velocidade", group = "WellBot",
bases = {},
description = [[
Equipamento para realizar o controle PID sobre uma variavel.
Esse equipamento possui o metodo Executar Controle que implementa um algoritmo
PID de velocidade, conforme modelo ISA, baseado em um ganho proporcional adimensional
e em ganhos de tempo integral e derivativo em segundos que, considerando os valores
historicos e o modo de operacao, calcula o valor de correcao.
Se os atributos PV Minimo, PV Maximo, MV Minimo e MV Maximo forem definidos, o
calculo e feito normalizado.
O controlador calcula do delta da variavel manipulada, mas nao aplica diretamente na
valvula.
Modelo de PID para ser usado com o acoplador anti-golfadas. Taxa de amostragem
fixa em 30s.
]],
attributes = {
{ id = "pv", name = "PV", type = "REAL_POINT", access = "rw",
description = [[Ponto real que define a variavel de processo (PV).]],
},
{ id = "sp", name = "SP", type = "REAL_POINT", access = "rw",
description = [[Ponto real que define o set point (SP).]],
},
{ id = "sp_cas", name = "SP Cascata", type = "REAL_POINT", access = "rw",
description = [[Ponto real que define o set point em modo cascata (SP Cas).]],
},
{ id = "mv", name = "MV", type = "REAL_POINT", access = "rw",
description = [[Ponto real que define a variavel manipulada (MV).]],
},
{ id = "modo", name = "Modo", type = "INTEGER_POINT", access = "rw",
description = [[O modo de operacao (0=manual, 1=automatico, 2=cascata).]],
},
{ id = "tol_erro", name = "Tolerancia ao Erro", type = "REAL", access = "g",
description = [[
Valor que define uma faixa na qual o erro sera coonsiderado nulo.
Esse atributo permite que caso a diferença entre PV e SP se mantenha
dentro de uma banda o controle considere que o valor de SP foi alcançado.
]],
},
{ id = "delta_max", name = "Delta Maximo", type = "REAL", access = "g",
description = [[
Valor que define o limite de variacao que pode ser aplicado na MV em
um passo de execucao do controlador.
]],
},
{ id = "kp", name = "KP", type = "REAL_POINT", access = "rw",
description = [[O valor de ganho proporcional.]],
},
{ id = "ti", name = "TI", type = "REAL_POINT", access = "rw",
description = [[O valor do tempo integral, em segundos.]],
},
{ id = "td", name = "TD", type = "REAL_POINT", access = "rw",
description = [[O valor do tempo derivativo, em segundos.]],
},
{ id = "acao", name = "Acao", type = "INTEGER_POINT", access = "rw",
description = [[A forma de acao sobre a MV (0=direta, 1=inversa).]],
},
{ id = "pv_minimo", name = "PV Minimo", type = "REAL_POINT", access = "rw",
description = [[O menor valor da faixa de variacao da PV.]],
},
{ id = "pv_maximo", name = "PV Maximo", type = "REAL_POINT", access = "rw",
description = [[O maior valor da faixa de variacao da PV.]],
},
{ id = "mv_minimo", name = "MV Minimo", type = "REAL_POINT", access = "rw",
description = [[O menor valor da faixa de variacao da MV.]],
},
{ id = "mv_maximo", name = "MV Maximo", type = "REAL_POINT", access = "rw",
description = [[O maior valor da faixa de variacao da MV.]],
},
{ id = "rastrear_pv", name = "Rastrear PV", type = "BOOLEAN_POINT", access = "rw",
description = [[
A indicacao se deve rastrear a PV quando em modo manual:
- true , rastrear;
- false , não rastrear.
]],
},
{ id = "usar_dpv", name = "Usar Delta PV", type = "BOOLEAN", access = "",
description = [[
Indica, quando verdadeiro que Delta PV deve ser utilizado para calcular proporcional.
]],
},
{ id = "ffw", name = "Antecipacao (FFW)", type = "REAL", access = "gs",
description = [[O valor da antecipacao a ser somada à MV.]],
},
{ id = "erro", name = "ERRO", type = "REAL_POINT", access = "rw",
description = [[O valor do erro do PID.]],
},
{ id = "P", name = "Acao Proporcional", type = "REAL_POINT", access = "rw",
description = [[O valor da acao proporcional do controlador.]],
},
{ id = "I", name = "Acao Integral", type = "REAL_POINT", access = "rw",
description = [[O valor da acao integral do controlador.]],
},
{ id = "D", name = "Acao Derivativa", type = "REAL_POINT", access = "rw",
description = [[O valor da acao derivativa do controlador.]],
},
{ id = "DPID", name = "DPID", type = "REAL_POINT", access = "rw",
description = [[Delta da MV calculado pelo PID.]],
},
},
code = [==[
function _CLASS:init()
if not self.mv then self._mv = 50 end
if not self.sp then self._sp = 50 end
if not self.pv then self._pv = 50 end
if not self.td then self._td = 1 end
if not self.ti then self._ti = 1 end
if not self.kp then self._kp = 1 end
if not self.acao then self._acao = 0 end -- acao padrao e direta
if not self.modo then self._modo = 1 end -- modo padrao e automatico
end
]==],
methods = {
{ id = "somar_ffw",
name = "Somar Antecipacao",
description = [[Soma o valor informado ao valor atual da antecipacao da MV.]],
parameters = {
{ name = "Antecipacao", type = "REAL" },
},
results = {
},
code = [==============================================================[
function(self, v)
self.ffw = v + (self.ffw or 0)
end
]==============================================================],
},
{ id = "informar_variacao_mv",
name = "Informar Variacao de MV",
description = [[Informa variacao que foi aplicada a  MV na ultima execucao do algoritmo.
(Se o PID estiver em modo manual o metodo retornara zero).]],
parameters = {
},
results = {
{ name = "Variacao MV", type = "REAL" },
},
code = [==============================================================[
function(self)
if self.variacao_mv==nil or self:informar_modo()==0 then
return 0
end
return self.variacao_mv
end
]==============================================================],
},
{ id = "executar_controle",
name = "Executar Controle",
description = [[
Executa o controle do PID sobre o processo.
Esta funcao implementa um algoritmo PID baseado em um ganho proporcional
adimensional e em ganhos de tempo integral e derivativo em segundos que,
considerando os valores historicos e o modo de operacao, calcula o valor
de correcao e atua diretamente sobre a MV. A equacao implementada e:
KP*[(Erro[0]-Erro[-1]) or (PV[0]-PV[-1])] +
(KP/TI)*Erro[0]*dt +
((KP*TD)/dt)*(PV[0]-2*PV[-1]+PV[-2])
Onde Erro[0] e o erro atual, Erro[-1] e o erro da avaliacao anterior,
Erro[-2] e o erro de duas avaliacoes anteriores e dt e a diferenca de
tempo, em segundos, entre a avaliacao anterior e a atual.
O calculo e feito normalizado. O valor e convertido para unidades
de engenharia e aplicado ao ponto que define a MV.
Enquanto em modo manual, o algoritmo ira atualizar o erro ou rastrear a PV de
acordo com a configuracao do atributo "Rastrear PV".
Se o atrbituo "Usar Delta PV" for configurado como 'true', a variacao da PV em
relacao ao passo anterior sera usado no lugar de Erro[0]-Erro[-1] para o fator
proporcional.
]],
parameters = {
},
results = {
},
code = [==============================================================[
function(self, v)
self:atualizar_tempos()
local pv = self:informar_pv()
local modo = self:informar_modo()
local sp
if (modo==0 or modo==1) then -- manual ou automatico
sp = self:informar_sp()
else -- cascata
sp = self:informar_sp_cas()
end
if self.pv_maximo and pv_minimo then
self:atualizar_normais(sp, pv)
end
self:atualizar_erro(sp, pv)
if (modo == 0) then -- manual
local rastrear_pv = self:informar_rastrear_pv()
if rastrear_pv then
self:ajustar_sp(pv)
end
self.ffw = 0
else -- automatico ou cascata
self:atualizar_mv_engenharia()
end
end
]==============================================================],
},
{ id = "atualizar_tempos",
name = "",
description = [[]],
parameters = {
},
results = {
},
code = [==============================================================[
function(self)
self.t_1 = self.t_0
self.t_0 = time()
end
]==============================================================],
},
{ id = "atualizar_normais",
name = "",
description = [[]],
parameters = {
},
results = {
},
code = [==============================================================[
function(self, sp, pv)
local pv_min = self:informar_pv_minimo()
local pv_max = self:informar_pv_maximo()
local pv_dif = pv_max-pv_min
if (pv_dif == 0) then
self.pv_normal = 0
self.sp_normal = 0
else
local modo = self:informar_modo()
self.pv_normal = ((pv-pv_min)/pv_dif)*100
self.sp_normal = ((sp-pv_min)/pv_dif)*100
end
end
]==============================================================],
},
{ id = "atualizar_mv_engenharia",
name = "",
description = [[]],
parameters = {
},
results = {
},
code = [==============================================================[
function(self)
local mv, mv_max, mv_min, mv_dif = self:informar_mv_engenharia()
if mv_dif == 0 then
self.variacao_mv = 0
return
end
local delta_mv = self:calcular_delta_mv()
local delta_max = self.delta_max
if delta_max then
delta_mv = limitar(delta_mv,-delta_max,delta_max)
end
local nova_mv = mv + delta_mv
if mv_max and mv_min then
nova_mv = math.max(0, math.min(100, nova_mv))
local mv_normal = ((mv-mv_min)/mv_dif)*100
self.variacao_mv = nova_mv - mv
--self:ajustar_mv(nova_mv)
else
--self:ajustar_mv(nova_mv)
self.variacao_mv = delta_mv
end
end
]==============================================================],
},
{ id = "informar_mv_engenharia",
name = "",
description = [[]],
parameters = {
},
results = {
},
code = [==============================================================[
function(self)
local mv = self:informar_mv()
local mv_min = self:informar_mv_minimo()
local mv_max = self:informar_mv_maximo()
if mv_min and mv_max then
local mv_dif = mv_max-mv_min
return mv, mv_max, mv_min, mv_dif
else
return mv
end
end
]==============================================================],
},
{ id = "calcular_delta_mv",
name = "",
description = [[]],
parameters = {
},
results = {
},
code = [===[ function(self)
local acao = self:informar_acao()
local kp = self:informar_kp()
local ti = self:informar_ti()
local td = self:informar_td()
local ac
if not self.t_1 then -- na primeira execução não tem como calcular
return 0
end
local dt = self.t_0 - self.t_1
if dt == 0 then -- tempo muito curto para a execução
return 0
end
if not kp then -- sem constante proporcional, nao tem como calcular
return 0
end
if (acao == 0) then -- direta
ac = 1
else --inversa
ac = -1
end
local P, I, D = 0, 0, 0
if self.usar_dpv then
P = ac*kp*self.d_pv
else
P = ac*kp*self.de
end
if ti and ti~=0 then
I = ac*(kp/ti)*self.erro_t_0*dt
end
if td then
ad = td/(td+100*dt)
bd = ac*kp*td*100/(td+100*dt)
Dant = D or (bd*self.eD/ad)
D = ad*Dant - bd*self.eD
end
local ffw = self.ffw or 0
self.ffw = 0
self.p = P
self.i = I
self.d = D
return P+I+D+ffw
end ]===],
},
{ id = "atualizar_erro",
name = "",
description = [[]],
parameters = {
},
results = {
},
code = [==============================================================[
function(self, sp, pv)
self.d_pv = - pv + (self.pv_ant or pv)
if self.pv_ant==nil or self.pv_ant2==(nil or 0) then
self.eD=0
else
self.eD = pv - 2*self.pv_ant + self.pv_ant2
end
self.pv_ant2 = self.pv_ant or 0
self.pv_ant = pv or 0
self.erro_t_2 = self.erro_t_1 or 0
self.erro_t_1 = self.erro_t_0
self.erro_t_0 = self:calcular_erro(sp, pv)
if (self.erro_t_1 == nil)then
self.de = 0
else
self.de = self.erro_t_0 - self.erro_t_1
end
end
]==============================================================],
},
{ id = "calcular_erro",
name = "",
description = [[]],
parameters = {
},
results = {
},
code = [==============================================================[
function(self, sp, pv)
local acao = self:informar_acao()
local erro
erro = (self.sp_normal or sp) - (self.pv_normal or pv)
if self.tol_erro and math.abs(erro) < self.tol_erro then
return 0
else
return erro
end
end
]==============================================================],
},
{ id = "informar_rastrear_pv", name = "Informar Rastrear PV",
descriprastrear_pvon = [[Informa rastrear PV do controlador.]],
parameters = {
},
results = {
{name = "Rastrear PV", type = "REAL"}
},
code = [=[ function(self)
local rastrear_pv = self._rastrear_pv or (self.rastrear_pv and self.rastrear_pv:read())
return rastrear_pv