ajustes calculo vazao por fluxo, saude do mov por frequencia por parametro
This commit is contained in:
parent
9b5fdf267f
commit
bbd5f4bfec
|
|
@ -129,16 +129,21 @@ namespace AgroBase.Models.Modules
|
|||
{
|
||||
get
|
||||
{
|
||||
int pulsos = (int)(SensorFluxoLinha?.ValoresLeituras?.FirstOrDefault(x => x.funcao == FuncoesPinout.QtdPulsos)?.atual?.valor ?? 0.0);
|
||||
int pulsos = (int)(SensorFluxoLinha?.ValoresLeituras?
|
||||
.FirstOrDefault(x => x.funcao == FuncoesPinout.QtdPulsos)?
|
||||
.atual?.valor ?? 0.0);
|
||||
|
||||
int periodo = (int)(SensorFluxoLinha?.ValoresLeituras?.FirstOrDefault(x => x.funcao == FuncoesPinout.Periodo)?.atual?.valor ?? 0.0);
|
||||
int periodo = (int)(SensorFluxoLinha?.ValoresLeituras?
|
||||
.FirstOrDefault(x => x.funcao == FuncoesPinout.Periodo)?
|
||||
.atual?.valor ?? 0.0);
|
||||
|
||||
if (pulsos <= 0 || periodo <= 0)
|
||||
return 0.0;
|
||||
|
||||
const double FatorCalibracaoFluxo = 0.776;
|
||||
|
||||
double frequencia = (double)pulsos / periodo * 1000.0;
|
||||
|
||||
// Fabricante: F = 8.1*q - 3, q em L/min
|
||||
double q_L_min = (frequencia + 3.0) / 8.1;
|
||||
|
||||
if (q_L_min < 0)
|
||||
|
|
@ -147,7 +152,7 @@ namespace AgroBase.Models.Modules
|
|||
if (q_L_min > VazaoMaximaSensor_LMin)
|
||||
q_L_min = VazaoMaximaSensor_LMin;
|
||||
|
||||
return q_L_min * 1000.0 / 60.0;
|
||||
return q_L_min * 1000.0 / 60.0 * FatorCalibracaoFluxo;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -235,44 +235,107 @@ namespace AgroBase.Models.Modules
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
private DateTime _ultimoEnvioControleMov = DateTime.MinValue;
|
||||
private DateTime _ultimoRegistroLogMov = DateTime.MinValue;
|
||||
|
||||
private static readonly TimeSpan IntervaloControleMov = TimeSpan.FromSeconds(1);
|
||||
private static readonly TimeSpan IntervaloLogMov = TimeSpan.FromSeconds(1);
|
||||
private async Task tmrRegistradorMOV_Tick()
|
||||
{
|
||||
if (Variaveis.Fechando) return;
|
||||
if (Variaveis.Fechando)
|
||||
return;
|
||||
|
||||
if (!OIDCanService.Iniciado && SerialService.DispositivosMapeados.Any(x => x.Dispositivo == T_Code.Mov))
|
||||
DateTime agora = DateTime.Now;
|
||||
|
||||
if (!OIDCanService.Iniciado &&
|
||||
SerialService.DispositivosMapeados.Any(x => x.Dispositivo == T_Code.Mov))
|
||||
{
|
||||
foreach (var Leitura in OIDCanService.DadosLeitura.Where(x => x.UltimoComandoRecebido.AddSeconds(10) < DateTime.Now))
|
||||
foreach (var leitura in OIDCanService.DadosLeitura
|
||||
.Where(x => x.UltimoComandoRecebido.AddSeconds(10) < agora))
|
||||
{
|
||||
OIDCanService.RequisitarDado(_EnderecoCAN_Tx, _EnderecoCAN_Rx, OIDCanService.OidHandler.OidParametros.CodErro);
|
||||
OIDCanService.RequisitarDado(
|
||||
leitura.EnderecoTx,
|
||||
leitura.EnderecoRx,
|
||||
OIDCanService.OidHandler.OidParametros.CodErro
|
||||
);
|
||||
}
|
||||
|
||||
tmrRegistradorMOV.SetInterval(3000);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
foreach (var Modulo in Modulos)
|
||||
bool deveEnviarControle =
|
||||
_ultimoEnvioControleMov == DateTime.MinValue ||
|
||||
agora - _ultimoEnvioControleMov >= IntervaloControleMov;
|
||||
|
||||
bool deveRegistrarLog =
|
||||
_ultimoRegistroLogMov == DateTime.MinValue ||
|
||||
agora - _ultimoRegistroLogMov >= IntervaloLogMov;
|
||||
|
||||
bool enviouControle = false;
|
||||
bool registrouLog = false;
|
||||
|
||||
var controleMov =
|
||||
deveEnviarControle
|
||||
? Variaveis.OperacaoEmAndamento.Controle.TiposControle?
|
||||
.FirstOrDefault(x => x.Tipo == T_Code.Mov)
|
||||
: null;
|
||||
|
||||
foreach (var modulo in Modulos)
|
||||
{
|
||||
if (Modulo.MovMotor.Inicializado)
|
||||
if (!modulo.MovMotor.Inicializado)
|
||||
continue;
|
||||
|
||||
byte addrTx = modulo.MovMotor._EnderecoCAN_Tx;
|
||||
byte addrRx = modulo.MovMotor._EnderecoCAN_Rx;
|
||||
|
||||
/*
|
||||
* Esse continua em todo tick.
|
||||
* O OIDCanService já segura throttle, pendência e rodízio.
|
||||
*/
|
||||
OIDCanService.RequisitarProximoDado(addrTx, addrRx);
|
||||
|
||||
/*
|
||||
* Desligado por enquanto para aliviar CAN.
|
||||
*/
|
||||
// modulo.MovMotor.RequisitarDadosSensoresExternos();
|
||||
|
||||
/*
|
||||
* Controle só a cada 1s.
|
||||
* Se o EnviarComandoControle já tiver dedupe interno, melhor ainda.
|
||||
*/
|
||||
if (deveEnviarControle && controleMov != null)
|
||||
{
|
||||
byte addrTx = Modulo.MovMotor._EnderecoCAN_Tx;
|
||||
byte addrRx = Modulo.MovMotor._EnderecoCAN_Rx;
|
||||
OIDCanService.RequisitarProximoDado(addrTx, addrRx);
|
||||
Modulo.MovMotor.RequisitarDadosSensoresExternos();
|
||||
modulo.MovMotor.EnviarComandoControle(controleMov.UltimaDirecao);
|
||||
enviouControle = true;
|
||||
}
|
||||
|
||||
var Controle = Variaveis.OperacaoEmAndamento.Controle.TiposControle?.FirstOrDefault(x => x.Tipo == T_Code.Mov);
|
||||
if (Controle != null)
|
||||
{
|
||||
Modulo.MovMotor.EnviarComandoControle(Controle.UltimaDirecao);
|
||||
}
|
||||
/*
|
||||
* Essa leitura é local, pode deixar no tick.
|
||||
*/
|
||||
modulo.MovMotor.ConfigFreio.Leitura =
|
||||
modulo.MovMotor.Leitura?.Freado ?? false;
|
||||
|
||||
Modulo.MovMotor.ConfigFreio.Leitura = Modulo.MovMotor.Leitura?.Freado ?? false;
|
||||
|
||||
Variaveis.OperacaoEmAndamento.DispMvd.Dados.RegistrarLogMov(Modulo);
|
||||
/*
|
||||
* Log só a cada 1s para não virar serragem de JSON.
|
||||
*/
|
||||
if (deveRegistrarLog)
|
||||
{
|
||||
Variaveis.OperacaoEmAndamento.DispMvd.Dados.RegistrarLogMov(modulo);
|
||||
registrouLog = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (enviouControle)
|
||||
_ultimoEnvioControleMov = agora;
|
||||
|
||||
if (registrouLog)
|
||||
_ultimoRegistroLogMov = agora;
|
||||
|
||||
tmrRegistradorMOV.SetInterval(OIDCanService.TaxaAmostragem);
|
||||
|
||||
await Task.CompletedTask;
|
||||
}
|
||||
|
||||
private async Task tmrRegistradorDIR_Tick()
|
||||
|
|
|
|||
|
|
@ -11,8 +11,7 @@ namespace AgroBase.Services
|
|||
{
|
||||
public class OIDCanService
|
||||
{
|
||||
public static List<OIDModel> DadosLeitura =
|
||||
new List<OIDModel>();
|
||||
public static List<OIDModel> DadosLeitura = new List<OIDModel>();
|
||||
|
||||
private static T_Code Dispositivo { get; set; } =
|
||||
T_Code.Oid;
|
||||
|
|
@ -22,72 +21,33 @@ namespace AgroBase.Services
|
|||
|
||||
private static AsyncTaskTimerModel tmrHeartbeat;
|
||||
|
||||
private static readonly object _sync =
|
||||
new object();
|
||||
|
||||
private static readonly HashSet<byte> _handlersRegistrados =
|
||||
new HashSet<byte>();
|
||||
|
||||
private static readonly Dictionary<byte, DateTime>
|
||||
_ultimoEnvioConsultaPorDriver =
|
||||
new Dictionary<byte, DateTime>();
|
||||
|
||||
private static readonly Dictionary<string, DateTime>
|
||||
_ultimoEnvioParametro =
|
||||
new Dictionary<string, DateTime>();
|
||||
|
||||
private static readonly Dictionary<byte, OidParametros>
|
||||
_ultimaConsultaPendente =
|
||||
new Dictionary<byte, OidParametros>();
|
||||
|
||||
private static readonly Dictionary<byte, int>
|
||||
_cursorPollingPorDriver =
|
||||
new Dictionary<byte, int>();
|
||||
|
||||
private static readonly Dictionary<string, string>
|
||||
_ultimoComandoControleAssinatura =
|
||||
new Dictionary<string, string>();
|
||||
|
||||
private static readonly Dictionary<string, DateTime>
|
||||
_ultimoComandoControleQuando =
|
||||
new Dictionary<string, DateTime>();
|
||||
private static readonly object _sync = new object();
|
||||
private static readonly HashSet<byte> _handlersRegistrados = new HashSet<byte>();
|
||||
private static readonly Dictionary<byte, DateTime> _ultimoEnvioConsultaPorDriver = new Dictionary<byte, DateTime>();
|
||||
private static readonly Dictionary<string, DateTime> _ultimoEnvioParametro = new Dictionary<string, DateTime>();
|
||||
private static readonly Dictionary<byte, OidParametros> _ultimaConsultaPendente = new Dictionary<byte, OidParametros>();
|
||||
private static readonly Dictionary<byte, int> _cursorPollingPorDriver = new Dictionary<byte, int>();
|
||||
private static readonly Dictionary<string, string> _ultimoComandoControleAssinatura = new Dictionary<string, string>();
|
||||
private static readonly Dictionary<string, DateTime> _ultimoComandoControleQuando = new Dictionary<string, DateTime>();
|
||||
|
||||
/*
|
||||
* Consultas síncronas do OID respondem sempre com DATA[0]=0x0F.
|
||||
* A diferença fica em DATA[1]. Para evitar confusão no CanService,
|
||||
* enviaremos no máximo uma consulta pendente por driver.
|
||||
*/
|
||||
private static readonly TimeSpan IntervaloMinimoConsultaPorDriver =
|
||||
TimeSpan.FromMilliseconds(120);
|
||||
|
||||
private static readonly TimeSpan IntervaloMinimoMesmoParametro =
|
||||
TimeSpan.FromMilliseconds(300);
|
||||
|
||||
private static readonly TimeSpan JanelaConsultaPendente =
|
||||
TimeSpan.FromMilliseconds(450);
|
||||
|
||||
private static readonly TimeSpan JanelaDedupeComandoControle =
|
||||
TimeSpan.FromMilliseconds(80);
|
||||
|
||||
private static readonly TimeSpan TempoRespostaRecente =
|
||||
TimeSpan.FromSeconds(3);
|
||||
|
||||
private static readonly TimeSpan TempoRemoverDriver =
|
||||
TimeSpan.FromSeconds(15);
|
||||
|
||||
/*
|
||||
* O manual sugere heartbeat com período metade do timeout.
|
||||
* O timer continua em 500ms, mas o payload passa a seguir o manual:
|
||||
* DATA[0] = 0x00.
|
||||
*/
|
||||
private static readonly TimeSpan PeriodoHeartbeat =
|
||||
TimeSpan.FromMilliseconds(500);
|
||||
private static readonly TimeSpan IntervaloMinimoConsultaPorDriver = TimeSpan.FromMilliseconds(120);
|
||||
private static readonly TimeSpan IntervaloMinimoMesmoParametro = TimeSpan.FromMilliseconds(300);
|
||||
private static readonly TimeSpan JanelaConsultaPendente = TimeSpan.FromMilliseconds(450);
|
||||
private static readonly TimeSpan JanelaDedupeComandoControle = TimeSpan.FromMilliseconds(80);
|
||||
private static readonly TimeSpan TempoRespostaRecente = TimeSpan.FromSeconds(3);
|
||||
private static readonly TimeSpan TempoRemoverDriver = TimeSpan.FromSeconds(15);
|
||||
private static readonly TimeSpan PeriodoHeartbeat = TimeSpan.FromMilliseconds(500);
|
||||
|
||||
/*
|
||||
* Polling recomendado. Se outro ponto do sistema ainda chamar
|
||||
* RequisitarDado() em massa, o throttle interno também segura.
|
||||
*/
|
||||
private static readonly OidParametros[] OrdemPolling =
|
||||
public static readonly OidParametros[] OrdemPolling =
|
||||
{
|
||||
OidParametros.VelocidadeAtual,
|
||||
OidParametros.CorrenteMotor,
|
||||
|
|
@ -101,24 +61,264 @@ namespace AgroBase.Services
|
|||
OidParametros.IO_Status,
|
||||
};
|
||||
|
||||
private static readonly Dictionary<OidParametros, TimeSpan>
|
||||
IntervaloParametro =
|
||||
new Dictionary<OidParametros, TimeSpan>
|
||||
private static readonly Dictionary<OidParametros, TimeSpan> IntervaloParametro = new Dictionary<OidParametros, TimeSpan>
|
||||
{
|
||||
{ OidParametros.VelocidadeAtual, TimeSpan.FromMilliseconds(160) },
|
||||
{ OidParametros.CorrenteMotor, TimeSpan.FromMilliseconds(300) },
|
||||
{ OidParametros.CorrenteBarramento, TimeSpan.FromMilliseconds(350) },
|
||||
{ OidParametros.CodErro, TimeSpan.FromMilliseconds(750) },
|
||||
{ OidParametros.Tensao, TimeSpan.FromSeconds(1) },
|
||||
{ OidParametros.Temperatura, TimeSpan.FromSeconds(1) },
|
||||
{ OidParametros.CicloTrabalho, TimeSpan.FromMilliseconds(500) },
|
||||
{ OidParametros.Potencia, TimeSpan.FromMilliseconds(500) },
|
||||
{ OidParametros.PosicaoAbsoluta, TimeSpan.FromMilliseconds(500) },
|
||||
{ OidParametros.PosicaoRelativa, TimeSpan.FromMilliseconds(500) },
|
||||
{ OidParametros.ModoCodificador, TimeSpan.FromSeconds(2) },
|
||||
{ OidParametros.ErroLerCache, TimeSpan.FromSeconds(5) },
|
||||
{ OidParametros.IO_Status, TimeSpan.FromSeconds(2) },
|
||||
};
|
||||
|
||||
|
||||
public class OidParametroHealthConfig
|
||||
{
|
||||
public OidParametros Parametro { get; set; }
|
||||
public string RedisKey { get; set; }
|
||||
|
||||
/*
|
||||
* Frequência esperada para health.
|
||||
* Não precisa ser a frequência máxima possível.
|
||||
* É o que consideramos saudável para operação.
|
||||
*/
|
||||
public double FreqBaseHz { get; set; }
|
||||
|
||||
/*
|
||||
* Abaixo disso começa alerta.
|
||||
* Sugestão: 50% a 60% da base, dependendo da importância.
|
||||
*/
|
||||
public double FreqMinHz { get; set; }
|
||||
|
||||
public bool EmUsoHealth { get; set; } = true;
|
||||
}
|
||||
|
||||
public static readonly Dictionary<OidParametros, OidParametroHealthConfig> HealthParametroConfig = new Dictionary<OidParametros, OidParametroHealthConfig>
|
||||
{
|
||||
/*
|
||||
* Runtime importante.
|
||||
*/
|
||||
{
|
||||
OidParametros.VelocidadeAtual,
|
||||
new OidParametroHealthConfig
|
||||
{
|
||||
{ OidParametros.VelocidadeAtual, TimeSpan.FromMilliseconds(160) },
|
||||
{ OidParametros.CorrenteMotor, TimeSpan.FromMilliseconds(300) },
|
||||
{ OidParametros.CorrenteBarramento, TimeSpan.FromMilliseconds(350) },
|
||||
{ OidParametros.CodErro, TimeSpan.FromMilliseconds(750) },
|
||||
{ OidParametros.Tensao, TimeSpan.FromSeconds(1) },
|
||||
{ OidParametros.Temperatura, TimeSpan.FromSeconds(1) },
|
||||
{ OidParametros.CicloTrabalho, TimeSpan.FromMilliseconds(500) },
|
||||
{ OidParametros.Potencia, TimeSpan.FromMilliseconds(500) },
|
||||
{ OidParametros.PosicaoAbsoluta, TimeSpan.FromMilliseconds(500) },
|
||||
{ OidParametros.PosicaoRelativa, TimeSpan.FromMilliseconds(500) },
|
||||
{ OidParametros.ModoCodificador, TimeSpan.FromSeconds(2) },
|
||||
{ OidParametros.ErroLerCache, TimeSpan.FromSeconds(5) },
|
||||
{ OidParametros.IO_Status, TimeSpan.FromSeconds(2) },
|
||||
};
|
||||
Parametro = OidParametros.VelocidadeAtual,
|
||||
RedisKey = "rpm",
|
||||
FreqBaseHz = 1.0,
|
||||
FreqMinHz = 0.45,
|
||||
EmUsoHealth = true
|
||||
}
|
||||
},
|
||||
{
|
||||
OidParametros.CorrenteMotor,
|
||||
new OidParametroHealthConfig
|
||||
{
|
||||
Parametro = OidParametros.CorrenteMotor,
|
||||
RedisKey = "corrente_motor",
|
||||
FreqBaseHz = 1.0,
|
||||
FreqMinHz = 0.45,
|
||||
EmUsoHealth = true
|
||||
}
|
||||
},
|
||||
{
|
||||
OidParametros.CorrenteBarramento,
|
||||
new OidParametroHealthConfig
|
||||
{
|
||||
Parametro = OidParametros.CorrenteBarramento,
|
||||
RedisKey = "corrente_barramento",
|
||||
FreqBaseHz = 1.0,
|
||||
FreqMinHz = 0.45,
|
||||
EmUsoHealth = true
|
||||
}
|
||||
},
|
||||
|
||||
/*
|
||||
* Estado elétrico/térmico. Pode ser mais lento.
|
||||
*/
|
||||
{
|
||||
OidParametros.Tensao,
|
||||
new OidParametroHealthConfig
|
||||
{
|
||||
Parametro = OidParametros.Tensao,
|
||||
RedisKey = "tensao",
|
||||
FreqBaseHz = 0.5,
|
||||
FreqMinHz = 0.20,
|
||||
EmUsoHealth = true
|
||||
}
|
||||
},
|
||||
{
|
||||
OidParametros.Temperatura,
|
||||
new OidParametroHealthConfig
|
||||
{
|
||||
Parametro = OidParametros.Temperatura,
|
||||
RedisKey = "temperatura",
|
||||
FreqBaseHz = 0.5,
|
||||
FreqMinHz = 0.20,
|
||||
EmUsoHealth = true
|
||||
}
|
||||
},
|
||||
|
||||
/*
|
||||
* Diagnóstico/telemetria secundária.
|
||||
*/
|
||||
{
|
||||
OidParametros.CodErro,
|
||||
new OidParametroHealthConfig
|
||||
{
|
||||
Parametro = OidParametros.CodErro,
|
||||
RedisKey = "erro",
|
||||
FreqBaseHz = 0.5,
|
||||
FreqMinHz = 0.20,
|
||||
EmUsoHealth = true
|
||||
}
|
||||
},
|
||||
{
|
||||
OidParametros.CicloTrabalho,
|
||||
new OidParametroHealthConfig
|
||||
{
|
||||
Parametro = OidParametros.CicloTrabalho,
|
||||
RedisKey = "ciclo_trabalho",
|
||||
FreqBaseHz = 0.5,
|
||||
FreqMinHz = 0.20,
|
||||
EmUsoHealth = true
|
||||
}
|
||||
},
|
||||
{
|
||||
OidParametros.Potencia,
|
||||
new OidParametroHealthConfig
|
||||
{
|
||||
Parametro = OidParametros.Potencia,
|
||||
RedisKey = "potencia",
|
||||
FreqBaseHz = 0.5,
|
||||
FreqMinHz = 0.20,
|
||||
EmUsoHealth = true
|
||||
}
|
||||
},
|
||||
|
||||
/*
|
||||
* Por enquanto, não cobra no health se não for usado.
|
||||
*/
|
||||
{
|
||||
OidParametros.PosicaoAbsoluta,
|
||||
new OidParametroHealthConfig
|
||||
{
|
||||
Parametro = OidParametros.PosicaoAbsoluta,
|
||||
RedisKey = "posicao_absoluta",
|
||||
FreqBaseHz = 0.2,
|
||||
FreqMinHz = 0.08,
|
||||
EmUsoHealth = false
|
||||
}
|
||||
},
|
||||
{
|
||||
OidParametros.IO_Status,
|
||||
new OidParametroHealthConfig
|
||||
{
|
||||
Parametro = OidParametros.IO_Status,
|
||||
RedisKey = "io_status",
|
||||
FreqBaseHz = 0.2,
|
||||
FreqMinHz = 0.08,
|
||||
EmUsoHealth = false
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
public static OidParametroHealthConfig ObterConfigHealth(OidParametros parametro)
|
||||
{
|
||||
if (HealthParametroConfig.TryGetValue(parametro, out var cfg))
|
||||
{
|
||||
return cfg;
|
||||
}
|
||||
|
||||
return new OidParametroHealthConfig
|
||||
{
|
||||
Parametro = parametro,
|
||||
RedisKey = parametro.ToString().ToLowerInvariant(),
|
||||
FreqBaseHz = 0.5,
|
||||
FreqMinHz = 0.2,
|
||||
EmUsoHealth = false
|
||||
};
|
||||
}
|
||||
|
||||
public static double ObterFreqBaseHz(OidParametros parametro)
|
||||
{
|
||||
return ObterConfigHealth(parametro).FreqBaseHz;
|
||||
}
|
||||
|
||||
public static double ObterFreqMinHz(OidParametros parametro)
|
||||
{
|
||||
return ObterConfigHealth(parametro).FreqMinHz;
|
||||
}
|
||||
|
||||
public static bool ParametroEmUsoHealth(OidParametros parametro)
|
||||
{
|
||||
return ObterConfigHealth(parametro).EmUsoHealth;
|
||||
}
|
||||
|
||||
public static double ObterIntervaloPollingParametroMs(OidParametros parametro)
|
||||
{
|
||||
if (IntervaloParametro.TryGetValue(parametro, out TimeSpan intervalo))
|
||||
{
|
||||
return intervalo.TotalMilliseconds;
|
||||
}
|
||||
|
||||
return 500.0;
|
||||
}
|
||||
|
||||
public static (string campo, object valor)[] GerarCamposRedisHealthBase(int enderecoMov)
|
||||
{
|
||||
var campos = new List<(string campo, object valor)>();
|
||||
|
||||
foreach (var kv in HealthParametroConfig)
|
||||
{
|
||||
var cfg = kv.Value;
|
||||
string key = cfg.RedisKey;
|
||||
|
||||
campos.Add((
|
||||
$"{enderecoMov}.freq_base.{key}",
|
||||
cfg.FreqBaseHz
|
||||
));
|
||||
|
||||
campos.Add((
|
||||
$"{enderecoMov}.freq_min.{key}",
|
||||
cfg.FreqMinHz
|
||||
));
|
||||
|
||||
campos.Add((
|
||||
$"{enderecoMov}.freq_uso.{key}",
|
||||
cfg.EmUsoHealth
|
||||
));
|
||||
|
||||
campos.Add((
|
||||
$"{enderecoMov}.polling_ms.{key}",
|
||||
ObterIntervaloPollingParametroMs(kv.Key)
|
||||
));
|
||||
}
|
||||
|
||||
campos.Add((
|
||||
$"{enderecoMov}.polling.intervalo_timer_ms",
|
||||
TaxaAmostragem
|
||||
));
|
||||
|
||||
campos.Add((
|
||||
$"{enderecoMov}.polling.qtd_parametros",
|
||||
OrdemPolling.Length
|
||||
));
|
||||
|
||||
campos.Add((
|
||||
$"{enderecoMov}.polling.ordem",
|
||||
OrdemPolling.Select(x => ObterConfigHealth(x).RedisKey).ToList()
|
||||
));
|
||||
|
||||
return campos.ToArray();
|
||||
}
|
||||
|
||||
|
||||
public static bool Iniciado
|
||||
{
|
||||
|
|
@ -542,47 +742,25 @@ namespace AgroBase.Services
|
|||
|
||||
private static OidParametros? EscolherProximoParametro(byte idTx)
|
||||
{
|
||||
DateTime agora =
|
||||
DateTime.Now;
|
||||
DateTime agora = DateTime.Now;
|
||||
|
||||
int cursor =
|
||||
_cursorPollingPorDriver.TryGetValue(
|
||||
idTx,
|
||||
out int c
|
||||
)
|
||||
? c
|
||||
: 0;
|
||||
int cursor = _cursorPollingPorDriver.TryGetValue(idTx, out int c) ? c : 0;
|
||||
|
||||
for (int tentativa = 0;
|
||||
tentativa < OrdemPolling.Length;
|
||||
tentativa++)
|
||||
for (int tentativa = 0; tentativa < OrdemPolling.Length; tentativa++)
|
||||
{
|
||||
int index =
|
||||
(cursor + tentativa) %
|
||||
OrdemPolling.Length;
|
||||
int index = (cursor + tentativa) % OrdemPolling.Length;
|
||||
|
||||
OidParametros parametro =
|
||||
OrdemPolling[index];
|
||||
OidParametros parametro = OrdemPolling[index];
|
||||
|
||||
string chave =
|
||||
idTx.ToString("X2") +
|
||||
":" +
|
||||
((byte)parametro).ToString("X2");
|
||||
string chave = idTx.ToString("X2") + ":" + ((byte)parametro).ToString("X2");
|
||||
|
||||
TimeSpan intervalo =
|
||||
IntervaloParametro.TryGetValue(
|
||||
parametro,
|
||||
out TimeSpan valor
|
||||
)
|
||||
? valor
|
||||
: TimeSpan.FromMilliseconds(500);
|
||||
TimeSpan intervalo = IntervaloParametro.TryGetValue(parametro, out TimeSpan valor)
|
||||
? valor
|
||||
: TimeSpan.FromMilliseconds(500);
|
||||
|
||||
if (!_ultimoEnvioParametro.TryGetValue(chave, out DateTime ultimo) ||
|
||||
agora - ultimo >= intervalo)
|
||||
if (!_ultimoEnvioParametro.TryGetValue(chave, out DateTime ultimo) || agora - ultimo >= intervalo)
|
||||
{
|
||||
_cursorPollingPorDriver[idTx] =
|
||||
(index + 1) %
|
||||
OrdemPolling.Length;
|
||||
_cursorPollingPorDriver[idTx] = (index + 1) % OrdemPolling.Length;
|
||||
|
||||
return parametro;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -424,13 +424,20 @@ namespace AgroBase.Services.Operadores
|
|||
);
|
||||
|
||||
int endereco_mov = mod.MovMotor._EnderecoCAN_Tx;
|
||||
RedisService.AtualizarCampos(
|
||||
RedisService.ModKey(Enums.T_Code.Mov),
|
||||
var camposMov = new List<(string campo, object valor)>
|
||||
{
|
||||
($"{endereco_mov}.timestamp", agora),
|
||||
($"{endereco_mov}.conectado", mod.MovMotor.Inicializado),
|
||||
($"{endereco_mov}.freq_base", 1),
|
||||
|
||||
// legado
|
||||
($"{endereco_mov}.freq_base",
|
||||
OIDCanService.ObterFreqBaseHz(
|
||||
OIDCanService.OidHandler.OidParametros.VelocidadeAtual
|
||||
)),
|
||||
|
||||
($"{endereco_mov}.endereco", mod.MovMotor._EnderecoCAN_Tx),
|
||||
($"{endereco_mov}.mod_id", mod.Modulo_ID),
|
||||
|
||||
($"{endereco_mov}.cod_erro", mod.MovMotor.CodigoAlarme),
|
||||
($"{endereco_mov}.rpm", mod.MovMotor.RPM_Roda),
|
||||
($"{endereco_mov}.rpm_sp", mod.MovMotor.RPM_SP_Leitura),
|
||||
|
|
@ -440,12 +447,21 @@ namespace AgroBase.Services.Operadores
|
|||
($"{endereco_mov}.temperatura_driver", mod.MovMotor.TemperaturaDriver),
|
||||
($"{endereco_mov}.temperatura_motor", mod.MovMotor.Temperatura),
|
||||
($"{endereco_mov}.freado", mod.MovMotor.Leitura?.Freado ?? false),
|
||||
|
||||
($"{endereco_mov}.freq.erro", mod.MovMotor.Leitura?.CodigoAlarme?.frequencia ?? 0),
|
||||
($"{endereco_mov}.freq.rpm", mod.MovMotor.Leitura?.ERPM?.frequencia ?? 0),
|
||||
($"{endereco_mov}.freq.tensao", mod.MovMotor.Leitura?.Tensao?.frequencia ?? 0),
|
||||
($"{endereco_mov}.freq.corrente_motor", mod.MovMotor.Leitura?.CorrenteMotor?.frequencia ?? 0),
|
||||
($"{endereco_mov}.freq.corrente_barramento", mod.MovMotor.Leitura?.CorrenteBarramento?.frequencia ?? 0),
|
||||
($"{endereco_mov}.freq.temperatura", mod.MovMotor.Leitura?.Temperatura?.frequencia ?? 0)
|
||||
($"{endereco_mov}.freq.temperatura", mod.MovMotor.Leitura?.Temperatura?.frequencia ?? 0),
|
||||
|
||||
($"{endereco_mov}.freq.ciclo_trabalho", mod.MovMotor.Leitura?.CicloTrabalho?.frequencia ?? 0),
|
||||
($"{endereco_mov}.freq.potencia", mod.MovMotor.Leitura?.Potencia?.frequencia ?? 0),
|
||||
};
|
||||
camposMov.AddRange(OIDCanService.GerarCamposRedisHealthBase(endereco_mov));
|
||||
RedisService.AtualizarCampos(
|
||||
RedisService.ModKey(Enums.T_Code.Mov),
|
||||
camposMov.ToArray()
|
||||
);
|
||||
|
||||
dirAtivos.Add(endereco_dir);
|
||||
|
|
|
|||
|
|
@ -152,6 +152,8 @@ class SensorFluxo_v2 : public ComponenteCAN {
|
|||
float CalcularVazao(uint16_t pulsos, unsigned long periodoMs) {
|
||||
if (periodoMs == 0) return 0.0f;
|
||||
|
||||
const float FATOR_CALIBRACAO_FLUXO = 0.776f;
|
||||
|
||||
float frequenciaHz = ((float)pulsos) * 1000.0f / (float)periodoMs;
|
||||
|
||||
float q_L_min = (frequenciaHz + 3.0f) / 8.1f;
|
||||
|
|
@ -159,6 +161,9 @@ class SensorFluxo_v2 : public ComponenteCAN {
|
|||
if (q_L_min > 10.0f) q_L_min = 10.0f;
|
||||
|
||||
float q_mL_s = q_L_min * (1000.0f / 60.0f);
|
||||
|
||||
q_mL_s *= FATOR_CALIBRACAO_FLUXO;
|
||||
|
||||
return q_mL_s;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue