arduino

Calculate Temperature with Arduino Nano or Arduino Uno and NTC Thermistor Code, Function 2

Introduction

In Function 1 of this serial nosotros discussed edifice a circuit to read the temperature of an NTC thermistor using an Arduino Nano or Uno to an accuracy of ±1 °C from 0 °C to 70 °C. In this installment, nosotros will discuss the code used to run the excursion. As a recap, here is the circuit we will use:

Figure 1. Thermistor Breadboard Circuit Using Arduino Nano, screenshot captured using Fritzing

Figure one. Thermistor Breadboard Circuit Using Arduino Nano, screenshot captured using Fritzing

Code Layout and Organisation

This example lawmaking is written to be both simple and modular then that information technology can quickly be adjusted for other uses or fifty-fifty for other programming languages. Each step in the measurement process is written every bit an individual function using inputs, local variables, and outputs that tin can exist adapted into larger projects without needing global variables other than pin names. For now we will use the delay( ) part to look during times we demand to expect for simplicity's sake, and later in this series we discuss the use of non-blocking timers instead of delay( ), which you volition likely want to utilise in practice.

Code

A detailed explanation of each section is built into the comments of the code itself. An boosted explanation of the code is also in the paragraphs below the code. Y'all tin can download the original code file here. It is easier to read the downloaded version of the code equally it will have more consistent formatting and spacing.

                  /**                  The excursion used in this example has more than explanation hither:                  https://www.northstarsensors.com/blog/temperature-from-thermistor-arduino-circuit                  Basically a voltage divider is formed with a 10 kΩ thermistor at 25 °C going from ground to pivot A0, and a ten kΩ resistor going from pin A0 to pin A1.                                    There is a 0.1 μF capacitor from footing to A0 for noise reduction on the ADC input.                  Pivot A1 is used as a voltage output, and A0 is used as an ADC input.                  https://www.northstarsensors.com/weblog/temperature-from-thermistor-arduino-code                  **/                  /**                                    Define all our pins as constants that practice not change.                  We are attempting to isolate the analog and digital sides of the Arduino Nano/Uno.                                    (As a design principle, we don't desire other noisy pins and thermistor analog read pin physically next to each other to become the cleanest analog readings possible.)                  **/                  #ascertain thermistor_current_pin A1                  #define thermistor_analog_read_pin A0                  // A voltage divider is used with the thermistor to be able to sense the voltage of the thermistor in comparason to the full scale voltage when taking an analog reading                  void                  setup() {                  // Initialize serial port equally nosotros will be printing temperature data to information technology.                  Serial.brainstorm(9600);                  // Setup how our pins are used                  pinMode(thermistor_current_pin, OUTPUT);     pinMode(thermistor_analog_read_pin, INPUT); }                  // End setup                  void                  loop() {        charge_input_capacitor();                  int                  raw_thermistor_reading                  =                  read_thermistor_data();                  // Serial.println(raw_thermistor_reading);                  double                  unfiltered_resistance                  =                  calculate_resistance_from_analog_read(raw_thermistor_reading);                  // Serial.println(unfiltered_resistance);                  double                  filtered_resistance                  =                  filter_resistance_reading(unfiltered_resistance);                  // Serial.println(filtered_resistance);                  float                  kelvin_thermistor_temperature                  =                  calculate_temperature_from_resistance(filtered_resistance);                  float                  celcius_thermistor_temperature                  =                  kelvin_thermistor_temperature                  -                  273.15;                  float                  fahrenheit_thermistor_temperature                  =                  ((celcius_thermistor_temperature*                  ix)/                  five.0)                  +                  32.0;     Serial.println(fahrenheit_thermistor_temperature);                  // This delay hither is a temporary placeholder                  delay(900); }                  // End main loop                  // This function charges upwardly the ADC input capacitor                  // and does non go along until it is charged                  void                  charge_input_capacitor(){                  // Beginning by charging up the capacitor on the input pin                  digitalWrite(thermistor_current_pin, Loftier);                  // Wait 100 milliseconds for the input capacitor to fully accuse.                  // Currently delay() is used every bit a placeholder.                  // For well-nigh applications we will want to apply a non-blocking timer function.                  delay(100); }                  // End charge_input_capacitor function                  // This office records and returns an analog reading.                  // It as well turns off the electric current pin once complete                  int                  read_thermistor_data(){                  // Read analog data from charged capacitor.                  int                  raw_thermistor_reading                  =                  analogRead(thermistor_analog_read_pin);                  // Turn off the thermistor electric current pin to minimize cocky-heating of temperature sensor                  digitalWrite(thermistor_current_pin, Depression);                  return                  raw_thermistor_reading; }                  // End read_thermistor_data function                  /**                                                        This function calculates the rough resistance of the thermistor but does non filter the results for more accuracy.                                                        That is handled in some other role.                                      For the math here, the full calibration range of the analog read is 0 to 1023, (1024 steps) considering the arduino nano has a 10bit ADC.                                      two^x = 1024                                      raw_thermistor_reading / (1023.0 - raw_thermistor_reading) calculates the proportion of the voltage across the thermistor in the voltage divider comparated to the voltage acrross the constant resistor in the voltage divider.                                      Once the proportion of that voltage is known, nosotros can calulate the resistance of the thermistor by multiplying that proportion by the resitance of the constant resistor in the voltage divider.                  **/                  double                  calculate_resistance_from_analog_read(int                  raw_thermistor_reading){                  // The resistance of the 10 kΩ resistor in the voltage divider is included hither as a local variable.                  // If you accept a more precise reading of the resistor you tin can change it here for more accuracy                                    double                  voltage_divider_resistor                  =                  10000.0;                  // If there is a full scale reading (1023) at that place is an open circuit, and we end the function early on and simply return 999999 to avoid dividing by 0                  if(raw_thermistor_reading                  >=                  1023){                  return                  999999.9;     }                  // Encounter function comment for more than caption of the math                  double                  unfiltered_resistance                  =                  voltage_divider_resistor                  *                  (         raw_thermistor_reading                  /                  (1023.0                  -                  raw_thermistor_reading)                                                                  );                  return                  unfiltered_resistance; }                  // End calculate_resistance_from_analog_read function                  /**                                      This role filters the resistance reading. Filtering gives better results because no measurement system is perfect.                                      In this case, measuring the voltage of the thermistor absorbs some of it's current during the read procedure, and slightly alters the true voltage of the thermistor.                                                        This function compensates that and returns resistance readings much closer to their true value.                                      **/                  double                  filter_resistance_reading(double                  unfiltered_resistance){                  // These compensation values are specific to the ADC of the Arduino Nano or Uno, to the resistance of the voltage divider, capacitance at the input, and wait time betwixt measurements.                                    // If any of those parameters alter, the values will likely accept to exist adapted.                  double                  calibration_factor                  =                  -                  iii.27487396E-07                  *                  unfiltered_resistance                  +                  viii.25744292E-03;                  double                  filtered_resistance                  =                  unfiltered_resistance                  *                  (one                  +                  calibration_factor);                  return                  filtered_resistance; }                  // end filter_resistance_reading office                  /**                                      This function uses the 4 term Steinhart-Hart equation to determine the temperature of a thermistor from its resistance.                                      Go to https://world wide web.northstarsensors.com/computing-temperature-from-resistance                                      for more data nigh the Steinhart-Hart equation                  **/                  bladder                  calculate_temperature_from_resistance(double                  thermistor_resistance){                  // These abiding values are for a Due north Star Sensors, curve 44, 10 kΩ at 25 °C thermistor.                  // They are generated from 4 data points at 0, 25, fifty, and 70 °C.                  // If y'all are measuring exterior that range, use constants specialized with data points in the range yous demand.                  double                  SH_A_constant                  =                  1.21500454194620E-03;                  double                  SH_B_constant                  =                  2.05334949463842E-04;                  double                  SH_C_constant                  =                  three.19176316497180E-06;                  double                  SH_D_constant                  =                  -                  ii.93752010251114E-08;                  // In arduino log() calculates the natural logarithm sometimes written as ln, not log base 10                  double                  natural_log_of_resistance                  =                  log(thermistor_resistance);                  // prisoner of war() is a function which rases a number to its ability.                  // For instance x to the power of 2, x^ii, is prisoner of war(x, 2)                  float                  thermistor_temperature_kelvin                  =                  1                  /                  ( SH_A_constant                  +                  SH_B_constant                  *                  natural_log_of_resistance                  +                  SH_C_constant                  *                  pw(natural_log_of_resistance,                  2)                  +                  SH_D_constant                  *                  pw(natural_log_of_resistance,                  3)                                               );                  render                  thermistor_temperature_kelvin; }                  // finish calculate_temperature_from_resistance function                

