melhorado saude do atuador, incluido cavitacao na propria bomba

This commit is contained in:
Diego Freitas 2026-07-01 09:00:39 -03:00
parent d7f1689610
commit 64fce863d5
6 changed files with 358 additions and 49 deletions

View File

@ -719,7 +719,7 @@ namespace AgroBase.Models.Modules
analise_health = true,
maximo = 120,
minimo = 0,
nominal = 85,
nominal = 20,
unidade_medida = "PSI"
}
}
@ -764,7 +764,7 @@ namespace AgroBase.Models.Modules
posicao = CanMessagePosicaoDados.Dados1,
indice = 2,
analise_health = true,
maximo = 20,
maximo = 100,
minimo = 0,
nominal = 0,
unidade_medida = "mL/s"
@ -1080,7 +1080,7 @@ namespace AgroBase.Models.Modules
},
new SensorValoresLeituraModel()
{
funcao = FuncoesPinout.PressaoSPExtra,
funcao = FuncoesPinout.BitmapDiagnostico,
posicao = CanMessagePosicaoDados.Dados2,
indice = 5,
},
@ -2329,7 +2329,42 @@ namespace AgroBase.Models.Modules
public double _PotenciaFinal => ValoresLeituras?.FirstOrDefault(x => x.posicao == CanMessagePosicaoDados.Dados2 && x.funcao == FuncoesPinout.Potencia)?.atual?.valor ?? 0;
public double _PressaoSensor => ValoresLeituras?.FirstOrDefault(x => x.posicao == CanMessagePosicaoDados.Dados2 && x.funcao == FuncoesPinout.Pressao)?.atual?.valor ?? 0;
public double _PressaoSPControle => ValoresLeituras?.FirstOrDefault(x => x.posicao == CanMessagePosicaoDados.Dados2 && x.funcao == FuncoesPinout.PressaoSP)?.atual?.valor ?? 0;
public bool _PressaoSPForaDoMapa => ValoresLeituras?.FirstOrDefault(x => x.posicao == CanMessagePosicaoDados.Dados2 && x.funcao == FuncoesPinout.PressaoSPExtra)?.atual?.valor ?? false;
private int _BitmapDiagnostico
{
get
{
try
{
var valor = ValoresLeituras?
.FirstOrDefault(x =>
x.posicao == CanMessagePosicaoDados.Dados2 &&
x.funcao == FuncoesPinout.BitmapDiagnostico)
?.atual?.valor;
if (valor == null)
return 0;
return Convert.ToInt32(valor);
}
catch
{
return 0;
}
}
}
private bool TemFlagDiagnostico(int bit)
{
return (_BitmapDiagnostico & (1 << bit)) != 0;
}
public bool _PressaoSPForaDoMapa => TemFlagDiagnostico(0);
public bool _FluxoInsuficiente => TemFlagDiagnostico(1);
public bool _RecuperacaoFluxoAtiva => TemFlagDiagnostico(2);
public bool _CavitacaoSuspeita => TemFlagDiagnostico(3);
public bool _Cavitada => TemFlagDiagnostico(4);
public bool _CorteSegurancaAtivo => TemFlagDiagnostico(5);
public bool _PressaoSPLimitadoPorCapacidade => TemFlagDiagnostico(6);
public int Atuacoes { get; set; }
@ -2912,7 +2947,7 @@ namespace AgroBase.Models.Modules
int potenciaFinal = data.Length > 4 ? data[4] : 0;
int pressaoSensor = data.Length > 5 ? data[5] : 0;
int pressaoSpControle = data.Length > 6 ? data[6] : 0;
bool pressaoSpForaDoMapa = data.Length > 7 && data[7] == 1;
byte flags = data.Length > 7 ? data[7] : (byte)0;
AtualizarDados(
ID_Num,
posicao,
@ -2924,7 +2959,7 @@ namespace AgroBase.Models.Modules
potenciaFinal,
pressaoSensor,
pressaoSpControle,
pressaoSpForaDoMapa
flags
}
);

View File

@ -442,6 +442,7 @@ namespace AgroBase.Models.Modules
Botao,
MalhaFechada,
PressaoSPExtra,
BitmapDiagnostico
}
public static class PinoutUtils

