agrobot_base/Firmware/Modulos/SensorChaveBotaoModel.h

182 lines
4.2 KiB
C++

#include "SerialService.h"
#include "Pinout.h"
#include "Utils.h"
#include "IComponenteCAN.h"
#ifndef SensorChaveBotaoModel
#define SensorChaveBotaoModel
class SensorChaveBotao : public ComponenteCAN {
public:
String ID;
uint8_t ID_Num = 0;
PinoModel _pino;
bool Iniciado = false;
// Leitura bruta do pino
bool LeituraBruta = false;
// Resultado final já considerando inversão e debounce
bool Pressionado = false;
// Estado anterior estável
bool PressionadoAnterior = false;
// Flag útil para detectar borda
bool MudouEstado = false;
// Configuração
bool InverterLogica = true;
bool UsarDebounce = true;
unsigned long TempoDebounceMs = 50;
SensorChaveBotao() {}
SensorChaveBotao(
const String& id,
uint8_t idNum,
int pino,
TiposBarramentos tipoBarramento,
int canalMux = -1,
bool inverterLogica = true,
bool usarDebounce = true,
unsigned long tempoDebounceMs = 50
) :
ID(id),
ID_Num(idNum),
_pino(PinoModel(pino, tipoBarramento, _INPUT_PULLUP, DIGITAL, idNum, canalMux)),
InverterLogica(inverterLogica),
UsarDebounce(usarDebounce),
TempoDebounceMs(tempoDebounceMs)
{
}
void Inicializar() {
if (Iniciado) {
MostrarLog("Sensor ja inicializado");
return;
}
LeituraBruta = false;
Pressionado = false;
PressionadoAnterior = false;
MudouEstado = false;
ultimaLeituraTratada = false;
ultimaLeituraInstavel = false;
ultimoTempoMudanca = 0;
_pino.Conectar();
Iniciado = _pino.Definido();
if (Iniciado) {
RequisitarDados();
}
MostrarLog(Iniciado ? "Sensor iniciado" : "Sensor nao iniciado");
}
void Desligar() {
if (!Iniciado) {
MostrarLog("Sensor nao esta inicializado");
return;
}
_pino.Desconectar();
Iniciado = false;
LeituraBruta = false;
Pressionado = false;
PressionadoAnterior = false;
MudouEstado = false;
MostrarLog("Sensor desligado");
}
void RequisitarDados() {
if (!Iniciado) return;
AferirEstado();
}
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: {
RequisitarDados();
data.push_back(Pressionado ? 1 : 0);
data.push_back(LeituraBruta ? 1 : 0);
data.push_back(MudouEstado ? 1 : 0);
break;
}
}
return data;
}
private:
bool DebugMode = false;
bool ultimaLeituraTratada = false;
bool ultimaLeituraInstavel = false;
unsigned long ultimoTempoMudanca = 0;
void MostrarLog(String mensagem) {
if (DebugMode) {
PrintTela("[BTN " + ID + "] " + mensagem);
}
}
void AferirEstado() {
int leituraDigital = _pino.get(1);
LeituraBruta = leituraDigital > 0;
bool leituraTratada = InverterLogica ? !LeituraBruta : LeituraBruta;
if (!UsarDebounce) {
PressionadoAnterior = Pressionado;
Pressionado = leituraTratada;
MudouEstado = (Pressionado != PressionadoAnterior);
return;
}
unsigned long agora = millis();
if (leituraTratada != ultimaLeituraInstavel) {
ultimaLeituraInstavel = leituraTratada;
ultimoTempoMudanca = agora;
}
if ((agora - ultimoTempoMudanca) >= TempoDebounceMs) {
if (ultimaLeituraInstavel != ultimaLeituraTratada) {
ultimaLeituraTratada = ultimaLeituraInstavel;
PressionadoAnterior = Pressionado;
Pressionado = ultimaLeituraTratada;
MudouEstado = (Pressionado != PressionadoAnterior);
} else {
MudouEstado = false;
}
} else {
MudouEstado = false;
}
MostrarLog("Bruto: " + String(LeituraBruta ? 1 : 0) +
", Pressionado: " + String(Pressionado ? 1 : 0) +
", Mudou: " + String(MudouEstado ? 1 : 0));
}
};
#endif