Adicionado modo de controle na bomba pressurizadora

This commit is contained in:
Diego Freitas 2026-06-09 10:39:44 -03:00
parent e25f2ee259
commit d7c7b538d7
23 changed files with 1522 additions and 100 deletions

View File

@ -152,19 +152,19 @@ namespace AgroBase.Forms.Atuador
{
var Bomba = Variaveis.OperacaoEmAndamento.DispAtu.Dados.BombasPressurizadoras.FirstOrDefault();
Variaveis.OperacaoEmAndamento.Parametros.Controle.AtuPressaoLinha = Convert.ToInt32(((NumericUpDown)sender).Value);
GeneralJoystick.EnviarComandoAtuador(S_Code.sBMB, Bomba.ID, Status: Bomba.ComandoAtuar);
GeneralJoystick.EnviarComandoAtuador(S_Code.sBMB, Bomba.ID, Status: Bomba.ComandoAtuar, Comando: Services.CanMessagePosicaoDados.Command1);
}
private void btnLigarBomba_Click(object sender, EventArgs e)
{
var Bomba = Variaveis.OperacaoEmAndamento.DispAtu.Dados.BombasPressurizadoras.FirstOrDefault();
GeneralJoystick.EnviarComandoAtuador(S_Code.sBMB, Bomba.ID, Status: true, Forcar: true);
GeneralJoystick.EnviarComandoAtuador(S_Code.sBMB, Bomba.ID, Status: true, Comando: Services.CanMessagePosicaoDados.Command1, Forcar: true);
}
private void btnDesligarBomba_Click(object sender, EventArgs e)
{
var Bomba = Variaveis.OperacaoEmAndamento.DispAtu.Dados.BombasPressurizadoras.FirstOrDefault();
GeneralJoystick.EnviarComandoAtuador(S_Code.sBMB, Bomba.ID, Status: false, Forcar: true);
GeneralJoystick.EnviarComandoAtuador(S_Code.sBMB, Bomba.ID, Status: false, Comando: Services.CanMessagePosicaoDados.Command1, Forcar: true);
}
private void pnlBico_Paint(object sender, PaintEventArgs e)

View File

