« Fedora Linux – using Sound via Cron | Main | Creating Color Gradients with RRDTOOL & Bash (using temperatures) »
Reading DS18B20 Temperature sensors with DigiTemp
By Dale Reagan | April 25, 2012
Over the past several months I have collected quite a number of temperature readings from a custom sensor network. I started with ~30 sensors and maxed out at ~42 sensors (due to limitations/quirks of 1-Wire protocol/networks.) For background on this project visit the related posts.
I am using Digitemp because it simply works – but it does require specific USB interfaces like the LinkUSB; I run a custom Bash script from cron several times an hour which makes two ‘passes’ on the network; the process currently takes ~65 seconds to make two passes with ~40 sensors. More resources: Digitemp on Google Groups, Digitemp on GitHub.
Some Stats since this project started
Year |Mon.| # Records
2011 | 07 | 64,428
2011 | 08 | 782,857
2011 | 09 | 760,007
2011 | 10 | 770,143
2011 | 11 | 764,658
2011 | 12 | 787,618
2012 | 01 | 785,231
2012 | 02 | 723,985
2012 | 03 | 932,438
I’m anticipating ~9,000,000+ records at month 12
The read/record frequency has been increased from every 5 to every 3 minutes. So far, the majority of these readings have been recorded using a binary executable named digitemp_DS9097U (digitemp – see link above.) Note that I did explore using Arduino for this project but I reached network limitations that the LinkUSB seems to over-come.
I’ve encountered a number of issues while collecting this data:
- intermittent network disruptions – partly to power outages, partly due to quirks of 1-Wire networks using star topologies
- OS level resource contention – Device locking implemented by digitemp (on my Fedora system) is not working so I implemented some locking at the shell script level
- the ‘-i’ option of DigiTemp creates an ‘initialization file’; I re-create it during each run of my script and check for ‘network changes’
- if the current sensor count is above a threshold then I record data
- if the sensor count is below the minimum required number of sensors then I re-scan the network (and give up after 3 tries)
- audible alarms will sound if the sensor count falls below the minimum (during appropriate times of day…) 🙂
From the DigiTemp Docs [my comments within brackets]
- “Before you can read the sensors you need to initialize the list of serial numbers (each 1-wire sensor has a unique 64 bit serial number used to address it on the bus).
- When you add [or Remove] sensors to your lan you need to rerun the initialization process — be aware that the order that they are detected in depends on their [serial] number,
- so when you add [or Remove] new sensors it may change the order of your sensors [in your configuration file].”
Using DigiTemp – command line options
$ digitemp_DS9097U ## no options and with format options not listed ## Error! Not enough arguements. DigiTemp v3.5.0 Copyright 1996-2007 by Brian C. Lane GNU Public License v2.0 - http://www.digitemp.com Compiled for DS9097U Usage: digitemp [-s -i -I -U -l -r -v -t -a -d -n -o -c] -i Initalize .digitemprc file -I Initalize .digitemprc file w/sorted serial #s -w Walk the full device tree -s /dev/ttyS0 Set serial port -l /var/log/temperature Send output to logfile -c digitemp.conf Configuration File -r 1000 Read delay in mS -v Verbose output -t 0 Read Sensor # -q No Copyright notice -a Read all Sensors -d 5 Delay between samples (in sec.) -n 50 Number of times to repeat 0=loop forever
Some notes for using digitemp:
- Command line options are provided to over-ride the default configuration file settings ~/.digitemprc
- If you don’t supply arguments then whatever is in your digitemprc file will be used.
- The default configuration file is auto-created when you run the ‘initialize’ option.
- To read all known sensors simply use the ‘-a’ switch.
- To discover sensors use ‘-i’ or ‘-I’
- To read a single, known sensor use ‘-t Sensor_Number_From’ ~/.digitemprc OR your_config_file
- Reading a sensor with a specific 1-Wire serial number is not currently supported – at least not directly – I borrowed the code from a Google Groups post and tweaked a bit (and noting that there is little/no error checking but this may provide a starting place for folks.)
Read.On.sh – Simple Bash script – read one sensor using Digitemp
- creates a temp config file for digitemp based on a user supplied 1-Wire serial number and
- prints out the command needed to the use config file
- note that using a config file with just one sensor ‘-a’ (read all) ~= ‘-t 0’ (read the first sensor)
#!/bin/bash
## Read.One.sh
## http://web-tech.ga-usa.com/ - sample script by Dale Reagan
## Dallas/Maxim 1-Wire devices have a unique serial number
## Digitemp requires that this serial number be available in HEX
## a 'normal' Digitemp Config file would contain a list of ALL
## sensors on the network; this is an artificial config file
## containing only One sensor ID - which is supplied by the user.
######################
### create needed format from Sensor ID string using some Bash magic via
### in-place, positional variable extraction
### noting that we start our 'character count' at '0'
function set_vars {
A=0x${SENSOR_ID:0:2} ## extract 1st two characters
B=0x${SENSOR_ID:2:2}
C=0x${SENSOR_ID:4:2} ## extract 2 chars starting at character 4
D=0x${SENSOR_ID:6:2}
E=0x${SENSOR_ID:8:2}
F=0x${SENSOR_ID:10:2}
G=0x${SENSOR_ID:12:2}
H=0x${SENSOR_ID:14:2}
}
########################
### a 'here document' to create the
### configuration file
function share_conf {
cat << END_OF_CONF > ${ONE_CONF}
### Sensor ID: ${SENSOR_ID}
TTY /dev/ttyUSB0
READ_TIME 1000
LOG ${ONE_CONF}.log
LOG_TYPE 1
LOG_FORMAT "%b %d %H:%M:%S Sensor %s C: %.3C F: %.2F"
CNT_FORMAT "%b %d %H:%M:%S Sensor %s #%n %C"
HUM_FORMAT "%b %d %H:%M:%S Sensor %s C: %.3C F: %.2F H: %h%%"
SENSORS 1
ROM 0 $A $B $C $D $E $F $G $H
################################################
### Read ONE Sensor with ID: ${SENSOR_ID}
### $(date) ###
################################################
END_OF_CONF
}
###
function show_usage {
printf "\nERRor - need 1-Wire Serial Number...\n"
printf "####################################\n\n"
exit 1
}
#################
### the 'main' for this script
ONE_CONF=/tmp/Read.One.1wire.conf
SENSOR_ID="$1"
if [[ "${SENSOR_ID}" == "" ]] ; then show_usage ; fi
set_vars
share_conf
cat ${ONE_CONF}
ls -l ${ONE_CONF}
D_CMD1="digitemp_DS9097U -q -s /dev/ttyUSB0 -c ${ONE_CONF} -a"
D_CMD2="digitemp_DS9097U -q -s /dev/ttyUSB0 -c ${ONE_CONF} -t 0"
printf "\n ${D_CMD1}\n ${D_CMD2}\n\n"
Output from Read.One.sh (1-Wire/digitemp)
$ bash Read.One.sh 28123456789ABCDE ### Sensor ID: 28123456789ABCDE TTY /dev/ttyUSB0 READ_TIME 1000 LOG /tmp/Read.One.1wire.conf.log LOG_TYPE 1 LOG_FORMAT "%b %d %H:%M:%S Sensor %s C: %.3C F: %.2F" CNT_FORMAT "%b %d %H:%M:%S Sensor %s #%n %C" HUM_FORMAT "%b %d %H:%M:%S Sensor %s C: %.3C F: %.2F H: %h%%" SENSORS 1 ROM 0 0x28 0x12 0x34 0x56 0x78 0x9A 0xBC 0xDE ################################################ ### Read ONE Sensor with ID: 28123456789ABCDE ### Wed Apr 25 09:00:41 EDT 2012 ### ################################################ -rw-rw-r-- 1 root root 506 Apr 25 09:00 /tmp/Read.One.1wire.conf digitemp_DS9097U -q -s /dev/ttyUSB0 -c /tmp/Read.One.1wire.conf -a digitemp_DS9097U -q -s /dev/ttyUSB0 -c /tmp/Read.One.1wire.conf -t 0
Other Open Source Software supporting 1-Wire Devices
- OWFS – One Wire File System; sensors are ‘mounted’ under a special file system and accessed via a simple ‘cat /mnt/1wire/28.xxxxxx/temperature’ (or similar path) – I found OWFS to be somewhat slow and quirky – sensors ‘left’ the list [could be due to my using the same USB device via Digitemp…]
- Arduino 1-Wire Libraries – build your own network of devices; write your own code; great learning environment! (note that this is another post on this site written during the research stage of this project.)
Of course, your mileage should vary – at least a small bit… 🙂
Topics: 1-Wire, Computer Technology, Unix-Linux-Os, Web Problem Solving | Comments Off on Reading DS18B20 Temperature sensors with DigiTemp
Comments are closed.