View File

@ -3551,17 +3551,19 @@ namespace AgroBase.Models
PotenciaFinal = bombaLinha?._PotenciaFinal ?? 0,
PressaoSensor = bombaLinha?._PressaoSensor ?? 0,
PressaoSPControle = bombaLinha?._PressaoSPControle ?? 0,
PressaoSPForaDoMapa = bombaLinha?._PressaoSPForaDoMapa ?? false,
FluxoInsuficiente = bombaLinha?._FluxoInsuficiente ?? false,
RecuperacaoFluxoAtiva = bombaLinha?._RecuperacaoFluxoAtiva ?? false,
CavitacaoSuspeita = bombaLinha?._CavitacaoSuspeita ?? false,
Cavitada = bombaLinha?._Cavitada ?? false,
CorteSegurancaAtivo = bombaLinha?._CorteSegurancaAtivo ?? false,
PressaoSPLimitadoPorCapacidade = bombaLinha?._PressaoSPLimitadoPorCapacidade ?? false,
TempoPulverizadorAtuado = dadosAtu.TempoAtuado,
TempoBombaAtuada = dadosAtu.TempoAtuado,
BombaCavitada =
dadosAtu.Conectado &&
dadosAtu.PressaoLinha < (pControle?.AtuPressaoLinha ?? 0) &&
dadosAtu.PressaoLinha < VariaveisEquipamento.PressaoMinimaCavitacao &&
bombaLinha?._EstadoLeitura == Estado.Ligado &&
(bombaLinha?._PotenciaFinal ?? bombaLinha?._Potencia ?? 0) > 20,
BombaCavitada = dadosAtu.Conectado && (bombaLinha?._Cavitada ?? false),
ModoControleAgitador = pControle?.AtuAgitadorModo ?? ModoAgitadorCalda.SemAgitacao,
PotenciaAgitador = dadosAtu.AgitadorDeCalda?.PotenciaMediaAtiva ?? 0,
@ -4978,7 +4980,15 @@ namespace AgroBase.Models
public double PotenciaFinal { get; set; }
public double PressaoSensor { get; set; }
public double PressaoSPControle { get; set; }
// Flags de cavitaao
public bool PressaoSPForaDoMapa { get; set; }
public bool FluxoInsuficiente { get; set; }
public bool RecuperacaoFluxoAtiva { get; set; }
public bool CavitacaoSuspeita { get; set; }
public bool Cavitada { get; set; }
public bool CorteSegurancaAtivo { get; set; }
public bool PressaoSPLimitadoPorCapacidade { get; set; }
public double TempoPulverizadorAtuado { get; set; }
public double TempoBombaAtuada { get; set; }
@ -5055,7 +5065,14 @@ namespace AgroBase.Models
PotenciaFinal = PotenciaFinal,
PressaoSensor = PressaoSensor,
PressaoSPControle = PressaoSPControle,
PressaoSPForaDoMapa = PressaoSPForaDoMapa,
FluxoInsuficiente = FluxoInsuficiente,
RecuperacaoFluxoAtiva = RecuperacaoFluxoAtiva,
CavitacaoSuspeita = CavitacaoSuspeita,
Cavitada = Cavitada,
CorteSegurancaAtivo = CorteSegurancaAtivo,
PressaoSPLimitadoPorCapacidade = PressaoSPLimitadoPorCapacidade,
TempoPulverizadorAtuado = TempoPulverizadorAtuado,
TempoBombaAtuada = TempoBombaAtuada,

View File

@ -432,6 +432,7 @@ namespace AgroBase.Services
}
);
op = Variaveis.OperacaoEmAndamento;
op.Sensoriamento.Operacao.ModsCalibragem.TryGetValue(T_Code.Mov, out var m);
if (m == null)

View File

