Raspberry Pi library for sensors DHT11, BMP085, DS18B20, WireGate DR9490R and more!

Working with sensors on the Raspberry Pi is real fun. You can try out stuff, expand the Internet of things, make automations and so on.

The problem for me was that there were so many different scripts out there with different functionalities and outputs. I wanted to make on package with unified in and output and there it is. It would have never been possible with the excellent work of Adafruit Industries (DHT, DS18B20 and BMP085 driver) and of course Matt Hawkins from www.raspberrypi-spy.co.uk (Ultrasonic and PIR driver)

Currently supported sensors: DHT11, DHT22, AM2302 (temperature and humidity), DS18B20 (temperature, with kernel driver or Wiregate), HC-SR04 (Ultrasonic distance sensor), BMP085 (Temperature, pressure, altitude), PIR (Motion detection)

DHT11, DHT22, AM2302, DS18B20, WireGate DR9490R, HC-SR04 (Ultrasonic Sensor),  BMP085 (Temperate, Pressure, Altitude), PIR

 

You can get the whole package from here: rpi_sensors

Or get it via Github (make sure to put all into one directory)

git clone https://github.com/syss/rpi_sensors
git clone https://github.com/adafruit/Adafruit-Raspberry-Pi-Python-Code/tree/master/Adafruit_BMP085

When you want to use this library you need to install the following packages: python-dev python-smbus owfs-fuse

This can be done by the following command

#update lists and upgrade software first
sudo apt-get update && sudo apt-get upgrade
sudo apt-get install -y python-dev python-smbus owfs-fuse

It is very convenient to load all needed modules on startup. You need to disable the blacklisted modules (default on raspbian image) here:

/etc/modprobe.d/raspi-blacklist.conf

