Multiple DS18B20 Sensors on a single Raspberry PI

I had a need to connect multiple DS18B20 temperature sensors to a PI.  The breadboard route worked for a minute – until the cat tried using the hanging sensors as a trapeze. So, I broke out my best crayons and construction paper and drew up an expansion PCB.

Raspberry PI DS18B20 expansion board
  • Inexpensive.
  • Connect 6 or more DS18B20 temperature sensors to a single PI.
  • Keep the expansion port open for other devices.
  • Option to use plug-in or bulk sensors.
  • Automatically detect and display additional sensors.
  • Option to rename sensors to something real world.

The expansion PCB uses the standard PI header interface and has a duplicate interface so it’s not hogging up the only port.

I have a few extra boards and sensors. Let me know if you’re interested.

Files:
RaspberryDS.py – Python script which reads the sensors and updates index.html

cf – Configuration. Haven’t done much with it. Line 1 designates Celsius or Fahrenheit (0 or 1). Line 2 is the page title.

sensormap – One line for each sensor. Each line is two parts. The physical sensor ID and the logical name. Don’t mess with the ID. Change the name to what ever you want. The script will automatically populate this file. You can edit this while running. Do NOT delete entries or fields.

Todo:
Add over and under temps for each sensor
Add a signaling method (sound, screen color/flash, email) for over/under temps
Make the web interface pretty
Generate a temperature log
Build an apt-get package

# apt-get -y install apache wget
# wget /var/www/html http://code.jquery.com/jquery-1.9.1.min.js
# mkdir ds18b20; cd ds18b20
# "0\nDS18B20\n" >> cf
# touch sensormap

RaspberryDS.py


import os
import glob
import time
import datetime

os.system('modprobe w1-gpio')
os.system('modprobe w1-therm')

# read the contents of a file 
def read_lines(devicefile):
 f = open(devicefile, 'r')
 lines = f.readlines()
 f.close()
 return lines


# Add new temperature sensors to sensormap file 
def push_new_devices_to_sensormap():
 # get a list of temperature sensors
 devicefiles = glob.glob('/sys/bus/w1/devices/28*/w1_slave')
 # read the sensormap file: physicalname,logicalname\n
 sensorlines = read_lines ("sensormap")

# iterate through each system device
 for devicefile in devicefiles:
 # split the sixth element in the file path and make it lowercase
 device = devicefile.split('/')[5]
 device = device.lower()
 # device file vs sensor file match flag
 wasFound = False
 
 # iterate through the list of sensor lines.
 for sensorline in sensorlines:
 # split a line, make the first element lowercase
 sensor = sensorline.split(',')[0]
 sensor = sensor.lower()

# if there is a match set the flag
 if sensor == device:
 wasFound = True
 
 # this flag is false when the device name isn't in the sensormap
 if wasFound == False:
 # append the device to the sensormap
 with open('sensormap', 'a') as the_file:
 #PhysicalName,LogicalName,LowTempWarn,HighTempWarn,PlaySound 
 the_file.write(device + ',' + device + ",0,100,0\n")
#end


 
def get_temperature(devicefile, cf):
 temp="Sensor not ready."
 lines = read_lines(devicefile)
 # check line for the word "YES"
 if lines[0].strip()[-3:] == 'YES':
 # Grab data after "t=", on the second line
 equals_pos = lines[1].find('t=')

# -1 is NO DATA
 if equals_pos != -1:
 temp_string = lines[1][equals_pos+2:]

if int(cf) == 1:
 temp = "%.1f" % ((float(temp_string) / 1000.0) * 9.0 / 5.0 + 32.0 ) + "F"
 else:
 temp = "%.1f" % ((float(temp_string) / 1000.0) ) + "C"

return temp
#end

# get the device's logical name from the sensormap
def get_logical_name(devicefile,sensorlines):
 # split the line - it's a file path and we only want the sixth element, and make it lowercase
 device = devicefile.split('/')[5]
 device = device.lower()
 # iterate throught the sensormap and return the logical name
 for sensorline in sensorlines:
 # split a line, make the first element lowercase
 sensor = sensorline.split(',')[0]
 sensor = sensor.lower()
 
 # if there is a match set the flag
 if sensor == device:
 return sensorline.split(',')[1]
 return device
