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.
- 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)
Where can I get a board? How much do they cost? Do they come with sensors?
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!
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?
Yes, the DS18b20 leads can be soldered directly to the board.
I’ll shoot you an email with payment options.
Hi Dave,
Is this still available? I would really like one.
Thanks!
Hey Marco.
Yes, I have a few bare boards left. Received you email, I’ll shoot you a PP request. Do you need any connectors?
_Dave
Hi Dave,
The only connector I need is the one that connects the GPIO to the expansion board. Thanks!
You’re Pi’s GPIO… Does it have:
A male header (pins)
A female receptacle (plug)
Or is it empty?
Hi, it has a male headers
Ok. Email sent.
Do you have any boards left?
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.
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.
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!
I am also interested in a couple of these bare boards. Would you please contact me a my email address?
I’m also interested in a PCB. How can we connect?
Right here.
Great! I’d be interested in two.
Thanks!
I’ll shoot you an email.
I am interested in a populated board, for 4-5 temp sensors.
I’m soldering?
With 5 sensors?