just comment out the blacklist lines with a sharp (#)

# blacklist spi and i2c by default (many users don't need them)

#blacklist spi-bcm2708
#blacklist i2c-bcm2708

then you need to set the modules which should be loaded on startup. You will find them here:

/etc/modules

edit it so it looks like this.

# /etc/modules: kernel modules to load at boot time.
#
# This file contains the names of kernel modules that should be loaded
# at boot time, one per line. Lines beginning with "#" are ignored.
# Parameters can be specified after the module name.

snd-bcm2835
#Used for BMP085
i2c-dev
i2c-bcm2708
spi_bcm2708
#Used for 1-Wire DS18B20
w1-gpio
w1-therm

If you use the Dallas Wiregate (DR9490R) you can do these easy steps to make it work with this python library. (make sure you have installed the package owfs-fuse). I found the commands from this site

sudo mkdir /media/1-wire
sudo owfs --allow_other -u /media/1-wire

Now you are done and can use the Python library for your projects.

Some examples will follow in the next days.

 

 

 

Get model number and more details of your Raspberry Pi

For better programming with GPIO on the Raspberry Pi it is required to know on which board revision the program is running on.

The following programcode is best used to determine which GPIO ports are available for interacting.

#!/usr/bin/python
# -*- coding: utf-8 -*- 
################################################
# Stefan Süss - www.sysstem.at
################################################

# Listmodel from http://elinux.org/RPi_HardwareHistory
class BoardRevision(object):
        def __init__(self,revision,releasedate,model,pcbrevision,memory,notes):
            self.revision=revision
            self.releasedate=releasedate
            self.model=model
            self.pcbrevision=pcbrevision
            self.memory=memory
            self.notes=notes

#http://elinux.org/RPi_Low-level_peripherals#GPIO_hardware_hacking
pcb_r1_gpio_ports= (0,1,4,7,8,9,10,11,14,15,17,18,21,22,23,24,25)
pcb_r2_gpio_ports= (2,3,4,7,8,9,10,11,14,15,17,18,22,23,24,25,27,28,29,30,31)            

# Listcontent from http://elinux.org/RPi_HardwareHistory
boardrevisionlist=[]
boardrevisionlist.append(BoardRevision("Beta","Q1 2012","B (Beta)","unknown",256000000,"Beta Board"))
boardrevisionlist.append(BoardRevision(0x0002,"Q1 2012","B",1.0,256000000,""))
boardrevisionlist.append(BoardRevision(0x0003,"Q3 2012","B (ECN0001)",1.0,256000000,"Fuses mod and D14 removed"))
boardrevisionlist.append(BoardRevision(0x0004,"Q3 2012","B",2.0,256000000,"(Mfg by Sony)"))
boardrevisionlist.append(BoardRevision(0x0005,"Q4 2012","B",2.0,256000000,"(Mfg by Qisda)"))
boardrevisionlist.append(BoardRevision(0x0006,"Q4 2012","B",2.0,256000000,"(Mfg by Egoman)"))
boardrevisionlist.append(BoardRevision(0x0007,"Q1 2013","A",2.0,256000000,"(Mfg by Egoman)"))
boardrevisionlist.append(BoardRevision(0x0008,"Q1 2013","A",2.0,256000000,"(Mfg by Sony)"))
boardrevisionlist.append(BoardRevision(0x0009,"Q1 2013","A",2.0,256000000,"(Mfg by Qisda)"))
boardrevisionlist.append(BoardRevision(0x000d,"Q4 2012","B",2.0,512000000,"(Mfg by Egoman)"))
boardrevisionlist.append(BoardRevision(0x000e,"Q4 2012","B",2.0,512000000,"(Mfg by Sony)"))
boardrevisionlist.append(BoardRevision(0x000f,"Q4 2012","B",2.0,512000000,"(Mfg by Qisda)"))

def getRevision():
    revisionstring="Revision"
    revision="unknown BoardRevision"
    with open("/proc/cpuinfo","r") as file:
        for line in file.readlines():
            if line.find(revisionstring)!=-1:
                revision="0x"+line.split(":")[1][1:-1]           
    return revision

def getBoardRevision(revision=getRevision()):
    try:
        #only check the last 2 Bytes for revision (ingore overvoltage indicator)
        #http://elinux.org/RPi_HardwareHistory
        revision=int(revision,16)&0xFFFF
    except ValueError:
        revision=revision
    for boardrevision in boardrevisionlist:
        if revision == boardrevision.revision:
            return boardrevision
    return "unknown BoardRevision"

def getGPIOPorts():
    rpi=getBoardRevision()
    try:
        if rpi.pcbrevision == 1.0:
            return pcb_r1_gpio_ports
        if rpi.pcbrevision == 2.0:
            return pcb_r2_gpio_ports
        else:
            return ()
    except AttributeError:
        return ()

def hasBeenOverVolted():
    ovvalue=0x1000000
    try:
        ov=int(getRevision(),16)&ovvalue
        if ov==ovvalue:
            return 1
        else:
            return 0
    #could not determine due to error in reading Revision
    except ValueError:
        return -1

An example of how you can use the code:

#!/usr/bin/python
import rpi_version

print "GPIO Ports: ", rpi_version.getGPIOPorts()
print "Has been overvolted: ",rpi_version.hasBeenOverVolted()
rpi=rpi_version.getBoardRevision()
try:
    print       "Revision: ",hex(rpi.revision)
    print       "Releasedate: ",rpi.releasedate
    print       "Model: ",rpi.model
    print       "PCB Revision: ",rpi.pcbrevision
    print       "Memory: ",rpi.memory*10**-6,"MB"
    print       "Notes: ",rpi.notes
except ValueError:
    print "Could not detect model"

Output:

GPIO Ports:  (2, 3, 4, 7, 8, 9, 10, 11, 14, 15, 17, 18, 22, 23, 24, 25, 27, 28, 29, 30, 31)
Has been overvolted:  0
Revision:  0xd
Releasedate:  Q4 2012
Model:  B
PCB Revision:  2.0
Memory:  512.0 MB
Notes:  (Mfg by Egoman)

I hope that you save some time by using my python code!

 

 

7 Segment Display with 74HC595 Shift Register and Raspberry Pi

This project shows how to use the Raspberry Pi to drive a 7 Segment Display with the help of a 74HC595 chip.

Parts used in this project:

  • Breadboard
  • Wiring cables (Male-Male, Female-Male)
  • 7 Segement display (it actually has 8 segments because of the dot)
  • 74HC595 Chip
  • Raspberry Pi Revision 2
  • some Python code

Here is a schematic made with fritzing of the project when it is ready. Here a link to download the 7-segment-display with 74HC595 and Raspberry Pi fritzing project.

7-Segment-Display_Steckplatine

the interresting thing here is the 74HC595 Chip. It takes some time to understand what it does. I think that the video from Kevin Darrah describes it fast and easy.

Here is the Python code: rpi_7_segment_74hc595

#!/usr/bin/python

import RPi.GPIO as GPIO
import time

#Data Pins needed on the RPi
DATAIN=17 #DS
LATCH=27  #STCP
CLOCK=22  #SHCP
CLEAR=25  #MR Low
OE=11     #Output Enable Low

#inter character sleep
icsleep=0.06 

#defining all the single LEDs
led1=0x80 #10000000
led2=0x40 #01000000
led3=0x20 #00100000
led4=0x10 #00010000
led5=0x08 #00001000
led6=0x04 #00000100
led7=0x02 #00000010
led8=0x01 #00000001

#definition of all writeable letters and numbers
letter={"0":0xFC,
        "1":0x30,
        "2":0xDA,
        "3":0x7A,
        "4":0x36,
        "5":0x6E,
        "6":0xEE,
        "7":0x38,
        "8":0xFE,
        "9":0x3E,
        "a":0xBE,
        "b":0xE6,
        "c":0xCC,
        "d":0xF2,
        "e":0xCE,
        "f":0x8E,
        "g":0x7E,
        "h":0xB6,
        "i":0x30,
        "j":0xF0,
        "l":0xC4,
        "n":0xBC,
        "o":0xFC,
        "p":0x9E,
        "s":0x6E,
        "t":0x38,
        "u":0xF4,
        "x":0xB4,
        "y":0x76,
        "z":0xDE
}

#loading function sequence
load1=0x06 #00000110
load2=0x22 #00100010
load3=0x60 #01100000
load4=0xC0 #11000000
load5=0x82 #10000010
load6=0x12 #00010010
load7=0x18 #00011000
load8=0x0C #00001100

#up-down loading function sequence
ud1=led8
ud2=led2
ud3=led1+led3
ud4=led7
ud5=led6+led4
ud6=led5

#left-right loading function sequence
lr1=led1+led6
lr2=led2+led5+led7
lr3=led3+led4
lr4=led8

#rotational loading function sequence
rot1=led2+led5
rot2=led1+led6+led3+led4+led7

#putting all segments of the sequences in a list
letterrange=[]
hexrange=[]
for value in letter.values():
    letterrange.append(value)
for value in letter.values():
    if value != "g":
        hexrange.append(value)
loadrange=[load1,load2,load3,load4,load5,load6,load7,load8]
udrange=[ud1,ud2,ud3,ud4,ud5,ud6]
ledrange=[led1,led2,led3,led4,led5,led6,led7,led8]
lrrange=[lr1,lr2,lr3,lr4]
rotrange=[rot1,rot2]
spinrange=[led1,led2,led3,led4,led5,led6]

#GPIO definition
def setup():
    GPIO.setmode(GPIO.BCM)
    GPIO.cleanup()
    GPIO.setup(DATAIN,GPIO.OUT)
    GPIO.setup(CLOCK,GPIO.OUT)
    GPIO.setup(LATCH,GPIO.OUT)
    GPIO.setup(CLEAR,GPIO.OUT)
    GPIO.setup(OE,GPIO.OUT)

    GPIO.output(LATCH,False) #Latch is used to output the saved data
    GPIO.output(CLEAR,True)  #Clear must always be true. False clears registers
    GPIO.output(OE,False)    #Output Enable speaks for itself. Must be False to display
    GPIO.output(CLOCK,False) #Used to shift the value of DATAIN to the register
    GPIO.output(DATAIN,False)#Databit to be shifted into the register 

    #Clean up GPIO, set display to no character
def cleanup():
    #Set all leds to off
    writenumber(0)
    #writeout stored in character
    writeout()
    #writeout "nothing"
    writeout()
    time.sleep(0.7)
    GPIO.cleanup()

#shifts in a bit (but does not write it yet)
def shift(input):
   if input == 1:
       input=True
   else:
       input=False

   GPIO.output(DATAIN,input)
   GPIO.output(CLOCK,GPIO.HIGH)
   GPIO.output(CLOCK,GPIO.LOW)
   GPIO.output(DATAIN,GPIO.LOW)

#writes the stored data from register out to pins
def writeout():
   #Display LEDs
   GPIO.output(LATCH,GPIO.HIGH)
   #needed to read characters. otherwise the characters would be display to fast after each other
   time.sleep(icsleep)
   GPIO.output(LATCH,GPIO.LOW)

#writes a character to the register
def writenumber(number):
    for x in range(0,8):
        shift((number>>x)%2)

#writes a range of character to the display        
def writerange(range):
    for x in range:
        writenumber(x)
        writeout()

#additive and following substractive writeout of a range of characters
def writeaddrange(range):
    character=0
    for x in range:
        character+=x
        writenumber(character)
        writeout()
    for x in range:
        character-=x
        writenumber(character)
        writeout()

#additive and following substractive writeout with reversed call of a range of characters
def writeaddremrange(range):
    character=0
    for x in range:
        character+=x
        writenumber(character)
        writeout()
    for x in range:
        character-=x
        writenumber(character)
        writeout()
    for x in reversed(range):
        character+=x
        writenumber(character)
        writeout()
    for x in reversed(range):
        character-=x
        writenumber(character)
        writeout()

#additive and following reversed substractive writeout of characters        
def writeaddbackrange(range):
    character=0
    for x in range:
        character+=x
        writenumber(character)
        writeout()
    for x in reversed(range):
        character-=x
        writenumber(character)
        writeout()

#chained XORed and reversed XORed writeout of characters
def writexorrange(range):
    #close the chain to have no interrupts while displaying
    character=range[0]&range[-1]
    for x in range:
        character^=x
        writenumber(character)
        writeout()
    for x in range:
        character^=x
        writenumber(character)
        writeout()
    for x in reversed(range):
        character^=x
        writenumber(character)
        writeout()
    for x in reversed(range):
        character^=x
        writenumber(character)
        writeout()

print("####Setup####")
setup()

#Tryout of most ranges and displayfunctions
try:
    print("####Write Stuff####")
    while True:
        writerange(letterrange)
        writerange(hexrange)
        writerange(loadrange)
        writeaddremrange(udrange)
        writexorrange(loadrange)
        writexorrange(udrange)
        writexorrange(ledrange)
        writexorrange(lrrange)
        writexorrange(rotrange)
        writexorrange(spinrange)
        writeaddrange(ledrange) 
        writeaddbackrange(ledrange)
#Wait for KeyboardInterrupt or SystemExit (called by kill or others)
except (KeyboardInterrupt, SystemExit):
    print("Exit...")

finally:
    cleanup()

Raspberry Pi drives a 7 Segment Display with the help of a 74HC595.

Have fun driving your 7 Segment display with the Raspberry Pi.