ajuste pid bomba

This commit is contained in:
Diego Freitas 2026-06-09 12:25:22 -03:00
parent d7c7b538d7
commit 386520716e
3 changed files with 131 additions and 44 deletions

View File

@ -88,7 +88,7 @@
this.chbSonarAtivado = new System.Windows.Forms.CheckBox(); this.chbSonarAtivado = new System.Windows.Forms.CheckBox();
this.lblPressao = new System.Windows.Forms.Label(); this.lblPressao = new System.Windows.Forms.Label();
this.label1 = new System.Windows.Forms.Label(); this.label1 = new System.Windows.Forms.Label();
this.nudPotenciaBomba = new System.Windows.Forms.NumericUpDown(); this.nudPotenciaBombaMin = new System.Windows.Forms.NumericUpDown();
this.groupBox2 = new System.Windows.Forms.GroupBox(); this.groupBox2 = new System.Windows.Forms.GroupBox();
this.groupBox3 = new System.Windows.Forms.GroupBox(); this.groupBox3 = new System.Windows.Forms.GroupBox();
this.cmbModoAgitador = new System.Windows.Forms.ComboBox(); this.cmbModoAgitador = new System.Windows.Forms.ComboBox();
@ -101,6 +101,8 @@
this.txtKi = new System.Windows.Forms.TextBox(); this.txtKi = new System.Windows.Forms.TextBox();
this.label6 = new System.Windows.Forms.Label(); this.label6 = new System.Windows.Forms.Label();
this.txtKd = new System.Windows.Forms.TextBox(); this.txtKd = new System.Windows.Forms.TextBox();
this.label7 = new System.Windows.Forms.Label();
this.nudPotenciaBombaMax = new System.Windows.Forms.NumericUpDown();
((System.ComponentModel.ISupportInitialize)(this.chartGraficos)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.chartGraficos)).BeginInit();
this.tabControl1.SuspendLayout(); this.tabControl1.SuspendLayout();
this.tabMapa.SuspendLayout(); this.tabMapa.SuspendLayout();
@ -114,9 +116,10 @@
this.pnlDir_ET.SuspendLayout(); this.pnlDir_ET.SuspendLayout();
this.pnlDir_DT.SuspendLayout(); this.pnlDir_DT.SuspendLayout();
this.pnlDir_DF.SuspendLayout(); this.pnlDir_DF.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.nudPotenciaBomba)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.nudPotenciaBombaMin)).BeginInit();
this.groupBox2.SuspendLayout(); this.groupBox2.SuspendLayout();
this.groupBox3.SuspendLayout(); this.groupBox3.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.nudPotenciaBombaMax)).BeginInit();
this.SuspendLayout(); this.SuspendLayout();
// //
// pnlAtuadores // pnlAtuadores
@ -751,27 +754,29 @@
this.label1.Location = new System.Drawing.Point(6, 94); this.label1.Location = new System.Drawing.Point(6, 94);
this.label1.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0); this.label1.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0);
this.label1.Name = "label1"; this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(77, 13); this.label1.Size = new System.Drawing.Size(50, 13);
this.label1.TabIndex = 35; this.label1.TabIndex = 35;
this.label1.Text = "Potencia SP"; this.label1.Text = "Pot Min";
// //
// nudPotenciaBomba // nudPotenciaBombaMin
// //
this.nudPotenciaBomba.Font = new System.Drawing.Font("Microsoft Sans Serif", 7.8F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.nudPotenciaBombaMin.Font = new System.Drawing.Font("Microsoft Sans Serif", 7.8F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.nudPotenciaBomba.Location = new System.Drawing.Point(6, 111); this.nudPotenciaBombaMin.Location = new System.Drawing.Point(6, 111);
this.nudPotenciaBomba.Margin = new System.Windows.Forms.Padding(2); this.nudPotenciaBombaMin.Margin = new System.Windows.Forms.Padding(2);
this.nudPotenciaBomba.Maximum = new decimal(new int[] { this.nudPotenciaBombaMin.Maximum = new decimal(new int[] {
200, 200,
0, 0,
0, 0,
0}); 0});
this.nudPotenciaBomba.Name = "nudPotenciaBomba"; this.nudPotenciaBombaMin.Name = "nudPotenciaBombaMin";
this.nudPotenciaBomba.Size = new System.Drawing.Size(121, 19); this.nudPotenciaBombaMin.Size = new System.Drawing.Size(55, 19);
this.nudPotenciaBomba.TabIndex = 34; this.nudPotenciaBombaMin.TabIndex = 34;
this.nudPotenciaBomba.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; this.nudPotenciaBombaMin.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
// //
// groupBox2 // groupBox2
// //
this.groupBox2.Controls.Add(this.label7);
this.groupBox2.Controls.Add(this.nudPotenciaBombaMax);
this.groupBox2.Controls.Add(this.label6); this.groupBox2.Controls.Add(this.label6);
this.groupBox2.Controls.Add(this.txtKd); this.groupBox2.Controls.Add(this.txtKd);
this.groupBox2.Controls.Add(this.label5); this.groupBox2.Controls.Add(this.label5);
@ -783,7 +788,7 @@
this.groupBox2.Controls.Add(this.btnLigarBomba); this.groupBox2.Controls.Add(this.btnLigarBomba);
this.groupBox2.Controls.Add(this.label1); this.groupBox2.Controls.Add(this.label1);
this.groupBox2.Controls.Add(this.btnDesligarBomba); this.groupBox2.Controls.Add(this.btnDesligarBomba);
this.groupBox2.Controls.Add(this.nudPotenciaBomba); this.groupBox2.Controls.Add(this.nudPotenciaBombaMin);
this.groupBox2.Controls.Add(this.nudPressaoSP); this.groupBox2.Controls.Add(this.nudPressaoSP);
this.groupBox2.Controls.Add(this.lblPressaoSP); this.groupBox2.Controls.Add(this.lblPressaoSP);
this.groupBox2.Location = new System.Drawing.Point(5, 6); this.groupBox2.Location = new System.Drawing.Point(5, 6);
@ -905,6 +910,32 @@
this.txtKd.TabIndex = 44; this.txtKd.TabIndex = 44;
this.txtKd.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; this.txtKd.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
// //
// label7
//
this.label7.AutoSize = true;
this.label7.Font = new System.Drawing.Font("Microsoft Sans Serif", 7.8F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.label7.Location = new System.Drawing.Point(78, 94);
this.label7.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0);
this.label7.Name = "label7";
this.label7.Size = new System.Drawing.Size(53, 13);
this.label7.TabIndex = 47;
this.label7.Text = "Pot Max";
//
// nudPotenciaBombaMax
//
this.nudPotenciaBombaMax.Font = new System.Drawing.Font("Microsoft Sans Serif", 7.8F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.nudPotenciaBombaMax.Location = new System.Drawing.Point(72, 111);
this.nudPotenciaBombaMax.Margin = new System.Windows.Forms.Padding(2);
this.nudPotenciaBombaMax.Maximum = new decimal(new int[] {
200,
0,
0,
0});
this.nudPotenciaBombaMax.Name = "nudPotenciaBombaMax";
this.nudPotenciaBombaMax.Size = new System.Drawing.Size(55, 19);
this.nudPotenciaBombaMax.TabIndex = 46;
this.nudPotenciaBombaMax.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
//
// frmOperacaoManual // frmOperacaoManual
// //
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
@ -959,11 +990,12 @@
this.pnlDir_DT.PerformLayout(); this.pnlDir_DT.PerformLayout();
this.pnlDir_DF.ResumeLayout(false); this.pnlDir_DF.ResumeLayout(false);
this.pnlDir_DF.PerformLayout(); this.pnlDir_DF.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.nudPotenciaBomba)).EndInit(); ((System.ComponentModel.ISupportInitialize)(this.nudPotenciaBombaMin)).EndInit();
this.groupBox2.ResumeLayout(false); this.groupBox2.ResumeLayout(false);
this.groupBox2.PerformLayout(); this.groupBox2.PerformLayout();
this.groupBox3.ResumeLayout(false); this.groupBox3.ResumeLayout(false);
this.groupBox3.PerformLayout(); this.groupBox3.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.nudPotenciaBombaMax)).EndInit();
this.ResumeLayout(false); this.ResumeLayout(false);
this.PerformLayout(); this.PerformLayout();
@ -1026,7 +1058,7 @@
private System.Windows.Forms.Label lblPressao; private System.Windows.Forms.Label lblPressao;
private System.Windows.Forms.Label lblStatusCarroMapa; private System.Windows.Forms.Label lblStatusCarroMapa;
private System.Windows.Forms.Label label1; private System.Windows.Forms.Label label1;
private System.Windows.Forms.NumericUpDown nudPotenciaBomba; private System.Windows.Forms.NumericUpDown nudPotenciaBombaMin;
private System.Windows.Forms.GroupBox groupBox3; private System.Windows.Forms.GroupBox groupBox3;
private System.Windows.Forms.GroupBox groupBox2; private System.Windows.Forms.GroupBox groupBox2;
private System.Windows.Forms.Label label2; private System.Windows.Forms.Label label2;
@ -1039,5 +1071,7 @@
private System.Windows.Forms.TextBox txtKi; private System.Windows.Forms.TextBox txtKi;
private System.Windows.Forms.Label label4; private System.Windows.Forms.Label label4;
private System.Windows.Forms.TextBox txtKp; private System.Windows.Forms.TextBox txtKp;
private System.Windows.Forms.Label label7;
private System.Windows.Forms.NumericUpDown nudPotenciaBombaMax;
} }
} }

