Analog Temperature Modules

temperature modules

Do you need to know the temperature for one of your Arduino projects? In this tutorial we learn how to use analog temperature modules.

Analog Temperature Modules

A temperature module is an interesting option for beginner projects with your Arduino. One could e.g. control a fan, build a frost alert or even a small a weather station. There are plenty of projects out there that make use of temperature sensors and I encourage you to create your own. In this tutorial you will learn, how to use analog temperature modules with the Arduino. These modules typically use an NTC thermistor. If you want to know more about thermistors, you might want to read the background tutorials on thermistors and the temperature calculation formulas.

Before we go on, I want to make clear that there are different analog temperature modules available. There are two main types: temperature switches and modules for measuring an absolute temperature value. The picture shows the former type on the left side and the latter on the right. In this tutorial we will focus on temperature measurement. I used the KY-013 module, but I will also show you how to directly use an NTC thermistor. For projects, where you don't need the actual temperature value, the first type should be considered as an easier to use alternative. These modules allow you to set a threshold using a potentiometer. They possess a digital output that changes once this threshold is crossed. We will look at this alternative in the next tutorial. Enough talking, let's get started!

Different Types of Temperature Modules

Using the Temperature Module

Circuit diagram and wiring of the KY-013 temperature module

Connecting the temperature module to the Arduino is pretty straight forward. The pin for the output signal is marked with an S and has to be connected to an analog pin of the Arduino. I chose pin A0. Next we need to connect the supply voltage. For my module GND has to be connected with the left pin that is marked with . The middle pin gets connected to 5V.

Next to the wiring diagram I put down the schematic of the module. It is basically a simple voltage divider circuit for resistance measurement with the NTC thermistor and a 10 kΩ resistor as R1.

There are apparently some KY-013 modules that are labeled the wrong way around. If the code from this tutorial does not work, you need to find the correct pinout with a multimeter. You can easily identify the analog output S by measuring the resistance. The output pin has a resistance of about 10 kΩ to the other two pins. If you heat up the sensor and end up with lower temperature values printed out in the serial monitor, 5V and GND need to be swapped.

How can we calculate the temperature? We need to measure the voltage on A0 and then calculate resistance and temperature:

// Measurements and Calculations
 float voltage = analogRead(A0)*5/1024.0;
 float resistance = calculateSensorResistance(voltage);
 float temperature = calculateTemperature(resistance);

The code uses two helper functions: calculateSensorResistance calculates the resistance of the thermistor using the measured voltage and calculateTemperature finally calculates the temperature value in degree Celsius. If you need the temperature in degree Fahrenheit an additional step to convert the result is needed. This can be solved using a simple conversion function:

float convertTemperatureFahrenheit(float tDegree) {
  return tDegree/5.0*9.0 + 32.0;
}

Let's have a look at the resistance calculation. We can simply use the voltage divider formula and solve it for R2. The input voltage is 5 V. R1 is our fixed 10 kΩ resistor. In the code, I named its resistance R_FIXED. The resulting code for the resistance calculation function looks like this:

// Fixed resistor in voltage divider
const float R_FIXED = 10000;

float calculateSensorResistance(float voltage) {
  return R_FIXED / (5.0/voltage - 1);
}

Next, the helper function for the temperature calculation. I chose to use the beta equation. To calculate the correct temperature reading we need to know the beta value of the thermistor used on the KY-013 module. In my case this is 3435 K. The resulting temperature calculation code looks like this:

// Temperature sensor
const float B = 3435;

const float R0 = 10000;
const float ABS_ZERO = -273.15;
const float T0 = 25-ABS_ZERO;

float calculateTemperature(float resistance) {
  return 1.0 / (log(resistance/R0)/B+1.0/T0) + ABS_ZERO;
}

Different NTC thermistors may have a different temperature-resistance curves. The beta value is specific to the NTC thermistor type used on your KY-013 module. Unfortunately, there can be versions of this module that use a different thermistor. If temperature values shown in the serial console are incorrect, please verify if that you used the beta value given in the datasheet of your thermistor. For information how to find out what sensor you have, even if you don't have a datasheet, refer to the background tutorial on the temperature calculation formulas. It describes a possible procedure for calibrating your sensor.

Let's combine everything into an Arduino program that prints out the measurements to the serial monitor. The full code looks like this:

// Temperature sensor
const float B = 3435;

const float R0 = 10000;
const float ABS_ZERO = -273.15;
const float T0 = 25-ABS_ZERO;

float calculateTemperature(float resistance) {
  return 1.0 / (log(resistance/R0)/B+1.0/T0) + ABS_ZERO;
}

float convertTemperatureFahrenheit(float tDegree) {
  return tDegree/5.0*9.0 + 32.0;
}

// Fixed resistor in voltage divider
const float R_FIXED = 10000;

