This is a Python package that enables Raspberry Pi to read various sensors (and interact with some non-sensors). It has been tested on Python 2.7 running on Raspbian on Raspberry Pi 2 Model B.
Supported devices include:
- DS18B20 temperature sensor
- BMP180 pressure and temperature sensor
- HTU21D humidity and temperature sensor
- ML8511 UV sensor
- MCP3004 A/D Converter (MCP3008 also compatible)
- LCD1602 and LCD2004 display
The chief motivation for this package is educational. I am teaching a Raspberry Pi course, and find it very troublesome for students having to download a separate library every time they use another sensor. With this package, download once and they are set (for my course, anyway). I hope you find it useful, too.
It is best to update Linux first.
sudo apt-get update
sudo apt-get upgrade
For Raspbian Jessie, you may have to do the following to fix pip
(because of its using an older version of requests
):
sudo apt-get remove python-pip
sudo easy_install -U pip
Install this package:
sudo pip install sensor
But the sensor
package would not work by itself. Communicating with sensors often requires some sort of serial protocol, such as 1-wire, I2C, or SPI. You have to know which sensor speaks which, and set up Linux and Python accordingly.
sudo nano /boot/config.txt
, add this line:
dtoverlay=w1-gpio
Reboot.
sudo apt-get install i2c-tools python-smbus
sudo nano /etc/modules
, add this line:
i2c-dev
sudo nano /boot/config.txt
, add this line:
dtparam=i2c1=on
Reboot.
sudo apt-get install python-dev
sudo pip install spidev
sudo nano /boot/config.txt
, add this line:
dtparam=spi=on
Reboot.
Unlike many libraries out there, this library knows no default bus number and no default device address. I want learners to be explicitly aware of those numbers, even if they are fixed.
For example:
- I2C bus is numbered 1
- SPI bus is numbered 0
To find out individual sensor's address:
- For 1-wire sensors, go to
/sys/bus/w1/devices/
, and look for a long sequence of numbers - For I2C sensors, use
i2cdetect -y 1
- For SPI sensors, you should know which CS pin you used
Unlike many libraries out there, this library does not return a simple Celcius degree when reading temperatures, does not return a simple hPa value when reading pressure, does not return a simple RH% when reading humidity, etc. Instead, I return a namedtuple representing the quantity, which offers two benefits:
- No more conversion needed. Suppose you get a Temperature called
t
, you may access the Celcius degree byt.C
as easily as you do Fahrenheit byt.F
. - Namedtuples may have methods. For example, a Pressure has a method called
altitude()
, which tells you how high you are above mean sea level. It is convenient and intuitive.
Keep reading to see how it really works ...
-
Temperature, 1-wire
-
To find out the sensor's address:
$ cd /sys/bus/w1/devices/ $ ls 28-XXXXXXXXXXXX w1_bus_master1
Read the sensor as follows:
from sensor import DS18B20
ds = DS18B20.DS18B20('28-XXXXXXXXXXXX')
t = ds.temperature() # read temperature
print t # this is a namedtuple
print t.C # Celcius
print t.F # Fahrenheit
print t.K # Kelvin
- Pressure + Temperature, I2C
- Use
i2cdetect -y 1
to check address. It is probably0x77
.
from sensor import BMP180
# I2C bus=1, Address=0x77
bmp = BMP180.BMP180(1, 0x77)
p = bmp.pressure() # read pressure
print p # namedtuple
print p.hPa # hPa value
t = bmp.temperature() # read temperature
print t # namedtuple
print t.C # Celcius degree
p, t = bmp.all() # read both at once
print p # Pressure namedtuple
print t # Temperature namedtuple
# Look up mean sea level pressure from local observatory.
# 1009.1 hPa is only for example.
a = p.altitude(1009.1)
print a # Altitude ...
print a.m # in metre
print a.ft # in feet
- Humidity + Temperature, I2C
- Use
i2cdetect -y 1
to check address. It is probably0x40
.
from sensor import HTU21D
# I2C bus=1, Address=0x40
htu = HTU21D.HTU21D(1, 0x40)
h = htu.humidity() # read humidity
print h # namedtuple
print h.RH # relative humidity
t = htu.temperature() # read temperature
print t # namedtuple
print t.F # Fahrenheit
h, t = htu.all() # read both at once
- UV intensity, Analog output
- Cannot interface with Pi directly. Must do so via an A/D converter, e.g. MCP3004.
- Output is expressed in mW/cm2 (milli-Watt per cm2), and cannot be translated into a UV index simply.
# another style of import
from sensor.ML8511 import ML8511
from sensor.MCP3004 import MCP3004
# A/D converter
# SPI bus=0, CS=0, V_ref=3.3V
mcp = MCP3004(0, 0, 3.3)
# analog output -> channel 0 on MCP3004
ml = ML8511(mcp, 0)
uv = ml.uv() # read UV intensity
print uv # namedtuple
print uv.mW_cm2 # mW/cm2
- Not a sensor, obviously. Useful for displaying sensor data.
- Use
i2cdetect -y 1
to check address. It is probably0x27
. - Both are used the same way. Just supply the correct class name, as below.
from sensor.LCD1602 import LCD1602
# I2C bus=1, Address=0x27
lcd = LCD1602(1, 0x27)
lcd.display('Nick Lee', 1) # show my name on line 1
lcd.display('Hong Kong', 2) # show my city on line 2
lcd.clear()