@ -527,7 +527,7 @@ namespace AgroBase.Forms.IHM
{
var Bomba = Variaveis.OperacaoEmAndamento.DispAtu.Dados.BombasPressurizadoras.FirstOrDefault();
Variaveis.OperacaoEmAndamento.Parametros.Controle.AtuPressaoLinha = Pressao + 10;
GeneralJoystick.EnviarComandoAtuador(S_Code.sBMB, Bomba.ID, Status: Ligar);
GeneralJoystick.EnviarComandoAtuador(S_Code.sBMB, Bomba.ID, Status: Ligar, Comando: CanMessagePosicaoDados.Command1);
DateTime inicio = DateTime.Now;
while (DateTime.Now < inicio.AddMilliseconds(Timeout))

View File

@ -54,10 +54,11 @@
this.tabInformacoes = new System.Windows.Forms.TabPage();
this.gridDados = new System.Windows.Forms.DataGridView();
this.tabDeteccoes = new System.Windows.Forms.TabPage();
this.lblStatusCarroMapa = new System.Windows.Forms.Label();
this.pnlDeteccoesRua = new System.Windows.Forms.Panel();
this.tabPulverizador = new System.Windows.Forms.TabPage();
this.lblPotenciaSP = new System.Windows.Forms.Label();
this.nudPotenciaSP = new System.Windows.Forms.NumericUpDown();
this.nudPotenciaAgitador = new System.Windows.Forms.NumericUpDown();
this.btnDeslsigarAgitador = new System.Windows.Forms.Button();
this.btnLigarAgitador = new System.Windows.Forms.Button();
this.lblPressaoSP = new System.Windows.Forms.Label();
@ -86,7 +87,20 @@
this.flwCamerasSolo = new System.Windows.Forms.FlowLayoutPanel();
this.chbSonarAtivado = new System.Windows.Forms.CheckBox();
this.lblPressao = new System.Windows.Forms.Label();
this.lblStatusCarroMapa = new System.Windows.Forms.Label();
this.label1 = new System.Windows.Forms.Label();
this.nudPotenciaBomba = new System.Windows.Forms.NumericUpDown();
this.groupBox2 = new System.Windows.Forms.GroupBox();
this.groupBox3 = new System.Windows.Forms.GroupBox();
this.cmbModoAgitador = new System.Windows.Forms.ComboBox();
this.label2 = new System.Windows.Forms.Label();
this.label3 = new System.Windows.Forms.Label();
this.cmbModoBomba = new System.Windows.Forms.ComboBox();
this.txtKp = new System.Windows.Forms.TextBox();
this.label4 = new System.Windows.Forms.Label();
this.label5 = new System.Windows.Forms.Label();
this.txtKi = new System.Windows.Forms.TextBox();
this.label6 = new System.Windows.Forms.Label();
this.txtKd = new System.Windows.Forms.TextBox();
((System.ComponentModel.ISupportInitialize)(this.chartGraficos)).BeginInit();
this.tabControl1.SuspendLayout();
this.tabMapa.SuspendLayout();
@ -94,12 +108,15 @@
((System.ComponentModel.ISupportInitialize)(this.gridDados)).BeginInit();
this.tabDeteccoes.SuspendLayout();
this.tabPulverizador.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.nudPotenciaSP)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.nudPotenciaAgitador)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.nudPressaoSP)).BeginInit();
this.pnlDir_EF.SuspendLayout();
this.pnlDir_ET.SuspendLayout();
this.pnlDir_DT.SuspendLayout();
this.pnlDir_DF.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.nudPotenciaBomba)).BeginInit();
this.groupBox2.SuspendLayout();
this.groupBox3.SuspendLayout();
this.SuspendLayout();
//
// pnlAtuadores
@ -364,6 +381,16 @@
this.tabDeteccoes.Text = "Detecção rua";
this.tabDeteccoes.UseVisualStyleBackColor = true;
//
// lblStatusCarroMapa
//
this.lblStatusCarroMapa.AutoSize = true;
this.lblStatusCarroMapa.Font = new System.Drawing.Font("Microsoft Sans Serif", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.lblStatusCarroMapa.Location = new System.Drawing.Point(10, 269);
this.lblStatusCarroMapa.Name = "lblStatusCarroMapa";
this.lblStatusCarroMapa.Size = new System.Drawing.Size(168, 16);
this.lblStatusCarroMapa.TabIndex = 1;
this.lblStatusCarroMapa.Text = "Status: Parado | Conf: 1.000";
//
// pnlDeteccoesRua
//
this.pnlDeteccoesRua.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Zoom;
@ -375,14 +402,8 @@
//
// tabPulverizador
//
this.tabPulverizador.Controls.Add(this.lblPotenciaSP);
this.tabPulverizador.Controls.Add(this.nudPotenciaSP);
this.tabPulverizador.Controls.Add(this.btnDeslsigarAgitador);
this.tabPulverizador.Controls.Add(this.btnLigarAgitador);
this.tabPulverizador.Controls.Add(this.lblPressaoSP);
this.tabPulverizador.Controls.Add(this.nudPressaoSP);
this.tabPulverizador.Controls.Add(this.btnDesligarBomba);
this.tabPulverizador.Controls.Add(this.btnLigarBomba);
this.tabPulverizador.Controls.Add(this.groupBox3);
this.tabPulverizador.Controls.Add(this.groupBox2);
this.tabPulverizador.Location = new System.Drawing.Point(4, 22);
this.tabPulverizador.Margin = new System.Windows.Forms.Padding(2);
this.tabPulverizador.Name = "tabPulverizador";
@ -396,31 +417,31 @@
//
this.lblPotenciaSP.AutoSize = true;
this.lblPotenciaSP.Font = new System.Drawing.Font("Microsoft Sans Serif", 7.8F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.lblPotenciaSP.Location = new System.Drawing.Point(21, 57);
this.lblPotenciaSP.Location = new System.Drawing.Point(6, 56);
this.lblPotenciaSP.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0);
this.lblPotenciaSP.Name = "lblPotenciaSP";
this.lblPotenciaSP.Size = new System.Drawing.Size(77, 13);
this.lblPotenciaSP.TabIndex = 33;
this.lblPotenciaSP.Text = "Potencia SP";
//
// nudPotenciaSP
// nudPotenciaAgitador
//
this.nudPotenciaSP.Font = new System.Drawing.Font("Microsoft Sans Serif", 7.8F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.nudPotenciaSP.Location = new System.Drawing.Point(21, 73);
this.nudPotenciaSP.Margin = new System.Windows.Forms.Padding(2);
this.nudPotenciaSP.Name = "nudPotenciaSP";
this.nudPotenciaSP.Size = new System.Drawing.Size(79, 19);
this.nudPotenciaSP.TabIndex = 32;
this.nudPotenciaSP.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
this.nudPotenciaSP.ValueChanged += new System.EventHandler(this.nudPotenciaSP_ValueChanged);
this.nudPotenciaAgitador.Font = new System.Drawing.Font("Microsoft Sans Serif", 7.8F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.nudPotenciaAgitador.Location = new System.Drawing.Point(6, 72);
this.nudPotenciaAgitador.Margin = new System.Windows.Forms.Padding(2);
this.nudPotenciaAgitador.Name = "nudPotenciaAgitador";
this.nudPotenciaAgitador.Size = new System.Drawing.Size(121, 19);
this.nudPotenciaAgitador.TabIndex = 32;
this.nudPotenciaAgitador.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
this.nudPotenciaAgitador.ValueChanged += new System.EventHandler(this.nudPotenciaSP_ValueChanged);
//
// btnDeslsigarAgitador
//
this.btnDeslsigarAgitador.Font = new System.Drawing.Font("Microsoft Sans Serif", 7.8F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.btnDeslsigarAgitador.Location = new System.Drawing.Point(244, 67);
this.btnDeslsigarAgitador.Location = new System.Drawing.Point(312, 34);
this.btnDeslsigarAgitador.Margin = new System.Windows.Forms.Padding(2);
this.btnDeslsigarAgitador.Name = "btnDeslsigarAgitador";
this.btnDeslsigarAgitador.Size = new System.Drawing.Size(120, 28);
this.btnDeslsigarAgitador.Size = new System.Drawing.Size(136, 28);
this.btnDeslsigarAgitador.TabIndex = 31;
this.btnDeslsigarAgitador.Text = "Desligar Agitador";
this.btnDeslsigarAgitador.UseVisualStyleBackColor = true;
@ -429,10 +450,10 @@
// btnLigarAgitador
//
this.btnLigarAgitador.Font = new System.Drawing.Font("Microsoft Sans Serif", 7.8F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.btnLigarAgitador.Location = new System.Drawing.Point(118, 67);
this.btnLigarAgitador.Location = new System.Drawing.Point(312, 66);
this.btnLigarAgitador.Margin = new System.Windows.Forms.Padding(2);
this.btnLigarAgitador.Name = "btnLigarAgitador";
this.btnLigarAgitador.Size = new System.Drawing.Size(104, 28);
this.btnLigarAgitador.Size = new System.Drawing.Size(136, 28);
this.btnLigarAgitador.TabIndex = 30;
this.btnLigarAgitador.Text = "Ligar Agitador";
this.btnLigarAgitador.UseVisualStyleBackColor = true;
@ -442,7 +463,7 @@
//
this.lblPressaoSP.AutoSize = true;
this.lblPressaoSP.Font = new System.Drawing.Font("Microsoft Sans Serif", 7.8F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.lblPressaoSP.Location = new System.Drawing.Point(18, 11);
this.lblPressaoSP.Location = new System.Drawing.Point(6, 55);
this.lblPressaoSP.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0);
this.lblPressaoSP.Name = "lblPressaoSP";
this.lblPressaoSP.Size = new System.Drawing.Size(72, 13);
@ -452,7 +473,7 @@
// nudPressaoSP
//
this.nudPressaoSP.Font = new System.Drawing.Font("Microsoft Sans Serif", 7.8F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.nudPressaoSP.Location = new System.Drawing.Point(18, 27);
this.nudPressaoSP.Location = new System.Drawing.Point(6, 72);
this.nudPressaoSP.Margin = new System.Windows.Forms.Padding(2);
this.nudPressaoSP.Maximum = new decimal(new int[] {
200,
@ -460,7 +481,7 @@
0,
0});
this.nudPressaoSP.Name = "nudPressaoSP";
this.nudPressaoSP.Size = new System.Drawing.Size(79, 19);
this.nudPressaoSP.Size = new System.Drawing.Size(121, 19);
this.nudPressaoSP.TabIndex = 28;
this.nudPressaoSP.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
this.nudPressaoSP.ValueChanged += new System.EventHandler(this.nudPressaoSP_ValueChanged);
@ -468,10 +489,10 @@
// btnDesligarBomba
//
this.btnDesligarBomba.Font = new System.Drawing.Font("Microsoft Sans Serif", 7.8F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.btnDesligarBomba.Location = new System.Drawing.Point(244, 21);
this.btnDesligarBomba.Location = new System.Drawing.Point(312, 71);
this.btnDesligarBomba.Margin = new System.Windows.Forms.Padding(2);
this.btnDesligarBomba.Name = "btnDesligarBomba";
this.btnDesligarBomba.Size = new System.Drawing.Size(120, 28);
this.btnDesligarBomba.Size = new System.Drawing.Size(136, 28);
this.btnDesligarBomba.TabIndex = 27;
this.btnDesligarBomba.Text = "Desligar Bomba";
this.btnDesligarBomba.UseVisualStyleBackColor = true;
@ -480,10 +501,10 @@
// btnLigarBomba
//
this.btnLigarBomba.Font = new System.Drawing.Font("Microsoft Sans Serif", 7.8F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.btnLigarBomba.Location = new System.Drawing.Point(118, 21);
this.btnLigarBomba.Location = new System.Drawing.Point(312, 103);
this.btnLigarBomba.Margin = new System.Windows.Forms.Padding(2);
this.btnLigarBomba.Name = "btnLigarBomba";
this.btnLigarBomba.Size = new System.Drawing.Size(104, 28);
this.btnLigarBomba.Size = new System.Drawing.Size(136, 28);
this.btnLigarBomba.TabIndex = 26;
this.btnLigarBomba.Text = "Ligar Bomba";
this.btnLigarBomba.UseVisualStyleBackColor = true;
@ -723,15 +744,166 @@
this.lblPressao.TabIndex = 38;
this.lblPressao.Text = "80 psi";
//
// lblStatusCarroMapa
// label1
//
this.lblStatusCarroMapa.AutoSize = true;
this.lblStatusCarroMapa.Font = new System.Drawing.Font("Microsoft Sans Serif", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.lblStatusCarroMapa.Location = new System.Drawing.Point(10, 269);
this.lblStatusCarroMapa.Name = "lblStatusCarroMapa";
this.lblStatusCarroMapa.Size = new System.Drawing.Size(168, 16);
this.lblStatusCarroMapa.TabIndex = 1;
this.lblStatusCarroMapa.Text = "Status: Parado | Conf: 1.000";
this.label1.AutoSize = true;
this.label1.Font = new System.Drawing.Font("Microsoft Sans Serif", 7.8F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.label1.Location = new System.Drawing.Point(6, 94);
this.label1.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(77, 13);
this.label1.TabIndex = 35;
this.label1.Text = "Potencia SP";
//
// nudPotenciaBomba
//
this.nudPotenciaBomba.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.nudPotenciaBomba.Margin = new System.Windows.Forms.Padding(2);
this.nudPotenciaBomba.Maximum = new decimal(new int[] {
200,
0,
0,
0});
this.nudPotenciaBomba.Name = "nudPotenciaBomba";
this.nudPotenciaBomba.Size = new System.Drawing.Size(121, 19);
this.nudPotenciaBomba.TabIndex = 34;
this.nudPotenciaBomba.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
//
// groupBox2
//
this.groupBox2.Controls.Add(this.label6);
this.groupBox2.Controls.Add(this.txtKd);
this.groupBox2.Controls.Add(this.label5);
this.groupBox2.Controls.Add(this.txtKi);
this.groupBox2.Controls.Add(this.label4);
this.groupBox2.Controls.Add(this.txtKp);
this.groupBox2.Controls.Add(this.label3);
this.groupBox2.Controls.Add(this.cmbModoBomba);
this.groupBox2.Controls.Add(this.btnLigarBomba);
this.groupBox2.Controls.Add(this.label1);
this.groupBox2.Controls.Add(this.btnDesligarBomba);
this.groupBox2.Controls.Add(this.nudPotenciaBomba);
this.groupBox2.Controls.Add(this.nudPressaoSP);
this.groupBox2.Controls.Add(this.lblPressaoSP);
this.groupBox2.Location = new System.Drawing.Point(5, 6);
this.groupBox2.Name = "groupBox2";
this.groupBox2.Size = new System.Drawing.Size(453, 141);
this.groupBox2.TabIndex = 37;
this.groupBox2.TabStop = false;
this.groupBox2.Text = "Bomba Pressurizadora";
//
// groupBox3
//
this.groupBox3.Controls.Add(this.label2);
this.groupBox3.Controls.Add(this.cmbModoAgitador);
this.groupBox3.Controls.Add(this.nudPotenciaAgitador);
this.groupBox3.Controls.Add(this.btnLigarAgitador);
this.groupBox3.Controls.Add(this.lblPotenciaSP);
this.groupBox3.Controls.Add(this.btnDeslsigarAgitador);
this.groupBox3.Location = new System.Drawing.Point(5, 177);
this.groupBox3.Name = "groupBox3";
this.groupBox3.Size = new System.Drawing.Size(453, 106);
this.groupBox3.TabIndex = 38;
this.groupBox3.TabStop = false;
this.groupBox3.Text = "Agitador de Calda";
//
// cmbModoAgitador
//
this.cmbModoAgitador.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.cmbModoAgitador.FormattingEnabled = true;
this.cmbModoAgitador.Location = new System.Drawing.Point(6, 32);
this.cmbModoAgitador.Name = "cmbModoAgitador";
this.cmbModoAgitador.Size = new System.Drawing.Size(121, 21);
this.cmbModoAgitador.TabIndex = 34;
//
// label2
//
this.label2.AutoSize = true;
this.label2.Font = new System.Drawing.Font("Microsoft Sans Serif", 7.8F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.label2.Location = new System.Drawing.Point(6, 16);
this.label2.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(107, 13);
this.label2.TabIndex = 37;
this.label2.Text = "Modo de Controle";
//
// label3
//
this.label3.AutoSize = true;
this.label3.Font = new System.Drawing.Font("Microsoft Sans Serif", 7.8F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.label3.Location = new System.Drawing.Point(6, 16);
this.label3.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0);
this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(107, 13);
this.label3.TabIndex = 39;
this.label3.Text = "Modo de Controle";
//
// cmbModoBomba
//
this.cmbModoBomba.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.cmbModoBomba.FormattingEnabled = true;
this.cmbModoBomba.Location = new System.Drawing.Point(6, 32);
this.cmbModoBomba.Name = "cmbModoBomba";
this.cmbModoBomba.Size = new System.Drawing.Size(121, 21);
this.cmbModoBomba.TabIndex = 38;
//
// txtKp
//
this.txtKp.Location = new System.Drawing.Point(149, 32);
this.txtKp.Name = "txtKp";
this.txtKp.Size = new System.Drawing.Size(68, 20);
this.txtKp.TabIndex = 40;
this.txtKp.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
//
// label4
//
this.label4.AutoSize = true;
this.label4.Font = new System.Drawing.Font("Microsoft Sans Serif", 7.8F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.label4.Location = new System.Drawing.Point(146, 16);
this.label4.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0);
this.label4.Name = "label4";
this.label4.Size = new System.Drawing.Size(22, 13);
this.label4.TabIndex = 41;
this.label4.Text = "Kp";
//
// label5
//
this.label5.AutoSize = true;
this.label5.Font = new System.Drawing.Font("Microsoft Sans Serif", 7.8F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.label5.Location = new System.Drawing.Point(146, 55);
this.label5.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0);
this.label5.Name = "label5";
this.label5.Size = new System.Drawing.Size(18, 13);
this.label5.TabIndex = 43;
this.label5.Text = "Ki";
//
// txtKi
//
this.txtKi.Location = new System.Drawing.Point(149, 71);
this.txtKi.Name = "txtKi";
this.txtKi.Size = new System.Drawing.Size(68, 20);
this.txtKi.TabIndex = 42;
this.txtKi.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
//
// label6
//
this.label6.AutoSize = true;
this.label6.Font = new System.Drawing.Font("Microsoft Sans Serif", 7.8F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.label6.Location = new System.Drawing.Point(146, 94);
this.label6.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0);
this.label6.Name = "label6";
this.label6.Size = new System.Drawing.Size(22, 13);
this.label6.TabIndex = 45;
this.label6.Text = "Kd";
//
// txtKd
//
this.txtKd.Location = new System.Drawing.Point(149, 110);
this.txtKd.Name = "txtKd";
this.txtKd.Size = new System.Drawing.Size(68, 20);
this.txtKd.TabIndex = 44;
this.txtKd.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
//
// frmOperacaoManual
//
@ -777,8 +949,7 @@
this.tabDeteccoes.ResumeLayout(false);
this.tabDeteccoes.PerformLayout();
this.tabPulverizador.ResumeLayout(false);
this.tabPulverizador.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.nudPotenciaSP)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.nudPotenciaAgitador)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.nudPressaoSP)).EndInit();
this.pnlDir_EF.ResumeLayout(false);
this.pnlDir_EF.PerformLayout();
@ -788,6 +959,11 @@
this.pnlDir_DT.PerformLayout();
this.pnlDir_DF.ResumeLayout(false);
this.pnlDir_DF.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.nudPotenciaBomba)).EndInit();
this.groupBox2.ResumeLayout(false);
this.groupBox2.PerformLayout();
this.groupBox3.ResumeLayout(false);
this.groupBox3.PerformLayout();
this.ResumeLayout(false);
this.PerformLayout();
@ -846,8 +1022,22 @@
private System.Windows.Forms.Button btnDeslsigarAgitador;
private System.Windows.Forms.Button btnLigarAgitador;
private System.Windows.Forms.Label lblPotenciaSP;
private System.Windows.Forms.NumericUpDown nudPotenciaSP;
private System.Windows.Forms.NumericUpDown nudPotenciaAgitador;
private System.Windows.Forms.Label lblPressao;
private System.Windows.Forms.Label lblStatusCarroMapa;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.NumericUpDown nudPotenciaBomba;
private System.Windows.Forms.GroupBox groupBox3;
private System.Windows.Forms.GroupBox groupBox2;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.ComboBox cmbModoAgitador;
private System.Windows.Forms.Label label3;
private System.Windows.Forms.ComboBox cmbModoBomba;
private System.Windows.Forms.Label label6;
private System.Windows.Forms.TextBox txtKd;
private System.Windows.Forms.Label label5;
private System.Windows.Forms.TextBox txtKi;
private System.Windows.Forms.Label label4;
private System.Windows.Forms.TextBox txtKp;
}
}

View File

@ -40,10 +40,32 @@ namespace AgroBase.Forms.Operacoes
private void frmOperacaoManual_Load(object sender, EventArgs e)
{
var pC = Variaveis.OperacaoEmAndamento.Parametros.Controle;
cmbTipoMovimento.Items.Clear();
cmbTipoMovimento.Items.AddRange(Enum.GetNames(typeof(TipoMovimentoDirecional)));
cmbTipoMovimento.SelectedIndex = (int)Variaveis.OperacaoEmAndamento.Controle.TipoMovimento;
cmbModoBomba.Items.Clear();
cmbModoBomba.Items.AddRange(Enum.GetNames(typeof(ModoControleBomba)));
cmbModoBomba.SelectedIndex = (int)pC.AtuModoControle;
cmbModoAgitador.Items.Clear();
cmbModoAgitador.Items.AddRange(Enum.GetNames(typeof(ModoAgitadorCalda)));
cmbModoAgitador.SelectedIndex = (int)pC.AtuAgitadorModo;
var b = Variaveis.OperacaoEmAndamento.DispAtu.Dados.BombasPressurizadoras.FirstOrDefault(x => x.ID == "BMBLN");
if (b != null)
{
txtKp.Text = b.Controle.Kp.ToString();
txtKi.Text = b.Controle.Ki.ToString();
txtKd.Text = b.Controle.Kd.ToString();
}
nudPressaoSP.Value = Convert.ToInt32(pC.AtuPressaoLinha);
nudPotenciaBomba.Value = 100;
nudPotenciaAgitador.Value = 100;
flwCamerasSolo.Controls.Clear();
for (int i = 0; i < Variaveis.OperacaoEmAndamento.DispSen.Dados.CamerasSolo.Count(); i++)
{
@ -59,9 +81,9 @@ namespace AgroBase.Forms.Operacoes
flwCamerasSolo.Controls.Add(pnlCam);
}
chbPulverizador.Checked = Variaveis.OperacaoEmAndamento.Parametros.Controle.PulverizadorAutomatico;
chbSonarAtivado.Checked = Variaveis.OperacaoEmAndamento.Parametros.Controle.MovAuxilioSonar;
chbSonarAtivado.Checked = Variaveis.OperacaoEmAndamento.Parametros.Controle.DirAuxilioSonar;
chbPulverizador.Checked = pC.PulverizadorAutomatico;
chbSonarAtivado.Checked = pC.MovAuxilioSonar;
chbSonarAtivado.Checked = pC.DirAuxilioSonar;
InicializarComandosDirecional();
PopularInformacoesGerais();
@ -589,9 +611,7 @@ namespace AgroBase.Forms.Operacoes
private void PopularBicos()
{
var Atuador = Variaveis.OperacaoEmAndamento.DispAtu;
nudPressaoSP.Value = Convert.ToInt32(Variaveis.OperacaoEmAndamento.Parametros.Controle.AtuPressaoLinha);
nudPotenciaSP.Value = 100;
int panelWidth = pnlAtuadores.Width;
int circleDiameter = 40; // Diâmetro dos círculos grandes
int spaceBetweenCircles = (panelWidth - (circleDiameter * (Variaveis.OperacaoEmAndamento.Parametros.QtdBicos ?? VariaveisEquipamento.QuantidadeBicosPulverizadores))) / ((Variaveis.OperacaoEmAndamento.Parametros.QtdBicos ?? VariaveisEquipamento.QuantidadeBicosPulverizadores) + 1);
@ -647,28 +667,44 @@ namespace AgroBase.Forms.Operacoes
{
var Bomba = Variaveis.OperacaoEmAndamento.DispAtu.Dados.BombasPressurizadoras.FirstOrDefault(x => x.ID == "BMBLN");
if (Bomba != null)
GeneralJoystick.EnviarComandoAtuador(Bomba.Componente, Bomba.ID, Status: true, Valores: new System.Collections.Generic.List<double?>() { Convert.ToInt32(nudPotenciaSP.Value), Convert.ToInt32(nudPressaoSP.Value) }, Forcar: true);
{
Variaveis.OperacaoEmAndamento.Parametros.Controle.AtuModoControle = (ModoControleBomba)cmbModoBomba.SelectedIndex;
double potencia = Convert.ToInt32(nudPotenciaBomba.Value);
double Kp = Convert.ToDouble(txtKp.Text);
double Ki = Convert.ToDouble(txtKi.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);
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);
}
}
private void btnDesligarBomba_Click(object sender, EventArgs e)
{
var Bomba = Variaveis.OperacaoEmAndamento.DispAtu.Dados.BombasPressurizadoras.FirstOrDefault(x => x.ID == "BMBLN");
if (Bomba != null)
GeneralJoystick.EnviarComandoAtuador(Bomba.Componente, Bomba.ID, Status: false, Forcar: true);
GeneralJoystick.EnviarComandoAtuador(Bomba.Componente, Bomba.ID, Status: false, Comando: CanMessagePosicaoDados.Command1, Forcar: true);
}
private void btnLigarAgitador_Click(object sender, EventArgs e)
{
var Agitador = Variaveis.OperacaoEmAndamento.DispAtu.Dados.BombasPressurizadoras.FirstOrDefault(x => x.ID == "BMBAGT");
if (Agitador != null)
GeneralJoystick.EnviarComandoAtuador(Agitador.Componente, Agitador.ID, Status: true, Valores: new System.Collections.Generic.List<double?>() { Convert.ToInt32(nudPotenciaSP.Value) }, Forcar: true);
{
Variaveis.OperacaoEmAndamento.Parametros.Controle.AtuAgitadorModo = (ModoAgitadorCalda)cmbModoAgitador.SelectedIndex;
double potencia = Convert.ToInt32(nudPotenciaAgitador.Value);
GeneralJoystick.EnviarComandoAtuador(Agitador.Componente, Agitador.ID, Status: true, Valores: new System.Collections.Generic.List<double?>() { potencia }, Comando: CanMessagePosicaoDados.Command1, Forcar: true);
}
}
private void btnDeslsigarAgitador_Click(object sender, EventArgs e)
{
var Agitador = Variaveis.OperacaoEmAndamento.DispAtu.Dados.BombasPressurizadoras.FirstOrDefault(x => x.ID == "BMBAGT");
if (Agitador != null)
GeneralJoystick.EnviarComandoAtuador(Agitador.Componente, Agitador.ID, Status: false, Forcar: true);
GeneralJoystick.EnviarComandoAtuador(Agitador.Componente, Agitador.ID, Status: false, Comando: CanMessagePosicaoDados.Command1, Forcar: true);
}
private void nudPressaoSP_ValueChanged(object sender, EventArgs e)

View File

@ -135,6 +135,7 @@
sQAR = 32,
sCHV = 33,
sSRV = 34,
sBOT = 35,
}
public enum BotoesJoystick
@ -382,5 +383,11 @@
Intermitente = 2,
}
public enum ModoControleBomba
{
OnOff = 0,
PID = 1
}
}
}

