Thursday, May 27, 2010

Inclinometer in Python, for Symbian phones with accelerometer

Another example of how easy and fast applications can be developed in Python.

An example of a simple inclinometer (tilt meter, tilt indicator, slope alert, slope gauge, gradient meter, gradiometer, level gauge, level meter, declinometer, and pitch & roll indicator).

But first you need to install Python for Symbian S60. This can be installed on phones with Symbian OS 3rd or 5th edition. Download PyS60 binaries and install the runtime and the shell (copy the .sis files to phone and launch to install or install with your phones software).
The setup for Windows OS is for creation of installable packages from your Python application.

The code is the following:

from sensor import *
import e32
from appuifw import *
from random import randint

print "Accelorometer by Lazar Laszlo (c) 2009"

# Define exit function
def quit():
    App_lock.signal()
app.exit_key_handler = quit
 
app.screen = 'large' # Screen size set to 'large'
c = Canvas()
app.body = c
s1,s2=app.layout(EScreen)
mx = s1[0]
my = s1[1]
m2x = mx/2
m2y = my/2
sleep = e32.ao_sleep

# Function which draws circle with given radius at given co-ordinate
def circle(x,y,radius=5, outline=0, fill=0xffff00, width=1):
  c.ellipse((x-radius, y-radius, x+radius, y+radius), outline, fill, width)
 

class Inclinometer():
    def __init__(self):
        self.accelerometer = \
            AccelerometerXYZAxisData(data_filter=LowPassFilter())
        self.accelerometer.set_callback(data_callback=self.sensor_callback)
        self.counter = 0

    def sensor_callback(self):
        # reset inactivity watchdog at every 20th read
        if self.counter % 20 == 0:
            e32.reset_inactivity()

        # redraw at every 5th read
        if self.counter % 5 == 0:
            c.clear()
            circle(m2x+self.accelerometer.x*2, 160-self.accelerometer.y*2, 7, fill=0x0000ff)
            if self.accelerometer.z > 0:
                c.rectangle((0,m2y,15,m2y+self.accelerometer.z*2),fill=0x00ff00)
            if self.accelerometer.z < 0:
                c.rectangle((0,m2y+self.accelerometer.z*2,15,m2y),fill=0x00ff00)
            c.line((0,m2y,mx,m2y),outline=0,width=1)
            c.line((m2x,0,m2x,my),outline=0,width=1)
        self.counter = self.counter + 1

    def run(self):
        self.accelerometer.start_listening()

if __name__ == '__main__':
    d = Inclinometer()
    d.run()
    App_lock = e32.Ao_lock()
    App_lock.wait()  # Wait for exit event
    d.accelerometer.stop_listening()
    print "Exiting Accelorometer"


The appuifw module contains the functions and objects for the graphical user interface. You can set the applications window size with the app.screen variable. To use the whole screen as a drawing canvas set app.screen = 'large' and set the application body to the Canvas object.

The application gets the accelerometer data through a callback. In order to do not redraw the screen at every read, a simple counter is used. I doubled the accelerometers values to increase the circles movement. The x and y values are displayed as a circle centered to the screens center. The z value is displayed as a green bar.

I reset the phones inactivity watchdog with the e32.reset_inactivity() function to keep the back-light on while the application is running.

If your phone has a magnetometer (compass) you can switch the sensor from AccelerometerXYZAxisData to MagnetometerXYZAxisData and the self.accelerometer variables to self.magnetometer to display the direction to North.

To run the application just save the code to a text file with .py extension, copy the file to the phones \DATA\PYTHON directory (or into the \PYTHON directory in the phone memory).

Screen shots from my Nokia E52:








Feel free to use and play with this small code.

No comments:

Post a Comment