Temperature Sensing and LEDs

Project 8: Temperature Sensing Thermistor

What you will need:

  • Raspberry Pi
  • Breadboard
  • Red LEDs
  • 2 Yellow LEDs
  • 2 Green LEDs
  • 2 Blue LEDs
  • 1 330nf Ceramic Disk Capacitor
  • 2 1kΩ Resistors —[III I]—
  • 1 10kΩ NTC Radial Thermistor
  • 8 220Ω to 330Ω Resistor —[III I]—
  • 11 Female to Male Jumper Wires
  • 1 Male to Male Jumper Wires

Instructions:

This Raspberry Pi project definitely increased the complexity of what my son and I had accomplished to date. It incorporated elements from our Project 4: Sequential LEDs while bringing in many new concepts. The purpose of this project is to attempt to read our room’s ambient temperature by utilizing a thermistor while visually indicating the temperature through illuminated LEDs.

A thermistor is a device which changes its resistance based upon temperature. The thermistor we chose to use for this project was a Vishay 10k NTC Radial variety that we found on Amazon.com. Since we are located in the United States, our entire project uses Fahrenheit for temperatures.

As a side note, be extra careful when populating the breadboard layout above, we discovered a popular thermistor tutorial online that had the capacitor charging and discharging pins reversed on their layout which caused difficulties for us during troubleshooting. Our thermistor circuit is using GPIO pins 23 and 24. We are also using a lot of additional GPIO pins for this Raspberry Pi project so be sure the LEDs are correctly connected to GPIO pins 17, 27, 22, 10, 9, 11, 13, and 26.

After you have finished populating the breadboard, create the following Python script in your favorite editor:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
#  temp_LED.py
#
# Use a thermistor to read temperatures and illuminate
# a number of LEDs based upon the returned temperature
#
#  Copyright 2015  Ken Powers
#

import time, math
import RPi.GPIO as GPIO

# Set GPIO pins to Broadcom numbering system
GPIO.setmode(GPIO.BCM)

# Define our constants
RUNNING = True
led_list = [17,27,22,10,9,11,13,26] # GPIO pins for LEDs
temp_low = 70 # Lowest temperature for LEDs (F)
temp_high = 86 # Highest temperature for LEDs (F)
a_pin = 23
b_pin = 24

# Set up our LED GPIO pins as outputs
for x in range(0,8):
	GPIO.setup(led_list[x], GPIO.OUT)
	GPIO.output(led_list[x], GPIO.LOW)

# Try to keep this value near 1 but adjust it until
# the temperature readings match a known thermometer
adjustment_value = 0.97

# Create a function to take an analog reading of the
# time taken to charge a capacitor after first discharging it
# Perform the procedure 100 times and take an average
# in order to minimize errors and then convert this
# reading to a resistance
def resistance_reading():
	total = 0
	for i in range(1, 100):
		# Discharge the 330nf capacitor
		GPIO.setup(a_pin, GPIO.IN)
		GPIO.setup(b_pin, GPIO.OUT)
		GPIO.output(b_pin, False)
		time.sleep(0.01)
		# Charge the capacitor until our GPIO pin
		# reads HIGH or approximately 1.65 volts
		GPIO.setup(b_pin, GPIO.IN)
		GPIO.setup(a_pin, GPIO.OUT)
		GPIO.output(a_pin, True)
		t1 = time.time()
		while not GPIO.input(b_pin):
			pass
		t2 = time.time()
		# Record the time taken and add to our total for
		# an eventual average calculation
		total = total + (t2 - t1) * 1000000
	# Average our time readings
	reading = total / 100
	# Convert our average time reading to a resistance
	resistance = reading * 6.05 - 939
	return resistance