View File

@ -627,7 +627,7 @@ namespace AgroBase
for (int i = 0; i < 1; i++)
{
EnviarComandoAtuador(comp, Comando.IDcontrolar, Status: Comando.EstadoAplicar);
EnviarComandoAtuador(comp, Comando.IDcontrolar, Status: Comando.EstadoAplicar, Comando: Comando.Comando);
}
}
@ -829,7 +829,7 @@ namespace AgroBase
}
}
public static void EnviarComandoAtuador(S_Code Componente, string ID, bool? Status = null, List<double?> Valores = null, bool Forcar = false)
public static void EnviarComandoAtuador(S_Code Componente, string ID, bool? Status = null, List<double?> Valores = null, CanMessagePosicaoDados Comando = CanMessagePosicaoDados.Command1, bool Forcar = false)
{
var DispAtu = Variaveis.OperacaoEmAndamento.DispAtu;
if (!DispAtu.Dados.Conectado)
@ -843,7 +843,7 @@ namespace AgroBase
}
int id_num = -1;
CanMessagePosicaoDados posicao = CanMessagePosicaoDados.Command1;
CanMessagePosicaoDados comando = Comando;
byte[] data = null;
switch (Componente)
@ -851,17 +851,30 @@ namespace AgroBase
case S_Code.sMOD:
if (DispAtu?.Dados != null && Status == true)
{
(id_num, posicao, data) = DispAtu.Dados.ProtocoloComandoReset();
(id_num, comando, data) = DispAtu.Dados.ProtocoloComandoReset();
}
break;
case S_Code.sBMB:
var Bomba = DispAtu?.Dados?.BombasPressurizadoras?.FirstOrDefault(x => x.ID == ID);
if (Bomba != null)
{
if (Status != null) Bomba.ComandoAtuar = (bool)Status;
if (Valores?.Count() > 0 && Valores[0] is double) Bomba.PotenciaSP = (double)Valores[0];
if (Valores?.Count() > 1 && Valores[1] is double) Bomba.PressaoSP = (double)Valores[1];
(id_num, posicao, data) = Bomba.ProtocoloComando();
switch (comando)
{
case CanMessagePosicaoDados.Command1:
if (Status != null) Bomba.ComandoAtuar = (bool)Status;
if (Valores?.Count() > 0 && Valores[0] is double) Bomba.PotenciaSP = (double)Valores[0];
if (Valores?.Count() > 1 && Valores[1] is double) Bomba.PressaoSP = (double)Valores[1];
(id_num, comando, data) = Bomba.ProtocoloComando(comando);
break;
case CanMessagePosicaoDados.Command2:
if (Valores?.Count() > 0 && Valores[0] is double) Bomba.Controle.Modo = (ModoControleBomba)((int)Valores[0]);
if (Valores?.Count() > 1 && Valores[1] is double) Bomba.Controle.PotenciaMinPID = (double)Valores[1];
if (Valores?.Count() > 2 && Valores[2] is double) Bomba.Controle.Kp = (double)Valores[2];
if (Valores?.Count() > 3 && Valores[3] is double) Bomba.Controle.Ki = (double)Valores[3];
if (Valores?.Count() > 4 && Valores[4] is double) Bomba.Controle.Kd = (double)Valores[4];
(id_num, comando, data) = Bomba.ProtocoloComando(comando);
break;
}
}
break;
case S_Code.sBIC:
@ -870,12 +883,12 @@ namespace AgroBase
{
if (Status != null) Bico.ComandoAtuar = (bool)Status;
if (Valores?.Count() > 0) Bico.AnguloControle = (int)Valores[0];
(id_num, posicao, data) = Bico.ProtocoloComando();
(id_num, comando, data) = Bico.ProtocoloComando();
}
break;
}
DispAtu.AdicionarMensagemFila(id_num, posicao, posicao, data, false);
DispAtu.AdicionarMensagemFila(id_num, comando, comando, data, false);
}
@ -979,6 +992,7 @@ namespace AgroBase
{
public BotoesJoystick botaoJoy { get; set; }
public Keys key { get; set; }
public CanMessagePosicaoDados Comando { get; set; } = CanMessagePosicaoDados.Command1;
public T_Code Dispositivo { get; set; }
public bool PararAoSoltar { get; set; }
public string IDcontrolar { get; set; }

View File

@ -377,7 +377,7 @@ namespace AgroBase.Models.Modules
}
}
},
// massa 31 ~ 40
// massa 31 ~ 35
new SensorModel()
{
ID = "MASRS",
@ -429,6 +429,48 @@ namespace AgroBase.Models.Modules
}
}
},
// pressao 36 ~ 40
new SensorModel()
{
ID = "BOTLAV",
ID_Num = 36,
Descricao = "Botão para lavagem do sistema hidráulico",
Componente = S_Code.sBOT,
Aferir = true,
Mandatorio = false,
Funcoes = new List<FuncoesPinout>()
{
FuncoesPinout.Botao,
},
Parametros = new List<SensorParametroModel>(),
ValoresLeituras = new List<SensorValoresLeituraModel>()
{
new SensorValoresLeituraModel()
{
funcao = FuncoesPinout.Iniciado,
posicao = CanMessagePosicaoDados.Status,
indice = 0,
},
new SensorValoresLeituraModel()
{
funcao = FuncoesPinout.Botao,
posicao = CanMessagePosicaoDados.Dados1,
indice = 0,
},
new SensorValoresLeituraModel()
{
funcao = FuncoesPinout.LeituraBruta,
posicao = CanMessagePosicaoDados.Dados1,
indice = 1,
},
new SensorValoresLeituraModel()
{
funcao = FuncoesPinout.EstadoLeitura,
posicao = CanMessagePosicaoDados.Dados1,
indice = 2,
},
}
},
// magnetico 41 ~ 50
new SensorModel()
{
@ -596,7 +638,21 @@ namespace AgroBase.Models.Modules
funcao = FuncoesPinout.Pressao,
posicao = CanMessagePosicaoDados.Dados1,
indice = 4,
},
new SensorValoresLeituraModel()
{
funcao = FuncoesPinout.ModoControleBomba,
posicao = CanMessagePosicaoDados.Dados1,
indice = 5,
}
},
Controle = new AtuadorBombaModel.BombaModoControleModel()
{
Modo = ModoControleBomba.PID,
PotenciaMinPID = 40,
Kp = 6.0,
Ki = 0.2,
Kd = 0.0,
}
},
new AtuadorBombaModel()
@ -651,7 +707,17 @@ namespace AgroBase.Models.Modules
funcao = FuncoesPinout.Pressao,
posicao = CanMessagePosicaoDados.Dados1,
indice = 4,
},
new SensorValoresLeituraModel()
{
funcao = FuncoesPinout.ModoControleBomba,
posicao = CanMessagePosicaoDados.Dados1,
indice = 5,
}
},
Controle = new AtuadorBombaModel.BombaModoControleModel()
{
Modo = ModoControleBomba.OnOff,
}
},
},
@ -1028,7 +1094,8 @@ namespace AgroBase.Models.Modules
bomba.Componente,
bomba.ID,
Status: statusDesejado,
Valores: new List<double?>() { potenciaDesejada, pressaoDesejada }
Valores: new List<double?>() { potenciaDesejada, pressaoDesejada },
Comando: CanMessagePosicaoDados.Command1
);
}
}
@ -1077,8 +1144,19 @@ namespace AgroBase.Models.Modules
}
Bomba.PotenciaSP = 100;
Bomba.PressaoSP = Bomba.ID == "BMBLN" ? Variaveis.OperacaoEmAndamento.Parametros.Controle.AtuPressaoLinha : -1;
GeneralJoystick.EnviarComandoAtuador(Bomba.Componente, Bomba.ID, Status: true, Valores: new List<double?>() { Bomba.PotenciaSP, Bomba.PressaoSP }, Forcar: true);
if (Bomba.ID == "BMBLN")
{
Bomba.Controle.Modo = Variaveis.OperacaoEmAndamento.Parametros.Controle.AtuModoControle;
GeneralJoystick.EnviarComandoAtuador(Bomba.Componente, Bomba.ID, Status: true, Valores: new List<double?>() { (int)Bomba.Controle.Modo, Bomba.Controle.PotenciaMinPID, Bomba.Controle.Kp, Bomba.Controle.Ki, Bomba.Controle.Kd }, Comando: CanMessagePosicaoDados.Command2, Forcar: true);
Bomba.PressaoSP = Variaveis.OperacaoEmAndamento.Parametros.Controle.AtuPressaoLinha;
GeneralJoystick.EnviarComandoAtuador(Bomba.Componente, Bomba.ID, Status: true, Valores: new List<double?>() { Bomba.PotenciaSP, Bomba.PressaoSP }, Comando: CanMessagePosicaoDados.Command1, Forcar: true);
}
else
{
Bomba.PressaoSP = -1;
GeneralJoystick.EnviarComandoAtuador(Bomba.Componente, Bomba.ID, Status: true, Valores: new List<double?>() { Bomba.PotenciaSP, Bomba.PressaoSP }, Comando: CanMessagePosicaoDados.Command1, Forcar: true);
}
if (Bomba.Sensor_ID_Num == -1)
{
@ -1340,6 +1418,7 @@ namespace AgroBase.Models.Modules
}
}
public List<SensorValoresLeituraModel> ValoresLeituras { get; set; }
public BombaModoControleModel Controle { get; set; }
public Estado _EstadoLeitura => ValoresLeituras?.FirstOrDefault(x => x.funcao == FuncoesPinout.EstadoLeitura)?.atual?.valor ?? Estado.Desligado;
public double _Potencia => ValoresLeituras?.FirstOrDefault(x => x.funcao == FuncoesPinout.Potencia)?.atual?.valor ?? 0;
public bool _BombaLigada => _Potencia > 0;
@ -1369,22 +1448,69 @@ namespace AgroBase.Models.Modules
};
}
public (int, CanMessagePosicaoDados, byte[]) ProtocoloComando()
public (int, CanMessagePosicaoDados, byte[]) ProtocoloComando(CanMessagePosicaoDados comando)
{
return (
ID_Num,
CanMessagePosicaoDados.Command1,
new byte[]
{
(byte)(ComandoAtuar ? Estado.Ligado : Estado.Desligado),
(byte)(PotenciaSP),
(byte)(PressaoSP)
}
);
byte ConverterPIDParaByte(double valor)
{
// Escala x10:
// 8.0 -> 80
// 0.4 -> 4
// 1.5 -> 15
valor = FuncoesMatematicas.Clamp(valor, 0.0, 25.5);
return (byte)Math.Round(valor * 10.0);
}
switch (comando)
{
case CanMessagePosicaoDados.Command1:
return (
ID_Num,
comando,
new byte[]
{
(byte)(ComandoAtuar ? Estado.Ligado : Estado.Desligado),
(byte)(PotenciaSP),
(byte)(PressaoSP)
}
);
case CanMessagePosicaoDados.Command2:
return (
ID_Num,
comando,
new byte[]
{
(byte)Controle.Modo,
(byte)Controle.PotenciaMinPID,
ConverterPIDParaByte(Controle.Kp),
ConverterPIDParaByte(Controle.Ki),
ConverterPIDParaByte(Controle.Kd),
}
);
default:
throw new ArgumentOutOfRangeException(
nameof(comando),
comando,
"Comando CAN não suportado pela bomba pressurizadora.");
}
}
public bool AtingiuPressao() => _PressaoAtual >= Variaveis.OperacaoEmAndamento.Parametros.Controle.AtuPressaoLinha;
public class BombaModoControleModel
{
public ModoControleBomba Modo { get; set; } = ModoControleBomba.OnOff;
public double PotenciaMinPID { get; set; } = 30.0;
public double Kp { get; set; } = 6.0;
public double Ki { get; set; } = 0.2;
public double Kd { get; set; } = 0.0;
}
}
public class CalibragemVazao
@ -1817,7 +1943,8 @@ namespace AgroBase.Models.Modules
int percentualPotencia = data[4];
int pressaoSp = data[5];
int pressaoAtual = data[6];
AtualizarDados(ID_Num, posicao, componente, new List<dynamic>() { estado, potenciaSp, percentualPotencia, pressaoSp, pressaoAtual });
ModoControleBomba modo = (ModoControleBomba)data[7];
AtualizarDados(ID_Num, posicao, componente, new List<dynamic>() { estado, potenciaSp, percentualPotencia, pressaoSp, pressaoAtual, modo });
break;
}
}
@ -1844,6 +1971,27 @@ namespace AgroBase.Models.Modules
}
break;
}
case S_Code.sBOT:
{
switch (posicao)
{
case CanMessagePosicaoDados.Status:
{
bool Iniciado = data[2] == 1;
AtualizarDados(ID_Num, posicao, componente, new List<dynamic>() { Iniciado });
break;
}
case CanMessagePosicaoDados.Dados1:
{
bool pressionado = data[2] == 1;
bool leitura = data[3] == 1;
bool mudou = data[4] == 1;
AtualizarDados(ID_Num, posicao, componente, new List<dynamic>() { pressionado, leitura, mudou });
break;
}
}
break;
}
}

