XLoLevel - Turn your Raspberry Pi into a spirit level

We were placing shelves in the office today and decided the trusty spirit level was a bit old fashioned, why not use a Raspberry Pi and XLoBorg instead.


We came up with XLoLevel, a script to turn your Raspberry Pi into a digital spirit level
There are some options you can configure from lines 5 to 10:
  • filterLength is the amount of readings to average over, increase to reduce noisy readings
  • fps is the rate we wish to run at, larger values will use more processor time
  • windowX is the width of the window drawn
  • windowY is the height of the window drawn
  • bubbleSize is the diameter of the on screen "bubble"
  • sensitivity is how much the bubble moves for a movement, at 2.0 the window edges are a 45° tilt

Here's the code, you can download the XLoLevel script file as text here
Save the text file on your pi as XLoLevel.py, in the ~/xloborg directory
Make the script executable using
chmod +x ~/xloborg/XLoLevel.py
and run using
~/xloborg/XLoLevel.py

#!/usr/bin/env python
# coding: latin-1

# User settings
filterLength = 10                       # Filter size, larger is smoother but slower to update
fps = 30                                # Frames to draw per second, larger values use more CPU
windowX = 400                           # Window width
windowY = 400                           # Window height
bubbleSize = 20                         # Width of the bubble on screen
sensitivity = 2.0                       # How much the bubble moves, at 1.0 the edges are full scale

# Import library functions we need
import time
import pygame
import XLoBorg
XLoBorg.Init()

# Setup pygame and key states
global quit
quit = False
pygame.init()
fpsClock = pygame.time.Clock()
screen = pygame.display.set_mode((windowX, windowY))
pygame.display.set_caption("XLoLevel - Press [ESC] to quit")
backColour = pygame.Color(255, 255, 255)
guideColour = pygame.Color(0, 0, 0)
bubbleColour = pygame.Color(255, 0, 0)

# Function to handle pygame events
def PygameHandler(events):
    # Variables accessible outside this function
    global quit
    # Handle each event individually
    for event in events:
        if event.type == pygame.QUIT:
            # User exit
            quit = True
        elif event.type == pygame.KEYDOWN:
            # A key has been pressed, see if it is one we want
            if event.key == pygame.K_ESCAPE:
                quit = True

# Function used to provide a simple averaging window on a value
def BoxFilter(value, filterStorage):
    if len(filterStorage) == 0:
        # Setup the filter for first use
        for i in range(filterLength):
            filterStorage.append(value)
    else:
        # Insert the new value into the filter and remove the oldest
        filterStorage.pop()
        filterStorage.insert(0, value)
        # Generate a new average value
        value = 0.0
        divisor = float(len(filterStorage))
        for raw in filterStorage:
            value += raw / divisor
    return value

try:
    filterX = []
    filterY = []
    filterZ = []
    print 'Press [ESC] to quit'
    # Loop indefinitely
    while True:
        # Get the currently pressed keys on the keyboard
        PygameHandler(pygame.event.get())
        if quit:
            # Exit the loop
            break
        # Read the accelerometer and filter the results
        x, y, z = XLoBorg.ReadAccelerometer()
        x = BoxFilter(x, filterX)
        y = BoxFilter(y, filterY)
        z = BoxFilter(z, filterZ)
        # Convert into screen positions
        x *= sensitivity
        y *= sensitivity
        x = int((1.0 + x) * (windowX / 2) + 0.5)
        y = int((1.0 - y) * (windowY / 2) + 0.5)
        # Limit positions to on-screen
        if x < 0:
            x = 0
        elif x >= windowX:
            x = windowX - 1
        if y < 0:
            y = 0
        elif y >= windowY:
            y = windowY - 1
        # Draw the screen
        screen.fill(backColour)
        pygame.draw.line(screen, guideColour, (windowX / 2, 0), (windowX / 2, windowY - 1), 1)
        pygame.draw.line(screen, guideColour, (0, windowY / 2), (windowX - 1, windowY / 2), 1)
        pygame.draw.circle(screen, guideColour, (windowX / 2, windowY / 2), bubbleSize / 2 + 1, 2)
        pygame.draw.circle(screen, bubbleColour, (x, y), bubbleSize / 2, 0)
        pygame.display.update()
        # Wait for the next frame (will not run faster than fps, but may run slower)
        fpsClock.tick(fps)
except KeyboardInterrupt:
    # CTRL+C exit, terminate
    pass
Subscribe to Comments for &quot;XLoLevel - Turn your Raspberry Pi into a spirit level&quot;