@ -23,9 +23,10 @@ class ModuloAtuador(ModuloDiagnosticoBase):
RESPOSTA_RECENTE_MS = 8000.0
RESPOSTA_LENTA_MS = 4500.0
COMANDO_GRACE_MS = 900.0
COMANDO_ALERTA_MS = 2500.0
COMANDO_FALHA_MS = 6000.0
COMANDO_GRACE_MS = 1500.0
COMANDO_ALERTA_MS = 4000.0
COMANDO_FALHA_MS = 8000.0
PROCESSO_GRACE_MS = 2500.0
FREQ_MIN_DEFAULT_FACTOR = 0.35
PENALIDADE_FREQ_MAX_PADRAO = 4
@ -467,8 +468,8 @@ class ModuloAtuador(ModuloDiagnosticoBase):
score = min(score, 90)
if label_sensor == "PRSLN":
bomba_on = self._bomba_principal_ligada(ctx)
if bomba_on and not ctx["pressao_linha_regular"]:
bomba_on = self._bomba_principal_ligada_fisica(ctx)
if bomba_on and not self._pulverizacao_em_transicao(ctx) and not ctx["pressao_linha_regular"]:
pressao = ctx["pressao_linha"]
motivos.append(f"Pressão baixa com bomba ligada ({pressao:.1f} psi)")
condicoes.append({
@ -485,11 +486,11 @@ class ModuloAtuador(ModuloDiagnosticoBase):
score = min(score, 70)
if label_sensor == "FLXLN":
bicos_on = len(ctx["bicos_ligados"]) > 0 or len(ctx["bicos_comandados"]) > 0
bomba_on = self._bomba_principal_ligada(ctx)
bicos_on = len(ctx["bicos_ligados"]) > 0
bomba_on = self._bomba_principal_ligada_fisica(ctx)
vazao = ctx["vazao_linha_mls"]
if bicos_on and bomba_on and vazao <= self.FLUXO_MIN_COM_BICOS_MLS:
if bicos_on and bomba_on and not self._pulverizacao_em_transicao(ctx) and vazao <= self.FLUXO_MIN_COM_BICOS_MLS:
motivos.append(f"Fluxo baixo com bicos e bomba ativos ({vazao:.1f} mL/s)")
condicoes.append({
"label": "Fluxo de linha",
@ -597,24 +598,27 @@ class ModuloAtuador(ModuloDiagnosticoBase):
}
if comando and not estado_on:
severidade = 92 if tem_idade_comando and ultimo_comando_ms >= self.COMANDO_FALHA_MS else 75
motivos.append(f"Bico comandado ligado, mas leitura indica desligado ({label})")
severidade = 85 if tem_idade_comando and ultimo_comando_ms >= self.COMANDO_FALHA_MS else 70
motivos.append(f"Bico comandado ligado, mas leitura ainda indica desligado ({label})")
condicoes.append({
"label": "Bico",
"valor": 0,
"severidade": severidade,
"classe": "falha_hardware" if severidade > 90 else "processo",
"descricao": f"Bico {label} comandado ligado, mas estado lido está desligado",
"classe": "processo",
"descricao": f"Bico {label} comandado ligado, mas estado lido ainda está desligado",
"acoes": [
"Verificar solenoide do bico.",
"Verificar comando físico no ATU.",
"Aguardar próxima atualização CAN.",
"Verificar solenoide do bico se a divergência persistir.",
"Conferir alimentação e retorno do bico.",
],
})
score = min(score, 35 if severidade > 90 else 70)
score = min(score, 55 if severidade >= 85 else 75)
if not comando and estado_on:
severidade = 95 if tem_idade_comando and ultimo_comando_ms >= self.COMANDO_ALERTA_MS else 85
severidade = 95 if tem_idade_comando and ultimo_comando_ms >= self.COMANDO_FALHA_MS else 82
motivos.append(f"Bico ligado sem comando ({label})")
condicoes.append({
"label": "Bico",
@ -627,7 +631,8 @@ class ModuloAtuador(ModuloDiagnosticoBase):
"Verificar se o comando de desligamento chegou ao ATU.",
],
})
score = min(score, 25 if severidade > 90 else 60)
score = min(score, 25 if severidade > 90 else 65)
erro_ang = abs(angulo - angulo_desejado)
@ -747,24 +752,27 @@ class ModuloAtuador(ModuloDiagnosticoBase):
}
if comando and not bomba_ligada:
severidade = 92 if tem_idade_comando and ultimo_comando_ms >= self.COMANDO_FALHA_MS else 78
motivos.append(f"Bomba {label} comandada ligada, mas leitura não indica acionamento")
severidade = 85 if tem_idade_comando and ultimo_comando_ms >= self.COMANDO_FALHA_MS else 70
motivos.append(f"Bomba {label} comandada ligada, mas leitura ainda não indica acionamento")
condicoes.append({
"label": "Bomba",
"valor": potencia,
"severidade": severidade,
"classe": "falha_hardware" if severidade > 90 else "processo",
"descricao": f"Bomba {label} comandada ligada, mas estado/potência indicam desligado",
"classe": "processo",
"descricao": f"Bomba {label} comandada ligada, mas estado/potência ainda indicam desligado",
"acoes": [
"Verificar relé/driver da bomba.",
"Verificar alimentação da bomba.",
"Conferir comando físico Command1 do ATU.",
"Aguardar próxima atualização CAN.",
"Verificar relé/driver da bomba se a divergência persistir.",
"Conferir alimentação e retorno da bomba.",
],
})
score = min(score, 35 if severidade > 90 else 68)
score = min(score, 55 if severidade >= 85 else 75)
if not comando and bomba_ligada:
severidade = 95 if tem_idade_comando and ultimo_comando_ms >= self.COMANDO_ALERTA_MS else 85
severidade = 95 if tem_idade_comando and ultimo_comando_ms >= self.COMANDO_FALHA_MS else 82
motivos.append(f"Bomba {label} ligada sem comando")
condicoes.append({
"label": "Bomba",
@ -777,7 +785,8 @@ class ModuloAtuador(ModuloDiagnosticoBase):
"Verificar se comando de desligamento chegou ao ATU.",
],
})
score = min(score, 25 if severidade > 90 else 60)
score = min(score, 25 if severidade > 90 else 65)
if eh_principal and comando and bomba_ligada:
pressao_ref = pressao if pressao > 0 else ctx["pressao_linha"]
@ -799,7 +808,13 @@ class ModuloAtuador(ModuloDiagnosticoBase):
})
score = min(score, 25)
elif pressao_alvo > 0 and pressao_ref < max(0, pressao_alvo - self.PRESSAO_TOL_PSI):
elif (
pressao_alvo > 0 and
pressao_ref < max(0, pressao_alvo - self.PRESSAO_TOL_PSI) and
not ctx["calibrando"] and
not ctx["finalizando"] and
not self._pulverizacao_em_transicao(ctx)
):
severidade = 88 if len(ctx["bicos_ligados"]) > 0 else 75
motivos.append(f"Pressão abaixo do SP ({pressao_ref:.1f}/{pressao_alvo:.1f} psi)")
condicoes.append({
@ -855,7 +870,9 @@ class ModuloAtuador(ModuloDiagnosticoBase):
calibrando = ctx["calibrando"]
bomba_principal = ctx["bomba_principal"]
bomba_principal_on = self._bomba_principal_ligada(ctx)
em_transicao = self._pulverizacao_em_transicao(ctx)
bomba_principal_on = self._bomba_principal_ligada_fisica(ctx)
bomba_principal_cmd = self._bomba_principal_comandada(ctx)
bicos_cmd = len(ctx["bicos_comandados"]) > 0
bicos_on = len(ctx["bicos_ligados"]) > 0
@ -933,7 +950,15 @@ class ModuloAtuador(ModuloDiagnosticoBase):
})
score = min(score, 80)
if (bicos_cmd or bicos_on) and auto and not bomba_principal_on and not calibrando:
if (
(bicos_cmd or bicos_on) and
auto and
not bomba_principal_on and
not bomba_principal_cmd and
not calibrando and
not ctx["finalizando"] and
not em_transicao
):
pulverizacao_incoerente = True
motivos.append("Bicos ativos ou comandados com bomba principal desligada")
condicoes.append({
@ -950,7 +975,14 @@ class ModuloAtuador(ModuloDiagnosticoBase):
})
score = min(score, 35)
if bomba_principal_on and bicos_on and ctx["vazao_linha_mls"] <= self.FLUXO_MIN_COM_BICOS_MLS:
if (
bomba_principal_on and
bicos_on and
not calibrando and
not ctx["finalizando"] and
not em_transicao and
ctx["vazao_linha_mls"] <= self.FLUXO_MIN_COM_BICOS_MLS
):
motivos.append("Fluxo ausente com bomba e bicos ligados")
condicoes.append({
"label": "Fluxo de pulverização",
@ -964,7 +996,13 @@ class ModuloAtuador(ModuloDiagnosticoBase):
})
score = min(score, 62)
if bomba_principal_on and not ctx["pressao_linha_regular"]:
if (
bomba_principal_on and
not calibrando and
not ctx["finalizando"] and
not em_transicao and
not ctx["pressao_linha_regular"]
):
motivos.append("Pressão de linha irregular com bomba ligada")
condicoes.append({
"label": "Pressão de pulverização",
@ -1251,7 +1289,15 @@ class ModuloAtuador(ModuloDiagnosticoBase):
return item
return None
def _bomba_principal_ligada(self, ctx):
def _bomba_principal_comandada(self, ctx):
bomba = ctx.get("bomba_principal")
if not bomba:
return False
dados = bomba.get("dados", {})
return self._estado_desejado_ligado(dados)
def _bomba_principal_ligada_fisica(self, ctx):
bomba = ctx.get("bomba_principal")
if not bomba:
return False
@ -1259,9 +1305,29 @@ class ModuloAtuador(ModuloDiagnosticoBase):
dados = bomba.get("dados", {})
estado = self._get(dados, "estado_leitura", self._campo_atual(dados, "EstadoLeitura", 0))
potencia = self._float(self._get(dados, "potencia", self._campo_atual(dados, "Potencia", 0)), 0)
comando = self._bool(dados.get("comando_atuar", False))
return self._estado_ligado(estado) or potencia > self.POTENCIA_MIN_BOMBA_LIGADA or comando
return self._estado_ligado(estado) or potencia > self.POTENCIA_MIN_BOMBA_LIGADA
def _comando_em_transicao(self, dados, janela_ms=None):
janela_ms = janela_ms if janela_ms is not None else self.PROCESSO_GRACE_MS
ultimo_comando_ms = self._float(dados.get("ultimo_comando_ms", 999999), 999999)
return ultimo_comando_ms < 900000 and ultimo_comando_ms < janela_ms
def _pulverizacao_em_transicao(self, ctx):
bomba = ctx.get("bomba_principal")
if bomba and self._comando_em_transicao(bomba.get("dados", {})):
return True
for b in ctx.get("bicos_comandados", []) or []:
if self._comando_em_transicao(b.get("dados", {})):
return True
for b in ctx.get("bicos_ligados", []) or []:
if self._comando_em_transicao(b.get("dados", {})):
return True
return False
def _obter_ultima_resposta_ms(self, dados):
if not isinstance(dados, dict):
@ -1332,6 +1398,9 @@ class ModuloAtuador(ModuloDiagnosticoBase):
if not isinstance(dados, dict):
return False
if "comando_atuar" in dados:
return self._bool(dados.get("comando_atuar", False))
for key in [
"estado_desejado",
"status_desejado",
@ -1341,7 +1410,7 @@ class ModuloAtuador(ModuloDiagnosticoBase):
if key in dados:
return self._estado_ligado(dados.get(key))
return self._bool(dados.get("comando_atuar", False))
return False
@staticmethod

View File

@ -310,6 +310,27 @@ class BombaPressurizadora_v2 : public ComponenteCAN {
bool LinhaArmadaPorFluxo = false;
bool FalhaArmamentoLinhaAtual = false;
/*
Detector de cavitacao consolidado na firmware.
Nao corta a bomba neste primeiro momento.
Apenas informa estado diagnostico para o C# via CAN.
*/
bool HabilitarDetectorCavitacao = true;
double PressaoMinimaCavitacaoPsi = 8.0;
double MargemPressaoSPCavitacaoPsi = 6.0;
double PotenciaMinimaParaDetectarCavitacaoPct = 25.0;
double VazaoMinimaCavitacaoMLs = 2.0;
unsigned long TempoIgnorarAposLigarBombaMs = 1500;
unsigned long TempoIgnorarAposMudancaBicosMs = 900;
unsigned long TempoParaSuspeitarCavitacaoMs = 900;
unsigned long TempoParaConfirmarCavitacaoMs = 2500;
unsigned long TempoParaLimparCavitacaoMs = 1800;
bool CavitacaoSuspeitaAtual = false;
bool CavitadaAtual = false;
void ConfigurarBicos(BicoPulverizador_v2** bicos, size_t qtdBicos) {
_bicos = bicos;
_qtdBicos = qtdBicos;
@ -615,6 +636,8 @@ class BombaPressurizadora_v2 : public ComponenteCAN {
PercentualPotenciaLeitura = constrain(PotenciaFinalAtual, 0.0, 100.0);
PotenciaLeitura = (int)round(PercentualPotenciaLeitura);
EstadoLeitura = (PercentualPotenciaLeitura > 2.0) ? Estado::Ligado : Estado::Desligado;
AtualizarDetectorCavitacao();
}
void RequisitarDados() {
@ -694,7 +717,7 @@ class BombaPressurizadora_v2 : public ComponenteCAN {
data.push_back(LimitarByte(PotenciaFinalAtual)); // data[4]
data.push_back(LimitarByte(PressaoSensorAtual)); // data[5]
data.push_back(LimitarByte(PressaoSPControleAtual)); // data[6]
data.push_back(PressaoSPForaDoMapaAtual ? 1 : 0); // data[7]
data.push_back(MontarFlagsDiagnosticoBomba()); // data[7]
break;
}
@ -732,9 +755,18 @@ class BombaPressurizadora_v2 : public ComponenteCAN {
unsigned long _inicioSemFluxoMs = 0;
unsigned long _inicioComFluxoMs = 0;
unsigned long _ultimoComandoLigadoMs = 0;
unsigned long _ultimaMudancaBicosCavitacaoMs = 0;
unsigned long _inicioCondicaoCavitacaoMs = 0;
unsigned long _inicioCondicaoNormalCavitacaoMs = 0;
uint8_t _ultimaQtdBicosCavitacao = 0;
Estado _ultimoEstadoControleCavitacao = Estado::Desligado;
void ResetarControle() {
ResetarIntegralPressao();
ResetarSupervisorFluxo();
ResetarDetectorCavitacao();
ResetarKick();
_ultimoControleMs = 0;
_ultimoTempoDtMs = 0;
@ -760,6 +792,7 @@ class BombaPressurizadora_v2 : public ComponenteCAN {
void ResetarEstadosDeBicosFechados() {
ResetarIntegralPressao();
ResetarSupervisorFluxo();
ResetarDetectorCavitacao();
ResetarKick();
PotenciaFeedForwardAtual = 0.0;
CorrecaoPIAtual = 0.0;
@ -1421,6 +1454,159 @@ class BombaPressurizadora_v2 : public ComponenteCAN {
return (a > b) ? a : b;
}
void ResetarDetectorCavitacao() {
CavitacaoSuspeitaAtual = false;
CavitadaAtual = false;
_inicioCondicaoCavitacaoMs = 0;
_inicioCondicaoNormalCavitacaoMs = 0;
_ultimaMudancaBicosCavitacaoMs = 0;
_ultimoComandoLigadoMs = 0;
_ultimaQtdBicosCavitacao = 0;
_ultimoEstadoControleCavitacao = _EstadoControle;
}
void AtualizarDetectorCavitacao() {
unsigned long agora = millis();
if (!HabilitarDetectorCavitacao) {
ResetarDetectorCavitacao();
return;
}
if (_EstadoControle != _ultimoEstadoControleCavitacao) {
_ultimoEstadoControleCavitacao = _EstadoControle;
if (_EstadoControle == Estado::Ligado) {
_ultimoComandoLigadoMs = agora;
} else {
ResetarDetectorCavitacao();
return;
}
}
if (QtdBicosLigados != _ultimaQtdBicosCavitacao) {
_ultimaQtdBicosCavitacao = QtdBicosLigados;
_ultimaMudancaBicosCavitacaoMs = agora;
_inicioCondicaoCavitacaoMs = 0;
CavitacaoSuspeitaAtual = false;
}
if (_EstadoControle != Estado::Ligado) {
ResetarDetectorCavitacao();
return;
}
if (QtdBicosLigados == 0) {
ResetarDetectorCavitacao();
return;
}
if (!SensorFluxoDisponivel() || sensorPressao == nullptr) {
CavitacaoSuspeitaAtual = false;
CavitadaAtual = false;
_inicioCondicaoCavitacaoMs = 0;
_inicioCondicaoNormalCavitacaoMs = 0;
return;
}
bool emJanelaIgnorada = false;
if (_ultimoComandoLigadoMs > 0 && (agora - _ultimoComandoLigadoMs) < TempoIgnorarAposLigarBombaMs) {
emJanelaIgnorada = true;
}
if (_ultimaMudancaBicosCavitacaoMs > 0 && (agora - _ultimaMudancaBicosCavitacaoMs) < TempoIgnorarAposMudancaBicosMs) {
emJanelaIgnorada = true;
}
if (emJanelaIgnorada) {
_inicioCondicaoCavitacaoMs = 0;
CavitacaoSuspeitaAtual = false;
return;
}
bool bombaRealmenteAtiva =
EstadoLeitura == Estado::Ligado &&
PotenciaFinalAtual >= PotenciaMinimaParaDetectarCavitacaoPct;
bool pressaoMuitoBaixa =
PressaoFiltrada <= PressaoMinimaCavitacaoPsi;
bool pressaoAbaixoDoSP =
_PressaoSP > 0.0 &&
PressaoFiltrada <= (_PressaoSP - MargemPressaoSPCavitacaoPsi);
bool semFluxo =
!FluxoPresenteAtual &&
VazaoFluxoCorrigidaAtualMLs <= VazaoMinimaCavitacaoMLs;
bool condicaoCavitacao =
bombaRealmenteAtiva &&
pressaoMuitoBaixa &&
pressaoAbaixoDoSP &&
semFluxo;
if (condicaoCavitacao) {
if (_inicioCondicaoCavitacaoMs == 0) {
_inicioCondicaoCavitacaoMs = agora;
}
_inicioCondicaoNormalCavitacaoMs = 0;
unsigned long tempoCondicao = agora - _inicioCondicaoCavitacaoMs;
CavitacaoSuspeitaAtual =
tempoCondicao >= TempoParaSuspeitarCavitacaoMs;
if (tempoCondicao >= TempoParaConfirmarCavitacaoMs) {
CavitadaAtual = true;
}
return;
}
_inicioCondicaoCavitacaoMs = 0;
CavitacaoSuspeitaAtual = false;
bool condicaoNormal =
_EstadoControle != Estado::Ligado ||
QtdBicosLigados == 0 ||
FluxoPresenteAtual ||
VazaoFluxoCorrigidaAtualMLs > VazaoMinimaCavitacaoMLs ||
PressaoFiltrada >= (PressaoMinimaCavitacaoPsi + 3.0) ||
PotenciaFinalAtual < PotenciaMinimaParaDetectarCavitacaoPct;
if (CavitadaAtual && condicaoNormal) {
if (_inicioCondicaoNormalCavitacaoMs == 0) {
_inicioCondicaoNormalCavitacaoMs = agora;
}
if ((agora - _inicioCondicaoNormalCavitacaoMs) >= TempoParaLimparCavitacaoMs) {
CavitadaAtual = false;
_inicioCondicaoNormalCavitacaoMs = 0;
}
} else if (!condicaoNormal) {
_inicioCondicaoNormalCavitacaoMs = 0;
}
}
uint8_t MontarFlagsDiagnosticoBomba() {
uint8_t flags = 0;
if (PressaoSPForaDoMapaAtual) flags |= (1 << 0);
if (FluxoInsuficienteAtual) flags |= (1 << 1);
if (RecuperacaoFluxoAtiva) flags |= (1 << 2);
if (CavitacaoSuspeitaAtual) flags |= (1 << 3);
if (CavitadaAtual) flags |= (1 << 4);
if (CorteSegurancaAtivo) flags |= (1 << 5);
if (PressaoSPLimitadoPorCapacidade) flags |= (1 << 6);
return flags;
}
void MostrarLog(String mensagem) {
if (DebugMode) {
PrintTela("[BMB " + _ID + "] " + mensagem);