BrickPi Lego robot takes its first steps!

A little while back I wrote a post about creating a python script to control a brickpi robot, now that I actually have the brickpi components, motors and cables and have actually tried it out, I’ve made a few improvements to that script to make it work.

Installing Raspbian

Firstly, I had to revisit the raspbian installation. With the brickpi bundle I bought from Dexter Industries, it came with a pre-installed raspbian SD card. I’m not sure what was wrong, but I wasn’t able to boot into it, there were startup errors regarding /etc/init.d. A quick Google didn’t help, so I decided to flash a new SD card with a more recent version of raspbian.

It’s important to note that the stock raspbian image won’t automatically work with the brickpi, as some modifications are required in order to control I/O for the motors. You can make these modifications yourself as there are instructions on the brickpi website, but it’s far easier to just download the pre-modified raspbian from dexter industries.

This was quite simple, on a mac you can erase and format an SD card using Disk Utility, after that, use these commands to create the SD card image:

diskutil list
diskutil unmountdisk /dev/disk1
dd if=2013.07.27_BrickPi.img of=/dev/disk1 bs=2m

diskutil list will show you the drives attached, in my case the SD card was disk1 but it may vary for you. It takes around 10 minutes to flash the SD card so go make a brew.

Configuring WiFi

Setting up wifi on the pi is pretty easy, I have a USB wifi adapter, so it was just a case of configuring a wireless interface, which can be done by adding the following to /etc/network/interfaces

sudo nano /etc/network/interfaces
add
iface wlan0 inet dhcp
wpa-ssid "NETWORK_ID_HERE"
wpa-psk "NETWORK_PASSWORD_HERE"

Then do a sudo reboot

Expanding the SD card

In order to expand the root partition and make use of the entire SD card, run the following command and follow the menus to expand SD card

sudo raspi-config

Then do a sudo reboot

Setting up the brickpi dependencies

SSH onto the pi and run the following

mkdir brickpi
cd brickpi/
git clone https://github.com/DexterInd/BrickPi_Python.git
cd BrickPi_Python
sudo apt-get install python-setuptools
sudo python setup.py install

This will clone the BrickPi python repository (which contains a load of examples), install python-setuptools and install the brickpi module, so you can import Brickpi globally in your python scripts.

Controlling the robot

After testing out the brickpi examples, it was quite clear that I’d need to modify my original python script. I needed 2 threads.

  • Thread 1 would continually update the motors every 200ms, otherwise the motors would turn briefly and then remain still.
  • Thread 2 would process incoming commands and set the motor speeds.

Other than the threading code, the script is quite easy to follow

from BrickPi import *   #import BrickPi.py file to use BrickPi operations
import threading
import socket
import select
import Queue
from threading import Thread
import sys

BrickPiSetup()  # setup the serial port for communication
BrickPi.MotorEnable[PORT_A] = 1 #Enable the Motor A
BrickPi.MotorEnable[PORT_D] = 1 #Enable the Motor D
BrickPiSetupSensors()   #Send the properties of sensors to BrickPi

running = True

#This thread is used for keeping the motor running while the main thread waits for user input
class BrickPiThread (threading.Thread):
    def __init__(self, threadID, name, counter):
        threading.Thread.__init__(self)
        self.threadID = threadID
        self.name = name
        self.counter = counter
    def run(self):
        while running:
            BrickPiUpdateValues()       # Ask BrickPi to update values for sensors/motors
            time.sleep(.2)              # sleep for 200 ms

brickPiThread = BrickPiThread(1, "BrickPiThread", 1)                #Setup and start the thread
brickPiThread.setDaemon(True)
brickPiThread.start()

class ProcessCommandThread(Thread):
    def __init__(self):
        super(ProcessCommandThread, self).__init__()
        self.running = True
        self.q = Queue.Queue()

    def add(self, data):
        self.q.put(data)

    def stop(self):
        self.running = False

    def run(self):
        q = self.q
        while self.running:
            try:
                # block for 1 second only:
                value = q.get(block=True, timeout=1)
                process(value)
            except Queue.Empty:
                sys.stdout.write('.')
                sys.stdout.flush()
        if not q.empty():
            print "Elements left in the queue:"
            while not q.empty():
                print q.get()

commandThread = ProcessCommandThread()
commandThread.start()

def process(value):
    print "Processing [{v}]".format(v=value)

    # Left side
    if value == 'L-FORWARD-Start':
        print "L-FORWARD-Start"
        BrickPi.MotorSpeed[PORT_A] = 200
    elif value == 'L-FORWARD-Stop':
        print "L-FORWARD-Stop"
        BrickPi.MotorSpeed[PORT_A] = 0
    elif value == 'L-BACK-Start':
        print "L-BACK-Start"
        BrickPi.MotorSpeed[PORT_A] = -200
    elif value == 'L-BACK-Stop':
        print "L-BACK-Stop"
        BrickPi.MotorSpeed[PORT_A] = 0
    # Right side
    if value == 'R-FORWARD-Start':
        print "R-FORWARD-Start"
        BrickPi.MotorSpeed[PORT_D] = 200
    elif value == 'R-FORWARD-Stop':
        print "R-FORWARD-Stop"
        BrickPi.MotorSpeed[PORT_D] = 0
    elif value == 'R-BACK-Start':
        print "R-BACK-Start"
        BrickPi.MotorSpeed[PORT_D] = -200
    elif value == 'R-BACK-Stop':
        print "R-BACK-Stop"
        BrickPi.MotorSpeed[PORT_D] = 0