View File

@ -60,10 +60,11 @@ namespace AgroBase.Forms.Operacoes
txtKp.Text = b.Controle.Kp.ToString(); txtKp.Text = b.Controle.Kp.ToString();
txtKi.Text = b.Controle.Ki.ToString(); txtKi.Text = b.Controle.Ki.ToString();
txtKd.Text = b.Controle.Kd.ToString(); txtKd.Text = b.Controle.Kd.ToString();
nudPotenciaBombaMin.Value = Convert.ToInt32(b.Controle.PotenciaMinPID);
} }
nudPressaoSP.Value = Convert.ToInt32(pC.AtuPressaoLinha); nudPressaoSP.Value = Convert.ToInt32(pC.AtuPressaoLinha);
nudPotenciaBomba.Value = 100; nudPotenciaBombaMax.Value = 100;
nudPotenciaAgitador.Value = 100; nudPotenciaAgitador.Value = 100;
flwCamerasSolo.Controls.Clear(); flwCamerasSolo.Controls.Clear();
@ -670,14 +671,14 @@ namespace AgroBase.Forms.Operacoes
{ {
Variaveis.OperacaoEmAndamento.Parametros.Controle.AtuModoControle = (ModoControleBomba)cmbModoBomba.SelectedIndex; Variaveis.OperacaoEmAndamento.Parametros.Controle.AtuModoControle = (ModoControleBomba)cmbModoBomba.SelectedIndex;
double potencia = Convert.ToInt32(nudPotenciaBomba.Value); double pressao = Convert.ToInt32(nudPressaoSP.Value);
double potMin = Convert.ToInt32(nudPotenciaBombaMin.Value);
double potMax = Convert.ToInt32(nudPotenciaBombaMax.Value);
double Kp = Convert.ToDouble(txtKp.Text); double Kp = Convert.ToDouble(txtKp.Text);
double Ki = Convert.ToDouble(txtKi.Text); double Ki = Convert.ToDouble(txtKi.Text);
double Kd = Convert.ToDouble(txtKd.Text); double Kd = Convert.ToDouble(txtKd.Text);
GeneralJoystick.EnviarComandoAtuador(Bomba.Componente, Bomba.ID, Status: true, Valores: new System.Collections.Generic.List<double?>() { cmbModoBomba.SelectedIndex, potencia, Kp, Ki, Kd }, Comando: CanMessagePosicaoDados.Command2, Forcar: true); GeneralJoystick.EnviarComandoAtuador(Bomba.Componente, Bomba.ID, Status: true, Valores: new System.Collections.Generic.List<double?>() { cmbModoBomba.SelectedIndex, potMin, Kp, Ki, Kd }, Comando: CanMessagePosicaoDados.Command2, Forcar: true);
GeneralJoystick.EnviarComandoAtuador(Bomba.Componente, Bomba.ID, Status: true, Valores: new System.Collections.Generic.List<double?>() { potMax, pressao }, Comando: CanMessagePosicaoDados.Command1, Forcar: true);
double pressao = Convert.ToInt32(nudPressaoSP.Value);
GeneralJoystick.EnviarComandoAtuador(Bomba.Componente, Bomba.ID, Status: true, Valores: new System.Collections.Generic.List<double?>() { potencia, pressao }, Comando: CanMessagePosicaoDados.Command1, Forcar: true);
} }
} }