float calculateSensorResistance(float voltage) {
  return R_FIXED / (5.0/voltage - 1);
}

void setup() {
  // Init Serial Port
  Serial.begin(9600);
}

void loop() {
  // Measurements and Calculations
  float voltage = analogRead(A0)*5/1024.0;
  float resistance = calculateSensorResistance(voltage);
  float temperature = calculateTemperature(resistance);
  float temperatureF = convertTemperatureFahrenheit(temperature);
  
  // Print out result
  Serial.print("Voltage (V): ");
  Serial.println(voltage);
  
  Serial.print("Resistance (Ohm): ");
  Serial.println(resistance);
  
  Serial.print("Temperature (°C): ");
  Serial.println(temperature);

  Serial.print("Temperature (°F): ");
  Serial.println(temperatureF);

  // Wait for 1s
  delay(1000);
}

After uploading the code to your Arduino, open the serial monitor. You should see the measurement values there:

Voltage (V): 2.61
Resistance (Ohm): 10940.69
Temperature (°C): 22.69
Temperature (°F): 72.84

Using an NTC thermistor

Wiring and circuit for the use of an NTC thermistor

Instead of a pre-built module we could also use an arbitrary 10 kΩ NTC thermistor. We just need an additional 10 kΩ resistor and can then build up the voltage divider circuit by ourselves.

You might have noticed that there is a difference to the circuit of the original module. I chose to put in the NTC thermistor at the place where R1 was in the original circuit. The fixed resistor is now R2. There is no particular advantage in swapping both components, but it feels a bit more natural to me to use a circuit in which the voltage increases with increasing temperature. This is a question of personal taste, however. You have now seen both variants. Feel free to choose the one you like. Of course, we need to adjust the code to match our new circuit layout. For that we solve the voltage divider formula for R1 instead of R2:

float calculateSensorResistance(float voltage) {
  return R_FIXED * (5.0/voltage - 1);
}

With that done we need to adjust the code to the NTC. The sensor I used has a beta value of 4300 K. The adjusted temperature code looks like this:

// Temperature sensor
const float B = 4300;

const float R0 = 10000;
const float ABS_ZERO = -273.15;
const float T0 = 25-ABS_ZERO;

float calculateTemperature(float resistance) {
  return 1.0 / (log(resistance/R0)/B+1.0/T0) + ABS_ZERO;
}

In case you want to use the Steinhart-Hart equation instead of the beta equation, you need to adjust the calculateTemperature function to use the Steinhart-Hart equation with the three coefficients \(a\), \(b\) and \(c\) of your NTC:

// Temperature sensor
const float a = 0.00129495;
const float b = 0.000215997;
const float c = 0.000000891608;

const float ABS_ZERO = -273.15;

float calculateTemperature(float resistance) {
  float logR = log(resistance);
  return 1.0 / (a + b * logR + c * logR * logR * logR) + ABS_ZERO;
}

Different NTC thermistors may have a different temperature-resistance curves. The beta value and the Steinhart-Hart coefficients are specific to your NTC thermistor type. If temperature values shown in the serial console are incorrect, please verify if that you used the beta value or coefficients given in the datasheet of your thermistor. The Steinhart-Hart coefficient shown in the code above are calculated for my NTC thermistor with a beta value of 4300 K. For information how to find out what sensor you have, even if you don't have a datasheet, refer to the background tutorial on the temperature calculation formulas. It describes a possible procedure for calibrating your sensor.

Measurement accuracy

If you compare the temperature readings of the Arduino with other temperature modules or thermometers you will likely see some difference in the measurements values. NTC thermistors always have some inaccuracy. It is usually around ± 0.5 °C at 25 °C.

The unfortunate truth is, that there is another source for potential inaccuracies. The measurements are done using the 5 V input voltage as voltage reference. This is what we assumed in our code. There is nothing wrong about that, except that when the Arduino is powered via USB the supply voltage may not be exactly 5 V. The allowed voltage range according to the USB specification is 4.4 V to 5.25 V for USB 2.0 and 4.45 V to 5.25 V for USB 3.0. Usually, the voltage is pretty close to 5 V and there should not be an issue. However, don't take that for granted. If you run into issues check the supply voltage with a multimeter. If the supply voltage differs the inaccuracy of our measurement increases. A possible solution is to additionally connect a battery to the Arduino's DC jack. The Arduino will automatically switch over to the DC jack and use the 5 V voltage generated by the onboard voltage regulator. This regulator is not a hundred percent exact either but usually good enough for most use cases. The alternative would be to measure the actual supply voltage and use the measured value for the calculation, but this is a topic for a separate tutorial.

For most projects accuracy is not a big deal anyway. If you really need it, you should favor a factory calibrated digital temperature sensor.

Previous Post Next Post