2024-11-29 20:28:25 +00:00
|
|
|
#include "SerialService.h"
|
2024-12-02 19:12:39 +00:00
|
|
|
#include "SensorPressaoModel.h"
|
2024-11-29 20:28:25 +00:00
|
|
|
#include "Pinout.h"
|
|
|
|
|
#include "Utils.h"
|
|
|
|
|
#include <PID_v1.h>
|
|
|
|
|
|
|
|
|
|
#ifndef BombaPressurizadoraModel
|
|
|
|
|
#define BombaPressurizadoraModel
|
|
|
|
|
|
|
|
|
|
class BombaPressurizadora {
|
|
|
|
|
public:
|
|
|
|
|
|
2025-04-11 20:13:15 +00:00
|
|
|
static void ConfigurarBomba(std::vector<BombaPressurizadora*>& lista, std::vector<uint8_t>& data, const String& Mod_ID, std::vector<SensorPressao*>& sensoresPressao);
|
|
|
|
|
static void ComandarBomba(std::vector<BombaPressurizadora*>& lista, std::vector<uint8_t>& data, uint8_t& id);
|
2024-11-29 20:28:25 +00:00
|
|
|
|
|
|
|
|
BombaPressurizadora(String _modID, String _id) {
|
|
|
|
|
Mod_ID = _modID;
|
|
|
|
|
_ID = _id;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
String Mod_ID;
|
|
|
|
|
String _ID;
|
2025-04-10 20:59:50 +00:00
|
|
|
int ID_Num;
|
2024-11-29 20:28:25 +00:00
|
|
|
PinoModel _pinoEN;
|
|
|
|
|
PinoModel _pinoCS;
|
|
|
|
|
PinoModel _pinoINA;
|
|
|
|
|
PinoModel _pinoINB;
|
|
|
|
|
PinoModel _pinoPWM;
|
|
|
|
|
int _canal = 0;
|
|
|
|
|
|
2025-04-10 20:59:50 +00:00
|
|
|
float _Kp = 3.0;
|
|
|
|
|
float _Ki = 2.2;
|
|
|
|
|
float _Kd = 0.5;
|
2024-12-05 17:11:38 +00:00
|
|
|
const int histerese = 3;
|
2024-11-29 20:28:25 +00:00
|
|
|
bool bombaDesligadaPorPressao = false;
|
|
|
|
|
PID* _PID = nullptr;
|
|
|
|
|
|
2024-12-02 19:12:39 +00:00
|
|
|
SensorPressao* sensorPressao;
|
|
|
|
|
|
2024-11-29 20:28:25 +00:00
|
|
|
int ZeroRampa = 0;
|
|
|
|
|
int RampaMax = 1023;
|
|
|
|
|
|
|
|
|
|
bool Iniciado = false;
|
|
|
|
|
|
|
|
|
|
// Consumo
|
|
|
|
|
Estado EstadoLeitura = Desligado;
|
|
|
|
|
double PotenciaLeitura = 0;
|
2024-12-02 19:12:39 +00:00
|
|
|
double PercentualPotenciaLeitura = 0;
|
2024-11-29 20:28:25 +00:00
|
|
|
|
|
|
|
|
// Entrada de dados
|
|
|
|
|
Estado _EstadoControle = Desligado;
|
|
|
|
|
double _PressaoSP = 0;
|
|
|
|
|
|
|
|
|
|
void Inicializar() {
|
|
|
|
|
if (Iniciado) {
|
|
|
|
|
PrintTela(_ID + " ja inicializado");
|
|
|
|
|
return;
|
|
|
|
|
}
|
2025-04-10 20:59:50 +00:00
|
|
|
|
|
|
|
|
if (sensorPressao == nullptr) {
|
|
|
|
|
PrintTela("Sensor de pressao nao definido, bomba nao sera inicializada");
|
|
|
|
|
Iniciado = false;
|
|
|
|
|
return;
|
|
|
|
|
}
|
2024-11-29 20:28:25 +00:00
|
|
|
|
|
|
|
|
_EstadoControle = Desligado;
|
|
|
|
|
_pinoEN.Conectar(_EstadoControle);
|
|
|
|
|
_pinoCS.Conectar();
|
|
|
|
|
_pinoINA.Conectar(false);
|
|
|
|
|
_pinoINB.Conectar(true);
|
|
|
|
|
if (_pinoPWM.Definido()) {
|
|
|
|
|
ledcSetup(_canal, 1000, 10);
|
|
|
|
|
ledcAttachPin(_pinoPWM.num, _canal);
|
|
|
|
|
PotenciaLeitura = 0;
|
|
|
|
|
_PressaoSP = 0;
|
|
|
|
|
ledcWrite(_canal, _PressaoSP);
|
|
|
|
|
}
|
|
|
|
|
|
2025-04-10 20:59:50 +00:00
|
|
|
Iniciado = _pinoEN.Definido() && _pinoPWM.Definido();
|
2024-11-29 20:28:25 +00:00
|
|
|
|
2025-04-10 20:59:50 +00:00
|
|
|
AtualizarLeitura();
|
|
|
|
|
|
|
|
|
|
if (Iniciado) {
|
|
|
|
|
_PID = new PID(&sensorPressao->Pressao, &PotenciaLeitura, &_PressaoSP, _Kp, _Ki, _Kd, DIRECT);
|
|
|
|
|
_PID->SetOutputLimits(ZeroRampa, RampaMax);
|
|
|
|
|
_PID->SetMode(AUTOMATIC);
|
|
|
|
|
|
|
|
|
|
PrintTela(_ID + " iniciado");
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
PrintTela(_ID + " nao iniciado");
|
|
|
|
|
}
|
2024-11-29 20:28:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Desligar() {
|
|
|
|
|
if (!Iniciado) {
|
|
|
|
|
PrintTela(_ID + " nao esta inicializado");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
delete _PID;
|
|
|
|
|
_PID = nullptr;
|
2025-04-10 20:59:50 +00:00
|
|
|
delete sensorPressao;
|
|
|
|
|
sensorPressao = nullptr;
|
2024-11-29 20:28:25 +00:00
|
|
|
|
|
|
|
|
// Redefinir as configurações para os valores iniciais
|
|
|
|
|
_pinoPWM.Desconectar();
|
|
|
|
|
_pinoEN.Desconectar();
|
|
|
|
|
_pinoCS.Desconectar();
|
|
|
|
|
_pinoINA.Desconectar();
|
|
|
|
|
_pinoINB.Desconectar();
|
|
|
|
|
_pinoPWM.Desconectar();
|
|
|
|
|
|
|
|
|
|
PrintTela(_ID + " Desligado");
|
|
|
|
|
|
|
|
|
|
Iniciado = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AlterarStatusBomba() {
|
2025-04-10 20:59:50 +00:00
|
|
|
if (Iniciado) {
|
|
|
|
|
bool status = _EstadoControle == Ligado;
|
2024-11-29 20:28:25 +00:00
|
|
|
|
2025-04-10 20:59:50 +00:00
|
|
|
_pinoEN.set(status);
|
|
|
|
|
|
|
|
|
|
AtualizarLeitura();
|
|
|
|
|
}
|
2024-11-29 20:28:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Loop() {
|
2025-04-10 20:59:50 +00:00
|
|
|
if (Iniciado) {
|
|
|
|
|
sensorPressao->RequisitarDados();
|
2024-12-02 19:12:39 +00:00
|
|
|
double _PressaoAtual = sensorPressao->Pressao; // Obtém a leitura mais recente
|
|
|
|
|
|
2024-12-05 17:11:38 +00:00
|
|
|
if (_PressaoAtual >= (_PressaoSP + histerese)) {
|
|
|
|
|
bombaDesligadaPorPressao = true;
|
|
|
|
|
} else if (_PressaoAtual <= (_PressaoSP - histerese) && bombaDesligadaPorPressao) {
|
|
|
|
|
// Permite que o PID atue novamente se a pressão cair abaixo do set point - histerese
|
|
|
|
|
bombaDesligadaPorPressao = false;
|
2024-11-29 20:28:25 +00:00
|
|
|
}
|
2024-12-05 17:11:38 +00:00
|
|
|
|
|
|
|
|
if (_EstadoControle == Desligado || bombaDesligadaPorPressao) {
|
|
|
|
|
PotenciaLeitura = ZeroRampa;
|
|
|
|
|
} else {
|
|
|
|
|
_PID->Compute();
|
|
|
|
|
// Ajusta PotenciaAtual com base no PID
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ledcWrite(_canal, PotenciaLeitura);
|
|
|
|
|
|
|
|
|
|
AtualizarLeitura();
|
2024-11-29 20:28:25 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-04-10 20:59:50 +00:00
|
|
|
void RequisitarDados() {
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2025-04-11 20:13:15 +00:00
|
|
|
std::vector<uint8_t> MontarMensagemCAN(CanMessagePosicaoDados posicao) {
|
2025-04-10 20:59:50 +00:00
|
|
|
std::vector<uint8_t> data;
|
2025-04-11 20:13:15 +00:00
|
|
|
data.push_back(ID_Num);
|
|
|
|
|
data.push_back(static_cast<uint8_t>(posicao));
|
|
|
|
|
switch (posicao) {
|
|
|
|
|
case CanMessagePosicaoDados::Status: {
|
|
|
|
|
data.push_back(Iniciado ? 1 : 0);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case CanMessagePosicaoDados::Dados1: {
|
|
|
|
|
data.push_back(EstadoLeitura);
|
|
|
|
|
data.push_back(PercentualPotenciaLeitura);
|
|
|
|
|
data.push_back((int)_PressaoSP);
|
|
|
|
|
data.push_back((int)sensorPressao->Pressao);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-04-10 20:59:50 +00:00
|
|
|
return data;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
void AtualizarLeitura() {
|
|
|
|
|
if (Iniciado) {
|
|
|
|
|
EstadoLeitura = _pinoEN.get() == 1 ? Ligado : Desligado;
|
|
|
|
|
PercentualPotenciaLeitura = (PotenciaLeitura / RampaMax) * 100;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2024-11-29 20:28:25 +00:00
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
2025-04-11 20:13:15 +00:00
|
|
|
void BombaPressurizadora::ConfigurarBomba(std::vector<BombaPressurizadora*>& lista, std::vector<uint8_t>& data, const String& Mod_ID, std::vector<SensorPressao*>& sensoresPressao) {
|
|
|
|
|
if (data.size() < 8) return;
|
|
|
|
|
uint8_t idNum = data[1];
|
|
|
|
|
CanMessagePosicaoDados posicao = (CanMessagePosicaoDados)data[2];
|
|
|
|
|
switch (posicao) {
|
|
|
|
|
case CanMessagePosicaoDados::Config1: {
|
|
|
|
|
bool conectar = data[4] == 1;
|
|
|
|
|
int pressaoSp = (int)data[5];
|
|
|
|
|
int pinoEn = data[6];
|
|
|
|
|
int pinoPwm = data[7];
|
|
|
|
|
auto it = std::find_if(lista.begin(), lista.end(), [idNum](BombaPressurizadora* s) { return s->ID_Num == idNum; });
|
|
|
|
|
if (conectar) {
|
|
|
|
|
if (it == lista.end()) {
|
|
|
|
|
BombaPressurizadora* bomba = new BombaPressurizadora(Mod_ID, "sBMB_" + String(idNum));
|
|
|
|
|
if (sensoresPressao.size() > 0) {
|
|
|
|
|
if (sensoresPressao[0]->Iniciado) {
|
|
|
|
|
bomba->sensorPressao = sensoresPressao[0];
|
|
|
|
|
}
|
2024-12-02 19:12:39 +00:00
|
|
|
}
|
2025-04-11 20:13:15 +00:00
|
|
|
if (bomba->sensorPressao == nullptr) {
|
|
|
|
|
PrintTela("Nenhum sensor de pressão disponível para associar à bomba.");
|
|
|
|
|
delete bomba;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
bomba->ID_Num = idNum;
|
|
|
|
|
bomba->_pinoEN = PinoModel(pinoEn, CONTROLADOR, _OUTPUT);
|
|
|
|
|
bomba->_pinoPWM = PinoModel(pinoPwm, CONTROLADOR, _PWM);
|
|
|
|
|
bomba->_PressaoSP = (double)pressaoSp;
|
|
|
|
|
bomba->Inicializar();
|
|
|
|
|
lista.push_back(bomba);
|
|
|
|
|
PrintTela("Bomba Pressurizadora adicionado via CAN: sBMB_" + String(idNum));
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
if (it != lista.end()) {
|
|
|
|
|
BombaPressurizadora* bomba = *it;
|
|
|
|
|
bomba->Desligar();
|
|
|
|
|
delete bomba;
|
|
|
|
|
lista.erase(it);
|
|
|
|
|
PrintTela("Bomba Pressurizadora removido via CAN: sBMB_" + String(idNum));
|
2024-11-29 20:28:25 +00:00
|
|
|
}
|
|
|
|
|
}
|
2025-04-11 20:13:15 +00:00
|
|
|
break;
|
2024-11-29 20:28:25 +00:00
|
|
|
}
|
|
|
|
|
}
|
2025-04-11 20:13:15 +00:00
|
|
|
}
|
2024-12-02 19:12:39 +00:00
|
|
|
|
2025-04-11 20:13:15 +00:00
|
|
|
void BombaPressurizadora::ComandarBomba(std::vector<BombaPressurizadora*>& lista, std::vector<uint8_t>& data, uint8_t& id) {
|
|
|
|
|
if (data.size() < 6) return;
|
|
|
|
|
Estado novoEstado = (Estado)data[3];
|
|
|
|
|
int pressao = (int)data[4];
|
|
|
|
|
for (auto* _bomba : lista) {
|
|
|
|
|
if (_bomba && _bomba->ID_Num == id) {
|
|
|
|
|
_bomba->_EstadoControle = novoEstado;
|
|
|
|
|
_bomba->_PressaoSP = (double)pressao;
|
|
|
|
|
_bomba->AlterarStatusBomba();
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-11-29 20:28:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#endif
|