View File

@ -437,7 +437,9 @@ namespace AgroBase.Models.Modules
Periodo,
IN1,
IN2,
PotenciaSP
PotenciaSP,
ModoControleBomba,
Botao,
}
public static class PinoutUtils

View File

@ -515,6 +515,7 @@ namespace AgroBase.Models
AtuPercentualInicioPulverizacao = 70,
AtuPressaoLinha = 85,
AtuAgitadorModo = ModoAgitadorCalda.Continuo,
AtuModoControle = ModoControleBomba.PID,
};
p.ModulosMandatorios = new List<OperacaoModulosMandatoriosModel>()
{
@ -1621,7 +1622,7 @@ namespace AgroBase.Models
{
if (Bomba._EstadoLeitura == Estado.Desligado)
{
GeneralJoystick.EnviarComandoAtuador(Bomba.Componente, Bomba.ID, Status: true);
GeneralJoystick.EnviarComandoAtuador(Bomba.Componente, Bomba.ID, Status: true, Comando: CanMessagePosicaoDados.Command1);
}
}
}
@ -1824,11 +1825,20 @@ namespace AgroBase.Models
}
break;
case S_Code.sBMB:
valores = new List<double?>() { controleBase.Controle.Potencia, controleBase.Controle.Pressao };
switch (controleBase.Controle.Comando)
{
case CanMessagePosicaoDados.Command1:
valores = new List<double?>() { controleBase.Controle.Potencia, controleBase.Controle.Pressao };
break;
case CanMessagePosicaoDados.Command2:
Variaveis.OperacaoEmAndamento.Parametros.Controle.AtuModoControle = (ModoControleBomba)controleBase._comp_value;
valores = new List<double?>() { (int)controleBase._comp_value, controleBase.Controle.Potencia };
break;
}
break;
}
GeneralJoystick.EnviarComandoAtuador(comp, controleBase._comp_id, Status: controleBase.Controle.Estado, Valores: valores, Forcar: true);
GeneralJoystick.EnviarComandoAtuador(comp, controleBase._comp_id, Status: controleBase.Controle.Estado, Valores: valores, Comando: controleBase.Controle.Comando, Forcar: true);
return;
}
@ -2587,6 +2597,7 @@ namespace AgroBase.Models
public class OperacaoComandoBaseControleModel
{
public CanMessagePosicaoDados Comando { get; set; } = CanMessagePosicaoDados.Command1;
public double? PercentualVelocidadeSP { get; set; }
public double? AnguloSP { get; set; }
public TipoMovimentoDirecional? TipoMovimentoDirecional { get; set; }

View File

@ -365,7 +365,21 @@ namespace AgroBase.Models.Operacoes
}
}
}
private ModoControleBomba _atuModoControle;
public ModoControleBomba AtuModoControle
{
get => _atuModoControle;
set
{
if (_atuModoControle != value)
{
_atuModoControle = value;
OnPropertyChanged(nameof(AtuModoControle));
}
}
}
private double _atuPressaoLinha;
public double AtuPressaoLinha
{

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
{"ExpansorGPIO":false,"EnderecoGPIO":"","ExpansorADS":false,"EnderecoADS":"","Pinos":[{"Controlador":0,"Barramento":0,"Pino":99,"Descricao":"1","Funcao":0,"Habilitado":false,"ComponenteID":""},{"Controlador":0,"Barramento":0,"Pino":98,"Descricao":"2","Funcao":0,"Habilitado":false,"ComponenteID":""},{"Controlador":0,"Barramento":0,"Pino":97,"Descricao":"3","Funcao":0,"Habilitado":false,"ComponenteID":""},{"Controlador":0,"Barramento":0,"Pino":4,"Descricao":"4","Funcao":0,"Habilitado":true,"ComponenteID":""},{"Controlador":0,"Barramento":0,"Pino":5,"Descricao":"5","Funcao":0,"Habilitado":true,"ComponenteID":""},{"Controlador":0,"Barramento":0,"Pino":6,"Descricao":"6","Funcao":24,"Habilitado":true,"ComponenteID":"PRSLN"},{"Controlador":0,"Barramento":0,"Pino":7,"Descricao":"7","Funcao":25,"Habilitado":true,"ComponenteID":"FLXLN"},{"Controlador":0,"Barramento":0,"Pino":15,"Descricao":"8","Funcao":22,"Habilitado":true,"ComponenteID":"MASRS"},{"Controlador":0,"Barramento":0,"Pino":16,"Descricao":"9","Funcao":23,"Habilitado":true,"ComponenteID":"MASRS"},{"Controlador":0,"Barramento":0,"Pino":17,"Descricao":"10","Funcao":0,"Habilitado":true,"ComponenteID":""},{"Controlador":0,"Barramento":0,"Pino":18,"Descricao":"11","Funcao":0,"Habilitado":true,"ComponenteID":""},{"Controlador":0,"Barramento":0,"Pino":8,"Descricao":"12","Funcao":0,"Habilitado":true,"ComponenteID":""},{"Controlador":0,"Barramento":0,"Pino":3,"Descricao":"13","Funcao":0,"Habilitado":true,"ComponenteID":""},{"Controlador":0,"Barramento":0,"Pino":46,"Descricao":"14","Funcao":21,"Habilitado":true,"ComponenteID":"B07"},{"Controlador":0,"Barramento":0,"Pino":9,"Descricao":"15","Funcao":21,"Habilitado":true,"ComponenteID":"B06"},{"Controlador":0,"Barramento":0,"Pino":10,"Descricao":"16","Funcao":21,"Habilitado":true,"ComponenteID":"B05"},{"Controlador":0,"Barramento":0,"Pino":11,"Descricao":"17","Funcao":21,"Habilitado":true,"ComponenteID":"B04"},{"Controlador":0,"Barramento":0,"Pino":12,"Descricao":"18","Funcao":21,"Habilitado":true,"ComponenteID":"B03"},{"Controlador":0,"Barramento":0,"Pino":13,"Descricao":"19","Funcao":21,"Habilitado":true,"ComponenteID":"B02"},{"Controlador":0,"Barramento":0,"Pino":14,"Descricao":"20","Funcao":21,"Habilitado":true,"ComponenteID":"B01"},{"Controlador":0,"Barramento":0,"Pino":96,"Descricao":"21","Funcao":0,"Habilitado":false,"ComponenteID":""},{"Controlador":0,"Barramento":0,"Pino":95,"Descricao":"22","Funcao":0,"Habilitado":false,"ComponenteID":""},{"Controlador":0,"Barramento":0,"Pino":94,"Descricao":"23","Funcao":0,"Habilitado":false,"ComponenteID":""},{"Controlador":0,"Barramento":0,"Pino":93,"Descricao":"24","Funcao":0,"Habilitado":false,"ComponenteID":""},{"Controlador":0,"Barramento":0,"Pino":19,"Descricao":"25","Funcao":79,"Habilitado":true,"ComponenteID":"BOTLAV"},{"Controlador":0,"Barramento":0,"Pino":20,"Descricao":"26","Funcao":0,"Habilitado":true,"ComponenteID":""},{"Controlador":0,"Barramento":0,"Pino":21,"Descricao":"27","Funcao":0,"Habilitado":true,"ComponenteID":""},{"Controlador":0,"Barramento":0,"Pino":47,"Descricao":"28","Funcao":0,"Habilitado":true,"ComponenteID":""},{"Controlador":0,"Barramento":0,"Pino":48,"Descricao":"29","Funcao":0,"Habilitado":true,"ComponenteID":""},{"Controlador":0,"Barramento":0,"Pino":45,"Descricao":"30","Funcao":0,"Habilitado":true,"ComponenteID":""},{"Controlador":0,"Barramento":0,"Pino":0,"Descricao":"31","Funcao":0,"Habilitado":true,"ComponenteID":""},{"Controlador":0,"Barramento":0,"Pino":35,"Descricao":"32","Funcao":75,"Habilitado":true,"ComponenteID":"BMBLN"},{"Controlador":0,"Barramento":0,"Pino":36,"Descricao":"33","Funcao":76,"Habilitado":true,"ComponenteID":"BMBLN"},{"Controlador":0,"Barramento":0,"Pino":37,"Descricao":"34","Funcao":75,"Habilitado":true,"ComponenteID":"BMBAGT"},{"Controlador":0,"Barramento":0,"Pino":38,"Descricao":"35","Funcao":76,"Habilitado":true,"ComponenteID":"BMBAGT"},{"Controlador":0,"Barramento":0,"Pino":39,"Descricao":"36","Funcao":0,"Habilitado":true,"ComponenteID":""},{"Controlador":0,"Barramento":0,"Pino":40,"Descricao":"37","Funcao":0,"Habilitado":true,"ComponenteID":""},{"Controlador":0,"Barramento":0,"Pino":41,"Descricao":"38","Funcao":0,"Habilitado":true,"ComponenteID":""},{"Controlador":0,"Barramento":0,"Pino":42,"Descricao":"39","Funcao":0,"Habilitado":true,"ComponenteID":""},{"Controlador":0,"Barramento":0,"Pino":2,"Descricao":"40","Funcao":34,"Habilitado":true,"ComponenteID":"Atu"},{"Controlador":0,"Barramento":0,"Pino":1,"Descricao":"41","Funcao":33,"Habilitado":true,"ComponenteID":"Atu"},{"Controlador":0,"Barramento":0,"Pino":44,"Descricao":"42","Funcao":0,"Habilitado":false,"ComponenteID":""},{"Controlador":0,"Barramento":0,"Pino":43,"Descricao":"43","Funcao":0,"Habilitado":false,"ComponenteID":""},{"Controlador":0,"Barramento":0,"Pino":92,"Descricao":"44","Funcao":0,"Habilitado":false,"ComponenteID":""}]}

File diff suppressed because one or more lines are too long

View File

@ -122,6 +122,8 @@ class S_Code(IntEnum):
sIUV = 31
sQAR = 32
sCHV = 33
sSRV = 34
sBOT = 35
class StatusModulo(IntEnum):
DESCONECTADO = 0

View File

@ -0,0 +1,8 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
"version": "0.2.0",
"configurations": [
]
}

