Reading 14bit from an SI7021 temperature and humidity sensor

The Si7021-A20 is capable of providing up to 14bit resolution for temperature and up to 12bit for relative humidity, over an I2C connection. However, many examples on the internet only use 8bit. I tried to get the full resolution on a Raspberry Pi using Python, version 3.

I2C is a simple, serial protocol for interconnecting devices. It allows the transfer of small amounts of data between a master device and various slaved devices.

Prerequisites

You need to configure the I2C interface using raspi-config first. Then install some related tools:

sudo apt-get install python3-smbus
# at the time writing, i2c-tools are not available for python3 by default
sudo apt-get install -y i2c-tools

You can test, whether I2C is available and whethere a device is connected using the following command in the terminal:

sudo i2cdetect -y 1

You should get something like

     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- -- 
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
40: 40 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
70: -- -- -- -- -- -- -- --                         

This shows a single device connected at hardware address 0x40.

Getting data

Now here it gets tricky. Most of the examples on the internet did not work for me. Either they read the same data bytes twice or they produced an error, like in this raspberry forum thread.

I had success getting a single byte (8 bit) of information using the SMBus, but not more. I have asked a question on the Raspberry Pi Stackexchange. Look it up to find the corresponding script.

The solution

Joan at abyz.me.uk provides a complete Si7021.py python module with a class and a main function that allows to fully interface with the Si7021 sensor.

To use it, just download the ZIP and place the contained Si7021.py in a folder of your choice. Since the script requires pigpio as a daemon, you must install and start that first. The script runs for 10 seconds, takes repeated measurements and prints them out.

# installing pigpio first
sudo apt-get install pigpio python-pigpio python3-pigpio

# get the Si7021.py script
wget http://abyz.me.uk/rpi/pigpio/code/Si7021_py.zip
unzip Si7021_py.zip

# start the pigpiod daemon; -l disables the remote socket interface, it's not needed to read a local sensor
sudo pigpiod -l	
# start the main function in the module
python3 Si7021.py

# stop the daemon, if no longer used
sudo killall pigpiod

I have used the module in a simple script that just reads one value at maximum resolution, with a formatted output:

https://github.com/suterma/WeatherPress/blob/master/Si7021-singleread.py

import time
import Si7021
import pigpio

pi = pigpio.pi()

if not pi.connected:
   exit(0)
s = Si7021.sensor(pi)

# set the resolution
# 0 denotes the maxium available: Humidity 12 bits, Temperature 14 bits
# See the documentation for more details
s.set_resolution(0)

print("{:.3f} °C".format(s.temperature()))
print("{:.3f} %rH".format(s.humidity()))

s.cancel()
pi.stop()

This gives:

pi@raspberrypi:~ $ python3 Si7021-singleread.py 
27.303 °C
40.574 %rH

Now, these values actually represent a resolution of 12 and 14 bit, respectively.