View File

@ -80,6 +80,7 @@ class BombaPressurizadora_v2 : public ComponenteCAN {
double Kd = 0.0; double Kd = 0.0;
double erroAnterior = 0; double erroAnterior = 0;
double pressaoAnterior = 0.0;
double integralErro = 0; double integralErro = 0;
unsigned long ultimoPID_ms = 0; unsigned long ultimoPID_ms = 0;
@ -341,56 +342,107 @@ class BombaPressurizadora_v2 : public ComponenteCAN {
} }
void ResetPID() { void ResetPID() {
erroAnterior = 0; erroAnterior = 0.0;
integralErro = 0; integralErro = 0.0;
pressaoAnterior = 0.0;
ultimoPID_ms = millis(); ultimoPID_ms = millis();
} }
double CalcularPotenciaPID(double pressaoAtual) { double CalcularPotenciaPID(double pressaoAtual) {
unsigned long agora = millis(); const unsigned long agora = millis();
if (ultimoPID_ms == 0) { if (ultimoPID_ms == 0) {
ultimoPID_ms = agora; ultimoPID_ms = agora;
erroAnterior = _PressaoSP - pressaoAtual;
pressaoAnterior = pressaoAtual;
return 0.0;
} }
double dt = (agora - ultimoPID_ms) / 1000.0; double dt = (agora - ultimoPID_ms) / 1000.0;
ultimoPID_ms = agora; ultimoPID_ms = agora;
if (dt <= 0.001) { if (dt < 0.01) {
dt = 0.001; dt = 0.01;
}
if (dt > 0.5) {
dt = 0.5;
} }
double erro = _PressaoSP - pressaoAtual; double erro = _PressaoSP - pressaoAtual;
// Zona morta: se está perto do SP, evita ficar oscilando demais if (fabs(erro) <= DeadbandPressao) {
if (abs(erro) <= DeadbandPressao) { erro = 0.0;
erro = 0;
} }
integralErro += erro * dt; /*
integralErro = constrain(integralErro, IntegralMin, IntegralMax); Derivada feita sobre a medição, e não sobre o erro.
Isso reduz o tranco quando o SP muda.
*/
double derivadaMedicao =
(pressaoAtual - pressaoAnterior) / dt;
double derivada = (erro - erroAnterior) / dt; pressaoAnterior = pressaoAtual;
erroAnterior = erro;
double saida = (Kp * erro) + (Ki * integralErro) + (Kd * derivada); /*
Calcula primeiro sem atualizar a integral.
*/
double saidaSemIntegral =
(Kp * erro)
- (Kd * derivadaMedicao);
// Se passou da pressão desejada, deixa cortar a bomba double integralCandidata =
if (pressaoAtual >= _PressaoSP) { integralErro + (erro * dt);
saida = 0;
integralCandidata = constrain(
integralCandidata,
IntegralMin,
IntegralMax
);
double saidaCandidata =
saidaSemIntegral
+ (Ki * integralCandidata);
double teto = constrain(
_PotenciaSP,
0.0,
PotenciaMaxPID
);
/*
Anti-windup:
integra se não estiver saturado,
ou se o erro estiver ajudando a sair da saturação.
*/
bool saturadoSuperior = saidaCandidata >= teto;
bool saturadoInferior = saidaCandidata <= 0.0;
bool podeIntegrar =
(!saturadoSuperior && !saturadoInferior)
|| (saturadoSuperior && erro < 0)
|| (saturadoInferior && erro > 0);
if (podeIntegrar) {
integralErro = integralCandidata;
} }
// Limite máximo vindo do comando double saida =
double teto = _PotenciaSP > 0 ? _PotenciaSP : PotenciaMaxPID; saidaSemIntegral
teto = constrain(teto, PotenciaMinPID, PotenciaMaxPID); + (Ki * integralErro);
saida = constrain(saida, 0, teto); saida = constrain(saida, 0.0, teto);
// Degrau mínimo: se o PID quer ligar, liga com potência útil /*
if (saida > 0 && saida < PotenciaMinPID) { aplica o mínimo quando existe demanda real
para ligar a bomba.
*/
if (saida > 0.0 && saida < PotenciaMinPID) {
saida = PotenciaMinPID; saida = PotenciaMinPID;
} }
erroAnterior = erro;
return saida; return saida;
} }