View File

@ -0,0 +1,658 @@
// Dispositivo: Atuador
// Versão Firmware: 14
// Ultima atualização: 08/06/2026
// Atualização: Firmware mock
#include "C:\ZendionInc\agrobot_base\Firmware\Modulos\SerialService.h"
#include "C:\ZendionInc\agrobot_base\Firmware\Modulos\CanService.h"
#include "C:\ZendionInc\agrobot_base\Firmware\Modulos\EepromService.h"
#include "C:\ZendionInc\agrobot_base\Firmware\Modulos\I2CService.h"
#include "C:\ZendionInc\agrobot_base\Firmware\Modulos\Utils.h"
#include "C:\ZendionInc\agrobot_base\Firmware\Modulos\Pinout.h"
#include "C:\ZendionInc\agrobot_base\Firmware\Modulos\BicoPulverizadorModel_v2.h"
#include "C:\ZendionInc\agrobot_base\Firmware\Modulos\BombaPressurizadoraModel_v2.h"
#include "C:\ZendionInc\agrobot_base\Firmware\Modulos\SensorPressaoModel_v2.h"
#include "C:\ZendionInc\agrobot_base\Firmware\Modulos\SensorFluxoModel_v2.h"
#include "C:\ZendionInc\agrobot_base\Firmware\Modulos\SensorMassaModel_v2.h"
#include "C:\ZendionInc\agrobot_base\Firmware\Modulos\SensorMagneticoModel_v2.h"
#include "C:\ZendionInc\agrobot_base\Firmware\Modulos\SensorChaveBotaoModel.h"
// Configurações do CAN
uint8_t CanID = 0x12;
CanService canService = CanService(CanID);
#define D_Code Atu
int VERSION = 14;
const String Mod_ID = "Atu";
#define _pinoLED RGB_BUILTIN
bool Conectado = false;
bool Conectar = false;
int _TaxaAmostragem = 1000;
volatile bool RequisitarDados = false;
int latenciaLoop = 0;
int qtdEnviosStatus = 0;
int maxEnviosStatus = 5;
#pragma region PRESSAO
SensorPressao_v2 sPRS_Linha("PRSLN", 11, 6, TiposBarramentos::CONTROLADOR);
SensorPressao_v2* ObterPressaoPorId(uint8_t idNum) {
switch (idNum) {
case 11: return &sPRS_Linha;
default: return nullptr;
}
}
#pragma endregion
#pragma region FLUXO
SensorFluxo_v2 sFLX_Linha("FLXLN", 21, 7, TiposBarramentos::CONTROLADOR);
SensorFluxo_v2* ObterFluxoPorId(uint8_t idNum) {
switch (idNum) {
case 21: return &sFLX_Linha;
default: return nullptr;
}
}
#pragma endregion
#pragma region MASSA
SensorMassa_v2 sMAS_Reservatorio("MASRS", 31, 15, 16, TiposBarramentos::CONTROLADOR, -1.05);
SensorMassa_v2* ObterMassaPorId(uint8_t idNum) {
switch (idNum) {
case 31: return &sMAS_Reservatorio;
default: return nullptr;
}
}
#pragma endregion
#pragma region MAGNETICO
SensorMagnetico_v2 sMAG_Esquerdo("MAGDIR", 41, 0x36, 1);
SensorMagnetico_v2 sMAG_Direito("MAGESQ", 42, 0x36, 2);
SensorMagnetico_v2* ObterSensorMagneticoPorId(uint8_t idNum) {
switch (idNum) {
case 41: return &sMAG_Esquerdo;
case 42: return &sMAG_Direito;
default: return nullptr;
}
}
#pragma endregion
#pragma region BOTOES
SensorChaveBotao sBOT_Lavagem("BOTLAV", 36, 19, TiposBarramentos::CONTROLADOR);
SensorChaveBotao* ObterBotaoPorId(uint8_t idNum) {
switch (idNum) {
case 36: return &sBOT_Lavagem;
default: return nullptr;
}
}
#pragma endregion
#pragma region BICOS
BicoPulverizador_v2 sBIC_01("B01", 61, 14, true, TiposBarramentos::CONTROLADOR);
BicoPulverizador_v2 sBIC_02("B02", 62, 13, true, TiposBarramentos::CONTROLADOR);
BicoPulverizador_v2 sBIC_03("B03", 63, 12, true, TiposBarramentos::CONTROLADOR);
BicoPulverizador_v2 sBIC_04("B04", 64, 11, true, TiposBarramentos::CONTROLADOR);
BicoPulverizador_v2 sBIC_05("B05", 65, 10, true, TiposBarramentos::CONTROLADOR);
BicoPulverizador_v2 sBIC_06("B06", 66, 9, true, TiposBarramentos::CONTROLADOR);
BicoPulverizador_v2 sBIC_07("B07", 67, 46, true, TiposBarramentos::CONTROLADOR);
BicoPulverizador_v2* ObterBicoPorId(uint8_t idNum) {
switch (idNum) {
case 61: return &sBIC_01;
case 62: return &sBIC_02;
case 63: return &sBIC_03;
case 64: return &sBIC_04;
case 65: return &sBIC_05;
case 66: return &sBIC_06;
case 67: return &sBIC_07;
default: return nullptr;
}
}
constexpr size_t QUANTIDADE_BICOS = 7;
BicoPulverizador_v2* BicosPulverizadores[QUANTIDADE_BICOS] = {
&sBIC_01,
&sBIC_02,
&sBIC_03,
&sBIC_04,
&sBIC_05,
&sBIC_06,
&sBIC_07
};
#pragma endregion
#pragma region BOMBAS
BombaPressurizadora_v2 sBMB_Linha("BMBLN", 51, 35, 1, 36, 2, TiposBarramentos::CONTROLADOR, Sentido::Horario, &sPRS_Linha);
BombaPressurizadora_v2 sBMB_Agitador("BMBAGT", 52, 37, 3, 38, 4, TiposBarramentos::CONTROLADOR, Sentido::Horario);
BombaPressurizadora_v2* ObterBombaPorId(uint8_t idNum) {
switch (idNum) {
case 51: return &sBMB_Linha;
case 52: return &sBMB_Agitador;
default: return nullptr;
}
}
#pragma endregion
#pragma region LAVAGEM
bool LavagemAtiva = false;
bool EstadoAnteriorBotaoLavagem = false;
bool EstadoLavagemSalvo = false;
EstadoAnteriorBomba EstadoAnteriorBombaLinha;
EstadoAnteriorBomba EstadoAnteriorBombaAgitador;
EstadoAnteriorBico EstadosAnterioresBicos[QUANTIDADE_BICOS];
const double POTENCIA_LAVAGEM = 100.0;
const unsigned long INTERVALO_LEITURA_BOTAO_MS = 20;
const unsigned long INTERVALO_REFORCO_LAVAGEM_MS = 250;
unsigned long UltimaLeituraBotaoLavagemMs = 0;
unsigned long UltimoReforcoLavagemMs = 0;
void SalvarEstadoBomba(BombaPressurizadora_v2& bomba, EstadoAnteriorBomba& destino) {
bomba.RequisitarDados();
destino.estado = bomba._EstadoControle;
destino.potenciaSP = bomba._PotenciaSP;
destino.pressaoSP = bomba._PressaoSP;
destino.modoControle = bomba.ModoControle;
destino.kp = bomba.Kp;
destino.ki = bomba.Ki;
destino.kd = bomba.Kd;
destino.potenciaMinPID = bomba.PotenciaMinPID;
destino.potenciaMaxPID = bomba.PotenciaMaxPID;
}
void RestaurarEstadoBomba(BombaPressurizadora_v2& bomba, const EstadoAnteriorBomba& origem) {
bomba.ConfigurarPID(
origem.kp,
origem.ki,
origem.kd,
origem.potenciaMinPID,
origem.potenciaMaxPID
);
bomba.ConfigurarModoControle(origem.modoControle);
bomba.AtualizarControle(
origem.estado,
origem.potenciaSP,
origem.pressaoSP
);
}
void SalvarEstadoAntesDaLavagem() {
SalvarEstadoBomba(
sBMB_Linha,
EstadoAnteriorBombaLinha
);
SalvarEstadoBomba(
sBMB_Agitador,
EstadoAnteriorBombaAgitador
);
for (size_t i = 0; i < QUANTIDADE_BICOS; i++) {
BicoPulverizador_v2* bico = BicosPulverizadores[i];
if (bico == nullptr || !bico->Iniciado) {
EstadosAnterioresBicos[i].estado = Estado::Desligado;
EstadosAnterioresBicos[i].angulo = 0;
continue;
}
bico->AtualizarLeitura();
EstadosAnterioresBicos[i].estado = bico->_Status;
EstadosAnterioresBicos[i].angulo = bico->_AnguloAtual;
}
EstadoLavagemSalvo = true;
MostrarLog("Estados anteriores salvos para lavagem");
}
void AplicarEstadoLavagem() {
// Desliga o agitador
sBMB_Agitador.AtualizarControle(
Estado::Desligado,
0,
0
);
// Liga todos os bicos
for (size_t i = 0; i < QUANTIDADE_BICOS; i++) {
BicoPulverizador_v2* bico = BicosPulverizadores[i];
if (bico != nullptr && bico->Iniciado) {
bico->Ligar();
}
}
/*
PressaoSP = 0 força operação em malha aberta
no modelo atual da bomba.
Assim, durante a lavagem, a bomba trabalha
diretamente com POTENCIA_LAVAGEM.
*/
sBMB_Linha.AtualizarControle(
Estado::Ligado,
POTENCIA_LAVAGEM,
0
);
}
void IniciarLavagem() {
if (LavagemAtiva) {
return;
}
MostrarLog("Iniciando rotina de lavagem");
SalvarEstadoAntesDaLavagem();
LavagemAtiva = true;
UltimoReforcoLavagemMs = 0;
AplicarEstadoLavagem();
MostrarLog("Rotina de lavagem ativa");
}
void FinalizarLavagem() {
if (!LavagemAtiva) {
return;
}
MostrarLog("Finalizando rotina de lavagem");
/*
Primeiro encerra fisicamente o fluxo de lavagem.
*/
sBMB_Linha.AtualizarControle(
Estado::Desligado,
0,
0
);
for (size_t i = 0; i < QUANTIDADE_BICOS; i++) {
BicoPulverizador_v2* bico = BicosPulverizadores[i];
if (bico != nullptr && bico->Iniciado) {
bico->DesligarBico();
}
}
LavagemAtiva = false;
if (!EstadoLavagemSalvo) {
MostrarLog("Lavagem encerrada sem estado anterior salvo");
return;
}
/*
Restaura os bicos.
*/
for (size_t i = 0; i < QUANTIDADE_BICOS; i++) {
BicoPulverizador_v2* bico = BicosPulverizadores[i];
if (bico == nullptr || !bico->Iniciado) {
continue;
}
bico->AtualizarStatus(
EstadosAnterioresBicos[i].estado,
EstadosAnterioresBicos[i].angulo
);
}
/*
Restaura primeiro o agitador e depois a bomba da linha.
*/
RestaurarEstadoBomba(
sBMB_Agitador,
EstadoAnteriorBombaAgitador
);
RestaurarEstadoBomba(
sBMB_Linha,
EstadoAnteriorBombaLinha
);
EstadoLavagemSalvo = false;
MostrarLog("Estados anteriores restaurados");
}
void ProcessarBotaoLavagem() {
unsigned long agora = millis();
if (
agora - UltimaLeituraBotaoLavagemMs <
INTERVALO_LEITURA_BOTAO_MS
) {
return;
}
UltimaLeituraBotaoLavagemMs = agora;
sBOT_Lavagem.RequisitarDados();
bool botaoLigado = sBOT_Lavagem.Pressionado;
/*
Detecta borda de subida:
chave passou de desligada para ligada.
*/
if (botaoLigado && !EstadoAnteriorBotaoLavagem) {
IniciarLavagem();
}
/*
Detecta borda de descida:
chave passou de ligada para desligada.
*/
if (!botaoLigado && EstadoAnteriorBotaoLavagem) {
FinalizarLavagem();
}
EstadoAnteriorBotaoLavagem = botaoLigado;
/*
Enquanto a chave estiver ligada, reforça periodicamente
os estados de lavagem.
Isso torna a chave superior a qualquer outra lógica
local que possa alterar um componente.
*/
if (
LavagemAtiva &&
agora - UltimoReforcoLavagemMs >= INTERVALO_REFORCO_LAVAGEM_MS
) {
UltimoReforcoLavagemMs = agora;
AplicarEstadoLavagem();
}
}
#pragma endregion
void MostrarLog(String mensagem) {
bool _debugMode = false;
if (_debugMode) {
PrintTela(String("[ATU] ") + mensagem);
}
}
void inicializarDependenciasI2C() {
I2CService::IniciarI2C();
I2CService::IniciarMUX();
}
void setup() {
delay(5000);
inicializarDependenciasI2C();
sPRS_Linha.Inicializar();
sFLX_Linha.Inicializar();
sMAS_Reservatorio.Inicializar();
sBOT_Lavagem.Inicializar();
sMAG_Esquerdo.Inicializar();
sMAG_Direito.Inicializar();
sBIC_01.Inicializar();
sBIC_02.Inicializar();
sBIC_03.Inicializar();
sBIC_04.Inicializar();
sBIC_05.Inicializar();
sBIC_06.Inicializar();
sBIC_07.Inicializar();
sBMB_Linha.Inicializar();
sBMB_Agitador.Inicializar();
sBOT_Lavagem.RequisitarDados();
EstadoAnteriorBotaoLavagem = false;
if (sBOT_Lavagem.Pressionado) {
IniciarLavagem();
EstadoAnteriorBotaoLavagem = true;
}
// Registrar callback para processar mensagens CAN recebidas
canService.setReceiveCallback([](int packetSize, int senderId, CanMessagePosicaoDados posicao, byte* data, int dataLength) {
std::vector<uint8_t> fullData;
fullData.push_back(static_cast<uint8_t>(posicao)); // Primeiro byte é sempre a posicao
for (int i = 0; i < dataLength; i++) {
fullData.push_back(data[i]);
}
ProcessarFrameCAN(posicao, fullData);
});
canService.begin();
}
void loop() {
ProcessarBotaoLavagem();
if (!RequisitarDados) {
enviarLogsPeriodicamente();
}
sFLX_Linha.Loop();
sBMB_Linha.Loop();
sBMB_Agitador.Loop();
delay(1);
}
// Função para enviar logs do sensor periodicamente
unsigned long ultimoEnvioLogs = 0;
const unsigned long intervaloEnvioLogs = 1000; // 1 segundo
void enviarLogsPeriodicamente() {
unsigned long tempoAtual = millis();
// Verifica se o intervalo de 5 segundos já passou
if (tempoAtual - ultimoEnvioLogs >= _TaxaAmostragem) {
ultimoEnvioLogs = tempoAtual; // Atualiza o tempo do último envio
enviarDadosSensores(canService.ID_Num_sTOD, CanMessagePosicaoDados::DadosAll);
}
}
void enviarDadosSensores(uint8_t id_num, CanMessagePosicaoDados posicao) {
if (Conectado || posicao == CanMessagePosicaoDados::Status) {
unsigned long startLoop = millis();
bool enviarStatus = qtdEnviosStatus >= maxEnviosStatus && posicao != CanMessagePosicaoDados::Status;
bool todosDados = posicao == CanMessagePosicaoDados::DadosAll;
bool todosIDs = id_num == canService.ID_Num_sTOD;
if (id_num == canService.ID_Num_sMOD) {
EnviarDadosCAN(canService.MontarFrameReqStatusMod(D_Code, Conectado, VERSION));
return;
}
if (todosIDs)
MostrarLog("Atualizando dados dos sensores...");
if (todosIDs && enviarStatus) {
EnviarDadosCAN(canService.MontarFrameReqStatusMod(D_Code, Conectado, VERSION));
}
ComponenteCAN::ProcessarComponenteCAN(sPRS_Linha, {CanMessagePosicaoDados::Dados1}, todosIDs, id_num, enviarStatus, todosDados, posicao, EnviarDadosCAN);
ComponenteCAN::ProcessarComponenteCAN(sFLX_Linha, {CanMessagePosicaoDados::Dados1}, todosIDs, id_num, enviarStatus, todosDados, posicao, EnviarDadosCAN);
ComponenteCAN::ProcessarComponenteCAN(sMAS_Reservatorio, {CanMessagePosicaoDados::Dados1}, todosIDs, id_num, enviarStatus, todosDados, posicao, EnviarDadosCAN);
ComponenteCAN::ProcessarComponenteCAN(sBOT_Lavagem, {CanMessagePosicaoDados::Dados1}, todosIDs, id_num, enviarStatus, todosDados, posicao, EnviarDadosCAN);
ComponenteCAN::ProcessarComponenteCAN(sMAG_Esquerdo, {CanMessagePosicaoDados::Dados1}, todosIDs, id_num, enviarStatus, todosDados, posicao, EnviarDadosCAN);
ComponenteCAN::ProcessarComponenteCAN(sMAG_Direito, {CanMessagePosicaoDados::Dados1}, todosIDs, id_num, enviarStatus, todosDados, posicao, EnviarDadosCAN);
ComponenteCAN::ProcessarComponenteCAN(sBIC_01, {CanMessagePosicaoDados::Dados1}, todosIDs, id_num, enviarStatus, todosDados, posicao, EnviarDadosCAN);
ComponenteCAN::ProcessarComponenteCAN(sBIC_02, {CanMessagePosicaoDados::Dados1}, todosIDs, id_num, enviarStatus, todosDados, posicao, EnviarDadosCAN);
ComponenteCAN::ProcessarComponenteCAN(sBIC_03, {CanMessagePosicaoDados::Dados1}, todosIDs, id_num, enviarStatus, todosDados, posicao, EnviarDadosCAN);
ComponenteCAN::ProcessarComponenteCAN(sBIC_04, {CanMessagePosicaoDados::Dados1}, todosIDs, id_num, enviarStatus, todosDados, posicao, EnviarDadosCAN);
ComponenteCAN::ProcessarComponenteCAN(sBIC_05, {CanMessagePosicaoDados::Dados1}, todosIDs, id_num, enviarStatus, todosDados, posicao, EnviarDadosCAN);
ComponenteCAN::ProcessarComponenteCAN(sBIC_06, {CanMessagePosicaoDados::Dados1}, todosIDs, id_num, enviarStatus, todosDados, posicao, EnviarDadosCAN);
ComponenteCAN::ProcessarComponenteCAN(sBIC_07, {CanMessagePosicaoDados::Dados1}, todosIDs, id_num, enviarStatus, todosDados, posicao, EnviarDadosCAN);
ComponenteCAN::ProcessarComponenteCAN(sBMB_Linha, {CanMessagePosicaoDados::Dados1}, todosIDs, id_num, enviarStatus, todosDados, posicao, EnviarDadosCAN);
ComponenteCAN::ProcessarComponenteCAN(sBMB_Agitador, {CanMessagePosicaoDados::Dados1}, todosIDs, id_num, enviarStatus, todosDados, posicao, EnviarDadosCAN);
if (enviarStatus) {
qtdEnviosStatus = 0;
}
else {
qtdEnviosStatus++;
}
latenciaLoop = millis() - startLoop;
if (posicao == CanMessagePosicaoDados::DadosAll) {
EnviarDadosCAN(canService.MontarFrameReqDadosFim(latenciaLoop));
}
if (todosIDs)
MostrarLog("Ciclo concluido, latencia de loop: " + String(latenciaLoop));
}
}
void EnviarDadosCAN(std::vector<uint8_t> data) {
if (data.size() > 2) {
canService.adicionarMensagemFila(data);
}
}
void ProcessarFrameCAN(CanMessagePosicaoDados posicao, std::vector<uint8_t> data) {
if (data.size() < 1) return;
F_Code funcao = canService.FuncaoPorPosicao(posicao);
switch (funcao) {
case F_Code::ReqTx: ProcessarReq(data); break;
case F_Code::CmdTx: ProcessarCmd(data); break;
case F_Code::CfgTx: ProcessarCfg(data); break;
}
}
void ProcessarReq(std::vector<uint8_t> data) {
if (data.size() < 2) return;
CanMessagePosicaoDados posicao = (CanMessagePosicaoDados)data[0];
uint8_t id = data[1];
enviarDadosSensores(id, posicao);
}
void ProcessarCfg(std::vector<uint8_t> data) {
if (data.size() < 4) return;
std::vector<uint8_t> _chkRx;
CanMessagePosicaoDados posicao = (CanMessagePosicaoDados)data[0];
uint8_t id = data[1];
S_Code componente = DetectarComponente(id);
if (componente == S_Code::sMOD) {
switch (posicao) {
case CanMessagePosicaoDados::Config1: {
if (data.size() < 7) return;
bool conectar = data[2] == 1;
int taxa = data[3] * 1000;
bool requisitar = data[4] == 1;
int pinoSDA = data[5];
int pinoSCL = data[6];
_TaxaAmostragem = taxa;
RequisitarDados = requisitar;
//if (pinoSDA != PINO_INVALIDO && pinoSCL != PINO_INVALIDO) {
// if (I2CService::DefinirPinos(pinoSDA, pinoSCL) || !I2CService::I2CIniciado) {
// inicializarDependenciasI2C();
// }
//}
vTaskDelay(pdMS_TO_TICKS(100));
Conectado = conectar;
_chkRx = canService.MontarFrameReqStatusMod(D_Code, Conectado, VERSION);
MostrarLog("Configuracao do modulo concluida");
break;
}
}
}
EnviarDadosCAN(_chkRx);
}
void ProcessarCmd(std::vector<uint8_t> data) {
if (data.size() < 2) return;
CanMessagePosicaoDados posicao = (CanMessagePosicaoDados)data[0];
uint8_t id = data[1];
S_Code componente = DetectarComponente(id);
switch (componente) {
case sMOD: {
if (data.size() < 3) return;
switch (posicao) {
case CanMessagePosicaoDados::Command1: {
Estado estado = (Estado)data[2];
if (estado == Estado::Reset) {
delay(100);
esp_restart();
}
break;
}
}
break;
}
case sBIC: {
if (LavagemAtiva) {
MostrarLog("Comando de bico ignorado: lavagem ativa");
return;
}
BicoPulverizador_v2* bico = ObterBicoPorId(id);
if (bico == nullptr)
return;
bico->ProcessarComando(data);
break;
}
case sBMB: {
if (LavagemAtiva) {
MostrarLog("Comando de bomba ignorado: lavagem ativa");
return;
}
BombaPressurizadora_v2* bomba = ObterBombaPorId(id);
if (bomba == nullptr)
return;
bomba->ProcessarComando(data);
break;
}
default:
break;
}
}
S_Code DetectarComponente(uint8_t idNum) {
if (idNum == canService.ID_Num_sMOD) return S_Code::sMOD;
if (idNum == canService.ID_Num_sTOD) return S_Code::sTOD;
if (idNum == canService.ID_Num_sLRA) return S_Code::sLRA;
if (idNum >= 11 && idNum <= 20) return S_Code::sPRS;
if (idNum >= 21 && idNum <= 30) return S_Code::sFLX;
if (idNum >= 31 && idNum <= 35) return S_Code::sMAS;
if (idNum >= 36 && idNum <= 40) return S_Code::sBOT;
if (idNum >= 41 && idNum <= 50) return S_Code::sMAG;
if (idNum >= 51 && idNum <= 60) return S_Code::sBMB;
if (idNum >= 61 && idNum <= 70) return S_Code::sBIC;
return S_Code::sVZO;
}

