Official website for Linux User & Developer
FOLLOW US ON:
Jun
26

Raspberry Pi motion controller

by Russell Barnes

Use the accelerometer in PiBorg’s small and affordable XLoBorg device to turn your Pi into a game controller…

If you saw last issue you might remember the DoodleBorg, a massive remote-controlled tank of a vehicle designed and built by PiBorg, makers of add-ons for the Raspberry Pi. This month we’re looking at their XLoBorg, a board designed to help you measure movement and determine direction, among other things.

At under £10/$16, it’s a bargain too, because as well as featuring a three- axis accelerometer, it’s also kitted out with a three-axis magnetometer (digital compass). In this tutorial we’ll be using the accelerometer to turn our Pi into a tilt controller and mock up a simple demo to show how you could integrate it into your Pygame-powered games…

The board features both a three-axis accelerometer and a three- axis magnetometer so it can measure tilt and orientation
The board features both a three-axis accelerometer and a three- axis magnetometer so it can measure tilt and orientation

What you’ll need

Python2.7

PiBorg XLoBorg

Pygame

Step-by-step

Step 01 Install the XLoBorg

Installing the XLoBorg onto your Raspberry Pi really couldn’t be easier. It simply slots directly over your GPIO pins with the main body of the board facing over your Raspberry Pi. PiBorg has made the software side of the installation super easy too, by creating an installation script that automates the process of installing the required I2C drivers and library files on your Pi.

Step 02 Download the software

Make a new directory for the project files in your home folder by typing: mkdir ~/xloborg, enter the directory (with cd ~/xloborg) and download the package with:

$ wget www.piborg.org/downloads/xloborg/examples.zip

Now unzip the package with unzip examples.zip and make the install.sh script executable with chmod +x install.sh. Finally, run the script with ./install.sh and reboot your Pi once the installation has finished to finalise it.

Step 03 Inspect and test the library

Whenever you’re dealing with a new piece of hardware or a software library designed to abstract a particular process, it’s worth looking at the library directly to see how it works. The XLoBorg’s library is XLoBorg.py and it contains well- commented code that demonstrates the main functionality on the board well. The library is also executable with a simple routine to print the sensor results to the terminal. Run it with python XLoBorg.py from the terminal to ensure everything’s working properly. Move your Pi around to ensure the accelerometer readings change. If not, see the troubleshooting page.

Step 04 Start the script

All being well you’re seeing read-outs from running XLoBorg.py that change when you move the Raspberry Pi around. Now we know everything works, we can start our script with the core XLoBorg functionality. Open a new text editor file and save it as xloborg_app.py. First we need to initialise the XLoBorg in our script with XLoBorg.Init(), then we’re going to suppress the print function to save us wading through terminal output with a new line:

XLo.Borg.printprintFunction = XLoBorg.NoPrint

All we need to do now is create a variable that will carry the accelerometer readings. We’ve done this with the following line:

tilt = XLoBorg.ReadAccelerometer()

This will create a Tuple called tilt that containts x, y, z forces (in that order). We don’t need the z forces for this example, so we’ll inject the readings into a handy little function for our demo app by calling tilt[0] and tilt[1] for the x and y readings respectively.

Step 05 Pygame example app

Believe it or not, that’s all the XLoBorg code we need to turn our Raspberry Pi into a tilt controller. Next we’ll create a bare-bones graphical demo that could easily be turned into a marble tilt game or something similar. At the top of the script we’ve initiated some constants to cater for the screen size, ball size and colours. Then we initialise Pygame, creating a screen and setting a window caption. The main bulk of the program is a simple Ball class. The two methods update(x, y) and collide() ensure the ball position can be updated and the latter dictates what happens when the ball collides with the edge of the screen. We’ve constructed the update() method to take two variables – this is where we’ll inject our accelerometer values during the main loop of the script.

Step 06 The main loop
The main loop is designed to enter an infinite loop
using the variable game_over. While game_over is False everything after the while not game_over: line will be repeated 30 times every second until we quit it with the Escape key or CTRL+C. Before we start this loop, though, we ensure game_ over is indeed False and construct a ball. Once we enter the infinite loop we read the XLoBorg’s accelerometer, paint the screen black and call the ball.update(x, y) method using the tilt variable to pass the new readings to our ball. We then check the ball’s location to ensure it’s not trying to leave the screen, then we blit (or draw) the ball on the screen and redraw it using Pygame’s flip() function.

Once it’s complete, save the script and run it with python xloborg_app.py. Tilting your Raspberry Pi will move the ball on the screen – if the ball is moving in the wrong directions, simply ‘minus’ the respective reading as we’ve done in the example code on the right to flip them.

Code listing

#!/bin/bash/env python

import pygame
import XLoBorg

WIDTH = 800
HEIGHT = 600
REF_RATE = 30
BALL_SIZE = (24, 24) BLACK = (0, 0, 0)
WHITE = (255, 255, 255)

pygame.init()
XLoBorg.Init()
XLoBorg.printprintFunction = XLoBorg.NoPrint

screen = pygame.display.set_mode([WIDTH, HEIGHT])
clock = pygame.time.Clock()
pygame.display.set_caption('XLoBorg test - Press ESC to quit')

class Ball(pygame.sprite.Sprite):
   def __init__(self, width, height):
      pygame.sprite.Sprite.__init__(self)
      self.size = (width, height)
      self.image = pygame.Surface([width, height])
      self.image.fill(WHITE)
      self.rect = self.image.get_rect()
      self.rect.x, self.rect.y = WIDTH / 2, HEIGHT / 2
      self.speed = (50, 50)
      self.tilt = [0, 0]

   def update(self, x, y):
      self.rect.x += x * self.speed[0]
      self.rect.y += y * self.speed[1]
      print 'X =', x, 'Y =', y

   def collide(self):
      if self.rect.x > WIDTH - self.size[0]:
         self.rect.x = WIDTH - self.size[0]
      elif self.rect.x < 0:
         self.rect.x = 0
      if self.rect.y > HEIGHT - self.size[1]:
         self.rect.y = HEIGHT - self.size[1]
      elif self.rect.y < 0:
         self.rect.y = 0

def main_loop():
   game_over = False
   ball = Ball(50, 50)

   while not game_over:
      for event in pygame.event.get():
         if event.type == pygame.QUIT:
            game_over = True
         if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_ESCAPE:
               game_over = True

      tilt = XLoBorg.ReadAccelerometer()
      screen.fill(BLACK)
      ball.update(-tilt[0], tilt[1])
      ball.collide()
      screen.blit(ball.image, ball.rect)
      pygame.display.flip()
      clock.tick(REF_RATE)
   pygame.quit()

if __name__ == '__main__':
   try:
      main_loop()

   except KeyboardInterrupt:
      pygame.quit()

  • Tell a Friend
  • Follow our Twitter to find out about all the latest Linux news, reviews, previews, interviews, features and a whole more.