Mike's stuff

Using the SRF02 Ultrasonic Ranger with Python (pyserial)

posted 3 Oct 2010, 13:16 by Michael Strand   [ updated 5 Oct 2010, 01:37 ]

I recently purchased an SRF02 Unltrasonic Rangefinder along with a USB-I2C communications module. The SRF02 uses an I2C bus to communicate, the USB-I2C module appears on the PC as a serial port and provides an interface to the I2C bus.

I am new to playing with this kind of thing, but I have been wanting to get into some basic robotics as a hobby, so this is my starting point. I didn't know anything about the I2C bus and found it a bit confusing at first. Some guidance by a friend at work  (thanks Ben) soon had me getting some results.

The results however didn't make sense and it took a bit of experimenting to figure out. I didn't find much information about using Python to do this so I thought I would post my basic Python program here in the hope that it may help another newbie get started. Download py_SRF02.py

Created on Oct 2, 2010

@author: michael
import serial, time, os

#set up the serial connection
ser = serial.Serial(

#start the main loop
while True:
    #basic error handling, occasionally the device fails to respond. This keeps the 
    #loop running.
        #send the 5 byte command to start a ranging ping.
        #The 1st byte 0x55 is the start command for the USB-I2C module. 2nd byte 0xE0
        #is the address of the SRF02 on the I2C bus. 3rd byte 0x00 is the address 
        #register of the SRF02 that we are writing the command to. 4th byte 0x01 is 
        #the number of bytes in the command we are about to send. 5th byte 0x51 is 
        #the command to tell the SRF02 to initiate a range in cm.
        #wait for the range to finish
        #this 4byte command tells the SRF02 to send the result to the I2C bus for 
        #reading. The first byte 0x55 is the start command for the USB-I2C module. 
        #2nd byte 0xE1 is the SRF02s address plus one, this tells it that we are 
        #reading. 3rd byte 0x02 is 
        #the register thats holds the data we want to start reading from. 4th byte 
        #0x02 is the number of bytes to read. In this case we want 2bytes, the range 
        #high byte and the range low byte.
        #read 3 bytes. Why 3 when we only requested 2? The USB-I2C device returns a 
        #byte first to tell of success or fail
        s = ser.read(3)
        #clear the screen so we are not repeating up the screen
        #first check for a successful read response, first byte will be 1 if successful. 
        #Then print the second byte which is the range high followed byte the 3rd which 
        #is range low. Combine to get the actual range, we do this because each register 
        #is one byte of 8 bits, this only allows numbers to go to 255, this would give 
        #255cm on the low byte. But suppose we are measuring a range of 280cm, the low 
        #register maxes out at 255. We put a 1 in the high byte register to represent 
        #256 and the low byte starts again and counts to 24. So we can simply combine 
        #the high and the low bye h*256+l to get the range so in the example 1*256+24=280
        if ord(s[0]) == 1:
            print ord(s[1]), 'high'
            print ord(s[2]), 'low'
            print ord(s[1]) * 256 + ord(s[2]), 'range in cm'
            print 'error reading device'
        #slow the loop down a bit to give our eyes a chance to read the response
    #handle errors, the second "except" here takes all errors in it's stride and allows
    #the loop to continue. I did this because every now and again the USB-I2C device 
    #fails to respond and breaks the loop. By having a blanket error handling rule you 
    #could no longer interrupt the loop with a keyboard interrupt so I had to add an 
    #"except KeyboardInterrupt" rule to allow this to break the loop.  
    except KeyboardInterrupt:
        print ' Exiting...Keyboard interrupt'
        print 'unexpected error'

Set Gmail as default mail client using Google Apps in Linux

posted 25 Jan 2010, 22:19 by Michael Strand   [ updated 12 Jun 2010, 17:16 ]

You can have Google Apps as your default mail client in Linux.

First install gnome-gmail from here http://gnome-gmail.sourceforge.net/. This installs a Python script, /usr/bin/gnome-gmail. You can then go to "System > Preferences > Preferred Applications" and set gnome-gmail as your custom mail application.

*** UPDATE: Editing the script is no longer required *** Just install as set as the preferred mail app. Then logout and log back in and go to Applications > Configuration Editor and in the apps tree expand gnome-gmail. All you have to do is set your apps domain here.

This script is configured for Gmail not Google Apps but it is easy to change. Open /usr/bin/gnome-gmail with your text editor and there are three URL references to Gmail that we will change.


import sys
import urlparse
import gio
import string

def appendUrl( tourl, urltag, dict, dicttag ):
tourl = tourl + "&" + urltag + "=" + dict[dicttag][0]

return tourl

# get the path string from the 'possible' mailto url
usplit = urlparse.urlsplit( sys.argv[1], "mailto" )
except IndexError:
# couldn't even get an email address - just open a default mail page
gio.app_info_get_default_for_type( "text/html", 1 ).launch_uris( ["http://mail.yourdomain.com"] )
sys.exit( 0 )

path = usplit.path

# for some reason, urlsplit is not splitting off the query string
# do it here
( address, qs ) = string.split( path, "?", 1 )
except ValueError:
address = path
qs = usplit.query

qsdict = urlparse.parse_qs( qs )
qsdict['to'] = []
qsdict['to'].append( address )

tourl = "https://mail.google.com/a/yourdomain.com?view=cm&cmid=0&fs=1&tearoff=1"
tourl = "https://mail.google.com/a/yourdomain.com?view=cm&tf=0&fs=1"

tourl = appendUrl( tourl, "to", qsdict, "to" )
tourl = appendUrl( tourl, "su", qsdict, "subject" )
tourl = appendUrl( tourl, "body", qsdict, "body" )
tourl = appendUrl( tourl, "cc", qsdict, "cc" )
tourl = appendUrl( tourl, "bcc", qsdict, "bcc" )

print tourl

gio.app_info_get_default_for_type( "text/html", 1 ).launch_uris( [tourl] )

When you are in Google Mail check your URL and compare it to the URLs in the script, if your URLs are slightly different you can change the script to match your Google Apps mail URL.

Agere et-131x Ethernet driver on Fedora 12

posted 12 Jan 2010, 02:50 by Michael Strand   [ updated 3 Feb 2010, 00:57 ]

I have an LG W1 Express Dual laptop with an Agere Systems Ethernet port. When I loaded Fedora 12 the wireless and everything else worked perfectly except for the LAN. 

The process to install it was as follows and is almost a complete copy from http://r4ndom.wordpress.com/2009/06/08/agere-et131x-driver-finally/

save it to your /tmp directory and open a terminal window

$ cd /tmp

$ tar -xzvf et131x_staged_2_6_git.tar.gz

cd staged

The next step is to run make, this initially just resulted in errors for me.

make: *** /lib/modules/ No such file or directory

To get past this you need to install some other things first...

$ yum install gcc kernel-PAE-devel

or if you don't have a PAE kernel, you can check by running "uname -r" if you don't see PAE in the result run the following

$ yum install gcc kernel-devel

once you have these...

$ make

Once that finishes

$ su

make sure you are still in the staged directory


$ make modules_install

$ modprobe et131x

You should be up and running now.

1-3 of 3