236 lines
5.9 KiB
C++
236 lines
5.9 KiB
C++
#include "SerialService.h"
|
|
#include "Pinout.h"
|
|
#include "IComponenteCAN.h"
|
|
|
|
#ifndef SensorFluxoModel_v2_h
|
|
#define SensorFluxoModel_v2_h
|
|
|
|
class SensorFluxo_v2 : public ComponenteCAN {
|
|
public:
|
|
SensorFluxo_v2(
|
|
const String& id,
|
|
uint8_t idNum,
|
|
int pino,
|
|
TiposBarramentos barramento = CONTROLADOR
|
|
)
|
|
: _ID(id),
|
|
ID_Num(idNum),
|
|
_pino(pino, barramento, _INPUT_PULLUP, DIGITAL) {
|
|
}
|
|
|
|
String _ID;
|
|
uint8_t ID_Num = 0;
|
|
PinoModel _pino;
|
|
|
|
bool Iniciado = false;
|
|
|
|
unsigned long tempoAnterior = 0;
|
|
unsigned int _Pulsos = 0;
|
|
unsigned long _PeriodoTotal = 0;
|
|
bool ultimaLeitura = false;
|
|
unsigned long _UltimoPulsoMs = 0;
|
|
|
|
unsigned int _PulsosLeitura = 0;
|
|
unsigned long _PeriodoTotalLeitura = 0;
|
|
float _Vazao = 0.0f;
|
|
|
|
// Protege a janela de pulsos e o snapshot contra acessos concorrentes
|
|
// do loop rapido, task de telemetria e controle da bomba.
|
|
portMUX_TYPE _stateMux = portMUX_INITIALIZER_UNLOCKED;
|
|
|
|
void Inicializar() {
|
|
if (Iniciado) {
|
|
MostrarLog("Sensor ja inicializado");
|
|
return;
|
|
}
|
|
|
|
_pino.Conectar();
|
|
Iniciado = _pino.Definido();
|
|
|
|
if (Iniciado) {
|
|
ResetarEstado();
|
|
MostrarLog("Sensor iniciado");
|
|
} else {
|
|
MostrarLog("Sensor nao iniciado");
|
|
}
|
|
}
|
|
|
|
void Desligar() {
|
|
if (!Iniciado) {
|
|
MostrarLog("Sensor nao esta inicializado");
|
|
return;
|
|
}
|
|
|
|
_pino.Desconectar();
|
|
ResetarEstado();
|
|
|
|
_PulsosLeitura = 0;
|
|
_PeriodoTotalLeitura = 0;
|
|
_Vazao = 0.0f;
|
|
Iniciado = false;
|
|
|
|
MostrarLog("Sensor desligado");
|
|
}
|
|
|
|
void Loop() {
|
|
if (!Iniciado) return;
|
|
|
|
bool leituraAtual = (_pino.get() == 1);
|
|
unsigned long tempoAtual = millis();
|
|
|
|
portENTER_CRITICAL(&_stateMux);
|
|
|
|
if (leituraAtual != ultimaLeitura) {
|
|
//MostrarLog("Mudou: ultima=" + String(ultimaLeitura) + " atual=" + String(leituraAtual));
|
|
|
|
if (leituraAtual && !ultimaLeitura) {
|
|
unsigned long intervalo = tempoAtual - tempoAnterior;
|
|
tempoAnterior = tempoAtual;
|
|
|
|
_Pulsos++;
|
|
_PeriodoTotal += intervalo;
|
|
_UltimoPulsoMs = tempoAtual;
|
|
|
|
//MostrarLog("SUBIDA! Pulsos=" + String(_Pulsos) + " Periodo=" + String(_PeriodoTotal) + " Intervalo=" + String(intervalo));
|
|
}
|
|
|
|
ultimaLeitura = leituraAtual;
|
|
}
|
|
|
|
portEXIT_CRITICAL(&_stateMux);
|
|
}
|
|
|
|
void RequisitarDados() {
|
|
AtualizarLeitura();
|
|
}
|
|
|
|
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: {
|
|
unsigned int pulsosLeitura;
|
|
unsigned long periodoLeitura;
|
|
float vazao;
|
|
|
|
portENTER_CRITICAL(&_stateMux);
|
|
pulsosLeitura = _PulsosLeitura;
|
|
periodoLeitura = _PeriodoTotalLeitura;
|
|
vazao = _Vazao;
|
|
portEXIT_CRITICAL(&_stateMux);
|
|
|
|
uint16_t vazaoEscalada = (uint16_t)(vazao * 100.0f);
|
|
|
|
data.push_back((uint8_t)pulsosLeitura);
|
|
data.push_back((uint8_t)(periodoLeitura >> 8));
|
|
data.push_back((uint8_t)(periodoLeitura & 0xFF));
|
|
data.push_back((uint8_t)(vazaoEscalada >> 8));
|
|
data.push_back((uint8_t)(vazaoEscalada & 0xFF));
|
|
break;
|
|
}
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return data;
|
|
}
|
|
|
|
void ObterAmostragemAtual(unsigned int& pulsos, unsigned long& periodoMs) {
|
|
portENTER_CRITICAL(&_stateMux);
|
|
pulsos = _Pulsos;
|
|
periodoMs = _PeriodoTotal;
|
|
portEXIT_CRITICAL(&_stateMux);
|
|
}
|
|
|
|
// Snapshot somente-leitura para a malha rapida da bomba. A bomba nao chama
|
|
// Loop(), nao reinicia a janela e nao disputa a aquisicao do sensor.
|
|
void ObterSnapshotControle(
|
|
unsigned int& pulsos,
|
|
unsigned long& periodoMs,
|
|
unsigned long& ultimoPulsoMs
|
|
) {
|
|
portENTER_CRITICAL(&_stateMux);
|
|
pulsos = _Pulsos;
|
|
periodoMs = _PeriodoTotal;
|
|
ultimoPulsoMs = _UltimoPulsoMs;
|
|
portEXIT_CRITICAL(&_stateMux);
|
|
}
|
|
|
|
private:
|
|
bool DebugMode = false;
|
|
|
|
void AtualizarLeitura() {
|
|
if (!Iniciado) return;
|
|
|
|
unsigned int pulsos;
|
|
unsigned long periodoMs;
|
|
unsigned long agora = millis();
|
|
|
|
portENTER_CRITICAL(&_stateMux);
|
|
pulsos = _Pulsos;
|
|
periodoMs = _PeriodoTotal;
|
|
|
|
_Pulsos = 0;
|
|
_PeriodoTotal = 0;
|
|
tempoAnterior = agora;
|
|
portEXIT_CRITICAL(&_stateMux);
|
|
|
|
float vazao = CalcularVazao(pulsos, periodoMs);
|
|
|
|
portENTER_CRITICAL(&_stateMux);
|
|
_PulsosLeitura = pulsos;
|
|
_PeriodoTotalLeitura = periodoMs;
|
|
_Vazao = vazao;
|
|
portEXIT_CRITICAL(&_stateMux);
|
|
}
|
|
|
|
void ResetarEstado() {
|
|
bool leituraInicial = (_pino.get() == 1);
|
|
portENTER_CRITICAL(&_stateMux);
|
|
_Pulsos = 0;
|
|
_PeriodoTotal = 0;
|
|
tempoAnterior = millis();
|
|
ultimaLeitura = leituraInicial;
|
|
_UltimoPulsoMs = 0;
|
|
portEXIT_CRITICAL(&_stateMux);
|
|
}
|
|
|
|
void ReiniciarAmostragem() {
|
|
portENTER_CRITICAL(&_stateMux);
|
|
_Pulsos = 0;
|
|
_PeriodoTotal = 0;
|
|
tempoAnterior = millis();
|
|
portEXIT_CRITICAL(&_stateMux);
|
|
}
|
|
|
|
float CalcularVazao(uint16_t pulsos, unsigned long periodoMs) {
|
|
if (periodoMs == 0) return 0.0f;
|
|
|
|
float frequenciaHz = ((float)pulsos) * 1000.0f / (float)periodoMs;
|
|
|
|
float q_L_min = (frequenciaHz + 3.0f) / 8.1f;
|
|
if (q_L_min < 0.0f) q_L_min = 0.0f;
|
|
if (q_L_min > 10.0f) q_L_min = 10.0f;
|
|
|
|
float q_mL_s = q_L_min * (1000.0f / 60.0f);
|
|
|
|
return q_mL_s;
|
|
}
|
|
|
|
void MostrarLog(String mensagem) {
|
|
if (DebugMode) {
|
|
PrintTela("[FLX " + _ID + "] " + mensagem);
|
|
}
|
|
}
|
|
};
|
|
|
|
#endif
|