Thermistor APIs
The Thermistor APIs provide a set of functions to read the temperature from a thermistor. The thermistor stores the relevant information (from the datasheet) such as the B value, the nominal resistance, circuit configuration (upper or lower part of the voltage divider), the fixed resistor value, and the supply voltage.
It uses these data to compute the measured resistance of the thermistor, from which the temperature can then be calculated using the Steinhart-Hart equation. See the Wikipedia article for more information.
Using the Steinhart-Hart equation, the temperature can be calculated using the following formula:
where:
\(T\) is the temperature in Kelvin
\(T_0\) is the nominal temperature in Kelvin (e.g. 298.15 K, 25 °C)
\(B\) is the B (beta) value of the thermistor (e.g. 3950 K)
\(R\) is the resistance of the thermistor, measured in Ohm
\(R_0\) is the nominal resistance of the thermistor (e.g. 10000 Ohm at 25 °C)
Note: the thermistor component assumes that the thermistor is used within a voltage divider circuit, with a fixed resistor. The component can be configured so that either the thermistor or the fixed resistor is the upper part of the voltage divider.
API Reference
Header File
Classes
-
class Thermistor : public espp::BaseComponent
Thermistor class.
Reads voltage from a thermistor and converts it to temperature using the Steinhart-Hart equation. This class is designed to be used with a NTC (negative temperature coefficient) thermistor in a voltage divider configuration.
Validation Example
// create a lambda function for getting the voltage from the thermistor // this is just a simple voltage divider auto compute_voltage = [](float r1, float r2 = 10000, float v_in = 3300.0) -> float { return v_in * (r2 / (r1 + r2)); }; // create a table of datasheet info for the thermistor // this is used to calculate the temperature // the first value is the temperature in C // the second value is the resistance scale factor (R/R0) // This data is from the datasheet for the thermistor // https://product.tdk.com/system/files/dam/doc/product/sensor/ntc/chip-ntc-thermistor/data_sheet/50/db/ntc/ntc_smd_standard_series_0402.pdf // we chose a 10k NTC, which corresponds to the 8502 series column on // page 5 of the datasheet auto datasheet_info = std::vector<std::tuple<float, float>>{ {0, 3.2657}, {10, 1.9907}, {20, 1.2494}, {25, 1}, {30, .80552}, {40, .53229}, {50, .35981}, {75, .14763}, {100, .067488}, }; int i = 0; // create a lambda function for getting the voltage from the thermistor // using the datasheet info, this will return the voltage for the // current temperature (based on the index) auto get_voltage = [&compute_voltage, &i, &datasheet_info]() -> float { auto [temp, r_scale] = datasheet_info[i]; return compute_voltage(r_scale * 10000); }; // create a thermistor object espp::Thermistor thermistor({.divider_config = espp::Thermistor::ResistorDividerConfig::UPPER, .beta = 3940, // 25/50C beta since we're not planning on hot temps .nominal_resistance_ohms = 10000, .fixed_resistance_ohms = 10000, .supply_mv = 3300, .read_mv = get_voltage, .log_level = espp::Logger::Verbosity::INFO}); // see how bad the error is for (i = 0; i < datasheet_info.size(); i++) { auto [actual_celsius, r_scale] = datasheet_info[i]; auto actual_kelvin = actual_celsius + 273.15; // read the temperature auto kelvin = thermistor.get_kelvin(); auto celsius = thermistor.get_celsius(); // use kelvin for calculating error so we don't have to worry about division by zero auto error = std::abs(kelvin - actual_kelvin); logger.info("measured voltage: {:.2f} mV, calculated resistance: {:.2f} Ohm, calculated " "temp: {:.2f} C, actual: {:.2f} C; error: {:.2f} C", get_voltage(), thermistor.get_resistance(), celsius, actual_celsius, error); }
ADC Example
// create a continuous ADC which will sample and filter the thermistor // voltage on ADC1 channel 7 std::vector<espp::AdcConfig> channels{ {.unit = ADC_UNIT_1, .channel = ADC_CHANNEL_7, .attenuation = ADC_ATTEN_DB_11}}; // this initailizes the DMA and filter task for the continuous adc espp::ContinuousAdc adc( {.sample_rate_hz = 20 * 1000, .channels = channels, .convert_mode = ADC_CONV_SINGLE_UNIT_1, // or BOTH_UNIT, ALTER_UNIT, SINGLE_UNIT_1 .window_size_bytes = 1024, .log_level = espp::Logger::Verbosity::WARN}); adc.start(); // make a lambda function for getting the latest voltage from the adc auto get_voltage = [&adc, &channels]() -> float { auto maybe_mv = adc.get_mv(channels[0]); if (maybe_mv.has_value()) { return maybe_mv.value(); } else { return 0; } }; // create a thermistor object (based on the datasheet from // https://product.tdk.com/system/files/dam/doc/product/sensor/ntc/chip-ntc-thermistor/catalog/tpd_commercial_ntc-thermistor_ntcg_en.pdf // From the table (page 7): // clang-format off // Part Number. | R25(Ω) | Tolerance | B25/50(Κ) | B25/75(Κ) | B25/85(Κ) | B25/100(K) | Current (mA) | Operating Temp Range // NTCG103JF103FT1 | 10,000 | +/–1% | 3380 | 3422 | 3435 | 3453 +/–1% | 0.31 | –40 to 152 // clang-format on espp::Thermistor thermistor({.divider_config = espp::Thermistor::ResistorDividerConfig::UPPER, .beta = 3380, .nominal_resistance_ohms = 10000, .fixed_resistance_ohms = 10000, .supply_mv = 3300, .read_mv = get_voltage, .log_level = espp::Logger::Verbosity::INFO}); fmt::print("% time(s), temp(C)\n"); auto task_fn = [&thermistor](std::mutex &m, std::condition_variable &cv) { static auto start = std::chrono::high_resolution_clock::now(); auto now = std::chrono::high_resolution_clock::now(); float elapsed = std::chrono::duration<float>(now - start).count(); // read the temperature auto temp = thermistor.get_celsius(); // print out the temperature fmt::print("{:.3f}, {}\n", elapsed, temp); // NOTE: sleeping in this way allows the sleep to exit early when the // task is being stopped / destroyed { std::unique_lock<std::mutex> lk(m); cv.wait_until(lk, now + 10ms); } // don't want to stop the task return false; }; auto task = espp::Task({.callback = task_fn, .task_config = {.name = "Read Thermistor"}, .log_level = espp::Logger::Verbosity::INFO}); task.start();
Public Types
-
enum class ResistorDividerConfig
Enum for resistor divider configuration.
Values:
-
enumerator LOWER
Thermistor is the lower resistor.
-
enumerator UPPER
Thermistor is the upper resistor.
-
enumerator LOWER
-
typedef std::function<float(void)> read_mv_fn
Function type for reading voltage.
- Return
Voltage in millivolts
Public Functions
-
inline explicit Thermistor(const Config &config)
Constructor.
- Parameters
config – Configuration struct
-
inline float get_resistance()
Get resistance of the thermistor.
Reads the voltage from the thermistor and converts it to resistance
- Returns
Resistance of the thermistor in ohms
-
inline float get_kelvin()
Get the temperature in Kelvin.
Reads the voltage from the thermistor and converts it to temperature using the Steinhart-Hart equation.
- Returns
Temperature in Kelvin
-
inline float get_celsius()
Get the temperature in Celsius.
Reads the voltage from the thermistor and converts it to temperature using the Steinhart-Hart equation. The temperature is converted from Kelvin to Celsius.
See also
- Returns
Temperature in Celsius
-
inline float get_fahrenheit()
Get the temperature in Fahrenheit.
Reads the voltage from the thermistor and converts it to temperature using the Steinhart-Hart equation. The temperature is converted from Kelvin to Fahrenheit.
See also
- Returns
Temperature in Fahrenheit
-
inline const std::string &get_name() const
Get the name of the component
Note
This is the tag of the logger
- Returns
A const reference to the name of the component
-
inline void set_log_tag(const std::string_view &tag)
Set the tag for the logger
- Parameters
tag – The tag to use for the logger
-
inline espp::Logger::Verbosity get_log_level() const
Get the log level for the logger
See also
See also
- Returns
The verbosity level of the logger
-
inline void set_log_level(espp::Logger::Verbosity level)
Set the log level for the logger
See also
See also
- Parameters
level – The verbosity level to use for the logger
-
inline void set_log_verbosity(espp::Logger::Verbosity level)
Set the log verbosity for the logger
See also
See also
See also
Note
This is a convenience method that calls set_log_level
- Parameters
level – The verbosity level to use for the logger
-
inline espp::Logger::Verbosity get_log_verbosity() const
Get the log verbosity for the logger
See also
See also
See also
Note
This is a convenience method that calls get_log_level
- Returns
The verbosity level of the logger
-
inline void set_log_rate_limit(std::chrono::duration<float> rate_limit)
Set the rate limit for the logger
See also
Note
Only calls to the logger that have _rate_limit suffix will be rate limited
- Parameters
rate_limit – The rate limit to use for the logger
-
struct Config
Configuration struct for Thermistor.
Public Members
-
ResistorDividerConfig divider_config
Resistor divider configuration.
-
float beta
Beta coefficient of the thermistor at 25C, e.g. 3950.
-
float nominal_resistance_ohms
Resistance of the thermistor (in ohms) at 25C, e.g. 10000.
-
float fixed_resistance_ohms
Resistance of the fixed resistor in the voltage divider (in ohms), e.g. 10000
-
float supply_mv
Supply voltage of the voltage divider (in mv), e.g. 3300.
-
read_mv_fn read_mv
Function for reading voltage.
-
ResistorDividerConfig divider_config
-
enum class ResistorDividerConfig