agrobot_base/Firmware/Modulos/SensorFluxoModel.h

215 lines
5.7 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "SerialService.h"
#include "Pinout.h"
#include "IComponenteCAN.h"
#ifndef SensorFluxoModel
#define SensorFluxoModel
class SensorFluxo : public ComponenteCAN {
public:
SensorFluxo(String _modID, String _id) {
Mod_ID = _modID;
_ID = _id;
}
// Definições
String Mod_ID = "";
String _ID;
int ID_Num;
PinoModel _pino;
unsigned long tempoAnterior = 0;
unsigned int _Pulsos = 0;
unsigned long _PeriodoTotal = 0;
bool ultimaLeitura = false;
bool Iniciado = false;
// Consumo
unsigned int _PulsosLeitura = 0;
unsigned long _PeriodoTotalLeitura = 0;
float _Vazao = 0;
void Inicializar() {
if (Iniciado) {
PrintTela(_ID + " ja inicializado");
return;
}
_pino.Conectar();
Iniciado = _pino.Definido();
if (Iniciado) {
ResetarEstado();
PrintTela(_ID + " iniciado");
}
else {
PrintTela(_ID + " nao iniciado");
}
}
void Desligar() {
if (!Iniciado) {
PrintTela(_ID + " nao esta inicializado");
return;
}
// Redefinir as configurações para os valores iniciais
_pino.Desconectar();
ResetarEstado();
PrintTela(_ID + " Desligado");
Iniciado = false;
}
void RequisitarDados() {
AtualizarLeitura();
}
void Loop() {
if (Iniciado) {
bool Leitura = _pino.get() == 1;
if (Leitura != ultimaLeitura) {
if (Leitura && !ultimaLeitura) {
unsigned long tempoAtual = millis();
unsigned long intervalo = (unsigned long)(tempoAtual - tempoAnterior); // Garante cálculo correto
tempoAnterior = tempoAtual;
_Pulsos++;
_PeriodoTotal += intervalo;
}
ultimaLeitura = Leitura;
}
}
}
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: {
uint16_t vazaoEscalada = (uint16_t)(_Vazao * 100);
data.push_back(_PulsosLeitura);
data.push_back((uint8_t)(_PeriodoTotalLeitura >> 8)); data.push_back((uint8_t)(_PeriodoTotalLeitura & 0xFF));
data.push_back(vazaoEscalada >> 8); data.push_back(vazaoEscalada & 0xFF);
break;
}
}
return data;
}
static std::vector<uint8_t> ConfigurarSensor(std::vector<SensorFluxo*>& lista, std::vector<uint8_t>& data, const String& Mod_ID) {
std::vector<uint8_t> status;
if (data.size() < 2) return status;
CanMessagePosicaoDados posicao = (CanMessagePosicaoDados)data[0];
uint8_t idNum = data[1];
auto it = std::find_if(lista.begin(), lista.end(), [idNum](SensorFluxo* s) { return s->ID_Num == idNum; });
bool jaExiste = it != lista.end();
SensorFluxo* sensor;
switch (posicao) {
case CanMessagePosicaoDados::Config1: {
if (data.size() < 5) return status;
bool conectar = data[3] == 1;
int pino = data[4];
if (conectar) {
if (!jaExiste) {
sensor = new SensorFluxo(Mod_ID, "sFLX_" + String(idNum));
}
else {
sensor = *it;
}
if (!sensor->Iniciado) {
sensor->ID_Num = idNum;
sensor->_pino = PinoModel(pino, CONTROLADOR, _INPUT, DIGITAL);
sensor->Inicializar();
if (!jaExiste) {
lista.push_back(sensor);
PrintTela("Sensor de Fluxo adicionado via CAN: sFLX_" + String(idNum));
}
}
status = sensor->MontarMensagemCAN(CanMessagePosicaoDados::Status);
} else {
if (jaExiste) {
sensor = *it;
sensor->Desligar();
status = sensor->MontarMensagemCAN(CanMessagePosicaoDados::Status);
delete sensor;
lista.erase(it);
PrintTela("Sensor de Fluxo removido via CAN: sFLX_" + String(idNum));
}
}
break;
}
}
return status;
}
private:
void AtualizarLeitura() {
if (Iniciado) {
_PulsosLeitura = _Pulsos;
_PeriodoTotalLeitura = _PeriodoTotal;
_Vazao = CalcularVazao(_Pulsos, _PeriodoTotal);
ReiniciarAmostragem();
}
}
// Reseta o estado do sensor
void ResetarEstado() {
_Pulsos = 0;
_PeriodoTotal = 0;
tempoAnterior = millis();
ultimaLeitura = _pino.get() == 1;
}
// Reinicia amostragem
void ReiniciarAmostragem() {
// Reseta os valores para a próxima amostragem
_Pulsos = 0;
_PeriodoTotal = 0;
}
float CalcularVazao(uint16_t pulsos, unsigned long periodoMs) {
if (periodoMs == 0) return 0.0f; // evita divisão por zero
// F = pulsos / (periodoMs/1000) => Hz
float F = ((float)pulsos) * 1000.0f / (float)periodoMs;
// Equação do anúncio: F = 8.1*q - 3 (q em L/min)
float q_L_min = (F + 3.0f) / 8.1f;
// evita valores negativos perto do zero (offset -3)
if (q_L_min < 0.0f) q_L_min = 0.0f;
// limites do sensor informados: 0.310 L/min (opcional "clamp")
// se você quiser respeitar mínimo físico, pode usar 0.3f ao invés de 0.0f
if (q_L_min > 10.0f) q_L_min = 10.0f;
// L/min -> mL/s (1 L = 1000 mL; 1 min = 60 s)
float q_mL_s = q_L_min * (1000.0f / 60.0f);
return q_mL_s;
}
};
#endif