implementado recuperacao de barramento i2c

This commit is contained in:
Diego Freitas 2026-06-15 10:02:20 -03:00
parent 9a0e3cbb6b
commit c9b96c7861
2 changed files with 1940 additions and 216 deletions

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,419 @@
// Dispositivo: Sensoriamento
// Versão Firmware: 23
// Ultima atualização: 15/06/2026
// Atualização: Implementado melhoria na recuperação do barramento I2C
#include "C:\ZendionInc\agrobot_base\Firmware\Modulos\SerialService.h"
#include "C:\ZendionInc\agrobot_base\Firmware\Modulos\CanService.h"
#include "C:\ZendionInc\agrobot_base\Firmware\Modulos\EepromService.h"
#include "C:\ZendionInc\agrobot_base\Firmware\Modulos\I2CService.h"
#include "C:\ZendionInc\agrobot_base\Firmware\Modulos\Utils.h"
#include "C:\ZendionInc\agrobot_base\Firmware\Modulos\Pinout.h"
#include "C:\ZendionInc\agrobot_base\Firmware\Modulos\ServoAgroModel_v2.h"
#include "C:\ZendionInc\agrobot_base\Firmware\Modulos\ReleModel_v2.h"
#include "C:\ZendionInc\agrobot_base\Firmware\Modulos\SinaleiroModel_v2.h"
#include "C:\ZendionInc\agrobot_base\Firmware\Modulos\SensorTemperaturaNtcModel.h"
#include "C:\ZendionInc\agrobot_base\Firmware\Modulos\SensorCorrenteModel_v2.h"
#include "C:\ZendionInc\agrobot_base\Firmware\Modulos\SensorMagneticoModel_v2.h"
// Configurações do CAN
uint8_t CanID = 0x11;
CanService canService(CanID);
//LoRaService loraService(&canService);
#define D_Code Sen
int VERSION = 23;
String Mod_ID = "Sen";
#define _pinoLED RGB_BUILTIN
bool Conectado = false;
bool Conectar = false;
int _TaxaAmostragem = 1000;
volatile bool RequisitarDados = false;
int latenciaLoop = 0;
int qtdEnviosStatus = 0;
int maxEnviosStatus = 5;
#pragma region SINALEIROS
Sinaleiro_v2 sLED_Manual("LEDMN", 21, 37, TiposBarramentos::CONTROLADOR);
Sinaleiro_v2 sLED_Automatico("LEDAT", 22, 35, TiposBarramentos::CONTROLADOR);
Sinaleiro_v2 sLED_Operacao("LEDOP", 23, 36, TiposBarramentos::CONTROLADOR);
Sinaleiro_v2* ObterSinaleiroPorId(uint8_t idNum) {
switch (idNum) {
case 21: return &sLED_Manual;
case 22: return &sLED_Automatico;
case 23: return &sLED_Operacao;
default: return nullptr;
}
}
LedManager ledManager;
void LedTask(void* pv) {
while (true) {
ledManager.Atualizar();
vTaskDelay(pdMS_TO_TICKS(10)); // 100 Hz
}
}
#pragma endregion
#pragma region SERVOS
ServoAgro_v2 sSRV_FreioET("FROET", 41, true, 45, TiposBarramentos::CONTROLADOR);
ServoAgro_v2 sSRV_FreioDT("FRODT", 43, false, 47, TiposBarramentos::CONTROLADOR);
ServoAgro_v2* ObterServoPorId(uint8_t idNum) {
switch (idNum) {
case 41: return &sSRV_FreioET;
case 43: return &sSRV_FreioDT;
default: return nullptr;
}
}
#pragma endregion
#pragma region RELES
Rele_v2 sRLE_CoolerIn("RLCIN", 81, true, 19, TiposBarramentos::CONTROLADOR);
Rele_v2 sRLE_CoolerOut("RLCOUT", 82, true, 20, TiposBarramentos::CONTROLADOR);
Rele_v2* ObterRelePorId(uint8_t idNum) {
switch (idNum) {
case 81: return &sRLE_CoolerIn;
case 82: return &sRLE_CoolerOut;
default: return nullptr;
}
}
#pragma endregion
#pragma region TEMPERATURA NTC
SensorTemperaturaNtc sNTC_MotorET("TMVET", 1, 0, TiposBarramentos::EXPANSOR_ADS, -1, 0.0f);
SensorTemperaturaNtc sNTC_MotorDT("TMVDT", 3, 1, TiposBarramentos::EXPANSOR_ADS, -1, 0.0f);
SensorTemperaturaNtc sNTC_MotorEF("TMVEF", 2, 2, TiposBarramentos::EXPANSOR_ADS, -1, 0.0f);
SensorTemperaturaNtc sNTC_MotorDF("TMVDF", 4, 3, TiposBarramentos::EXPANSOR_ADS, -1, 0.0f);
SensorTemperaturaNtc* ObterTempNtcPorId(uint8_t idNum) {
switch (idNum) {
case 1: return &sNTC_MotorET;
case 2: return &sNTC_MotorEF;
case 3: return &sNTC_MotorDT;
case 4: return &sNTC_MotorDF;
default: return nullptr;
}
}
#pragma endregion
#pragma region CORRENTE
SensorCorrente_v2 sCOR_3V0 ("COR_AB3V", 11, 0x40, TiposShuntCorrente::INA219_3A2, 5);
SensorCorrente_v2 sCOR_5V0 ("COR_AB5V", 12, 0x40, TiposShuntCorrente::INA219_3A2, 4);
SensorCorrente_v2 sCOR_7V2 ("COR_AB7V2", 13, 0x40, TiposShuntCorrente::INA219_3A2, 2);
SensorCorrente_v2 sCOR_12V ("COR_AB12V", 14, 0x40, TiposShuntCorrente::INA228_50A, 3);
SensorCorrente_v2 sCOR_19V ("COR_AB19V", 15, 0x40, TiposShuntCorrente::INA228_10A, 1);
SensorCorrente_v2 sCOR_24V ("COR_AB24V", 16, 0x40, TiposShuntCorrente::INA228_50A, 6);
SensorCorrente_v2 sCOR_36V ("COR_AB36V", 17, 0x40, TiposShuntCorrente::INA228_100A, 7);
SensorCorrente_v2* ObterSensorCorrentePorId(uint8_t idNum) {
switch (idNum) {
case 11: return &sCOR_3V0;
case 12: return &sCOR_5V0;
case 13: return &sCOR_7V2;
case 14: return &sCOR_12V;
case 15: return &sCOR_19V;
case 16: return &sCOR_24V;
case 17: return &sCOR_36V;
default: return nullptr;
}
}
#pragma endregion
#pragma region MAGNETICOS
SensorMagnetico_v2 sMAG_MotorET("MAG_ET", 91, 0x36, 1);
SensorMagnetico_v2 sMAG_MotorDT("MAG_DT", 92, 0x36, 2);
SensorMagnetico_v2 sMAG_MotorEF("MAG_EF", 93, 0x36, 3);
SensorMagnetico_v2 sMAG_MotorDF("MAG_DF", 94, 0x36, 4);
SensorMagnetico_v2* ObterSensorMagneticoPorId(uint8_t idNum) {
switch (idNum) {
case 91: return &sMAG_MotorET;
case 92: return &sMAG_MotorDT;
case 93: return &sMAG_MotorEF;
case 94: return &sMAG_MotorDF;
default: return nullptr;
}
}
#pragma endregion
void MostrarLog(String mensagem) {
bool _debugMode = false;
if (_debugMode) {
PrintTela(String("[SEN] ") + mensagem);
}
}
void inicializarDependenciasI2C() {
I2CService::DefinirPinos(1, 2, 41, 42, 39, 40);
I2CService::IniciarI2C();
I2CService::IniciarADS();
I2CService::IniciarMUX();
I2CService::IniciarMCP();
}
void setup() {
delay(2000);
inicializarDependenciasI2C();
sSRV_FreioET.Inicializar();
sSRV_FreioDT.Inicializar();
sRLE_CoolerIn.Inicializar();
sRLE_CoolerOut.Inicializar();
sLED_Manual.Inicializar();
sLED_Automatico.Inicializar();
sLED_Operacao.Inicializar();
sNTC_MotorET.Inicializar();
sNTC_MotorDT.Inicializar();
sNTC_MotorEF.Inicializar();
sNTC_MotorDF.Inicializar();
sCOR_3V0.Inicializar();
sCOR_5V0.Inicializar();
sCOR_7V2.Inicializar();
sCOR_12V.Inicializar();
sCOR_19V.Inicializar();
sCOR_24V.Inicializar();
sCOR_36V.Inicializar();
//sMAG_MotorET.Inicializar();
//sMAG_MotorDT.Inicializar();
//sMAG_MotorEF.Inicializar();
//sMAG_MotorDF.Inicializar();
ledManager.Adicionar(&sLED_Manual);
ledManager.Adicionar(&sLED_Automatico);
ledManager.Adicionar(&sLED_Operacao);
xTaskCreatePinnedToCore(LedTask, "LedTask", 3000, NULL, 1, NULL, tskNO_AFFINITY);
// Registrar callback para processar mensagens CAN recebidas
canService.setReceiveCallback([](int packetSize, int senderId, CanMessagePosicaoDados posicao, byte* data, int dataLength) {
std::vector<uint8_t> fullData;
fullData.push_back(static_cast<uint8_t>(posicao)); // Primeiro byte é sempre a posicao
for (int i = 0; i < dataLength; i++) {
fullData.push_back(data[i]);
}
ProcessarFrameCAN(posicao, fullData);
});
canService.begin();
}
void loop() {
if (!RequisitarDados) {
enviarLogsPeriodicamente();
}
delay(1);
}
// Função para enviar logs do sensor periodicamente
unsigned long ultimoEnvioLogs = 0;
const unsigned long intervaloEnvioLogs = 1000; // 1 segundo
void enviarLogsPeriodicamente() {
unsigned long tempoAtual = millis();
// Verifica se o intervalo de 5 segundos já passou
if (tempoAtual - ultimoEnvioLogs >= _TaxaAmostragem) {
ultimoEnvioLogs = tempoAtual; // Atualiza o tempo do último envio
enviarDadosSensores(canService.ID_Num_sTOD, CanMessagePosicaoDados::DadosAll);
}
}
void enviarDadosSensores(uint8_t id_num, CanMessagePosicaoDados posicao) {
if (Conectado || posicao == CanMessagePosicaoDados::Status) {
unsigned long startLoop = millis();
bool enviarStatus = qtdEnviosStatus >= maxEnviosStatus && posicao != CanMessagePosicaoDados::Status;
bool todosDados = posicao == CanMessagePosicaoDados::DadosAll;
bool todosIDs = id_num == canService.ID_Num_sTOD;
if (id_num == canService.ID_Num_sMOD) {
EnviarDadosCAN(canService.MontarFrameReqStatusMod(D_Code, Conectado, VERSION));
return;
}
if (todosIDs)
MostrarLog("Atualizando dados dos sensores...");
if (todosIDs && enviarStatus) {
EnviarDadosCAN(canService.MontarFrameReqStatusMod(D_Code, Conectado, VERSION));
}
ComponenteCAN::ProcessarComponenteCAN(sSRV_FreioET, {CanMessagePosicaoDados::Dados1}, todosIDs, id_num, enviarStatus, todosDados, posicao, EnviarDadosCAN);
ComponenteCAN::ProcessarComponenteCAN(sSRV_FreioDT, {CanMessagePosicaoDados::Dados1}, todosIDs, id_num, enviarStatus, todosDados, posicao, EnviarDadosCAN);
ComponenteCAN::ProcessarComponenteCAN(sRLE_CoolerIn, {CanMessagePosicaoDados::Dados1}, todosIDs, id_num, enviarStatus, todosDados, posicao, EnviarDadosCAN);
ComponenteCAN::ProcessarComponenteCAN(sRLE_CoolerOut, {CanMessagePosicaoDados::Dados1}, todosIDs, id_num, enviarStatus, todosDados, posicao, EnviarDadosCAN);
ComponenteCAN::ProcessarComponenteCAN(sLED_Manual, {CanMessagePosicaoDados::Dados1}, todosIDs, id_num, enviarStatus, todosDados, posicao, EnviarDadosCAN);
ComponenteCAN::ProcessarComponenteCAN(sLED_Automatico, {CanMessagePosicaoDados::Dados1}, todosIDs, id_num, enviarStatus, todosDados, posicao, EnviarDadosCAN);
ComponenteCAN::ProcessarComponenteCAN(sLED_Operacao, {CanMessagePosicaoDados::Dados1}, todosIDs, id_num, enviarStatus, todosDados, posicao, EnviarDadosCAN);
ComponenteCAN::ProcessarComponenteCAN(sNTC_MotorET, {CanMessagePosicaoDados::Dados1}, todosIDs, id_num, enviarStatus, todosDados, posicao, EnviarDadosCAN);
ComponenteCAN::ProcessarComponenteCAN(sNTC_MotorDT, {CanMessagePosicaoDados::Dados1}, todosIDs, id_num, enviarStatus, todosDados, posicao, EnviarDadosCAN);
ComponenteCAN::ProcessarComponenteCAN(sNTC_MotorEF, {CanMessagePosicaoDados::Dados1}, todosIDs, id_num, enviarStatus, todosDados, posicao, EnviarDadosCAN);
ComponenteCAN::ProcessarComponenteCAN(sNTC_MotorDF, {CanMessagePosicaoDados::Dados1}, todosIDs, id_num, enviarStatus, todosDados, posicao, EnviarDadosCAN);
ComponenteCAN::ProcessarComponenteCAN(sCOR_3V0, {CanMessagePosicaoDados::Dados1}, todosIDs, id_num, enviarStatus, todosDados, posicao, EnviarDadosCAN);
ComponenteCAN::ProcessarComponenteCAN(sCOR_5V0, {CanMessagePosicaoDados::Dados1}, todosIDs, id_num, enviarStatus, todosDados, posicao, EnviarDadosCAN);
ComponenteCAN::ProcessarComponenteCAN(sCOR_7V2, {CanMessagePosicaoDados::Dados1}, todosIDs, id_num, enviarStatus, todosDados, posicao, EnviarDadosCAN);
ComponenteCAN::ProcessarComponenteCAN(sCOR_12V, {CanMessagePosicaoDados::Dados1, CanMessagePosicaoDados::Dados2}, todosIDs, id_num, enviarStatus, todosDados, posicao, EnviarDadosCAN);
ComponenteCAN::ProcessarComponenteCAN(sCOR_19V, {CanMessagePosicaoDados::Dados1, CanMessagePosicaoDados::Dados2}, todosIDs, id_num, enviarStatus, todosDados, posicao, EnviarDadosCAN);
ComponenteCAN::ProcessarComponenteCAN(sCOR_24V, {CanMessagePosicaoDados::Dados1, CanMessagePosicaoDados::Dados2}, todosIDs, id_num, enviarStatus, todosDados, posicao, EnviarDadosCAN);
ComponenteCAN::ProcessarComponenteCAN(sCOR_36V, {CanMessagePosicaoDados::Dados1, CanMessagePosicaoDados::Dados2}, todosIDs, id_num, enviarStatus, todosDados, posicao, EnviarDadosCAN);
//ComponenteCAN::ProcessarComponenteCAN(sMAG_MotorET, {CanMessagePosicaoDados::Dados1}, todosIDs, id_num, enviarStatus, todosDados, posicao, EnviarDadosCAN);
//ComponenteCAN::ProcessarComponenteCAN(sMAG_MotorDT, {CanMessagePosicaoDados::Dados1}, todosIDs, id_num, enviarStatus, todosDados, posicao, EnviarDadosCAN);
//ComponenteCAN::ProcessarComponenteCAN(sMAG_MotorEF, {CanMessagePosicaoDados::Dados1}, todosIDs, id_num, enviarStatus, todosDados, posicao, EnviarDadosCAN);
//ComponenteCAN::ProcessarComponenteCAN(sMAG_MotorDF, {CanMessagePosicaoDados::Dados1}, todosIDs, id_num, enviarStatus, todosDados, posicao, EnviarDadosCAN);
if (enviarStatus) {
qtdEnviosStatus = 0;
}
else {
qtdEnviosStatus++;
}
latenciaLoop = millis() - startLoop;
if (posicao == CanMessagePosicaoDados::DadosAll) {
EnviarDadosCAN(canService.MontarFrameReqDadosFim(latenciaLoop));
}
if (todosIDs)
MostrarLog("Ciclo concluido, latencia de loop: " + String(latenciaLoop));
}
}
void EnviarDadosCAN(std::vector<uint8_t> data) {
if (data.size() > 2) {
canService.adicionarMensagemFila(data);
}
}
void ProcessarFrameCAN(CanMessagePosicaoDados posicao, std::vector<uint8_t> data) {
if (data.size() < 1) return;
F_Code funcao = canService.FuncaoPorPosicao(posicao);
switch (funcao) {
case F_Code::ReqTx: ProcessarReq(data); break;
case F_Code::CmdTx: ProcessarCmd(data); break;
case F_Code::CfgTx: ProcessarCfg(data); break;
}
}
void ProcessarReq(std::vector<uint8_t> data) {
if (data.size() < 2) return;
CanMessagePosicaoDados posicao = (CanMessagePosicaoDados)data[0];
uint8_t id = data[1];
enviarDadosSensores(id, posicao);
}
void ProcessarCfg(std::vector<uint8_t> data) {
if (data.size() < 4) return;
std::vector<uint8_t> _chkRx;
CanMessagePosicaoDados posicao = (CanMessagePosicaoDados)data[0];
uint8_t id = data[1];
S_Code componente = DetectarComponente(id);
if (componente == S_Code::sMOD) {
switch (posicao) {
case CanMessagePosicaoDados::Config1: {
if (data.size() < 8) return;
bool conectar = data[2] == 1;
int taxa = data[3] * 1000;
bool requisitar = data[4] == 1;
//loraService.AddressBase = data[5];
int pinoSDA = data[6];
int pinoSCL = data[7];
_TaxaAmostragem = taxa;
RequisitarDados = requisitar;
//if (pinoSDA != PINO_INVALIDO && pinoSCL != PINO_INVALIDO) {
// if (I2CService::DefinirPinos(pinoSDA, pinoSCL) || !I2CService::I2CIniciado) {
// inicializarDependenciasI2C();
// }
//}
vTaskDelay(pdMS_TO_TICKS(100));
Conectado = conectar;
_chkRx = canService.MontarFrameReqStatusMod(D_Code, Conectado, VERSION);
MostrarLog("Configuracao do modulo concluida");
break;
}
}
}
EnviarDadosCAN(_chkRx);
}
void ProcessarCmd(std::vector<uint8_t> data) {
if (data.size() < 2) return;
CanMessagePosicaoDados posicao = (CanMessagePosicaoDados)data[0];
uint8_t id = data[1];
S_Code componente = DetectarComponente(id);
switch (componente) {
case sMOD: {
if (data.size() < 3) return;
switch (posicao) {
case CanMessagePosicaoDados::Command1: {
Estado estado = (Estado)data[2];
if (estado == Estado::Reset) {
delay(100);
esp_restart();
}
break;
}
}
break;
}
case sSRV: {
ServoAgro_v2* servo = ObterServoPorId(id);
if (servo == nullptr)
return;
servo->ProcessarComando(data);
break;
}
case sRLE: {
Rele_v2* rele = ObterRelePorId(id);
if (rele == nullptr)
return;
rele->ProcessarComando(data);
break;
}
case sLED: {
Sinaleiro_v2* sinaleiro = ObterSinaleiroPorId(id);
if (sinaleiro == nullptr)
return;
sinaleiro->ProcessarComando(data);
break;
}
default:
break;
}
}
S_Code DetectarComponente(uint8_t idNum) {
if (idNum == canService.ID_Num_sMOD) return S_Code::sMOD;
if (idNum == canService.ID_Num_sTOD) return S_Code::sTOD;
if (idNum == canService.ID_Num_sLRA) return S_Code::sLRA;
if (idNum >= 01 && idNum <= 10) return S_Code::sNTC;
if (idNum >= 11 && idNum <= 20) return S_Code::sCOR;
if (idNum >= 21 && idNum <= 30) return S_Code::sLED;
if (idNum >= 41 && idNum <= 50) return S_Code::sSRV;
if (idNum >= 81 && idNum <= 90) return S_Code::sRLE;
if (idNum >= 91 && idNum <= 100) return S_Code::sMAG;
return S_Code::sVZO;
}