# Create a function to convert a resistance reading from our
# thermistor to a temperature in Celsius which we convert to
# Fahrenheit and return to our main loop
def temperature_reading(R):
    B = 3977.0 # Thermistor constant from thermistor datasheet
    R0 = 10000.0 # Resistance of the thermistor being used
    t0 = 273.15 # 0 deg C in K
    t25 = t0 + 25.0 # 25 deg C in K
    # Steinhart-Hart equation
    inv_T = 1/t25 + 1/B * math.log(R/R0)
    T = (1/inv_T - t0) * adjustment_value
    return T * 9.0 / 5.0 + 32.0 # Convert C to F

# Main loop
try:
    while RUNNING:
		# Get the thermistor temperature
		t = temperature_reading(resistance_reading())

		# Print temperature values in real time
		print(t)

		# Turn off LEDs
		for x in range(0,8):
			GPIO.output(led_list[x], GPIO.LOW)

		# Calculate how many LEDs to illuminate
		# within our temp_low to temp_high range
		if t <= temp_low:
			t = temp_low
		if t >= temp_high:
			t = temp_high

		num_leds = int(round(((t-temp_low) / (temp_high-temp_low))*8))

		# Turn LEDs on
		for x in range(0,num_leds):
			GPIO.output(led_list[x], GPIO.HIGH)

		# Time interval for taking readings in seconds
		time.sleep(0.1)

# If CTRL+C is pressed the main loop is broken
except KeyboardInterrupt:
    RUNNING = False
    print "\Quitting"

# Actions under 'finally' will always be called
# regardless of what stopped the program
finally:
    # Stop and cleanup to finish cleanly so the pins
    # are available to be used again
    GPIO.cleanup()

Code Analysis:

Once again, our Python script begins by letting the interpreter know which language we are using in addition to supplying some brief comments that indicate our script’s purpose.

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
#  temp_LED.py
#
# Use a thermistor to read temperatures and illuminate
# a number of LEDs based upon the returned temperature
#
#  Copyright 2015  Ken Powers
#

Next, we import our necessary function libraries.

import time, math
import RPi.GPIO as GPIO

We then define our script’s constants. This includes a list of the pins we are using for our LEDs and two Fahrenheit temperature constants that determine the high and low limits of our LED temperature indicator. In this same code section, we make sure our Raspberry Pi’s LED GPIO pins are set to output mode and are initially turned off.

We also take the opportunity to create an adjustment_value variable that we can tweak in order to make our temperature reading coincide with a known thermometer. You should try to keep this close to a value of 1 but since there is a lot of variance between components, this is a handy addition to our code.

When we originally created this Python script, we just read the ambient temperature and lit a proportionate number of LEDs. However, the result was very boring and didn’t change much.

Therefore, we decided to change our script’s functionality so our ambient temperature lit a single LED and if we held the thermistor between our fingers, the LEDs sequentially lit until they hit about 86 degrees Fahrenheit. This made it a bit more fun with which to interact. Feel free to modify these two temperature values to provide the best effect when holding the thermistor between your fingers to increase its temperature reading.

# Define our constants
RUNNING = True
led_list = [17,27,22,10,9,11,13,26] # GPIO pins for LEDs
temp_low = 70 # Lowest temperature for LEDs (F)
temp_high = 86 # Highest temperature for LEDs (F)
a_pin = 23
b_pin = 24

# Set up our LED GPIO pins as outputs
for x in range(0,8):
	GPIO.setup(led_list[x], GPIO.OUT)
	GPIO.output(led_list[x], GPIO.LOW)

# Try to keep this value near 1 but adjust it until
# the temperature readings match a known thermometer
adjustment_value = 0.97

Our next section of the script defines 2 key functions which are based upon the Steinhart-Hart Equation as well as the work of Simon Monk from MonkMakes.com.

The first function, resistance_reading(), completely discharges our 330nf capacitor and then times how long it takes to charge it to the point where our GPIO pin returns a HIGH reading (around 1.65 volts). This process is repeated 100 times in order to reduce errors and the results are averaged. This average is used to calculate the thermistor’s current resistance.

Our second function takes the resistance supplied by our resistance_reading() function and converts it to a Celsius temperature by using the Steinhart-Hart Equation. Next, we convert this temperature to Fahrenheit and return the value to our Python script’s main loop.