View File

@ -7,6 +7,11 @@
#ifndef BicoPulverizadorModel_v2_h
#define BicoPulverizadorModel_v2_h
struct EstadoAnteriorBico {
Estado estado = Estado::Desligado;
int angulo = 0;
};
class BicoPulverizador_v2 : public ComponenteCAN {
public:
BicoPulverizador_v2(

View File

@ -7,6 +7,22 @@
#ifndef BombaPressurizadoraModel_v2_h
#define BombaPressurizadoraModel_v2_h
struct EstadoAnteriorBomba {
Estado estado = Estado::Desligado;
double potenciaSP = 0;
double pressaoSP = 0;
ModoControleBomba modoControle = ModoControleBomba::OnOff;
double kp = 0;
double ki = 0;
double kd = 0;
double potenciaMinPID = 0;
double potenciaMaxPID = 100;
};
class BombaPressurizadora_v2 : public ComponenteCAN {
public:
BombaPressurizadora_v2(
@ -56,6 +72,28 @@ class BombaPressurizadora_v2 : public ComponenteCAN {
double _PressaoSP = 0;
double _PotenciaSP = 0;
ModoControleBomba ModoControle = ModoControleBomba::OnOff;
// PID
double Kp = 8.0;
double Ki = 0.4;
double Kd = 0.0;
double erroAnterior = 0;
double integralErro = 0;
unsigned long ultimoPID_ms = 0;
// limites PID em percentual
double PotenciaMinPID = 25.0;
double PotenciaMaxPID = 100.0;
// proteção contra integral absurda
double IntegralMin = -100.0;
double IntegralMax = 100.0;
// zona morta para não ficar tremendo perto do SP
double DeadbandPressao = 1.0;
void VincularSensorPressao(SensorPressao_v2* sensor) {
sensorPressao = sensor;
MalhaFechada = (sensorPressao != nullptr);
@ -142,25 +180,33 @@ class BombaPressurizadora_v2 : public ComponenteCAN {
if (!Iniciado) return;
double pressaoAtual = 0;
bool ligado = _EstadoControle == Estado::Ligado;
if (ligado && MalhaFechada && sensorPressao != nullptr) {
sensorPressao->RequisitarDados();
pressaoAtual = sensorPressao->Pressao;
if (pressaoAtual >= (_PressaoSP + histerese)) {
bombaDesligadaPorPressao = true;
} else if (pressaoAtual <= (_PressaoSP - histerese)) {
bombaDesligadaPorPressao = false;
}
}
if (!ligado) {
PWM_SP = ZeroRampa;
ResetPID();
} else {
if (MalhaFechada) {
PWM_SP = bombaDesligadaPorPressao ? ZeroRampa : PWM_Set;
if (MalhaFechada && sensorPressao != nullptr && _PressaoSP > 0) {
if (ModoControle == ModoControleBomba::PID) {
double potenciaPID = CalcularPotenciaPID(pressaoAtual);
PWM_SP = int((potenciaPID / 100.0) * RampaMax);
}
else {
if (pressaoAtual >= (_PressaoSP + histerese)) {
bombaDesligadaPorPressao = true;
} else if (pressaoAtual <= (_PressaoSP - histerese)) {
bombaDesligadaPorPressao = false;
}
PWM_SP = bombaDesligadaPorPressao ? ZeroRampa : PWM_Set;
}
} else {
PWM_SP = PWM_Set;
}
@ -195,6 +241,18 @@ class BombaPressurizadora_v2 : public ComponenteCAN {
AtualizarControle(novoEstado, potencia, pressao);
return true;
}
case CanMessagePosicaoDados::Command2: {
if (data.size() < 4) return false;
ModoControle = (ModoControleBomba)data[2];
if (data.size() > 3) PotenciaMinPID = constrain((double)data[3], 0, 100);
if (data.size() > 6) {
Kp = data[4] / 10.0;
Ki = data[5] / 10.0;
Kd = data[6] / 10.0;
}
ResetPID();
return true;
}
default:
return false;
@ -219,12 +277,12 @@ class BombaPressurizadora_v2 : public ComponenteCAN {
data.push_back(static_cast<uint8_t>((int)_PotenciaSP));
data.push_back(static_cast<uint8_t>((int)PercentualPotenciaLeitura));
data.push_back(static_cast<uint8_t>((int)_PressaoSP));
int pressaoAtual = 0;
if (sensorPressao != nullptr) {
pressaoAtual = (int)sensorPressao->Pressao;
}
data.push_back(static_cast<uint8_t>(pressaoAtual));
data.push_back(static_cast<uint8_t>(ModoControle));
break;
}
}
@ -232,6 +290,24 @@ class BombaPressurizadora_v2 : public ComponenteCAN {
return data;
}
void ConfigurarModoControle(ModoControleBomba modo) {
ModoControle = modo;
ResetPID();
}
void ConfigurarPID(double kp, double ki, double kd, double potenciaMin, double potenciaMax = 100.0) {
Kp = kp;
Ki = ki;
Kd = kd;
PotenciaMinPID = constrain(potenciaMin, 0, 100);
PotenciaMaxPID = constrain(potenciaMax, PotenciaMinPID, 100);
ResetPID();
}
private:
bool DebugMode = false;
int histerese = 3;
@ -264,6 +340,60 @@ class BombaPressurizadora_v2 : public ComponenteCAN {
EstadoLeitura = (duty > 5) ? Estado::Ligado : Estado::Desligado;
}
void ResetPID() {
erroAnterior = 0;
integralErro = 0;
ultimoPID_ms = millis();
}
double CalcularPotenciaPID(double pressaoAtual) {
unsigned long agora = millis();
if (ultimoPID_ms == 0) {
ultimoPID_ms = agora;
}
double dt = (agora - ultimoPID_ms) / 1000.0;
ultimoPID_ms = agora;
if (dt <= 0.001) {
dt = 0.001;
}
double erro = _PressaoSP - pressaoAtual;
// Zona morta: se está perto do SP, evita ficar oscilando demais
if (abs(erro) <= DeadbandPressao) {
erro = 0;
}
integralErro += erro * dt;
integralErro = constrain(integralErro, IntegralMin, IntegralMax);
double derivada = (erro - erroAnterior) / dt;
erroAnterior = erro;
double saida = (Kp * erro) + (Ki * integralErro) + (Kd * derivada);
// Se passou da pressão desejada, deixa cortar a bomba
if (pressaoAtual >= _PressaoSP) {
saida = 0;
}
// Limite máximo vindo do comando
double teto = _PotenciaSP > 0 ? _PotenciaSP : PotenciaMaxPID;
teto = constrain(teto, PotenciaMinPID, PotenciaMaxPID);
saida = constrain(saida, 0, teto);
// Degrau mínimo: se o PID quer ligar, liga com potência útil
if (saida > 0 && saida < PotenciaMinPID) {
saida = PotenciaMinPID;
}
return saida;
}
void MostrarLog(String mensagem) {
if (DebugMode) {
PrintTela("[BMB " + _ID + "] " + mensagem);

View File

@ -82,6 +82,7 @@ enum S_Code {
sQAR = 32,
sCHV = 33,
sSRV = 34,
sBOT = 35,
};
enum Estado {
@ -125,7 +126,8 @@ enum TiposBarramentos {
enum TiposPinos {
_INPUT = 0,
_OUTPUT = 1,
_PWM = 2
_PWM = 2,
_INPUT_PULLUP = 3
};
enum TiposLeituras {
@ -161,4 +163,9 @@ enum TiposShuntCorrente {
INA228_100A = 3,
};
enum class ModoControleBomba : uint8_t {
OnOff = 0,
PID = 1
};
#endif

View File

@ -35,6 +35,8 @@ class PinoModel {
Conectado = true;
if (tipo == _INPUT) {
pinMode(num, INPUT);
} else if (tipo == _INPUT_PULLUP) {
pinMode(num, INPUT_PULLUP);
} else if (tipo == _OUTPUT) {
pinMode(num, OUTPUT);
set(statusInicial);
@ -47,6 +49,8 @@ class PinoModel {
}
if (tipo == _INPUT) {
I2CService::mcp.pinMode(num, INPUT);
} else if (tipo == _INPUT_PULLUP) {
I2CService::mcp.pinMode(num, INPUT_PULLUP);
} else if (tipo == _OUTPUT) {
I2CService::mcp.pinMode(num, OUTPUT);
set(statusInicial, false);

View File

@ -0,0 +1,182 @@
#include "SerialService.h"
#include "Pinout.h"
#include "Utils.h"
#include "IComponenteCAN.h"
#ifndef SensorChaveBotaoModel
#define SensorChaveBotaoModel
class SensorChaveBotao : public ComponenteCAN {
public:
String ID;
uint8_t ID_Num = 0;
PinoModel _pino;
bool Iniciado = false;
// Leitura bruta do pino
bool LeituraBruta = false;
// Resultado final já considerando inversão e debounce
bool Pressionado = false;
// Estado anterior estável
bool PressionadoAnterior = false;
// Flag útil para detectar borda
bool MudouEstado = false;
// Configuração
bool InverterLogica = true;
bool UsarDebounce = true;
unsigned long TempoDebounceMs = 50;
SensorChaveBotao() {}
SensorChaveBotao(
const String& id,
uint8_t idNum,
int pino,
TiposBarramentos tipoBarramento,
int canalMux = -1,
bool inverterLogica = true,
bool usarDebounce = true,
unsigned long tempoDebounceMs = 50
) :
ID(id),
ID_Num(idNum),
_pino(PinoModel(pino, tipoBarramento, _INPUT_PULLUP, DIGITAL, idNum, canalMux)),
InverterLogica(inverterLogica),
UsarDebounce(usarDebounce),
TempoDebounceMs(tempoDebounceMs)
{
}
void Inicializar() {
if (Iniciado) {
MostrarLog("Sensor ja inicializado");
return;
}
LeituraBruta = false;
Pressionado = false;
PressionadoAnterior = false;
MudouEstado = false;
ultimaLeituraTratada = false;
ultimaLeituraInstavel = false;
ultimoTempoMudanca = 0;
_pino.Conectar();
Iniciado = _pino.Definido();
if (Iniciado) {
RequisitarDados();
}
MostrarLog(Iniciado ? "Sensor iniciado" : "Sensor nao iniciado");
}
void Desligar() {
if (!Iniciado) {
MostrarLog("Sensor nao esta inicializado");
return;
}
_pino.Desconectar();
Iniciado = false;
LeituraBruta = false;
Pressionado = false;
PressionadoAnterior = false;
MudouEstado = false;
MostrarLog("Sensor desligado");
}
void RequisitarDados() {
if (!Iniciado) return;
AferirEstado();
}
std::vector<uint8_t> MontarMensagemCAN(CanMessagePosicaoDados posicao) {
std::vector<uint8_t> data;
data.push_back(static_cast<uint8_t>(posicao));
data.push_back(ID_Num);
switch (posicao) {
case CanMessagePosicaoDados::Status: {
data.push_back(Iniciado ? 1 : 0);
break;
}
case CanMessagePosicaoDados::Dados1: {
RequisitarDados();
data.push_back(Pressionado ? 1 : 0);
data.push_back(LeituraBruta ? 1 : 0);
data.push_back(MudouEstado ? 1 : 0);
break;
}
}
return data;
}
private:
bool DebugMode = false;
bool ultimaLeituraTratada = false;
bool ultimaLeituraInstavel = false;
unsigned long ultimoTempoMudanca = 0;
void MostrarLog(String mensagem) {
if (DebugMode) {
PrintTela("[BTN " + ID + "] " + mensagem);
}
}
void AferirEstado() {
int leituraDigital = _pino.get(1);
LeituraBruta = leituraDigital > 0;
bool leituraTratada = InverterLogica ? !LeituraBruta : LeituraBruta;
if (!UsarDebounce) {
PressionadoAnterior = Pressionado;
Pressionado = leituraTratada;
MudouEstado = (Pressionado != PressionadoAnterior);
return;
}
unsigned long agora = millis();
if (leituraTratada != ultimaLeituraInstavel) {
ultimaLeituraInstavel = leituraTratada;
ultimoTempoMudanca = agora;
}
if ((agora - ultimoTempoMudanca) >= TempoDebounceMs) {
if (ultimaLeituraInstavel != ultimaLeituraTratada) {
ultimaLeituraTratada = ultimaLeituraInstavel;
PressionadoAnterior = Pressionado;
Pressionado = ultimaLeituraTratada;
MudouEstado = (Pressionado != PressionadoAnterior);
} else {
MudouEstado = false;
}
} else {
MudouEstado = false;
}
MostrarLog("Bruto: " + String(LeituraBruta ? 1 : 0) +
", Pressionado: " + String(Pressionado ? 1 : 0) +
", Mudou: " + String(MudouEstado ? 1 : 0));
}
};
#endif

View File

@ -15,7 +15,7 @@ class SensorFluxo_v2 : public ComponenteCAN {
)
: _ID(id),
ID_Num(idNum),
_pino(pino, barramento, _INPUT, DIGITAL) {
_pino(pino, barramento, _INPUT_PULLUP, DIGITAL) {
}
String _ID;