#end

while True:
 # push_new_devices_to_sensormap only needs to run every 5 minutes or so. The user shouldn't be
 # hot swapping sensors while powered on.
 push_new_devices_to_sensormap()

# get a list of temperature sensors
 devicefiles = glob.glob('/sys/bus/w1/devices/28*/w1_slave')
 # read the sensor map file
 sensorlines = read_lines ("sensormap")
 # read cf file: [0]C=0 F=1[1],Title
 cf = read_lines("cf")
 
 # HTML main page 
 htmlfile = open("/var/www/html/index.html", "w")
 htmlfile.write("<!DOCTYPE html>\n<html lang='en'>\n<head>\n<meta charset='utf-8' />\n")
 htmlfile.write("<script src='jquery-1.9.1.min.js'></script><script> window.onload = startInterval; function startInterval(){ setInterval('loadTemps();',9000); } function loadTemps() { document.getElementById('success').innerHTML = temp.html; } </script><script> window.onload = refreshInterval; function refreshInterval() { setInterval('updateTemperature();',1000); } function updateTemperature() { $('#temperature').load('temp.html'); } </script>\n")
 htmlfile.write("<title>" + cf[1] + "</title>\n")
 htmlfile.write("</head><body>")
 htmlfile.write("<h1>" + cf[1] + "</h1>\n<div id='temperature'></div>\n")
 htmlfile.write("</body></html>\n")
 htmlfile.close()

# HTML temperature data
 tempfile = open("/var/www/html/temp.html", "w")
 tempfile.write("<table style='width:100%'>")
 # iterate through each system device
 for devicefile in devicefiles:
 tempfile.write("<tr>")
 # get the name and temperature
 tempfile.write("<td style='width:150px'><div id='logical_name'>")
 tempfile.write(get_logical_name(devicefile,sensorlines))
 tempfile.write("</div></td>")
 tempfile.write("<td><div id='temp'>")
 tempfile.write(get_temperature(devicefile, cf[0]))
 tempfile.write("</div></td></tr>")

tempfile.write("</table><br><br>")
 tempfile.write(datetime.datetime.now().strftime("%d %b %y %H:%M:%S"))
 tempfile.close()
 
 time.sleep(10)
Raspberry PI DS18B20 expansion board
Tagged with: , , , , , , , ,

23 Comments on “Multiple DS18B20 Sensors on a single Raspberry PI

    • The bare board is $2.00, USPS – US only. If you’re international, let me know.

      The connectors are extra since there are options – and you solder!

      • One or two main bus
      • PI connector (CONN HEADER .100 DUAL 40POS) @$3.00ea
      • Three pin sensor connectors (CONN HEADER VERT 3POS .100) @$.25ea
      • Temp sensors (with connector) @$4.50ea
  1. That’s great! I’ll take two boards with right angle connectors. I can solder the DS18b20’s to the board? How do I order/pay?

  2. Hey Rush, Yes, bare boards are available and are $2 shipped. If you need a 40 pin connector, let me know what you have on your board.

  3. the indentation of your python script isnt displayed right and im getting errors. could you share via email your script please?

    • I would but I’m out of town. It is all whitespace/indentation errors correctable with the space bar and enter key. Plug the code into an online php checker. Both pep8online.com and onlinegdb.com work.

  4. I would be interested in a couple boards if still available. Have you sold assembled boards for 4 sensors?

    • I do have a few boards available.

      I haven’t sold that particular configuration , I’ve sold a few fully populated board kits (two bus & 5 temp).

      So you’re looking for two boards with four sensor connectors and a 40-pin PI connector?
      There are choices for the 40-pin: right angle or straight and male pin or female socket?

      The bare board, with resistor, is $2.00, USPS – US only. If you’re international, let me know.

      The connectors are extra since there are options – and you solder!

      • PI connector (CONN HEADER .100 DUAL 40POS) @$3.00ea
      • Three pin sensor connectors (CONN HEADER VERT 3POS .100) @$.25ea
      • Temp sensors (with connector) @$4.50ea
  5. I am also interested in a couple of these bare boards. Would you please contact me a my email address?

Leave a Reply