It is important to note that the value of variable B in the second function was obtained from our thermistor’s Datasheet. Variable R0 also needs to indicate the resistance value of the thermistor being used.

#!/usr/bin/env python
# Create a function to take an analog reading of the
# time taken to charge a capacitor after first discharging it
# Perform the procedure 100 times and take an average
# in order to minimize errors and then convert this
# reading to a resistance
def resistance_reading():
	total = 0
	for i in range(1, 100):
		# Discharge the 330nf capacitor
		GPIO.setup(a_pin, GPIO.IN)
		GPIO.setup(b_pin, GPIO.OUT)
		GPIO.output(b_pin, False)
		time.sleep(0.01)
		# Charge the capacitor until our GPIO pin
		# reads HIGH or approximately 1.65 volts
		GPIO.setup(b_pin, GPIO.IN)
		GPIO.setup(a_pin, GPIO.OUT)
		GPIO.output(a_pin, True)
		t1 = time.time()
		while not GPIO.input(b_pin):
			pass
		t2 = time.time()
		# Record the time taken and add to our total for
		# an eventual average calculation
		total = total + (t2 - t1) * 1000000
	# Average our time readings
	reading = total / 100
	# Convert our average time reading to a resistance
	resistance = reading * 6.05 - 939
	return resistance

# Create a function to convert a resistance reading from our
# thermistor to a temperature in Celsius which we convert to
# Fahrenheit and return to our main loop
def temperature_reading(R):
    B = 3977.0 # Thermistor constant from thermistor datasheet
    R0 = 10000.0 # Resistance of the thermistor being used
    t0 = 273.15 # 0 deg C in K
    t25 = t0 + 25.0 # 25 deg C in K
    # Steinhart-Hart equation
    inv_T = 1/t25 + 1/B * math.log(R/R0)
    T = (1/inv_T - t0) * adjustment_value
    return T * 9.0 / 5.0 + 32.0 # Convert C to F

Our Python script’s main loop begins by using our functions to get the current temperature. We print this temperature to the screen so we can keep track of things. Next, we use a simple loop to turn all our LED GPIO pins to LOW which is an off state.

Next, we make sure our current temperature falls within the range we defined by our constants temp_low and temp_high. We use a simple equation to determine how many LEDs to illuminate with respect to our current temperature.

Next, we create a simple loop to set each LED’s GPIO pin to a HIGH state which is on for .1 seconds and then the entire process repeats until Ctrl + C is pressed.

# Main loop
try:
    while RUNNING:
		# Get the thermistor temperature
		t = temperature_reading(resistance_reading())

		# Print temperature values in real time
		print(t)

		# Turn off LEDs
		for x in range(0,8):
			GPIO.output(led_list[x], GPIO.LOW)

		# Calculate how many LEDs to illuminate
		# within our temp_low to temp_high range
		if t <= temp_low:
			t = temp_low
		if t >= temp_high:
			t = temp_high

		num_leds = int(round(((t-temp_low) / (temp_high-temp_low))*8))

		# Turn LEDs on
		for x in range(0,num_leds):
			GPIO.output(led_list[x], GPIO.HIGH)

		# Time interval for taking readings in seconds
		time.sleep(0.1)

# If CTRL+C is pressed the main loop is broken
except KeyboardInterrupt:
    RUNNING = False
    print "\Quitting"

# Actions under 'finally' will always be called
# regardless of what stopped the program
finally:
    # Stop and cleanup to finish cleanly so the pins
    # are available to be used again
    GPIO.cleanup()

My son and I were extremely pleased we were able to read a temperature from a simple thermistor connected to our Raspberry Pi. It was even more fun to directly correlate the temperature with a number of lit LEDs. We spent quite a bit of time taking turns holding the thermistor and watching the LEDs sequentially light and then sequentially extinguish once we let go.

Have fun experimenting with the above Python script and see what other modifications you can make. Above all, have fun!



One thought on “Project 8: Temperature Sensing Thermistor”

Leave a Reply