Thursday, January 7, 2016

DS18B20 temperature sensor with the Raspberry Pi

The Raspberry Pi is an ideal device as the central component in DIY projects like home automation or a weather station. One of the key sensors in these projects is a temperature sensor. In this blog post a tutorial will be provided on how to get started with some of these temperature sensors. This tutorial is a follow-up on my previous post about installing python 3.5.1 on the Raspberry Pi. However, in this tutorial I'm not (yet) using features of python that are not supported by the system installed version (3.4.2).

There are a lot of cheap temperature sensors available for these kind of projects on eBay. The first sensor that will be used in this tutorial is the  DS18B20. This component provides 9-bit to 12-bit Celsius temperature measurements, it also has an alarm function with nonvolatile user-programmable upper and lower trigger points. The DS18B20 communicates over a 1-Wire bus. If used in parasite power mode, this bus only needs 2 lines (data and ground) but power can also be provided by the third line. It measured temperature in the range of -55°C to +125°C and is accurate to ±0.5°C over the range of -10°C to +85°C. This component can be found in two versions a "normal" version (it looks like a transistor) and a waterproof version. The last one is nice for outdoor projects!

For this tutorial, the sensor is connected to the raspberry pi as follows:

  • PIN1: GND (pin 6)
  • PIN2: GPIO4 (pin 7) and with a 4.7k resistor to 3V3 (pin 1)
  • PIN3: 3V3 (pin 1)
As the latest raspbian is used, the drivers for the one-wire protocol are installed. They only need to be loaded on boot. Therefore, you need to add the following line to the file /boot/config.txt and reboot:

dtoverlay=w1-gpio

If you correctly connected the sensors, they should be detected by the system. Every one-wire sensor can be identified with its unique 64-bit identifier. In my case, I have two DS18B20 sensors connected in parallel (only one 4.7k resistor is needed). You can see which sensors are connected on the filesystem with the following command:

$ ls -als /sys/bus/w1/devices/
total 0
0 drwxr-xr-x 2 root root 0 Jan  7 21:57 .
0 drwxr-xr-x 4 root root 0 Jan  1 20:19 ..
0 lrwxrwxrwx 1 root root 0 Jan  2 12:57 28-0115153376ff -> ../../../devices/w1_bus_master1/28-0115153376ff
0 lrwxrwxrwx 1 root root 0 Jan  7 21:57 28-0215649194ff -> ../../../devices/w1_bus_master1/28-0215649194ff
0 lrwxrwxrwx 1 root root 0 Jan  7 21:57 w1_bus_master1 -> ../../../devices/w1_bus_master1

The sensor data can be gathered by reading the w1_slave file in each sensor folder. This file handle provides the most recent sensor data if the CRC check is valid. The value provided divided by 1000 is the temperature in °C. In this case, the sensor measures 20.75 °C.

$ cat /sys/bus/w1/devices/28-0115153376ff/w1_slave
4c 01 55 00 7f ff 0c 10 be : crc=be YES
4c 01 55 00 7f ff 0c 10 be t=20750

So a very basic python program that scans for available one-wire temperature sensors and dumps the current temperature is:

$ cat blog-temp.py 
import os

DEVICE_ROOT_DIR = '/sys/bus/w1/devices/'

def read_temp (device):
  full_filename = '{}{}/w1_slave'.format (DEVICE_ROOT_DIR, device)
  if not os.path.isfile (full_filename):
    raise IOError ('Temperature device {} not found on one-wire'.format (device))
  with open ('{}{}/w1_slave'.format (DEVICE_ROOT_DIR, device)) as f:
    lines = f.readlines ()
    status = lines[0][-4:-1]
    if status == 'YES':
      tempstr = lines[1][-6:-1]
      return float (tempstr) / 1000
    else:
      return None

def scan ():
  for filename in os.listdir (DEVICE_ROOT_DIR):
    if filename.startswith ('28-'):
      yield filename

if __name__ == '__main__':
    for device in scan ():
        print ("Temperature {}: {} °C".format (device, read_temp (device)))

If you run this program you can get the following output:

$ python3 blog-temp.py 
Temperature 28-0215649194ff: 18.187 °C
Temperature 28-0115153376ff: 20.812 °C

So, this was an introduction to the first temperature sensor. In a next blogpost, I will provide more information on the DHT11 sensor. This sensor also measures the humidity. However, it needs a bit more work to be used with a Raspberry Pi.

Friday, January 1, 2016

Build your own python version on Raspberry Pi

This post will provide a tutorial on how to install a specific python version on the raspberry pi. By default, raspbian does only provide a two python versions. At the time of writing, these python versions are respectively python 2.7.9 and python 3.4.2. Therefore, the available python versions lack support for the new async and await support introduced in python 3.5. This post can also be usefull if you need to build a specific older version of python for compatibility reasons.
You can already find some tutorials for building python 3.5 on the raspberry pi 2. However, this tutorial overwrites the system python version and so potentially it can break other programs.
In this tutorial, pyenv will be used to build and maintain different python versions next to each other.

Prepare the system

As a good practice, first update/upgrade the system packages to the latest versions.

