6#ifndef NTC_THERMISTOR_IMPL
7#define NTC_THERMISTOR_IMPL
11#ifdef NTC_THERMISTOR_HEADER_INCLUDED
12#include "../inc/ntc_thermistor.hpp"
13#include "../inc/ntc_conversion.hpp"
14#include "../inc/ntc_lookup_table.hpp"
36template <
typename AdcType>
38 AdcType *adc_interface) noexcept
39 : config_(), adc_interface_(adc_interface), initialized_(
false),
40 filtered_temperature_(ZERO_FLOAT_), filter_initialized_(
false) {
43 initializeConfigForType(ntc_type, &config_);
46template <
typename AdcType>
48 AdcType *adc_interface) noexcept
49 : config_(config), adc_interface_(adc_interface), initialized_(
false),
50 filtered_temperature_(ZERO_FLOAT_), filter_initialized_(
false) {}
62 NtcError validation_error = validateConfiguration(config_);
68 if (adc_interface_ ==
nullptr) {
73 if (!adc_interface_->IsInitialized()) {
74 if (!adc_interface_->EnsureInitialized()) {
80 if (!adc_interface_->IsChannelAvailable(config_.adc_channel)) {
85 filter_initialized_ =
false;
86 filtered_temperature_ = ZERO_FLOAT_;
92template <
typename AdcType>
99 filter_initialized_ =
false;
100 filtered_temperature_ = ZERO_FLOAT_;
105template <
typename AdcType>
110template <
typename AdcType>
113 if (config ==
nullptr) {
121template <
typename AdcType>
125 NtcError validation_error = validateConfiguration(config);
127 return validation_error;
133 filter_initialized_ =
false;
134 filtered_temperature_ = ZERO_FLOAT_;
143template <
typename AdcType>
145 float *temperature_celsius)
noexcept {
146 if (temperature_celsius ==
nullptr) {
155 float voltage_volts = 0.0F;
156 NtcError voltage_error = readAdcVoltage(&voltage_volts);
158 return voltage_error;
162 float resistance_ohms = 0.0F;
164 calculateResistance(voltage_volts, &resistance_ohms);
166 return resistance_error;
170 float raw_temperature = 0.0F;
172 convertResistanceToTemperature(resistance_ohms, &raw_temperature);
174 return conversion_error;
178 *temperature_celsius = raw_temperature + config_.calibration_offset;
181 if (config_.enable_filtering) {
182 *temperature_celsius = applyFiltering(*temperature_celsius);
187 config_.max_temperature)) {
194template <
typename AdcType>
196 float *temperature_fahrenheit)
noexcept {
197 if (temperature_fahrenheit ==
nullptr) {
201 float celsius = 0.0F;
202 NtcError error = ReadTemperatureCelsius(&celsius);
204 *temperature_fahrenheit = CelsiusToFahrenheit(celsius);
209template <
typename AdcType>
211 float *temperature_kelvin)
noexcept {
212 if (temperature_kelvin ==
nullptr) {
216 float celsius = 0.0F;
217 NtcError error = ReadTemperatureCelsius(&celsius);
219 *temperature_kelvin = CelsiusToKelvin(celsius);
224template <
typename AdcType>
227 if (reading ==
nullptr) {
233 reading->is_valid =
false;
234 reading->timestamp_us = 0;
235 reading->accuracy_celsius = 0.5F;
238 float temperature_celsius = 0.0F;
239 NtcError error = ReadTemperatureCelsius(&temperature_celsius);
243 float resistance_ohms = 0.0F;
244 GetResistance(&resistance_ohms);
246 float voltage_volts = 0.0F;
247 GetVoltage(&voltage_volts);
249 uint32_t adc_raw = 0U;
250 GetRawAdcValue(&adc_raw);
253 reading->temperature_celsius = temperature_celsius;
254 reading->temperature_fahrenheit = CelsiusToFahrenheit(temperature_celsius);
255 reading->temperature_kelvin = CelsiusToKelvin(temperature_celsius);
256 reading->resistance_ohms = resistance_ohms;
257 reading->voltage_volts = voltage_volts;
258 reading->adc_raw_value = adc_raw;
259 reading->is_valid =
true;
262 reading->error = error;
270template <
typename AdcType>
273 if (resistance_ohms ==
nullptr) {
281 float voltage_volts = 0.0F;
282 NtcError voltage_error = readAdcVoltage(&voltage_volts);
284 return voltage_error;
287 return calculateResistance(voltage_volts, resistance_ohms);
290template <
typename AdcType>
292 if (voltage_volts ==
nullptr) {
300 return readAdcVoltage(voltage_volts);
303template <
typename AdcType>
305 if (adc_value ==
nullptr) {
313 if (adc_interface_ ==
nullptr) {
338 if (config_.sample_count > 1) {
340 uint32_t successful_samples = 0;
342 for (uint32_t i = 0; i < config_.sample_count; ++i) {
343 uint32_t sample_value = 0;
345 adc_interface_->ReadChannelCount(config_.adc_channel, &sample_value);
348 successful_samples++;
351 if (i + 1 < config_.sample_count) {
352 delayBetweenSamples();
356 if (successful_samples == 0) {
360 *adc_value =
static_cast<uint32_t
>(sum / successful_samples);
365 uint32_t sample_value = 0;
367 adc_interface_->ReadChannelCount(config_.adc_channel, &sample_value);
369 return convert_error(err);
371 *adc_value = sample_value;
380template <
typename AdcType>
382 float reference_temperature_celsius)
noexcept {
388 float current_temperature = 0.0F;
389 NtcError read_error = ReadTemperatureCelsius(¤t_temperature);
396 config_.calibration_offset +=
397 reference_temperature_celsius - current_temperature;
402template <
typename AdcType>
405 config_.calibration_offset = offset_celsius;
409template <
typename AdcType>
411 float *offset_celsius)
const noexcept {
412 if (offset_celsius ==
nullptr) {
416 *offset_celsius = config_.calibration_offset;
420template <
typename AdcType>
422 return SetCalibrationOffset(ZERO_FLOAT_);
429template <
typename AdcType>
432 config_.conversion_method = method;
436template <
typename AdcType>
439 if (series_resistance <= ZERO_FLOAT_) {
443 config_.series_resistance = series_resistance;
447template <
typename AdcType>
450 if (reference_voltage <= ZERO_FLOAT_) {
454 config_.reference_voltage = reference_voltage;
458template <
typename AdcType>
464 config_.beta_value = beta_value;
468template <
typename AdcType>
470 if (adc_interface_ !=
nullptr &&
471 !adc_interface_->IsChannelAvailable(adc_channel)) {
475 config_.adc_channel = adc_channel;
479template <
typename AdcType>
481 uint32_t sample_count, uint32_t sample_delay_ms)
noexcept {
482 if (sample_count == 0) {
486 config_.sample_count = sample_count;
487 config_.sample_delay_ms = sample_delay_ms;
491template <
typename AdcType>
493 float alpha)
noexcept {
494 constexpr float MIN_FILTER_ALPHA_ = 0.0F;
495 constexpr float MAX_FILTER_ALPHA_ = 1.0F;
496 if (alpha < MIN_FILTER_ALPHA_ || alpha > MAX_FILTER_ALPHA_) {
500 config_.enable_filtering = enable;
501 config_.filter_alpha = alpha;
504 filter_initialized_ =
false;
505 filtered_temperature_ = ZERO_FLOAT_;
514template <
typename AdcType>
516 return (celsius * CELSIUS_TO_FAHRENHEIT_MULTIPLIER_) + FAHRENHEIT_OFFSET_;
519template <
typename AdcType>
521 return (fahrenheit - FAHRENHEIT_OFFSET_) * FAHRENHEIT_TO_CELSIUS_MULTIPLIER_;
524template <
typename AdcType>
526 return celsius + KELVIN_OFFSET_;
529template <
typename AdcType>
531 return kelvin - KELVIN_OFFSET_;
534template <
typename AdcType>
540 return "General failure";
542 return "Not initialized";
544 return "Already initialized";
546 return "Invalid parameter";
548 return "Null pointer";
550 return "Out of memory";
552 return "ADC read failed";
554 return "Invalid resistance value";
556 return "Temperature out of range";
558 return "Lookup table error";
560 return "Temperature conversion failed";
562 return "Calibration failed";
564 return "Operation not supported";
566 return "Operation timeout";
568 return "Hardware fault";
570 return "Unknown error";
574template <
typename AdcType>
580 return "NTCG163JFT103FT1S";
582 return "NTCG164JF103FT1S";
584 return "NTCG163JF103FT1S";
596template <
typename AdcType>
599 if (config.resistance_at_25c <= ZERO_FLOAT_) {
607 if (config.reference_voltage <= ZERO_FLOAT_) {
611 if (config.series_resistance <= ZERO_FLOAT_) {
615 if (config.sample_count == 0) {
619 if (config.min_temperature >= config.max_temperature) {
623 constexpr float MIN_FILTER_ALPHA_ = 0.0F;
624 constexpr float MAX_FILTER_ALPHA_ = 1.0F;
625 if (config.enable_filtering && (config.filter_alpha < MIN_FILTER_ALPHA_ ||
626 config.filter_alpha > MAX_FILTER_ALPHA_)) {
633template <
typename AdcType>
635 if (voltage_volts ==
nullptr) {
639 if (adc_interface_ ==
nullptr) {
664 if (config_.sample_count > 1) {
666 uint32_t successful_samples = 0;
668 for (uint32_t i = 0; i < config_.sample_count; ++i) {
671 adc_interface_->ReadChannelV(config_.adc_channel, &sample_voltage);
673 sum += sample_voltage;
674 successful_samples++;
677 if (i + 1 < config_.sample_count) {
678 delayBetweenSamples();
682 if (successful_samples == 0) {
686 *voltage_volts = sum /
static_cast<float>(successful_samples);
689 float sample_voltage = 0.0F;
691 adc_interface_->ReadChannelV(config_.adc_channel, &sample_voltage);
693 return convert_error(err);
695 *voltage_volts = sample_voltage;
699template <
typename AdcType>
702 float *resistance_ohms)
noexcept {
703 if (resistance_ohms ==
nullptr) {
708 voltage_volts, config_.reference_voltage, config_.series_resistance,
716template <
typename AdcType>
718 float resistance_ohms,
float *temperature_celsius)
noexcept {
719 if (temperature_celsius ==
nullptr) {
724 switch (config_.conversion_method) {
729 table, resistance_ohms, temperature_celsius)) {
744 resistance_ohms, config_.resistance_at_25c, config_.beta_value,
745 temperature_celsius)) {
752template <
typename AdcType>
754 if (config_.sample_delay_ms == 0U || adc_interface_ ==
nullptr) {
759 if constexpr (
requires(AdcType &adc, uint32_t ms) { adc.DelayMs(ms); }) {
760 adc_interface_->DelayMs(config_.sample_delay_ms);
764template <
typename AdcType>
766 if (!config_.enable_filtering) {
767 return new_temperature;
770 if (!filter_initialized_) {
771 filtered_temperature_ = new_temperature;
772 filter_initialized_ =
true;
773 return new_temperature;
777 filtered_temperature_ =
778 (config_.filter_alpha * new_temperature) +
779 ((ONE_FLOAT_ - config_.filter_alpha) * filtered_temperature_);
781 return filtered_temperature_;
784template <
typename AdcType>
787 if (config ==
nullptr) {
793 config->type = ntc_type;
Hardware-agnostic NTC thermistor driver.
Definition ntc_thermistor.hpp:75
NtcError SetVoltageDivider(float series_resistance) noexcept
Set voltage divider parameters.
Definition ntc_thermistor.ipp:438
NtcError SetBetaValue(float beta_value) noexcept
Set beta value.
Definition ntc_thermistor.ipp:459
NtcError GetVoltage(float *voltage_volts) noexcept
Get voltage across thermistor.
Definition ntc_thermistor.ipp:291
NtcError SetFiltering(bool enable, float alpha=0.1F) noexcept
Enable/disable filtering.
Definition ntc_thermistor.ipp:492
NtcError SetSamplingParameters(uint32_t sample_count, uint32_t sample_delay_ms) noexcept
Set sampling parameters.
Definition ntc_thermistor.ipp:480
NtcError ReadTemperatureCelsius(float *temperature_celsius) noexcept
Read temperature in Celsius.
Definition ntc_thermistor.ipp:144
static float FahrenheitToCelsius(float fahrenheit) noexcept
Convert Fahrenheit to Celsius.
Definition ntc_thermistor.ipp:520
NtcError SetConfiguration(const ntc_config_t &config) noexcept
Set configuration.
Definition ntc_thermistor.ipp:123
NtcError SetReferenceVoltage(float reference_voltage) noexcept
Set reference voltage.
Definition ntc_thermistor.ipp:449
static float CelsiusToKelvin(float celsius) noexcept
Convert Celsius to Kelvin.
Definition ntc_thermistor.ipp:525
NtcError SetConversionMethod(NtcConversionMethod method) noexcept
Set conversion method.
Definition ntc_thermistor.ipp:430
static const char * GetTypeString(NtcType type) noexcept
Get NTC type string.
Definition ntc_thermistor.ipp:575
NtcError ReadTemperatureFahrenheit(float *temperature_fahrenheit) noexcept
Read temperature in Fahrenheit.
Definition ntc_thermistor.ipp:195
NtcError SetCalibrationOffset(float offset_celsius) noexcept
Set calibration offset.
Definition ntc_thermistor.ipp:404
NtcError GetCalibrationOffset(float *offset_celsius) const noexcept
Get calibration offset.
Definition ntc_thermistor.ipp:410
NtcError GetResistance(float *resistance_ohms) noexcept
Get thermistor resistance.
Definition ntc_thermistor.ipp:272
static float KelvinToCelsius(float kelvin) noexcept
Convert Kelvin to Celsius.
Definition ntc_thermistor.ipp:530
NtcError ReadTemperature(ntc_reading_t *reading) noexcept
Read complete temperature information.
Definition ntc_thermistor.ipp:226
bool IsInitialized() const noexcept
Check if initialized.
Definition ntc_thermistor.ipp:106
NtcError GetConfiguration(ntc_config_t *config) const noexcept
Get current configuration.
Definition ntc_thermistor.ipp:112
static const char * GetErrorString(NtcError error) noexcept
Get error string.
Definition ntc_thermistor.ipp:535
NtcError SetAdcChannel(uint8_t adc_channel) noexcept
Set ADC channel.
Definition ntc_thermistor.ipp:469
static float CelsiusToFahrenheit(float celsius) noexcept
Convert Celsius to Fahrenheit.
Definition ntc_thermistor.ipp:515
NtcThermistor(NtcType ntc_type, AdcType *adc_interface) noexcept
Constructor with NTC type and ADC interface.
Definition ntc_thermistor.ipp:37
bool Initialize() noexcept
Initialize the NTC thermistor driver.
Definition ntc_thermistor.ipp:56
NtcError GetRawAdcValue(uint32_t *adc_value) noexcept
Get raw ADC value.
Definition ntc_thermistor.ipp:304
NtcError ReadTemperatureKelvin(float *temperature_kelvin) noexcept
Read temperature in Kelvin.
Definition ntc_thermistor.ipp:210
NtcError ResetCalibration() noexcept
Reset calibration.
Definition ntc_thermistor.ipp:421
bool Deinitialize() noexcept
Deinitialize the NTC thermistor driver.
Definition ntc_thermistor.ipp:93
NtcError Calibrate(float reference_temperature_celsius) noexcept
Calibrate the thermistor.
Definition ntc_thermistor.ipp:381
constexpr float CELSIUS_TO_FAHRENHEIT_MULTIPLIER_
Celsius to Fahrenheit multiplier.
Definition ntc_conversion.hpp:54
constexpr float ZERO_FLOAT_
Zero as float.
Definition ntc_conversion.hpp:47
constexpr float FAHRENHEIT_TO_CELSIUS_MULTIPLIER_
Fahrenheit to Celsius multiplier.
Definition ntc_conversion.hpp:57
constexpr float FAHRENHEIT_OFFSET_
Fahrenheit offset.
Definition ntc_conversion.hpp:56
constexpr float ONE_FLOAT_
One as float.
Definition ntc_conversion.hpp:46
constexpr float KELVIN_OFFSET_
Celsius to Kelvin conversion offset.
Definition ntc_conversion.hpp:16
constexpr float DEFAULT_BETA_VALUE_
Default beta value (3435K)
Definition ntc_types.hpp:159
constexpr float DEFAULT_RESISTANCE_AT_25C_
Default resistance at 25°C (10kΩ)
Definition ntc_types.hpp:157
bool FindTemperatureFromLookupTable(const ntc_lookup_table_t *table, float resistance_ohms, float *temperature_celsius) noexcept
Find temperature using lookup table.
Definition ntc_lookup_table.cpp:128
bool ConvertResistanceToTemperatureBeta(float resistance_ohms, float resistance_at_25c, float beta_value, float *temperature_celsius) noexcept
Convert resistance to temperature using beta parameter.
Definition ntc_conversion.cpp:27
bool CalculateThermistorResistance(float voltage_thermistor, float reference_voltage, float series_resistance, float *resistance_ohms) noexcept
Calculate thermistor resistance from voltage divider.
Definition ntc_conversion.cpp:221
bool ValidateTemperature(float temperature_celsius, float min_temperature, float max_temperature) noexcept
Validate temperature value.
Definition ntc_conversion.cpp:318
bool ValidateBetaValue(float beta_value) noexcept
Validate beta value.
Definition ntc_conversion.cpp:329
const ntc_lookup_table_t * GetNtcLookupTable(int ntc_type) noexcept
Get lookup table for NTC type.
Definition ntc_lookup_table.cpp:115
AdcError
ADC error codes.
Definition ntc_adc_interface.hpp:14
@ HardwareError
Hardware-level error.
@ Success
Operation successful.
@ ReadFailed
ADC read operation failed.
@ InvalidChannel
Invalid ADC channel.
@ NotInitialized
ADC not initialized.
@ Timeout
Operation timeout.
Mathematical conversion functions for NTC thermistor temperature.
Lookup table implementation for NTC thermistor temperature conversion.
Hardware-agnostic NTC thermistor driver for temperature measurement.
NtcError
NTC thermistor error codes.
Definition ntc_types.hpp:24
@ TemperatureOutOfRange
Temperature out of range.
@ NullPointer
Null pointer.
@ LookupTableError
Lookup table error.
@ Success
Operation successful.
@ HardwareFault
Hardware fault.
@ AdcReadFailed
ADC read failed.
@ InvalidParameter
Invalid parameter.
@ InvalidResistance
Invalid resistance value.
@ NotInitialized
Not initialized.
@ AlreadyInitialized
Already initialized.
@ OutOfMemory
Out of memory.
@ CalibrationFailed
Calibration failed.
@ Timeout
Operation timeout.
@ Failure
General failure.
@ UnsupportedOperation
Operation not supported.
@ ConversionFailed
Temperature conversion failed.
constexpr ntc_config_t GetDefaultNtcConfig() noexcept
Default NTC configuration.
Definition ntc_types.hpp:224
NtcConversionMethod
Temperature conversion methods.
Definition ntc_types.hpp:82
@ Auto
Auto-select based on accuracy requirements.
@ Mathematical
Use mathematical conversion (slower, more accurate)
@ LookupTable
Use lookup table (faster, less accurate)
NtcType
NTC thermistor types.
Definition ntc_types.hpp:58
@ NtcG163Jft103Ft1S
NTCG163JFT103FT1S (10kΩ @ 25°C, β=3435K)
@ NtcG164Jf103Ft1S
NTCG164JF103FT1S (10kΩ @ 25°C, β=3435K)
@ NtcG163Jf103Ft1S
NTCG163JF103FT1S (10kΩ @ 25°C, β=3435K)
Lookup table structure.
Definition ntc_lookup_table.hpp:31
NTC thermistor configuration structure.
Definition ntc_types.hpp:107
NTC thermistor reading structure.
Definition ntc_types.hpp:136