Thermistor temperature reading with BeagleBone

thermistor measurement setup

Well, no 3D printer is complete without the ability to measure the temperature, and the preferred way of determining temperatures around 220 deg is by using a thermistor. I’m using Python and I am also making use of this great python library called PyBBIO for doing it:

Installing PyBBIO

Update: Alex has now fixed this, so hopefully you will no longer get an error.

To install PyBBIO, just follow the instructions on GitHub. When you get the following error:

py_compile module missing; installing to /usr/lib/python2.7/py_compile.py

read this post: Post about how to fix the py_compile module.

Ok, spoiler alert! it’s:

cd /usr/lib/python2.7
wget http://hg.python.org/cpython/raw-file/4ebe1ede981e/Lib/py_compile.py

Ok, assuming you have the PyBBIO library installed, the reading of the thermistor is straight forward:

Wiring up

Alex has made a nice chart to help determine the pin-out.

schematic-thermistor

On the Replicape, the thermistor for the Heated Build Platform (HBP) is connected to BeagleBone pin P9_35 which is AIN6 (THERM_HBP) in the schematic above, thus the test script becomes:

Testscript

# Import PyBBIO library:
from bbio import *

therm1 = AIN6 # pin 37 on header P9

def readThermistor():
    # Get the ADC values:
    adc_val = analogRead(therm1)
    # And convert to voltages:
    voltage1 = inVolts(adc_val)
    print "AIN6 ADC value: %i, voltage: %fv" % (adc_val, voltage1)
    delay(500)

# Start the loop:
while 1:
    readThermistor()

Update: The above script works fine on my platform, but as I was cleaning up some code it started to NOT work and I could not figure out why. I’m used to be able to switch between “from bbio import *” and “import bbio as io”, but in the case of the latter form, be sure to call the function io.bbio_init() explicitly.

Voltage to resistance

A thermistor changes resistance value with temperature, so in order to get the temperature, we must know the resistance of the thermistor. The value read on the analog input is easily converted to volts by the formula:

Latex formula

where adc_val is the value read on the AIN6 pin, 1.8 is the reference voltage and 2^12 is the maximum value for the ADC (12 bits). The inVolts function used in the script above is from the PyBBIO library.

Now, according to the schematic above, the thermistor, together with a 4.7K resistor forms a voltage divider:

Latex formula

So R2 is the thermistor, R1 = 4.7K, Vin is the reference voltage (1.8V) and Vsense is the voltage read on the analog input (AIN6). Now rearranging to solve for R2 we get:

Latex formula

Converting to degrees

The thermistor in question here is from an old Cup Cake HBP. It seems Makerbot have removed all build instructions from their wiki so it’s impossible to find out which thermistor is used, but let’s say its the same one used on the MK4 plastruder, which is still in stock. It’s called B57560G104F and here is the datasheet for the thermistor. In the data sheet there is a list relating the resistance value of the thermistor to the temperature it then has.

A simple plot of the table reveals the highly unlinear behaviour of the thermistor.

plot of thermistor

This behaviour is somewhat linearized by the voltage diver, at least in the area of interest around 110 degrees C.

Here is a plot of the  Vin vs. temperature :

vin-vs-temperature

Anyways, once the conversion chart is in place (just copypasted from the data sheet), converting to degrees becomes trivial, here is the python script:

#!/usr/bin/python 

from bbio import *
import numpy as np

therm1 = AIN6 # pin 37 on header P9

# This conversion table has been found in the datasheet for B57560G104F
temp_chart = [
[0, 333964],
[5, 258497], 
[10, 201659], 
[15, 158499], 
[20, 125468], 
[25, 100000], 
[30, 80223], 
[35, 64759], 
[40, 52589], 
[45, 42951], 
[50, 35272],
[55, 29119], 
[60, 24161], 
[65, 20144], 
[70, 16874], 
[75, 14198], 
[80, 11998], 
[85, 10181], 
[90, 8674], 
[95, 7419], 
[100, 6369], 
[105, 5487], 
[110, 4744], 
[115, 4115], 
[120, 3581], 
[125, 3126], 
[130, 2737],
[135, 2404], 
[140, 2117], 
[145, 1869], 
[150, 1655], 
[155, 1469], 
[160, 1307], 
[165, 1166], 
[170, 1043], 
[175, 934.5], 
[180, 839.3], 
[185, 755.4], 
[190, 681.3], 
[195, 615.8], 
[200, 557.6], 
[205, 505.9], 
[210, 459.9], 
[215, 418.8], 
[220, 382.0], 
[225, 349.1], 
[230, 319.5], 
[235, 292.9], 
[240, 269.0], 
[245, 247.3], 
[250, 227.8], 
[255, 210.1], 
[260, 194.1], 
[265, 179.5], 
[270, 166.3], 
[275, 154.2], 
[280, 143.2], 
[285, 133.2], 
[290, 124.0], 
[295, 115.5], 
[300, 107.8]]

# Transpose the chart
temp_chart = map(list, zip(*temp_chart))

# Return the temperature nearest to the resistor value
def resistance_to_degrees(resistor_val):
    idx = (np.abs(np.array(temp_chart[1])-resistor_val)).argmin()
    return temp_chart[0][idx]

# Convert the voltage to a resistance value
def voltage_to_resistance(v_sense):
    return  4700.0/((1.8/v_sense)-1.0)

# Read thermistor value and print the result
def readThermistor():
    # Get the ADC values
    adc_val = 0
    for i in range(1000):
        adc_val+= analogRead(therm1)
    adc_val /= 1000.0
    voltage = inVolts(adc_val)                 # Convert to voltage
    res_val = voltage_to_resistance(voltage)    # Convert to resistance    
    temperature = resistance_to_degrees(res_val) # Convert to degrees
    print " AIN6 ADC value: %i - voltage: %fv - thermistor res: %f - Temperature: %f deg." % (adc_val, voltage, res_val, temperature)

# Start the loop:
while 1:
    readThermistor()

And this is what the readout looks like. The picture was taken just after the HBP was turned off, so it is actually on it’s way down in temperature:
thermistor readout

This is still very crude way of doing it. The 5 degree intervals are very coarse, there is no calibration and there is very much noise on the ACD input. As seen in the test script above, I am doing an averaging of 1000. Without the averaging the values were varying some 25 degrees in room temperature.

Nop head has a good introduction to more elaborate schemes for increasing the precision, this was just a “make it work” thing..

6 thoughts on “Thermistor temperature reading with BeagleBone

    • Great! I really like your library as well, very clean and simple.
      Btw, is there a way to mux the pwm-pins to gpio? I wasn’t able to do it..

      • Thanks!
        Yes it’s possible, but if you mean with PyBBIO then not quite yet. It’s on the list for the near future, I just have to decide how to handle all the corner cases that come with having multiple functions for pins.

          • Alex, that is great news! I actually built revision 1 of the Replicape based on the (primary) functions of the pins so I would not have to change your libray, but it’s good to know I need not worry about it in the future : )

  1. Pingback: PID control on BeagleBone | Hipstercircuits

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>