$ sudo apt-get update
$ sudo apt-get upgrade -y
$ sudo apt-get dist-upgrade

Some specific software packages will be needed as a dependency to build python (or optional python modules).

$ sudo apt-get install build-essential libncursesw5-dev libgdbm-dev libc6-dev zlib1g-dev libsqlite3-dev tk-dev libssl-dev openssl libbz2-dev libreadline-dev

Installing pyenv

In this post, everything will be installed in the home folder of the current user. Feel free to adapt the install location to a different location on the system if it should be shared with different users. Installing pyenv and pyenv-virtualenv is as simple as cloning the git repos and set some paths in the environment. Note that pyenv provides full code completion on the shell!

git clone https://github.com/yyuu/pyenv.git ~/.pyenv

echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.profile
echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.profile
echo 'eval "$(pyenv init -)"' >> ~/.profile

Now, relaunch the shell (or logout and login) to initialize pyenv in your shell.

Installing python

Finally, a specific python version can be installed in the pyenv folder. In this case, python 3.5.1 is being installed. Note that this can take a while.

$ pyenv install 3.5.1
Downloading Python-3.5.1.tgz...
-> https://www.python.org/ftp/python/3.5.1/Python-3.5.1.tgz
Installing Python-3.5.1...
Installed Python-3.5.1 to /home/pi/.pyenv/versions/3.5.1

A specific python version can now be activated with the following commands:

pi@raspberrypi:~ $ pyenv versions
* system (set by /home/pi/.pyenv/version)
  3.5.1
pi@raspberrypi:~ $ pyenv shell 3.5.1
pi@raspberrypi:~ $ python --version
Python 3.5.1

Sunday, January 25, 2009

Cloning a git svn clone

Looks like today with git 1.6.1 there is no default way to clone a git svn clone. The default command (git clone) does not include the original svn information, so your new clone is quiet useless.
Suggested on IRC is just to 'cp' or 'rsync' your clone with the little anoying side-effect that all non-tracked files are copied too :-/

Wednesday, November 12, 2008

Virtualbox to Qemu

Migrating from virtualbox to qemu can be as simple as this:

vditool COPYDD vbox-image.vdi raw-image.img
qemu-img convert -f raw raw-image.img -O qcow2 qemu-image.qcow

Kvm problems on intel

Kvm can sometimes just abort when trying to install a new OS in an image (Like Ubuntu 7.10). The solution is to install with the -no-kvm flag but it is just very slow
kvm ubuntu.img -cdrom ubuntu.iso -boot d -no-kvm

once installed you can run the image with the flag and run at full speed :-)
kvm ubuntu.img

Tuesday, November 4, 2008

Ubuntu 8.10 on Dell studio

I tried to install Ubuntu 8.10 on a new Dell studio desktop PC but encountered some problems with the sound card. After some browsing and trying different proposals this is how I got it working on my system:
1) Follow this instructions to install the latest alsa
2) use this line in your modprobe:
options snd-hda-intel model=6stack-dell probe_mask=1

3) reboot and adjust the volumes.

Saturday, June 28, 2008

Wiimote in Elisa

After trying the tutorial for activating the wiimote in linux I saw that there where some parts missing in the wiki. You also need some info from here.

sudo apt-get install wminput libbluetooth2 bluez-utils mouseemu lswm
sudo depmod -a
sudo modprobe uinput
sudo mkdir -p /opt/etc/wiimote

Edit the /opt/etc/wiimote/wminput-elisa file
# This is the /opt/etc/wiimote/wminput-elisa file
Wiimote.A = KEY_ENTER
Wiimote.B = KEY_SPACE
Wiimote.Up = KEY_UP
Wiimote.Down = KEY_DOWN
Wiimote.Left = KEY_LEFT
Wiimote.Right = KEY_RIGHT
Wiimote.Minus = KEY_UP
Wiimote.Plus = KEY_DOWN
Wiimote.Home = KEY_F23
Wiimote.1 = KEY_SPACE
#Wiimote.2 = KEY_Q

Check that the wiimote is working
lswm

and start the wiimote as a remote control
wminput -w -c /opt/etc/wiimote/wminput-elisa

Friday, June 27, 2008

Oprofile run

