Ajustes no calculo de vazao por bico

This commit is contained in:
Diego Freitas 2025-12-18 17:14:27 -03:00
parent ff4e6116d6
commit 2325d866fe
9 changed files with 101 additions and 64 deletions

View File

@ -668,7 +668,7 @@ namespace AgroBase.Forms.Operacoes
Atuado = x.ComandoAtuar, Atuado = x.ComandoAtuar,
Comandar = x.Comandar, Comandar = x.Comandar,
Inicializado = x.Inicializado, Inicializado = x.Inicializado,
MediaNivelFluxo = x.MediaNivelFluxo, MediaNivelFluxo = x.VazaoMediaMLs,
Posicao = x.Posicao, Posicao = x.Posicao,
StatusBico = x._EstadoLeitura == Estado.Ligado, StatusBico = x._EstadoLeitura == Estado.Ligado,
TempoAtuado = x.TempoAtuado, TempoAtuado = x.TempoAtuado,

View File

@ -176,7 +176,7 @@ namespace AgroBase.Forms.Operacoes
Atuado = x.ComandoAtuar, Atuado = x.ComandoAtuar,
Comandar = x.Comandar, Comandar = x.Comandar,
Inicializado = x.Inicializado, Inicializado = x.Inicializado,
MediaNivelFluxo = x.MediaNivelFluxo, MediaNivelFluxo = x.VazaoMediaMLs,
Posicao = x.Posicao, Posicao = x.Posicao,
StatusBico = x._EstadoLeitura == Enums.Estado.Ligado, StatusBico = x._EstadoLeitura == Enums.Estado.Ligado,
TempoAtuado = x.TempoAtuado, TempoAtuado = x.TempoAtuado,

View File

