136 lines
3.8 KiB
C++
136 lines
3.8 KiB
C++
#include "Arduino.h"
|
|
|
|
#include "HermitCrab.h"
|
|
#include "NTC_10K.h"
|
|
#include "Config.h"
|
|
|
|
const float resistance[] = {
|
|
3360850.37, // -40°C
|
|
1973470.32, // -35°C
|
|
1179560.43, // -30°C
|
|
718858.73, // -25°C
|
|
445267.47, // -20°C
|
|
281046.96, // -15°C
|
|
180321.36, // -10°C
|
|
117081.11, // -5°C
|
|
77147.90, // 0°C
|
|
51471.97, // 5°C
|
|
34838.43, // 10°C
|
|
23847.63, // 15°C
|
|
|
|
16594.38, // 20°C
|
|
12307.39, // 21°C
|
|
11739.87, // 22°C
|
|
11203.64, // 23°C
|
|
10696.86, // 24°C
|
|
10217.84, // 25°C
|
|
9527.52, // 26°C
|
|
9076.66, // 27°C
|
|
8656.02, // 28°C
|
|
8263.81, // 29°C
|
|
7897.84, // 30°C
|
|
|
|
5868.86, // 35°C
|
|
4383.72, // 40°C
|
|
3315.12, // 45°C
|
|
2527.73, // 50°C
|
|
1942.15, // 55°C
|
|
1505.11, // 60°C
|
|
1174.71, // 65°C
|
|
926.23, // 70°C
|
|
735.99, // 75°C
|
|
588.91, // 80°C
|
|
474.43, // 85°C
|
|
384.48, // 90°C
|
|
313.88, // 95°C
|
|
258.87, // 100°C
|
|
215.64, // 105°C
|
|
181.10, // 110°C
|
|
153.01, // 115°C
|
|
129.77, // 120°C
|
|
110.27, // 125°C
|
|
94.03, // 130°C
|
|
80.13, // 135°C
|
|
68.18, // 140°C
|
|
57.99, // 145°C
|
|
49.30 // 150°C
|
|
};
|
|
|
|
const int16_t temp_C[] = {
|
|
-40, -35, -30, -25, -20, -15, -10, -5, 0, 5, 10, 15,
|
|
20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
|
|
35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95, 100,
|
|
105, 110, 115, 120, 125, 130, 135, 140, 145, 150 };
|
|
|
|
NTC_10K ntc;
|
|
|
|
void NTC_10K::setup(bool bNegativePolarity) {
|
|
m_bNegativePolarity = bNegativePolarity;
|
|
_vRef = 3.3f;
|
|
_RESO = 4095;
|
|
m_nTemp = -9999;
|
|
m_fTemp = -9999.0;
|
|
m_fLastTemp = 0.0f;
|
|
|
|
pinMode(PIN_NTC, INPUT); // Set PIN_NTC as input
|
|
analogReadResolution(12); // Set ADC resolution to 12 bits (0-4095)
|
|
analogSetAttenuation(ADC_11db); // Set attenuation for full-scale 3.3V
|
|
}
|
|
|
|
/**
|
|
* @brief Reads NTC sensor, calculates temperature via interpolation,
|
|
* and applies an Exponential Moving Average (EMA) filter.
|
|
* * History:
|
|
* - 2026-04-16: Refactored from Simple Moving Average (SMA) to EMA with float buffer.
|
|
* - 2026-04-16: Optimized interpolation to reduce CPU cycles.
|
|
* - 2026-04-16: Implemented aggressive alpha (0.01) to mitigate 5°C PWM noise.
|
|
* - 2026-04-16: Upgraded lastTemp to float (m_fLastTemp) for total precision.
|
|
*/
|
|
void NTC_10K::readSensor() {
|
|
float Vin;
|
|
float currentInstantTemp; // High-precision intermediate
|
|
|
|
// 1. Hardware Acquisition
|
|
int adcValue = constrain(analogRead(PIN_NTC), 1, 4094);
|
|
|
|
// 2. Voltage and Resistance Calculation
|
|
Vin = (float)adcValue * _vRef / _RESO;
|
|
|
|
float r;
|
|
if (m_bNegativePolarity) {
|
|
r = (Vin / (_vRef - Vin)) * rRef;
|
|
} else {
|
|
r = ((_vRef - Vin) / Vin) * rRef;
|
|
}
|
|
|
|
// 3. Table Lookup
|
|
int i = 0;
|
|
int tableSize = sizeof(resistance) / sizeof(resistance[0]);
|
|
while (i < tableSize - 1 && resistance[i] > r) {
|
|
i++;
|
|
}
|
|
|
|
// 4. Interpolation Logic (Precise Float Math)
|
|
if (i == 0 || i == tableSize - 1) {
|
|
// Use last known good float value if out of bounds
|
|
currentInstantTemp = (m_fLastTemp != 0.0f) ? m_fLastTemp : 0.0f;
|
|
}
|
|
else {
|
|
// Faster Slope Calculation: y = y0 + m * (r - r0)
|
|
float m = (temp_C[i] - temp_C[i - 1]) / (resistance[i] - resistance[i - 1]);
|
|
currentInstantTemp = temp_C[i - 1] + m * (r - resistance[i - 1]);
|
|
}
|
|
|
|
// 5. Exponential Moving Average (EMA) Filtering
|
|
if (m_fTemp < -5000.0f) {
|
|
m_fTemp = currentInstantTemp;
|
|
} else {
|
|
// 0.01f Alpha: The 5°C PWM noise now only moves the buffer by 0.05°C per hit.
|
|
const float alpha = 0.05f;
|
|
m_fTemp = (currentInstantTemp * alpha) + (m_fTemp * (1.0f - alpha));
|
|
}
|
|
|
|
// 6. Update Outputs
|
|
m_fLastTemp = currentInstantTemp; // Store precise float for next loop
|
|
m_nTemp = (int16_t)roundf(m_fTemp * 10.0f); // Final integer output (e.g., 25.34 -> 253)
|
|
} |