Implementado CoolerControl
This commit is contained in:
parent
e14e6c343d
commit
2fddd47b02
|
|
@ -574,6 +574,7 @@
|
|||
<Compile Include="Services\CameraService.cs" />
|
||||
<Compile Include="Services\CANService.cs" />
|
||||
<Compile Include="Services\CANServiceWaveshare.cs" />
|
||||
<Compile Include="Services\CoolerControlService.cs" />
|
||||
<Compile Include="Services\CoulombCounterService.cs" />
|
||||
<Compile Include="Services\DispositivosService.cs" />
|
||||
<Compile Include="Forms\frmPrincipal.cs">
|
||||
|
|
|
|||
|
|
@ -224,7 +224,9 @@ namespace AgroBase.Models.Modules
|
|||
_EnderecoCAN_Rx = 0x12,
|
||||
_TaxaAmostragem = 1000,
|
||||
RequisitarDados = true,
|
||||
// 71 ~ 74
|
||||
BicosPulverizadores = new List<AtuadorBicoModel>(),
|
||||
// 51 ~ 51
|
||||
BombasPressurizadoras = new List<AtuadorBombaModel>()
|
||||
{
|
||||
new AtuadorBombaModel()
|
||||
|
|
@ -277,6 +279,7 @@ namespace AgroBase.Models.Modules
|
|||
}
|
||||
}
|
||||
},
|
||||
// 61 ~ 66
|
||||
Sensores = new List<SensorModel>()
|
||||
{
|
||||
new SensorModel()
|
||||
|
|
@ -418,7 +421,6 @@ namespace AgroBase.Models.Modules
|
|||
}
|
||||
}
|
||||
},
|
||||
|
||||
new SensorModel()
|
||||
{
|
||||
ID = "MAGESQ",
|
||||
|
|
@ -584,9 +586,6 @@ namespace AgroBase.Models.Modules
|
|||
},
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
|
||||
},
|
||||
};
|
||||
for (int i = 0; i < Variaveis.OperacaoEmAndamento.Parametros.QtdBicos; i++)
|
||||
|
|
|
|||
|
|
@ -431,7 +431,8 @@ namespace AgroBase.Models.Modules
|
|||
PressaoSP,
|
||||
CodAlarme,
|
||||
LeituraBruta,
|
||||
LeituraAngulo
|
||||
LeituraAngulo,
|
||||
Cooler
|
||||
}
|
||||
|
||||
public static class PinoutUtils
|
||||
|
|
|
|||
|
|
@ -73,6 +73,7 @@ namespace AgroBase.Models.Modules
|
|||
power = LoRaBaseService.CodigosPowers[22],
|
||||
};
|
||||
public CoulombCounterService ContadorCarga = new CoulombCounterService(VariaveisEquipamento.CorrenteMaximaBateria);
|
||||
public CoolerControlService CoolerControl = new CoolerControlService();
|
||||
public AsyncTaskTimerModel tmrRegistrador;
|
||||
private int _TempoReconexaoComponentes = 5;
|
||||
private int _VezesLeituraReconexao = 0;
|
||||
|
|
@ -87,6 +88,7 @@ namespace AgroBase.Models.Modules
|
|||
RequisitarDados = true,
|
||||
CameraCaminho = new OAKCameraModel(),
|
||||
CamerasSolo = new List<OAKCameraModel>(),
|
||||
// 21 ~ 23
|
||||
Sinaleiros = new List<SensorSinaleiroModel>()
|
||||
{
|
||||
new SensorSinaleiroModel()
|
||||
|
|
@ -191,6 +193,7 @@ namespace AgroBase.Models.Modules
|
|||
},
|
||||
Sensores = new List<SensorModel>()
|
||||
{
|
||||
// sTMP 1 ~ 5
|
||||
new SensorModel()
|
||||
{
|
||||
ID = "TMVET",
|
||||
|
|
@ -411,6 +414,7 @@ namespace AgroBase.Models.Modules
|
|||
}
|
||||
}
|
||||
},
|
||||
// sCOR 11 ~ 17
|
||||
new SensorModel()
|
||||
{
|
||||
ID = "AB3V",
|
||||
|
|
@ -1122,6 +1126,7 @@ namespace AgroBase.Models.Modules
|
|||
}
|
||||
}
|
||||
},
|
||||
// Torre 31 ~ 37
|
||||
new SensorModel()
|
||||
{
|
||||
ID = "LUZABT",
|
||||
|
|
@ -1517,7 +1522,7 @@ namespace AgroBase.Models.Modules
|
|||
}
|
||||
}
|
||||
},
|
||||
|
||||
// sMAG 91 ~ 94
|
||||
new SensorModel()
|
||||
{
|
||||
ID = "MAGET",
|
||||
|
|
@ -1740,6 +1745,7 @@ namespace AgroBase.Models.Modules
|
|||
},
|
||||
|
||||
},
|
||||
// 41 ~ 44
|
||||
Servos = new List<SensorServoModel>()
|
||||
{
|
||||
new SensorServoModel()
|
||||
|
|
@ -1867,7 +1873,68 @@ namespace AgroBase.Models.Modules
|
|||
}
|
||||
},
|
||||
},
|
||||
Reles = new List<SensorReleModel>(),
|
||||
// 81 ~ 82
|
||||
Reles = new List<SensorReleModel>()
|
||||
{
|
||||
new SensorReleModel()
|
||||
{
|
||||
ID = "RLCIN",
|
||||
ID_Num = 81,
|
||||
Descricao = "Rele Cooler Entrada",
|
||||
Componente = S_Code.sRLE,
|
||||
Controlar = true,
|
||||
Mandatorio = false,
|
||||
Funcoes = new List<FuncoesPinout>()
|
||||
{
|
||||
FuncoesPinout.Cooler,
|
||||
},
|
||||
AtuacaoNivelAlto = true,
|
||||
ValoresLeituras = new List<SensorValoresLeituraModel>()
|
||||
{
|
||||
new SensorValoresLeituraModel()
|
||||
{
|
||||
funcao = FuncoesPinout.Iniciado,
|
||||
posicao = CanMessagePosicaoDados.Status,
|
||||
indice = 0,
|
||||
},
|
||||
new SensorValoresLeituraModel()
|
||||
{
|
||||
funcao = FuncoesPinout.EstadoLeitura,
|
||||
posicao = CanMessagePosicaoDados.Dados1,
|
||||
indice = 0,
|
||||
},
|
||||
}
|
||||
},
|
||||
new SensorReleModel()
|
||||
{
|
||||
ID = "RLCOUT",
|
||||
ID_Num = 82,
|
||||
Descricao = "Rele Cooler Saida",
|
||||
Componente = S_Code.sRLE,
|
||||
Controlar = true,
|
||||
Mandatorio = false,
|
||||
Funcoes = new List<FuncoesPinout>()
|
||||
{
|
||||
FuncoesPinout.Cooler,
|
||||
},
|
||||
AtuacaoNivelAlto = true,
|
||||
ValoresLeituras = new List<SensorValoresLeituraModel>()
|
||||
{
|
||||
new SensorValoresLeituraModel()
|
||||
{
|
||||
funcao = FuncoesPinout.Iniciado,
|
||||
posicao = CanMessagePosicaoDados.Status,
|
||||
indice = 0,
|
||||
},
|
||||
new SensorValoresLeituraModel()
|
||||
{
|
||||
funcao = FuncoesPinout.EstadoLeitura,
|
||||
posicao = CanMessagePosicaoDados.Dados1,
|
||||
indice = 0,
|
||||
},
|
||||
}
|
||||
},
|
||||
},
|
||||
loRaService = new LoRaEspService()
|
||||
{
|
||||
ID = "LoRa",
|
||||
|
|
@ -2256,7 +2323,7 @@ namespace AgroBase.Models.Modules
|
|||
GeneralJoystick.EnviarComandoSensoriamento(S_Code.sLED, ledMN.ID, ledMN.Comportamento);
|
||||
}
|
||||
|
||||
foreach (var rele in Reles.Where(x => x.Controlar && x.Inicializado && !x.ControleExterno))
|
||||
foreach (var rele in Reles.Where(x => x.Controlar && x.Inicializado))
|
||||
{
|
||||
int leituraEstado = (int?)(rele.ValoresLeituras.FirstOrDefault(x => x.funcao == FuncoesPinout.EstadoLeitura)?.atual?.valor) ?? 0;
|
||||
if (leituraEstado != (int)rele.StatusControle)
|
||||
|
|
@ -2484,7 +2551,6 @@ namespace AgroBase.Models.Modules
|
|||
public string Descricao { get; set; }
|
||||
public S_Code Componente { get; set; }
|
||||
public List<FuncoesPinout> Funcoes { get; set; }
|
||||
public bool ControleExterno { get; set; }
|
||||
public bool Controlar { get; set; }
|
||||
public bool Mandatorio { get; set; }
|
||||
public bool Liberado
|
||||
|
|
|
|||
|
|
@ -2330,6 +2330,8 @@ namespace AgroBase.Models
|
|||
var _Bateria = _DispSen?.Dados?.ContadorCarga;
|
||||
var _Reservatorio = _DispAtu?.Dados?.ContadorCarga;
|
||||
|
||||
double tmp_max = Math.Max(Variaveis.OperacaoEmAndamento.DadosPerformance?.GPU_temp ?? 0, Variaveis.OperacaoEmAndamento.DadosPerformance?.CPU_temp ?? 0);
|
||||
_DispSen?.Dados?.CoolerControl?.Atualizar(tmp_max);
|
||||
_DispMvd?.Dados?.AtualizarDadosFreio();
|
||||
_Bateria?.AtualizarConsumo(_DispMvd?.Dados?.DistanciaPercorridaTotal ?? 0);
|
||||
_Reservatorio?.AtualizarConsumo(_DispMvd?.Dados?.DistanciaPercorridaTotal ?? 0, Variaveis.OperacaoEmAndamento.TempoDecorridoSegs);
|
||||
|
|
@ -2565,9 +2567,11 @@ namespace AgroBase.Models
|
|||
public OperacaoSensoriamentoLogModel Clone(bool comSonar = false)
|
||||
{
|
||||
var vw = OperadorVisual?.Clone();
|
||||
vw.CameraFrames = new Dictionary<CameraFrameType, OAKCameraFrameModel>();
|
||||
if (vw != null)
|
||||
vw.CameraFrames = new Dictionary<CameraFrameType, OAKCameraFrameModel>();
|
||||
var ww = OperadorErvas?.Clone();
|
||||
ww.CameraFrames = new Dictionary<CameraFrameType, OAKCameraFrameModel>();
|
||||
if (ww != null)
|
||||
ww.CameraFrames = new Dictionary<CameraFrameType, OAKCameraFrameModel>();
|
||||
|
||||
return new OperacaoSensoriamentoLogModel()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -0,0 +1,135 @@
|
|||
using AgroBase.Models;
|
||||
using AgroBase.Models.Modules;
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace AgroBase.Services
|
||||
{
|
||||
public class CoolerControlService
|
||||
{
|
||||
// Config
|
||||
public double TempOn { get; set; } = 30.0; // Liga ventilação básica
|
||||
public double TempTurbo { get; set; } = 35.0; // Liga entrada+saída
|
||||
public double TempCritical { get; set; } = 45.0; // Acima disso, alerta
|
||||
public double Histerese { get; set; } = 1.5; // Para evitar chattering
|
||||
|
||||
public TimeSpan MinOnTime { get; set; } = TimeSpan.FromSeconds(30);
|
||||
public TimeSpan MinOffTime { get; set; } = TimeSpan.FromSeconds(30);
|
||||
|
||||
// Filtro de temperatura (EMA)
|
||||
public double AlphaFiltro { get; set; } = 0.2;
|
||||
|
||||
// Estado interno
|
||||
public CoolerMode ModoAtual { get; private set; } = CoolerMode.Off;
|
||||
public Enums.Estado CoolerEntradaEstado => ModoAtual == CoolerMode.IntakeAndExhaust ? Enums.Estado.Ligado : Enums.Estado.Desligado;
|
||||
public Enums.Estado CoolerSaidaEstado => ModoAtual == CoolerMode.ExhaustOnly || ModoAtual == CoolerMode.IntakeAndExhaust ? Enums.Estado.Ligado : Enums.Estado.Desligado;
|
||||
|
||||
public double? TemperaturaFiltrada { get; private set; }
|
||||
public DateTime UltimaMudancaModo { get; private set; } = DateTime.MinValue;
|
||||
|
||||
public bool AlertaTemperaturaCritica { get; private set; }
|
||||
|
||||
private SensorReleModel ReleCoolerEntrada
|
||||
{
|
||||
get
|
||||
{
|
||||
var sRLE = Variaveis.OperacaoEmAndamento.DispSen?.Dados?.Reles?.FirstOrDefault(x => x.ID == "RLCIN" && x.Inicializado && x.Controlar);
|
||||
return sRLE;
|
||||
}
|
||||
}
|
||||
|
||||
private SensorReleModel ReleCoolerSaida
|
||||
{
|
||||
get
|
||||
{
|
||||
var sRLE = Variaveis.OperacaoEmAndamento.DispSen?.Dados?.Reles?.FirstOrDefault(x => x.ID == "RLCOUT" && x.Inicializado && x.Controlar);
|
||||
return sRLE;
|
||||
}
|
||||
}
|
||||
|
||||
public CoolerControlService()
|
||||
{
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
ModoAtual = CoolerMode.Off;
|
||||
TemperaturaFiltrada = null;
|
||||
UltimaMudancaModo = DateTime.MinValue;
|
||||
AlertaTemperaturaCritica = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Chamar a cada tick de atualização com a temperatura interna atual
|
||||
/// </summary>
|
||||
public void Atualizar(double temperaturaAtual_C)
|
||||
{
|
||||
DateTime agora = DateTime.Now;
|
||||
|
||||
// 1) Filtrar temperatura (EMA)
|
||||
if (TemperaturaFiltrada == null)
|
||||
{
|
||||
TemperaturaFiltrada = temperaturaAtual_C;
|
||||
}
|
||||
else
|
||||
{
|
||||
TemperaturaFiltrada = AlphaFiltro * temperaturaAtual_C + (1 - AlphaFiltro) * TemperaturaFiltrada.Value;
|
||||
}
|
||||
|
||||
var temp = TemperaturaFiltrada.Value;
|
||||
|
||||
// 2) Verificar limite crítico (para health_worker)
|
||||
AlertaTemperaturaCritica = temp >= TempCritical;
|
||||
|
||||
// 3) Respeitar permanência mínima de estado
|
||||
var tempoNoModoAtual = agora - UltimaMudancaModo;
|
||||
bool podeMudar =
|
||||
(ModoAtual == CoolerMode.Off && tempoNoModoAtual >= MinOffTime) ||
|
||||
(ModoAtual != CoolerMode.Off && tempoNoModoAtual >= MinOnTime);
|
||||
|
||||
if (!podeMudar)
|
||||
return;
|
||||
|
||||
// 4) Lógica com histerese
|
||||
CoolerMode novoModo = ModoAtual;
|
||||
|
||||
switch (ModoAtual)
|
||||
{
|
||||
case CoolerMode.Off:
|
||||
if (temp >= TempOn + Histerese)
|
||||
novoModo = CoolerMode.ExhaustOnly;
|
||||
break;
|
||||
|
||||
case CoolerMode.ExhaustOnly:
|
||||
if (temp <= TempOn - Histerese)
|
||||
novoModo = CoolerMode.Off;
|
||||
else if (temp >= TempTurbo + Histerese)
|
||||
novoModo = CoolerMode.IntakeAndExhaust;
|
||||
break;
|
||||
|
||||
case CoolerMode.IntakeAndExhaust:
|
||||
if (temp <= TempTurbo - Histerese)
|
||||
novoModo = CoolerMode.ExhaustOnly;
|
||||
break;
|
||||
}
|
||||
|
||||
if (novoModo != ModoAtual)
|
||||
{
|
||||
ModoAtual = novoModo;
|
||||
UltimaMudancaModo = agora;
|
||||
|
||||
if (ReleCoolerEntrada != null)
|
||||
GeneralJoystick.EnviarComandoSensoriamento(ReleCoolerEntrada.Componente, ReleCoolerEntrada.ID, CoolerEntradaEstado);
|
||||
if (ReleCoolerSaida != null)
|
||||
GeneralJoystick.EnviarComandoSensoriamento(ReleCoolerSaida.Componente, ReleCoolerSaida.ID, CoolerSaidaEstado);
|
||||
}
|
||||
}
|
||||
|
||||
public enum CoolerMode
|
||||
{
|
||||
Off,
|
||||
ExhaustOnly,
|
||||
IntakeAndExhaust
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -8,7 +8,7 @@ namespace AgroBase.Services
|
|||
{
|
||||
public class HerbicideCounterService
|
||||
{
|
||||
public HerbicideCounterService(double capacidadeLitros, double densidadeProduto, double l_m_base = 0.1188) // 3km/h ~ 3x 35 ml/s
|
||||
public HerbicideCounterService(double capacidadeLitros, double densidadeProduto, double l_m_base = 0.1188) // 3km/h ~ 3x 33 ml/s
|
||||
{
|
||||
CapacidadeLitros = capacidadeLitros;
|
||||
VolumeAtual_L = 0;
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -558,11 +558,11 @@ namespace OperationControl.Windows
|
|||
break;
|
||||
case AgroBase.Models.Enums.T_Code.Bat:
|
||||
iniciado = rover.DadosLeitura?.Bateria?.Iniciado ?? false;
|
||||
mod_label = "Bateria";
|
||||
//mod_label = "Bateria";
|
||||
break;
|
||||
case AgroBase.Models.Enums.T_Code.Trj:
|
||||
iniciado = rover.DadosLeitura?.Trajetoria?.QtdPontos > 0;
|
||||
mod_label = "Trajetória";
|
||||
//mod_label = "Trajetória";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -248,6 +248,7 @@ void ProcessarCmd(std::vector<uint8_t> data) {
|
|||
switch (componente) {
|
||||
case sBIC: {
|
||||
Rele::ComandarRele(listaBicos, data);
|
||||
ComponenteCAN::ProcessarComponentesCAN(listaBicos, {}, false, id, false, false, CanMessagePosicaoDados::Dados1, EnviarDadosCAN);
|
||||
break;
|
||||
}
|
||||
case sBMB: {
|
||||
|
|
|
|||
Loading…
Reference in New Issue