@ -124,36 +124,57 @@ namespace AgroBase.Models.Modules
private double _somaVazao; // Acumula a soma da vazão para calcular a média private double _somaVazao; // Acumula a soma da vazão para calcular a média
private int _contadorLeituras; // Conta o número de leituras feitas private int _contadorLeituras; // Conta o número de leituras feitas
private DateTime _ultimoRegistroVazao; // Armazena o horário da última atualização private DateTime _ultimoRegistroVazao; // Armazena o horário da última atualização
private readonly Dictionary<string, double> _tempoAtuadoBicoSeg = new Dictionary<string, double>();
public double VazaoFluxoMLpSMedia { get; set; } public double VazaoFluxoMLpSMedia { get; set; }
public double VolumeVazaoML { get; set; } public double VolumeVazaoML { get; set; }
public DateTime InicioAtuacao { get; set; } = DateTime.MinValue; public DateTime InicioAtuacao { get; set; } = DateTime.MinValue;
public double TempoAtuado { get; set; } = 0; public double TempoAtuado { get; set; } = 0;
private bool bicoAtivoAnterior = false;
public void AtualizaTempoAtuadoGeral() public void AtualizaTempoAtuadoGeral()
{ {
bool algumBicoAtivo = BicosPulverizadores.Any(x => x.Inicializado && x.ComandoAtuar); DateTime agora = DateTime.Now;
if (algumBicoAtivo) // Quem está ativo AGORA
var bicosAtivos = BicosPulverizadores.Where(x => x.Inicializado && x.ComandoAtuar).ToList();
bool algumBicoAtivo = bicosAtivos.Count > 0;
// Início de uma "sessão" (transição OFF -> ON)
if (algumBicoAtivo && !bicoAtivoAnterior)
{ {
if (InicioAtuacao == DateTime.MinValue) InicioAtuacao = agora;
{ _ultimoRegistroVazao = agora; // inicia integração a partir daqui
InicioAtuacao = DateTime.Now;
} // (opcional) se você quer métricas por sessão, zere volumes/médias aqui
else // foreach (var b in BicosPulverizadores) { b.VolumeVazadoML = 0; b.VazaoMediaMLs = 0; }
{ // _tempoAtuadoBicoSeg.Clear();
TempoAtuado += (DateTime.Now - InicioAtuacao).TotalMilliseconds;
InicioAtuacao = DateTime.Now;
}
}
else if (InicioAtuacao != DateTime.MinValue)
{
TempoAtuado += (DateTime.Now - InicioAtuacao).TotalMilliseconds;
InicioAtuacao = DateTime.MinValue;
} }
// Fim de sessão (transição ON -> OFF)
if (!algumBicoAtivo && bicoAtivoAnterior)
{
if (InicioAtuacao != DateTime.MinValue)
{
TempoAtuado += (agora - InicioAtuacao).TotalMilliseconds;
InicioAtuacao = DateTime.MinValue;
}
_ultimoRegistroVazao = DateTime.MinValue;
// zera instantânea quando não tem bico ativo
foreach (var b in BicosPulverizadores)
b.VazaoInstantaneaMLs = 0;
}
// Atualiza indicadores
AtualizaPercentualErvas(); AtualizaPercentualErvas();
AtualizaVazaoEVolume();
// Integra vazão/volume enquanto tiver bico ativo
AtualizaVazaoEVolume(bicosAtivos, agora);
bicoAtivoAnterior = algumBicoAtivo;
} }
public void AtualizaPercentualErvas() private void AtualizaPercentualErvas()
{ {
//double tempoTotalOperacao = Variaveis.OperacaoEmAndamento.Sensoriamento.TempoDecorridoSeg * 1000.0; //double tempoTotalOperacao = Variaveis.OperacaoEmAndamento.Sensoriamento.TempoDecorridoSeg * 1000.0;
double tempoTotalOperacao = (Variaveis.OperacaoEmAndamento.Sensoriamento?.Movimentacao?.TempoMovimentoSegs ?? 0) * 1000.0; double tempoTotalOperacao = (Variaveis.OperacaoEmAndamento.Sensoriamento?.Movimentacao?.TempoMovimentoSegs ?? 0) * 1000.0;
@ -168,38 +189,50 @@ namespace AgroBase.Models.Modules
PercentualErvasTerreno = 0; PercentualErvasTerreno = 0;
} }
} }
public void AtualizaVazaoEVolume() private void AtualizaVazaoEVolume(List<AtuadorBicoModel> bicosAtivos, DateTime agora)
{ {
// Captura a vazão instantânea // Só integra se houver bicos ativos
double vazaoInstantanea = VazaoFluxoMLpSInstantanea; if (bicosAtivos == null || bicosAtivos.Count == 0)
return;
// Captura vazão total instantânea (ml/s)
double vazaoTotalInst = VazaoFluxoMLpSInstantanea;
// Primeiro tick: arma o relógio
if (_ultimoRegistroVazao == DateTime.MinValue) if (_ultimoRegistroVazao == DateTime.MinValue)
{ {
_ultimoRegistroVazao = DateTime.Now; _ultimoRegistroVazao = agora;
return; return;
} }
// Calcula o tempo decorrido desde a última atualização (em segundos) // dt em segundos
double intervaloSegundos = (DateTime.Now - _ultimoRegistroVazao).TotalSeconds; double dt = (agora - _ultimoRegistroVazao).TotalSeconds;
_ultimoRegistroVazao = DateTime.Now; _ultimoRegistroVazao = agora;
if (intervaloSegundos > 0) if (dt <= 0)
return;
// Vazão instantânea por bico (distribuição uniforme)
double vazaoPorBicoInst = vazaoTotalInst / bicosAtivos.Count;
foreach (var bico in bicosAtivos)
{ {
// Atualiza o volume total vazado // Instantânea por bico
VolumeVazaoML += vazaoInstantanea * intervaloSegundos; bico.VazaoInstantaneaMLs = vazaoPorBicoInst;
// Acumula a vazão para o cálculo da média // Volume por bico (ml) = (ml/s) * s
_somaVazao += vazaoInstantanea; bico.VolumeVazadoML += vazaoPorBicoInst * dt;
_contadorLeituras++;
}
VazaoFluxoMLpSMedia = TempoAtuado == 0 ? 0 : VolumeVazaoML / TempoAtuado; // Tempo atuado por bico (seg)
string key = bico.ID; // ou bico.ID_Num.ToString()
if (!_tempoAtuadoBicoSeg.ContainsKey(key))
_tempoAtuadoBicoSeg[key] = 0;
var BicosAtuados = BicosPulverizadores.Where(x => x.Inicializado && x.ComandoAtuar).ToList(); _tempoAtuadoBicoSeg[key] += dt;
double vazaoInstantaneaBico = vazaoInstantanea / ((double)BicosAtuados.Count());
foreach (var Bico in BicosAtuados) // Média por bico (ml/s) = volume / tempo
{ double tempoBico = _tempoAtuadoBicoSeg[key];
Bico.MediaNivelFluxo = vazaoInstantaneaBico; bico.VazaoMediaMLs = tempoBico > 0 ? (bico.VolumeVazadoML / tempoBico) : 0;
} }
} }
@ -747,7 +780,7 @@ namespace AgroBase.Models.Modules
{ {
FuncoesPinout.Solenoide, FuncoesPinout.Solenoide,
}, },
MediaNivelFluxo = 0, VazaoMediaMLs = 0,
ValoresLeituras = new List<SensorValoresLeituraModel>() ValoresLeituras = new List<SensorValoresLeituraModel>()
{ {
new SensorValoresLeituraModel() new SensorValoresLeituraModel()
@ -1304,7 +1337,9 @@ namespace AgroBase.Models.Modules
} }
} }
public List<FuncoesPinout> Funcoes { get; set; } public List<FuncoesPinout> Funcoes { get; set; }
public double MediaNivelFluxo { get; set; } public double VazaoMediaMLs { get; set; }
public double VazaoInstantaneaMLs { get; set; }
public double VolumeVazadoML { get; set; }
public bool Inicializado { get; set; } public bool Inicializado { get; set; }
public DateTime UltimaLeitura public DateTime UltimaLeitura
{ {
@ -1380,12 +1415,6 @@ namespace AgroBase.Models.Modules
InicioAtuacao = DateTime.MinValue; InicioAtuacao = DateTime.MinValue;
} }
} }
if (Variaveis.OperacaoEmAndamento.DispAtu != null)
{
Variaveis.OperacaoEmAndamento.DispAtu.Dados.AtualizaTempoAtuadoGeral();
}
_estadoLeituraAnterior = estado_atual; _estadoLeituraAnterior = estado_atual;
} }
@ -1408,7 +1437,7 @@ namespace AgroBase.Models.Modules
ID_Num = ID_Num, ID_Num = ID_Num,
InicioAtuacao = InicioAtuacao, InicioAtuacao = InicioAtuacao,
ValoresLeituras = new List<SensorValoresLeituraModel>(ValoresLeituras), ValoresLeituras = new List<SensorValoresLeituraModel>(ValoresLeituras),
MediaNivelFluxo = MediaNivelFluxo, VazaoMediaMLs = VazaoMediaMLs,
Posicao = Posicao, Posicao = Posicao,
TempoAtuado = TempoAtuado TempoAtuado = TempoAtuado
}; };