def main():
    s = socket.socket()
    #host = socket.gethostname()
    host = "192.168.0.10"
    port = 3033
    s.bind((host, port))

    print "Server listening on port {p}...".format(p=port)

    s.listen(5)                 # Now wait for client connection.

    while True:
        try:
            client, addr = s.accept()
            ready = select.select([client, ], [], [], 2)
            if ready[0]:
                data = client.recv(4096)
                commandThread.add(data)
        except KeyboardInterrupt:
            print
            print "Stopping server."
            break
        except socket.error, msg:
            print "Socket error %s" % msg
            break

    cleanup()

def cleanup():
    commandThread.stop()
    commandThread.join()

if __name__ == "__main__":
    main()

Paste that into server.py then run the following:

sudo python server.py

You should see some output in the terminal as it’ll print out any incoming commands. Then its up to you to connect onto that socket with a client of your choice. I’m using an android app (which I’ve detailed here), but you could use something as simple as the following Java client

import java.io.*;
import java.net.Socket;

public class Runner {

    public static void main(String[] args) throws IOException {

        Socket socket = new Socket("raspberrypi", 3033);

        BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());

        OutputStreamWriter osw = new OutputStreamWriter(bos, "US-ASCII");

        osw.write("L-FORWARD-Stop");
        osw.flush();
    }
}

Resources

Any thoughts / suggestions? Please comment below!

Robots! (part 1)

Inspired by the android controlled lego robots I saw at DroidCon UK this year, and with difficulty finding a use for my raspberry pi, I’ve decided to have a go at building a robot that I can control via an android app. Having a 24 hour flight home from Australia at the weekend, I’ve had plenty of time to think about how I might approach this task (or challenge as I refer to it as I’ve no prior experience with robotics / socket programming).

Lego robot powered by the BrickPi

My plan is to have a python socket server running on the pi. This will provide a socket that an android client can invoke commands on. This python server will also interact with the python scripts that the BrickPi uses to control lego motors.

Whilst most of my experience revolves around Java, I’ve opted for python for the following reasons

  • Python is supported on the pi out of the box, no need to mess around with installing Java
  • The BrickPi has support for Python (and C)
  • I feel like learning something new

Baby steps…

Starting simple, I thought it best to create a simple script that listens on a socket, and then create a client that sends it some data to print out to the console. Once I have this working I can expand on it and make the client more sophisticated (an android app for example) and also enhance the server so it can handle different types of commands.

Server
There are plenty of example python scripts online, I found a good one here and tweaked it slightly to remove the parts I don’t want. (full credit to pythonadventures!)

#!/usr/bin/env python
# server.py

import socket
import select
import Queue
from threading import Thread
import sys

class ProcessThread(Thread):
    def __init__(self):
        super(ProcessThread, self).__init__()
        self.running = True
        self.q = Queue.Queue()

    def add(self, data):
        self.q.put(data)

    def stop(self):
        self.running = False

    def run(self):
        q = self.q
        while self.running:
            try:
                # block for 1 second only:
                value = q.get(block=True, timeout=1)
                process(value)
            except Queue.Empty:
                sys.stdout.write('.')
                sys.stdout.flush()
        #
        if not q.empty():
            print "Elements left in the queue:"
            while not q.empty():
                print q.get()

t = ProcessThread()
t.start()

def process(value):
    print value

def main():
    s = socket.socket()
    host = socket.gethostname()
    port = 3033
    s.bind((host, port))

    print "Server listening on port {p}...".format(p=port)

    s.listen(5)                 # Now wait for client connection.

    while True:
        try:
            client, addr = s.accept()
            ready = select.select([client,],[], [],2)
            if ready[0]:
                data = client.recv(4096)
                t.add(data)
        except KeyboardInterrupt:
            print
            print "Stopping server."
            break
        except socket.error, msg:
            print "Socket error %s" % msg
            break

    cleanup()

def cleanup():
    t.stop()
    t.join()

if __name__ == "__main__":
    main()

The socket is bound to a port, and then continually listens for incoming data. Once some data is received, it is added onto a queue, which is then sequentially executed.

Client
The client is is fairly straightforward, it involves opening a connection on a socket and writing data to it, a few lines of Java code.

public static void main(String[] args) throws IOException {

        InetAddress address = InetAddress.getLocalHost();
        Socket socket = new Socket(address, 3033);

        BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());

        OutputStreamWriter osw = new OutputStreamWriter(bos, "US-ASCII");

        System.out.println("Sending message...");

        osw.write("Hello!");
        osw.flush();
    }

Thats it for now, you can checkout my code on github (or just copy/paste the above) and run the client and server and see it in action.

I’ll start on the client next..

How to keep checking if port is open, by issuing socket connects

I recently need to check if a particular application is online and listening on a particular set of ports. I figured that the best way to do this was to periodically issue some socket connects onto those ports. If I got an exception, then clearly there would be an issue.

This was all running on a CentOS Linux machine, so I opted for a Python script, have a look at my sample below

# Socket Connect Script
# Author : James Elsey
# Date : 27 January 2011

# Imports
import socket
import sys
import time
import datetime

# Configure these as required..
remote_host = "127.0.0.1"

print "About to start running script..."

# run continuously
while True:
        time.sleep(60)
        for remote_port in [80,8080]:
                # Setup socket
                sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                sock.settimeout(60)
                now = datetime.datetime.now()
                now_text = now.strftime("%Y-%m-%d %H:%M:%S")

                try:
                        # Issue the socket connect on the host:port
                        sock.connect((remote_host, remote_port))
                except Exception,e:
                        print "%s %d closed - Exception thrown when attempting to connect. " % (now_text, remote_port)
                else:
                        print  "%s %d open" % (now_text, remote_port)
                sock.close()

So there you have it, take it and modify as you please! You could remove the while True and setup a for loop to check for a specific number of times, or leave the continual loop in and create another method of breaking out, for me I just wanted to leave it running in a putty window and watch for changes.

Also, to run it, just use save it into a .py file and call “python myFile.py”

Happy coding