Contents

Temperature Sensors

Thermal sensors are very cheap. It should be trivial to have a computer know the temperature of anything you want to monitor. But it’s not always so easy.

DS1820

(Everything I know about this is thanks to theamk!)

The inexpensive solution I used was a Dallas Semiconductor DS1820 wired directly to a 1-wire/USB converter using normal RJ11 4 wire telephone cable. The 1-wire protocol is explained in this wikipedia article.

Wiring

DS1820 leads go 1 to 3 left to right looking at contacts emerging from device with flat part facing up. Looking at the RJ11/12 receptacle with the retaining tab facing down, the contacts are numbered 1 to 6 (RJ12) or 1 to 4 (RJ11).

  • contact 1 = No connection

  • contact 2 = DS1820 lead #3 Vdd - Optional Vdd and lead #1 GND - Ground (joined)

  • contact 3 = middle lead #2 of DS1820 DQ - Data In/Out

  • contact 4 = No connection

I believe that multiple sensors can be wired in parallel up to some absurd limit (related to how long the cabling is; 100m cables (total) should be no problem for single devices.

my setup

One Wire File System (owfs)

You can query the state of the sensors using Linux’s one wire file system.

Warning
It can be tricky to install. On Ubuntu, don’t for get these packages: libusb-dev libfuse-dev fuse-utils (and maybe more). Though see below for modern improvements.

Raspberry Pi

Note that Raspberry Pis are ready to go with one wire right from the headers. Things will show up on /sys/bus/w1/devices as discussed here.

Old-Fashioned DIY

Load fuse module (fuse = filesystem in userspace) which will allow 1-wire information to be present as a virtual file system.

$ sudo modprobe fuse

Run the owfs binary that mounts the mountpoint (/mnt here) with the 1-wire data.

$ sudo ./module/owfs/src/c/owfs -u /mnt/
DEFAULT: ow_usb_msg.c:DS9490_open(263) Opened USB DS9490 bus master at 4:5.
DEFAULT: ow_usb_cycle.c:DS9490_ID_this_master(191) Set DS9490 4:5 unique id to 81 2C 70 26 00 00 00 75

Modern Pre-Packaged

In modern times (2018) it looks like it’s getting easier. Just plugging in my USB adaptor, I got this in dmesg.

usbcore: registered new interface driver DS9490R

Installing the system now is just what one would expect.

sudo apt-get install owfs

Then you can poke around a web interface at localhost:2121. Check that the owserver is up.

sudo service owserver status

Maybe make a directory for the mount and enable that in the config.

sudo mkdir /mnt/1wire

The debian system had a neat trick where it started up with dummy stuff as set by the config file, /etc/owfs.conf. This proved that the drivers were all working ok. Then you can switch over to your real hardware and start proper troubleshooting.

I found that I didn’t need the fancy web thing so I just turned it off. Then I used the old command as normal (in the default path now).

$ sudo service owftpd stop
$ sudo service owhttpd stop
$ sudo systemctl disable owftpd
$ sudo systemctl disable owhttpd
$ sudo mkdir /mnt/1wire
$ sudo owfs -u /mnt/1wire --allow_other
$ sleep 10 # Give it some time to get detected.
$ sudo cat /mnt/1wire/10.5BBC0F010800/temperature
22.0625

Don’t forget that allow_other (which comes from /etc/fuse.conf terminology) so that you don’t have to be root to poke through things. It also looks like you can specify this in /etc/owfs.conf.

Usage

Start querying the data. 10.5BBC0F010800 is the unique ID of my DS1820 sensor. Other sensors in the system will have other IDs.

$ printf "temp:%s\n" `sudo cat /mnt/10.5BBC0F010800/temperature`
temp:24.3125

Accuracy

The specified accuracy is +/-0.5C from -10C to +85C but I feel it’s generally within .2C. It’s certainly good enough for normal purposes. Strangely the temperature seems to be reported in full decimal notation where the resolution is 1/16 degree Celsius.

Cost

  • $2 sensor

  • $28 converter

  • $2 50ft RJ11 Modular Telephone Cord, 4 Conductor 6P4C, Pin 1-1

  • $3 Modular Surface Mount Jack, End Access, RJ12

Note
multiple sensors can use one converter.
Note
Prices in 2010.

Humidity

I haven’t tried these but if you’re interested in humidity it might be good to look into the Honeywell HIH-4000 Series of ICs. In 2018, they seem to be around $24.

acpi/thermal_zone

Often motherboard and CPU temperature sensors work out of the box with Linux:

$ cat /proc/acpi/thermal_zone/THM0/temperature
temperature:             50 C

It looks that that very handy virtual file is being replaced with a nice confusing mess which lives somewhere in the region of:

/sys/class/thermal

lm_sensors

If you’re pretty sure that there are sensors on the motherboard but acpi doesn’t show them, often lm_sensors can.

The major distributions usually have this available. To install lm_sensors on CentOS: sudo yum install lm_sensors. On Debian it seems to be lm-sensors.

Then you have to run sensors-detect as root. Do what it says. If, like me, you have no idea what it’s doing, it’s probably efficient to just accept all defaults with:

yes "" | sensors-detect

If all goes well you’ll be able to use the sensors command that produces all kinds of info including temparatures, voltages, and fan speeds.

Typical Output Of sensors Command
$ sensors
lm78-i2c-0-2d
Adapter: SMBus PIIX4 adapter at 0b00
VCore 1:   +1.74 V  (min =  +0.00 V, max =  +3.49 V)
VCore 2:   +1.68 V  (min =  +0.45 V, max =  +0.16 V)   ALARM
+3.3V:     +3.33 V  (min =  +2.85 V, max =  +2.77 V)   ALARM
+5V:       +5.59 V  (min =  +4.84 V, max =  +2.47 V)   ALARM
+12V:      +8.63 V  (min =  +8.15 V, max =  +1.46 V)   ALARM
-12V:      -5.90 V  (min =  -9.46 V, max =  -4.01 V)   ALARM
-5V:       -2.50 V  (min =  -3.95 V, max =  -2.70 V)
fan1:        0 RPM  (min = 3461 RPM, div = 2)          ALARM
fan2:        0 RPM  (min = 6818 RPM, div = 2)          ALARM
fan3:        0 RPM  (min = 168750 RPM, div = 2)          ALARM
temp:      +39.0°C  (high =   +32°C, hyst =  +105°C)   ALARM
vid:       +3.00 V
alarms:   Board temperature input (LM75)               ALARM
alarms:   Chassis intrusion detection                  ALARM

If all does not goe well, check out this really useful on-line diagnostic of your hardware. Just feed it the output of lspci -n.

Raspberry Pi

Since lm-sensors does not seem to find anything useful with Raspberry Pi hardware I’ve used, you have to look elsewhere. Fortunately there is a way.

function pitemp {
    # Internal temperature of a Raspberry Pi.
    vcgencmd measure_temp | sed "s:temp=\([0-9.][0-9.]*\)'C:\1:"
}

Temperature Monitoring

Often you are curious if some hardware instability is related to temperature. One easy thing to do is to set up a little script to log the temperature over time. Maybe you can see a temperature rise when the machine stops working (i.e. stops logging).

$ while sleep 10; do echo  `date` `sensors|grep ^temp|awk '{print $2}'` >> ~/tempwatch_node87; done &

Here’s a simple script to collect cpu average temperatures and hard drive temperature.

#!/bin/bash
# Succinct one line report of CPU average temps and hard drive temp.
DRIVE=/dev/sdb
CORES=$(grep ^processor /proc/cpuinfo | wc -l)
TS=$(date '+%Y%m%d-%H%M%S')
DT=$(sudo smartctl -a ${DRIVE} | grep Temperature_Celsius | awk '{print $10}')
CPUAVG=$(sensors | grep ^Core | cut -c16-19 | awk "{X+=\$1}END{print X/${CORES}}")
echo "${TS} CPU-${CPUAVG} HD-${DT}"

Commercial Temperature Monitoring Offerings

IPMI

IPMI stands for "Intelligent Platform Management Interface" and is a standard used by hardware to manage monitoring by various hardware devices. IPMI can support SNMP (Simple Network Management Protocol) for querying and setting hardware states.

OpenIPMI is probably a good place to start looking for Linux IPMI functionality.

Web Weather

Maybe you’d like your computer to get the best guess of a region’s weather without sensors, or more correctly, using someone else’s sensors. Here are some hints about how to get weather information off the internet.

weather.gov

This is the USA’s best source of data, but it is a patchwork of sources and formats. They do have an HTTP API though. You can find some documentation here.

First, make sure you get a User Agent ready (see here for more info).

UA="User-Agent: XedQuery/cxe-weathergovATxed.ch"

With that in place, you can make requests. It’s often helpful to use jq to parse the JSON that is returned. This queries the properties for a certain latitude/longitude to find the weather service’s 2.5kmx2.5km grid coordinates.

$ wget -qO- --header="${UA}" 'https://api.weather.gov/points/43.027985,-78.881360' |\
> jq '.properties.gridX,.properties.gridY'
34
52

What’s the "office" responsible for this grid location?

$ wget -qO- --header="${UA}" 'https://api.weather.gov/points/43.027985,-78.881360' |\
> jq '.properties.forecastOffice' | awk 'BEGIN{FS="/"}{print $NF}' | tr -d '"'
BUF

Note that you didn’t need to run those commands per se — you can just look at the output of that call. Now that you know the office and their grid location for the physical location you’re interested in, you can do this call.

wget -qO- --header="${UA}" 'https://api.weather.gov/gridpoints/BUF/34,52/forecast' |\
> jq '.properties.periods[].temperature' | awk '{print ($1-32)/9*5}'
32.7778
18.3333
21.1111
14.4444
22.2222
10
17.2222
10
20
12.7778
23.3333
15
25.5556
16.6667

This prints out the forecast temps (converted from freedom units).

Here’s one for hourly forecasts. Note it doesn’t have humidity and pressure and a bunch of stuff on the graphs.

https://api.weather.gov/gridpoints/BUF/34,52/forecast/hourly

Just need the official temperature in your data? Here is a way to query current status (in C, using awk to tame exuberant precision).

$ wget -qO- --header="${UA}" 'https://api.weather.gov/stations/KBUF/observations/latest' |\
> jq '.properties.temperature.value' | awk '{printf("%6.3f\n",$1)}'
27.200

Note the confusing "KBUF" instead of "BUF" as used in previous examples. KBUF is the "station" which is collecting the weather data; BUF is the weather service field office designation.