View File

@ -10,7 +10,6 @@ using static AgroBase.Services.LoRaEspService;
using AgroBase.Services.Operadores; using AgroBase.Services.Operadores;
using AgroBase.Models.Operadores; using AgroBase.Models.Operadores;
using System.Diagnostics; using System.Diagnostics;
using StackExchange.Redis;
namespace AgroBase.Models.Modules namespace AgroBase.Models.Modules
{ {
@ -2394,9 +2393,9 @@ namespace AgroBase.Models.Modules
public void AtualizarStatusSinaleiros(ModoOperacao Modo, StatusOperacao _statusOperacao) public void AtualizarStatusSinaleiros(ModoOperacao Modo, StatusOperacao _statusOperacao)
{ {
Sinaleiros.First(x => x.ID == "LEDMN").Comportamento.statusLED = Modo == ModoOperacao.Manual ? StatusLED.Aceso : StatusLED.Apagado; Sinaleiros.First(x => x.ID == "LEDMN").Comportamento = VariaveisEquipamento.ComportamentoLedPorStatus(Modo == ModoOperacao.Manual ? StatusLED.Aceso : StatusLED.Apagado);
Sinaleiros.First(x => x.ID == "LEDAT").Comportamento.statusLED = Modo == ModoOperacao.Manual ? StatusLED.Apagado : StatusLED.Aceso; Sinaleiros.First(x => x.ID == "LEDAT").Comportamento = VariaveisEquipamento.ComportamentoLedPorStatus(Modo == ModoOperacao.Manual ? StatusLED.Apagado : StatusLED.Aceso);
Sinaleiros.First(x => x.ID == "LEDOP").Comportamento = VariaveisEquipamento.ComportamentoLedPorStatus(status_operacao: _statusOperacao); Sinaleiros.First(x => x.ID == "LEDOP").Comportamento = VariaveisEquipamento.ComportamentoLedPorStatus(StatusLED.Piscando, status_operacao: _statusOperacao);
} }
} }
@ -2479,8 +2478,8 @@ namespace AgroBase.Models.Modules
} }
} }
public List<SensorValoresLeituraModel> ValoresLeituras { get; set; } public List<SensorValoresLeituraModel> ValoresLeituras { get; set; }
public int _StatusLedId => ValoresLeituras?.FirstOrDefault(x => x.funcao == FuncoesPinout.StatusLedID)?.atual?.valor ?? 99; public int _StatusLedId => (int)(ValoresLeituras?.FirstOrDefault(x => x.funcao == FuncoesPinout.StatusLedID)?.atual?.valor ?? 99);
public StatusLED _StatusLed => ValoresLeituras?.FirstOrDefault(x => x.funcao == FuncoesPinout.StatusLedLeitura)?.atual?.valor ?? StatusLED.Apagado; public StatusLED _StatusLed => (StatusLED)(ValoresLeituras?.FirstOrDefault(x => x.funcao == FuncoesPinout.StatusLedLeitura)?.atual?.valor ?? StatusLED.Apagado);
public (CanMessagePosicaoDados, byte[]) ProtocoloConfiguracao(PinoutDataModel pinout, bool conectar) public (CanMessagePosicaoDados, byte[]) ProtocoloConfiguracao(PinoutDataModel pinout, bool conectar)
{ {

View File

@ -1790,7 +1790,7 @@ namespace AgroBase.Models
Inicializado = Bico.Inicializado, Inicializado = Bico.Inicializado,
Comandar = Bico.Comandar, Comandar = Bico.Comandar,
Atuado = Bico.ComandoAtuar, Atuado = Bico.ComandoAtuar,
MediaNivelFluxo = Bico.MediaNivelFluxo, MediaNivelFluxo = Bico.VazaoMediaMLs,
Posicao = Bico.Posicao, Posicao = Bico.Posicao,
StatusBico = Bico._EstadoLeitura == Estado.Ligado, StatusBico = Bico._EstadoLeitura == Estado.Ligado,
Atuacoes = Bico.Atuacoes, Atuacoes = Bico.Atuacoes,
@ -2320,6 +2320,7 @@ namespace AgroBase.Models
double tmp_max = Math.Max(Variaveis.OperacaoEmAndamento.DadosPerformance?.GPU_temp ?? 0, Variaveis.OperacaoEmAndamento.DadosPerformance?.CPU_temp ?? 0); double tmp_max = Math.Max(Variaveis.OperacaoEmAndamento.DadosPerformance?.GPU_temp ?? 0, Variaveis.OperacaoEmAndamento.DadosPerformance?.CPU_temp ?? 0);
_DispMvd?.Dados?.AtualizarDadosFreio(); _DispMvd?.Dados?.AtualizarDadosFreio();
_DispSen?.Dados?.AtualizarStatusSinaleiros(Variaveis.OperacaoEmAndamento.Modo, Variaveis.OperacaoEmAndamento.StatusAtual); _DispSen?.Dados?.AtualizarStatusSinaleiros(Variaveis.OperacaoEmAndamento.Modo, Variaveis.OperacaoEmAndamento.StatusAtual);
_DispAtu?.Dados?.AtualizaTempoAtuadoGeral();
_Cooler?.Atualizar(tmp_max, DateTime.Now); _Cooler?.Atualizar(tmp_max, DateTime.Now);
_Bateria?.AtualizarConsumo(_DispMvd?.Dados?.DistanciaPercorridaTotal ?? 0); _Bateria?.AtualizarConsumo(_DispMvd?.Dados?.DistanciaPercorridaTotal ?? 0);
_Reservatorio?.AtualizarConsumo(_DispMvd?.Dados?.DistanciaPercorridaTotal ?? 0, Variaveis.OperacaoEmAndamento.TempoDecorridoSegs); _Reservatorio?.AtualizarConsumo(_DispMvd?.Dados?.DistanciaPercorridaTotal ?? 0, Variaveis.OperacaoEmAndamento.TempoDecorridoSegs);
@ -2373,7 +2374,7 @@ namespace AgroBase.Models
Inicializado = Bico.Inicializado, Inicializado = Bico.Inicializado,
Comandar = Bico.Comandar, Comandar = Bico.Comandar,
Atuado = Bico.ComandoAtuar, Atuado = Bico.ComandoAtuar,
MediaNivelFluxo = Bico.MediaNivelFluxo, MediaNivelFluxo = Bico.VazaoMediaMLs,
Posicao = Bico.Posicao, Posicao = Bico.Posicao,
StatusBico = Bico._EstadoLeitura == Estado.Ligado, StatusBico = Bico._EstadoLeitura == Estado.Ligado,
Atuacoes = Bico.Atuacoes, Atuacoes = Bico.Atuacoes,

View File

@ -156,7 +156,9 @@ namespace AgroBase.Models.Operacoes
LeituraAngulo = x._AnguloBicoLeitura, LeituraAngulo = x._AnguloBicoLeitura,
ComandoEstado = x.ComandoAtuar, ComandoEstado = x.ComandoAtuar,
LeituraEstado = x._EstadoLeitura == Estado.Ligado, LeituraEstado = x._EstadoLeitura == Estado.Ligado,
MediaVazaoMLs = x.MediaNivelFluxo, VazaoMediaMLs = x.VazaoMediaMLs,
VazaoInstantaneaMLs = x.VazaoInstantaneaMLs,
VolumeVazadoML = x.VolumeVazadoML,
QtdAtuacoes = x.Atuacoes, QtdAtuacoes = x.Atuacoes,
TempoAtuado = x.TempoAtuado, TempoAtuado = x.TempoAtuado,
TrechosPulverizando = new List<List<double[]>>(x.TrechosAtuado ?? new List<List<double[]>>()), TrechosPulverizando = new List<List<double[]>>(x.TrechosAtuado ?? new List<List<double[]>>()),
@ -428,7 +430,9 @@ namespace AgroBase.Models.Operacoes
public int LeituraAngulo { get; set; } public int LeituraAngulo { get; set; }
public int QtdAtuacoes { get; set; } public int QtdAtuacoes { get; set; }
public double TempoAtuado { get; set; } public double TempoAtuado { get; set; }
public double MediaVazaoMLs { get; set; } public double VazaoMediaMLs { get; set; }
public double VazaoInstantaneaMLs { get; set; }
public double VolumeVazadoML { get; set; }
public double AnguloAbertura { get; set; } public double AnguloAbertura { get; set; }
public List<List<double[]>> TrechosPulverizando { get; set; } public List<List<double[]>> TrechosPulverizando { get; set; }
public DateTime UltimoComandoRespondido { get; set; } public DateTime UltimoComandoRespondido { get; set; }

View File

@ -836,7 +836,7 @@ namespace OperationControl.Windows
{ {
Label = "Vazão", Label = "Vazão",
Unidade = "mL/s", Unidade = "mL/s",
Valor = b?.MediaVazaoMLs Valor = b?.VazaoInstantaneaMLs
}, },
}); });
break; break;
@ -1127,7 +1127,7 @@ namespace OperationControl.Windows
txtBico_Comando.Text = comando ? "Ligado" : "Desligado"; txtBico_Comando.Text = comando ? "Ligado" : "Desligado";
txtBico_StatusReal.Text = leitura ? "Ligado" : "Desligado"; txtBico_StatusReal.Text = leitura ? "Ligado" : "Desligado";
txtBico_TempoLigado.Text = (bico?.TempoAtuado ?? 0).ToString("0.00") + " ms"; txtBico_TempoLigado.Text = (bico?.TempoAtuado ?? 0).ToString("0.00") + " ms";
txtBico_Vazao.Text = (bico?.MediaVazaoMLs ?? 0).ToString("0.00") + " Ml/s"; txtBico_Vazao.Text = (bico?.VazaoInstantaneaMLs ?? 0).ToString("0.00") + " Ml/s";
txtBico_Pressao.Text = (rover?.Atuador?.PressaoLinhaPsi ?? 0).ToString("0.00") + " psi"; txtBico_Pressao.Text = (rover?.Atuador?.PressaoLinhaPsi ?? 0).ToString("0.00") + " psi";
txtBico_Atuacoes.Text = (bico?.QtdAtuacoes ?? 0).ToString(); txtBico_Atuacoes.Text = (bico?.QtdAtuacoes ?? 0).ToString();
@ -2028,7 +2028,7 @@ namespace OperationControl.Windows
bico.AnguloControle = _bc.ComandoAngulo; bico.AnguloControle = _bc.ComandoAngulo;
bico.IsCommandOn = _bc.ComandoEstado; bico.IsCommandOn = _bc.ComandoEstado;
bico.IsSpraying = _bc.LeituraEstado; bico.IsSpraying = _bc.LeituraEstado;
bico.Vazao = _bc.MediaVazaoMLs; bico.Vazao = _bc.VazaoInstantaneaMLs;
bico.Atuacoes = _bc.QtdAtuacoes; bico.Atuacoes = _bc.QtdAtuacoes;
bico.TempoAtuado = _bc.TempoAtuado / 1000.0; bico.TempoAtuado = _bc.TempoAtuado / 1000.0;
} }

View File

@ -86,7 +86,8 @@ class SensorMassa : public ComponenteCAN {
} }
case CanMessagePosicaoDados::Dados1: { case CanMessagePosicaoDados::Dados1: {
uint16_t massaEscalada = (uint16_t)(Massa * 100); uint16_t massaEscalada = (uint16_t)(Massa * 100);
data.push_back(leitura >> 8); data.push_back(leitura & 0xFF); uint16_t leituraEscalada = (uint16_t)(leitura * 100);
data.push_back(leituraEscalada >> 8); data.push_back(leituraEscalada & 0xFF);
data.push_back(massaEscalada >> 8); data.push_back(massaEscalada & 0xFF); data.push_back(massaEscalada >> 8); data.push_back(massaEscalada & 0xFF);
break; break;
} }

View File

@ -66,7 +66,10 @@ class Sinaleiro : public ComponenteCAN {
void AtualizarLeitura() { void AtualizarLeitura() {
if (Iniciado) { if (Iniciado) {
_StatusLeitura = (StatusLED)_pino.get(); if (_Qtd == 0)
_StatusLeitura = (StatusLED)_pino.get();
else
_StatusLeitura = StatusLED::Piscando;
} }
} }