So, oprofile is setup correctly now run it:
sudo opcontrol --start
sudo opcontrol --reset
... do your stuff here
sudo opcontrol --stop
opreport -l ~/build/lib/* ~/.gstreamer-0.10/plugins/* ~/build/lib/gstreamer-0.10/* -t 5

So opreport will dump it with all the symbols (-l) and with a minimum % of 5 (-t 5). you need to add a list with all the interesting libraries.
Result then is something like this:
CPU: PIII, speed 1862 MHz (estimated)
Counted CPU_CLK_UNHALTED events (clocks processor is not halted) with a unit mask of 0x00 (No unit mask) count 100000
samples % app name symbol name
48443 58.7865 libgstdeinterlace.so gst_deinterlace_transform_ip
10351 12.5611 libgstffmpegcolorspace.so yuv420p_to_rgb32

So, now you know where the CPU eathers are :-)

Oprofile setup on ubuntu

Installing oprofile on ubuntu goes like this
sudo apt-get install linux-kernel-devel fakeroot build-essential
sudo apt-get source linux-image-`uname -r`
sudo apt-get build-dep linux-image-`uname -r`
cd linux-source-`uname -r`
sudo make oldconfig
sudo make vmlinux
sudo apt-get install oprofile
sudo opcontrol --setup --vmlinux=`pwd`/vmlinux
sudo opcontrol --start

and then you should see something like this
Using 2.6+ OProfile kernel interface.
Reading module info.
Using log file /var/lib/oprofile/oprofiled.log
Daemon started.
Profiler running.

If you see some error's check if you sh is pointing to bash.
cd /bin
sudo rm sh
sudo ln -s -T bash sh

x2x

x2x allows the keyboard, mouse on one X display to be used to control another X display. It also shares X clipboards between the displays.

Install it on ubuntu is as easy as:
sudo apt-get install x2x

start it up on the server:
ssh -XC laptop x2x -east -to :0.0

Voila, now your keyboard,mouse and clipboard is shared with another x server...

Tuesday, June 17, 2008

Monday, June 16, 2008

Thursday, May 22, 2008

It's Awesome

If you want to play with a new window manager, but don't want to drop your current setup just yet, you can run this WM in the same session with Xephyr. I'm trying out awesome. So I have a script like this to lunch awesome in fullscreen mode in my current session.
#!/bin/bash
Xephyr :2 -ac -fullscreen &
sleep 2
export DISPLAY=:2
awesome
kill $!

The sleep is needed because Xephyr needs some time so setup the new display and awesome already expects that the display is available at startup.

Isn't that awesome ?

Friday, March 14, 2008

Fire Emblem: Radiant dawn


Yesterday I bought probably the best Wii game for the moment. At least if you are a fan of the Fire Emblem series. The new game is Fire Emblem: Radiant dawn.

One of the big advantages of this game is that it does not force the Wii to use all of its controller features. This means that you can you the normal Wii Remote, the GameCube controller but also the classic controller

Wednesday, January 30, 2008

Unrar for the NSLU2

A Colleague pointed me to this site that has the "non-free" version of unrar available for the NSLU2. It looks like this unrar program can handle more rar-files than the unrar-free package available from the debian-arm repositories.

Friday, January 4, 2008

N810 ordered and arrived

After reading this I checked and ... TADA ... The discount code also worked for me (Belgium shop). So an N810 is on its way ...

Update: N810 is arrived ( 2 workdays) and looks good :-)

Sunday, December 30, 2007

Dot graph from GStreamer pipeline

For creating a dot graph from a GStreamer pipeline set the environment variable GST_DEBUG_DUMP_DOT_DIR ( NOT GST_DEBUG_DUMP_DOT_FILES) to a correct output folder.
export GST_DEBUG_DUMP_DOT_DIR=/tmp

Start a pipeline:
gst-launch playbin uri=file:///home/thijs/Desktop/mewmew-vorbis-ssa.mkv

On warnings and error's this pipeline will create a dot file. A error can be generated by killing the output window. Now you can transform this dot file to a svg/png/... file. I prefer the use of svg files because the png file from this pipeline is more than 38000 pixels width and crashes my image viewer.
dot -Tsvg -o pipeline.svg 0:00:02.270914892-gst-launch.error.dot

Now you can view your pipeline in inkscape.

Thursday, August 16, 2007

Hildon banner in pymaemo

In my journey of exploring python for the N800 I spotted some problems with using the hildon banner with the pymaemo bindings.
Now these problems are fixed in the svn version (thanks to Lauro Moura). I made a little example file based on the C api how to use this hildon banner in pymaemo.


import gtk
import hildon

class hildonBannerWindow(hildon.Window):
def __init__(self):
hildon.Window.__init__(self)
self.button = gtk.Button('Show Info');
self.button.connect('clicked', self.show_banner_cb)
self.connect('destroy', gtk.main_quit)
self.add(self.button)
self.show_all()
self.banner_type = 1
self.banner = None

def show_banner_cb(self, widget):
if self.banner_type == 1:
hildon.hildon_banner_show_information(self, None, "Hello Information")
elif self.banner_type == 2:
self.banner = hildon.hildon_banner_show_animation(self, None, "Hello Animation")
elif self.banner_type == 3:
self.banner.destroy()
elif self.banner_type == 4:
self.banner = hildon.hildon_banner_show_progress(self, None, "Info with progress bar")
self.banner.set_fraction(0.2)
elif self.banner_type == 5:
self.banner.set_fraction(0.8)
elif self.banner_type == 6:
self.banner.destroy()
self.banner_type = 0
self.banner_type += 1

if __name__ == '__main__':
window = hildonBannerWindow()
gtk.main()


I shows there are 3 types of hildon banners:



hildon information : Just an information icon that shows up for a few seconds



hildon animation : Shows an spinning wheel whith some text ,this was the one I needed ;)



hildon progress : Can show a progressbar with some text next to it.

The two last one needs to be destroyed after using them.