Written Explanation of the Code

First nosotros turn on pivot A1 to accuse the input capacitor of the voltage divider. We wait 100 milliseconds and so information technology is fully charged and stable. Nosotros and then take an ADC reading on pivot A0, and then turn off pin A1.

We turn the circuit on and off like this to minimize whatever potential self-heating of the thermistor which would be aggravated by feeding the voltage divider a constant v Volts.

The resistance of the thermistor is calculated using the ADC reading and the known resistance of the 10 kΩ resistor in the voltage divider.

We then pass that resistance reading through a calibration filter designed specifically for this circuit which reduces our resistance reading error from effectually 1% to less than 0.3% over the resistance ranges we are measuring. The values for this calibration filter were adamant by recording multiple known resistances from 1.5 kΩ to 35 kΩ, calculating the measurement errors over that resistance range, and determining an equation which which compensates for those errors over that range. The consequence is that you when input an uncompensated resistance into that function, a compensated and more than accurate resistance is determined. These compensation values are specific to the ADC of the Arduino Nano or Uno, to the resistance of the voltage divider, the capacitance at the input, and the wait time between measurements. If any of those parameters change, the values will likely take to be adjusted.

The compensated resistance of the thermistor is and then processed through a 4 term Steinhart-Hart equation function which outputs the temperature of the thermistor in Kelvin.

Finally, that temperature is converted to Fahrenheit and Celsius and printed to the serial monitor.

The main loop then waits so that there is a measurement about once a second.

Thermistor Measurement with Unblocking Lawmaking

For simplicity, nosotros used the delay( ) office, but use of delay( ) blocks other code from running. In the next installment, we will use await timers that do not block other code from running.

Author: Tim Lavenuta