pequenos ajustes no sensor de temperatura e pinout

This commit is contained in:
Diego Freitas 2026-08-04 17:20:50 -03:00
parent 72bf996e7e
commit 6242d8b3dc
3 changed files with 212 additions and 38 deletions

View File

@ -7,6 +7,11 @@
#define PINO_INVALIDO 0xFF
enum class FormatoLeituraAnalogica : uint8_t {
Bruta,
Milivolts
};
class PinoModel {
public:
int num;
@ -20,6 +25,35 @@ class PinoModel {
PinoModel(int numero = PINO_INVALIDO, TiposBarramentos barr = CONTROLADOR, TiposPinos tp = _INPUT, TiposLeituras lt = DIGITAL, int _idSensor = 0, int canalMux = -1) : num(numero), barramento(barr), tipo(tp), leitura(lt), idSensor(_idSensor), _CanalMUX(canalMux) {
}
bool ConfigurarLeituraAnalogica(uint8_t resolucaoBits = 12, adc_attenuation_t atenuacao = ADC_11db) {
if (!Conectado || barramento != TiposBarramentos::CONTROLADOR || leitura != TiposLeituras::ANALOGICO) {
return false;
}
if (resolucaoBits < 9 || resolucaoBits > 12) {
MostrarLog(
"Resolucao ADC invalida no GPIO " +
String(num) +
": " +
String(resolucaoBits) +
" bits"
);
return false;
}
analogReadResolution(resolucaoBits);
analogSetPinAttenuation(num, atenuacao);
MostrarLog(
"ADC configurado | GPIO: " + String(num) +
" | Resolucao: " + String(resolucaoBits) +
" bits | Atenuacao: " + String(static_cast<int>(atenuacao))
);
return true;
}
bool Definido() {
bool barramentoIniciado =
(barramento == TiposBarramentos::CONTROLADOR) ||
@ -90,39 +124,73 @@ class PinoModel {
Conectado = false;
}
int get(int leituras = 1) {
if (Conectado) {
if (barramento == TiposBarramentos::CONTROLADOR) {
int get(int quantidadeLeituras = 1, FormatoLeituraAnalogica formato = FormatoLeituraAnalogica::Bruta) {
if (!Conectado || quantidadeLeituras <= 0) {
return -1;
}
bool retornarMilivolts = formato == FormatoLeituraAnalogica::Milivolts;
switch (barramento) {
case TiposBarramentos::CONTROLADOR: {
if (leitura == TiposLeituras::DIGITAL) {
if (retornarMilivolts) {
MostrarLog("Leitura em mV solicitada para pino digital: " + String(num));
return -1;
}
return digitalRead(num);
}
else if (leitura == TiposLeituras::ANALOGICO) {
double l = 0;
for (int i = 0; i < leituras; i++) {
vTaskDelay(1);
int leitura = analogRead(num);
MostrarLog("Leitura Controlador: " + String(leitura));
l += leitura;
if (leitura == TiposLeituras::ANALOGICO) {
uint64_t soma = 0;
for (int i = 0; i < quantidadeLeituras; i++) {
if (i > 0) {
vTaskDelay(pdMS_TO_TICKS(1));
}
return l / leituras;
const uint32_t valor = retornarMilivolts ? analogReadMilliVolts(num) : analogRead(num);
soma += valor;
}
const uint32_t media = static_cast<uint32_t>(soma / static_cast<uint64_t>(quantidadeLeituras));
MostrarLog(
"Leitura Controlador | GPIO: " + String(num) +
" | Valor: " + String(media) +
(retornarMilivolts ? " mV" : " raw") +
" | Amostras: " + String(quantidadeLeituras)
);
return media <= static_cast<uint32_t>(INT_MAX) ? static_cast<int>(media) : -1;
}
return -1;
}
case TiposBarramentos::EXPANSOR_GPIO: {
if (retornarMilivolts) {
MostrarLog("Leitura em mV nao suportada pelo expansor GPIO");
return -1;
}
if (!I2CService::McpIniciado) {
return -1;
}
else if (barramento == TiposBarramentos::EXPANSOR_GPIO) {
if (I2CService::McpIniciado) {
if (!I2CService::SolicitarAcessoI2C(idSensor, _CanalMUX)) {
return -1;
}
int leitura = I2CService::mcp.digitalRead(num);
const int valor = I2CService::mcp.digitalRead(num);
I2CService::LiberarAcessoI2C(idSensor);
return leitura;
}
}
else if (barramento == TiposBarramentos::EXPANSOR_ADS) {
return I2CService::RealizarLeituraADS(num, leituras, idSensor, _CanalMUX);
}
return valor;
}
case TiposBarramentos::EXPANSOR_ADS: {
if (retornarMilivolts) {
MostrarLog("Modo milivolts ainda nao definido para o ADS");
return -1;
}
return I2CService::RealizarLeituraADS(num, quantidadeLeituras, idSensor, _CanalMUX);
}
default:
return -1;
}
}
void set(bool status, bool reqMutex = true) {
if (Conectado) {

View File

@ -12,6 +12,7 @@ class SensorTemperaturaNtc : public ComponenteCAN {
String ID;
uint8_t ID_Num = 0;
PinoModel _pino;
bool _ntcGnd = false;
int leitura = 0;
double temperatura = -1;
@ -29,12 +30,14 @@ class SensorTemperaturaNtc : public ComponenteCAN {
int pino,
TiposBarramentos tipoBarramento,
int canalMux = -1,
float offsetTemperatura = 0.0f
float offsetTemperatura = 0.0f,
bool ntcGnd = false
) :
ID(id),
ID_Num(idNum),
_pino(PinoModel(pino, tipoBarramento, _INPUT, ANALOGICO, idNum, canalMux)),
OffsetTemperatura(offsetTemperatura)
OffsetTemperatura(offsetTemperatura),
_ntcGnd(ntcGnd)
{
}
@ -49,6 +52,7 @@ class SensorTemperaturaNtc : public ComponenteCAN {
tensao = 0;
_pino.Conectar();
_pino.ConfigurarLeituraAnalogica(12, ADC_11db);
Iniciado = _pino.Definido();
@ -123,14 +127,36 @@ class SensorTemperaturaNtc : public ComponenteCAN {
}
void AferirTemperatura() {
leitura = _pino.get(1);
// leitura = filtro.updateEstimate(leitura);
constexpr int QuantidadeAmostras = 16;
temperatura = CalcularTemperatura((float)leitura, OffsetTemperatura);
leitura = _pino.get(QuantidadeAmostras);
const int tensaoMv = _pino.get(QuantidadeAmostras, FormatoLeituraAnalogica::Milivolts);
MostrarLog("Leitura: " + String(leitura) +
", Tensao: " + String(tensao) +
", Temperatura: " + String(temperatura));
if (leitura < 0 || tensaoMv < 0) {
leitura = -1;
tensao = NAN;
temperatura = NAN;
MostrarLog("Falha na leitura do sensor NTC");
return;
}
tensao = tensaoMv / 1000.0f;
// Detecta curto, pino flutuante, circuito aberto ou saturação.
if (leitura <= 20 || leitura >= 4080) {
temperatura = NAN;
MostrarLog("Leitura NTC fora da faixa | Raw: " + String(leitura) + " | Tensao: " + String(tensao, 3) + " V");
return;
}
temperatura = CalcularTemperaturaPorTensao(static_cast<float>(tensaoMv), _ntcGnd, OffsetTemperatura);
MostrarLog(
"Leitura: " + String(leitura) +
" | Tensao: " + String(tensao, 3) + " V" +
" | Temperatura: " + String(temperatura, 2) + " C"
);
}
float CalcularTemperatura(float leituraAdc, float offset = 0.0f) {
@ -158,7 +184,87 @@ class SensorTemperaturaNtc : public ComponenteCAN {
return roundf(Tc * 100.0f) / 100.0f;
}
};
float CalcularTemperaturaPorTensao(float tensaoAdcMv, bool ntcGnd, float offset = 0.0f) {
constexpr float Vs = 5.0f;
constexpr float Rfixo = 10000.0f; // Resistor interno do motor
// Valores reais da placa:
constexpr float Rserie = 4700.0f; // Retorno até o GPIO
constexpr float Rgnd = 6800.0f; // GPIO até o GND
constexpr float Rcarga = Rserie + Rgnd;
constexpr float Beta = 3950.0f;
constexpr float T0 = 298.15f; // 25 °C em kelvin
constexpr float Rntc25 = 10000.0f;
const float vAdc = tensaoAdcMv / 1000.0f;
if (!isfinite(vAdc) || vAdc <= 0.01f || vAdc >= 3.05f)
return NAN;
// Tensão no retorno do motor, antes do resistor de 4,7 kΩ.
const float vRetorno = vAdc * (Rserie + Rgnd) / Rgnd;
if (!isfinite(vRetorno) || vRetorno <= 0.01f || vRetorno >= Vs - 0.01f) {
return NAN;
}
float resistenciaNtc = NAN;
if (ntcGnd) {
/*
5 V
|
Rfixo
|
retorno
|
NTC
|
GND
A carga externa Rcarga fica em paralelo com o NTC.
*/
const float rEquivalente = Rfixo * vRetorno / (Vs - vRetorno);
const float inversoRntc = (1.0f / rEquivalente) - (1.0f / Rcarga);
if (!isfinite(inversoRntc) || inversoRntc <= 0.0f)
return NAN;
resistenciaNtc = 1.0f / inversoRntc;
}
else {
/*
5 V
|
NTC
|
retorno
|
Rfixo
|
GND
A carga externa Rcarga fica em paralelo com Rfixo.
*/
const float rInferior = (Rfixo * Rcarga) / (Rfixo + Rcarga);
resistenciaNtc = rInferior * (Vs - vRetorno) / vRetorno;
}
if (!isfinite(resistenciaNtc) || resistenciaNtc <= 0.0f)
return NAN;
const float temperaturaK = 1.0f / ((1.0f / T0) + logf(resistenciaNtc / Rntc25) / Beta);
const float temperaturaC = temperaturaK - 273.15f + offset;
if (!isfinite(temperaturaC) || temperaturaC < -40.0f || temperaturaC > 150.0f) {
return NAN;
}
return roundf(temperaturaC * 100.0f) / 100.0f;
}
};

View File

@ -88,10 +88,10 @@ Rele_v2* ObterRelePorId(uint8_t idNum) {
#pragma endregion
#pragma region TEMPERATURA NTC
SensorTemperaturaNtc sNTC_MotorET("TMVET", 1, 6, TiposBarramentos::CONTROLADOR, -1, 0.0f);
SensorTemperaturaNtc sNTC_MotorDT("TMVDT", 3, 7, TiposBarramentos::CONTROLADOR, -1, 0.0f);
SensorTemperaturaNtc sNTC_MotorEF("TMVEF", 2, 8, TiposBarramentos::CONTROLADOR, -1, 0.0f);
SensorTemperaturaNtc sNTC_MotorDF("TMVDF", 4, 9, TiposBarramentos::CONTROLADOR, -1, 0.0f);
SensorTemperaturaNtc sNTC_MotorET("TMVET", 1, 6, TiposBarramentos::CONTROLADOR, -1, 0.0f, false);
SensorTemperaturaNtc sNTC_MotorDT("TMVDT", 3, 7, TiposBarramentos::CONTROLADOR, -1, 0.0f, true);
SensorTemperaturaNtc sNTC_MotorEF("TMVEF", 2, 8, TiposBarramentos::CONTROLADOR, -1, 0.0f, false);
SensorTemperaturaNtc sNTC_MotorDF("TMVDF", 4, 9, TiposBarramentos::CONTROLADOR, -1, 0.0f, true);
SensorTemperaturaNtc* ObterTempNtcPorId(uint8_t idNum) {
switch (idNum) {