Wednesday, 7 June 2017

Basic Bluetooth Network using Raspbian Jessie

Recently I wanted to setup a Bluetooth network to allow several Raspberry Pis to communicate amongst themselves and, as I'd not done this before, tried to search for articles on how to achieve this. I managed to find many, many articles covering this subject, unfortunately they tended to be either out of date (e.g. using Raspbian Wheezy + BlueZ 4.x), incomplete (starting from X do Y, without explaining how to achieve X) or just plain confusing.

After some further research, plus plenty of trial and error, I eventually got a bluetooth network up and running, connecting together one Raspberry Pi 3 with four Raspberry Pi Zero Ws, and decided to document the steps I took for my own reference, as well as for anyone else who would like to achieve the same.

To setup the Bluetooth network we need to allocate one Raspberry Pi to act as the central hub, responsible for allocating IP addresses, IP forwarding (if needed), along with one or more client Raspberry Pis to connect to it.

Setting up the Hub

  • Download the latest Raspbian image (Here I am using and write to an SD Card.
  • Boot the Raspberry Pi, login and run the 'raspi-config' application.
pi@raspberrypi:~$ sudo raspi-config
  • Select option 2 to change the hostname, setting it to 'hub'.
  • Select 'Finish', followed by 'Yes' to reboot.
  • Wait for the Raspberry Pi to reboot and log in again.
  • Setup a network connection. Depending on your setup this can be either by plugging in an Ethernet cable or by setting up a Wireless connection.
  • Install the packages required for setting up the bluetooth network.
pi@hub:~$ sudo apt-get install bluez-test-scripts bridge-utils dnsmasq python-dbus
  • Next we need to add the network interface we'll be using for Bluetooth. Edit the /etc/network/interfaces file and add the following to it.
auto pan0
 iface pan0 inet static
         bridge-ports none
         bridge-fd 0
  • And then we need to configure dnsmasq to listen on the pan0 interface and assign IP addresses in the correct range. Edit the /etc/dnsmasq.conf file and add the following
 # Enable DHCP for the 172.168.200.X range
  • To setup the bluetooth network we'll be using one of the BlueZ test scripts (installed as part of the bluez-test-scripts package earlier), however the test script exits after 16 minutes, so we need to copy and edit the script.
pi@hub:~$ sudo cp /usr/share/doc/bluez-test-scripts/examples/ /usr/local/sbin/
pi@hub:~$ sudo cp /usr/share/doc/bluez-test-scripts/examples/test-nap /usr/local/sbin/
pi@hub:~$ sudo chmod +x  /usr/local/sbin/test-nap
  • To keep the script running edit /usr/local/sbin/test-nap and change the lines :-
  • to
        while True:
  • We want the script to run at startup and one of the easiest ways is using the crontab file. Edit your crontab by running crontab -e and add the following line to the end.
@reboot sudo nohup /usr/local/sbin/test-nap pan0  &
  • Reboot once more (sudo reboot), log in and check that the pan0 interface exists, and the test-nap script is running.

pi@hub:~$ ifconfig pan0
pan0      Link encap:Ethernet  HWaddr da:87:54:2c:f8:66
          inet addr:  Bcast:  Mask:
          inet6 addr: fe80::d887:54ff:fe2c:f866/64 Scope:Link
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:60 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:0 (0.0 B)  TX bytes:9090 (8.8 KiB)

pi@hub:~$ ps ax | grep test-nap
   438 ?        S      0:00 sudo nohup /usr/local/sbin/test-nap pan0
   470 ?        S      0:00 /usr/bin/python /usr/local/sbin/test-nap pan0
   851 ttyS0    S+     0:00 grep --color=auto test-nap
  • If everything is running as expected we just need to take a note of the Bluetooth MAC so we can tell the clients who they need to contact. We can find this by running 'hciconfig dev'.

pi@hub:~$ hciconfig dev
hci0:   Type: BR/EDR  Bus: UART
        BD Address: B8:27:EB:25:A0:AE  ACL MTU: 1021:8  SCO MTU: 64:1
        UP RUNNING
        RX bytes:731 acl:0 sco:0 events:44 errors:0
        TX bytes:1784 acl:0 sco:0 commands:44 errors:0

Setting up a client

  • Download the latest Raspbian image (Here I am using and write to an SD Card.
  • Boot the Raspberry Pi, login and run the 'raspi-config' application.
pi@raspberrypi:~$ sudo raspi-config
  • Select option 2 to change the hostname, change it to 'client0'.
  • Select 'Finish', followed by 'Yes' to reboot.
  • Wait for the Raspberry to reboot and log in again.
  • Setup a network connection. Depending on your setup this can be either by plugging in an Ethernet cable or by setting up a Wireless connection.
  • Install the packages required for setting up the bluetooth network.
pi@client0: sudo apt-get install python-dbus
  • Download a helper script for establishing the bluetooth network.
pi@client0:~ $ wget
pi@client0:~ $ sudo mv bt-pan /usr/local/sbin/
pi@client0:~ $ sudo chmod +x /usr/local/sbin/bt-pan
  • Again we want to run this script at startup, so run crontab -e and add the following, replacing the MAC Address with that of your bluetooth dongle.
@reboot sudo noup /usr/local/sbin/bt-pan client B8:27:EB:25:A0:AE &

Pair client to hub

Before the network can be established a bluetooth connection first needs to be setup between the client device and the hub. This is achieved by making use of the 'bluetoothctl' application.
  • First setup the client so it can be discovered by running the commands in bold below.
pi@client0:~ $ sudo bluetoothctl

[NEW] Controller B8:27:EB:5B:CB:74 client0 [default]
[bluetooth]# power on
Changing power on succeeded
[bluetooth]# discoverable on
Changing discoverable on succeeded
[CHG] Controller B8:27:EB:5B:CB:74 Discoverable: yes
  • Then scan for, and connect to it, from the hub (again using the commands in bold). Once its found we want to pair and trust the client to allow it to auto connect in future,

pi@hub:~$ sudo bluetoothctl
[NEW] Controller B8:27:EB:25:A0:AE hub [default]
[bluetooth]# power on
Changing power on succeeded
[bluetooth]# agent on
Agent registered
[bluetooth]# scan on
Discovery started
[CHG] Controller B8:27:EB:25:A0:AE Discovering: yes
[NEW] Device B8:27:EB:5B:CB:74 client0
[bluetooth]# pair B8:27:EB:5B:CB:74
Attempting to pair with B8:27:EB:5B:CB:74
[CHG] Device B8:27:EB:5B:CB:74 Connected: yes
[CHG] Device B8:27:EB:5B:CB:74 UUIDs:
[CHG] Device B8:27:EB:5B:CB:74 Paired: yes
Pairing successful
[bluetooth]# trust B8:27:EB:5B:CB:74
[CHG] Device B8:27:EB:5B:CB:74 Trusted: yes
Changing B8:27:EB:5B:CB:74 trust succeeded
[CHG] Device B8:27:EB:5B:CB:74 Connected: no
  • With the client paired and trusted we can exit out of the bluetoothctl app on both the hub and client by using the quit command.
  • To check that the Bluetooth network is working reboot the client device (sudo reboot), log in and check if the bnep0 interface now exists and has been assigned an IP address.

pi@client0:~ $ ifconfig bnep0
bnep0     Link encap:Ethernet  HWaddr b8:27:eb:5b:cb:74
          inet addr:  Bcast:  Mask:
          inet6 addr: fe80::ba27:ebff:fe5b:cb74/64 Scope:Link
          RX packets:60 errors:0 dropped:0 overruns:0 frame:0
          TX packets:53 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
  • To confirm the connection has been established attempt to connect to the hub from the client.

pi@client0:~ $ ping
PING ( 56(84) bytes of data.
64 bytes from icmp_seq=1 ttl=64 time=190 ms
64 bytes from icmp_seq=2 ttl=64 time=33.7 ms

--- ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1000ms
rtt min/avg/max/mdev = 33.782/112.324/190.867/78.543 ms

If all has gone well you now have a working Bluetooth network, which you can now extend with multiple clients.

Optional extras

Setup static IP for a client

Sometimes its useful for a client to always be assigned the same IP address when it establishes the network connection and, luckily, this is easy to achieve.
  • First look up the client's bluetooth address using the 'hciconfig dev' command used earlier.
  • Then, on the hub, edit the /etc/dnsmasq.conf file and add the following entry, replacing the MAC with that of your client device.
    • Once the file has been updated we need to restart the dnsmasq service so the changes take effect.
    pi@hub:~$ sudo service dnsmasq restart
    • Now the next time the client requests an IP address it will receive the one listed in the file, and additional entries can be added for every client in the Bluetooth network.

    Enable IP port forwarding

    If your 'hub' Raspberry Pi has a Wireless or Ethernet network connection you can choose to share it with the client Raspberry Pis, in theory allowing them to access the internet via bluetooth.
    • To configure the 'hub' to forward its network connection first edit the /etc/sysctl.conf file and uncomment line 28 to read :-
    • Next edit the /etc/rc.local file and add, the following. Updating 'eth0' to match your upstream network interface (e.g. wlan0).
    # Enable port forwarding. Change eth0 to match the primary network connection name
    /sbin/iptables -P FORWARD ACCEPT
    /sbin/iptables --table nat -A POSTROUTING -o eth0 -j MASQUERADE
    • Finally reboot (sudo reboot), and you should now be able to access this shared network connection from any of the client Raspberry Pis.

    Wrap up

    Hopefully this set of instructions are relatively clear and cover all the steps needed to get a basic Bluetooth network up and running (Either using a Raspberry Pi with built in Bluetooth, or an older model with a USB bluetooth adaptor). More work would be needed to make this a robust solution (i.e. the client only tries to establish a connection when it first starts up) but its a solid base to build upon. In theory it should also work on none Raspberry Pi based hardware that is also running Debian Jessie or equivalent, but I've not tried myself.

    Whilst a bluetooth network is not as fast as a Wifi one (in my tests 200KB/s vs 1500KB/s) it uses slightly less power to run. On a PiZero W transferring files over WiFi seemed to pull about 0.1A more than when using Bluetooth, of course WiFi was also about 8 times faster. Not a huge difference, but if you are running the Raspberry Pi off battery, e.g. running a remote sensor, and are only transferring smaller amounts of data then this could add up to make a difference to the run time of the Pi.


    Thursday, 13 April 2017

    Pi Wars 2017 - Epilogue

    At the start of April was Pi Wars 3.0, the third instalment of the Raspberry Pi robot challenge event, taking place up at the Cambridge Computer Laboratory once again. There were quite a few differences this time tho, the main one being that the event was held over two days instead of just one. The Saturday being for School teams, and the Sunday for the beginners, intermediate and pros/veterans.

    Other changes were the introduction of two new challenges, Slightly Deranged Golf and Minimal Maze. Both proved tough new additions, with the smaller robots struggling with the 'grass' on the golf course, and the larger robots struggling to grab the golf ball when it ends up on the edges of the course. Whereas not many robots managed to successfully navigate the Minimal Maze at all, it being an autonomous challenge.

    Slightly Deranged Golf

    Minimal Maze
    The obstacle course also got an upgrade, doubling in size with several new obstacles to get around. Whilst the sharks were lacking in lasers quite a few robots ended up falling afoul of them, coming off the raised platform to end up sleeping with the sharks (At least until being rescued). The pebbles and scrunched up paper also being a surprisingly difficult obstacle to overcome, especially for those robots with low ground clearance.
    Obstacle course
    I decided to attend both days and, as I was only competing on the Sunday, volunteered to help out on the Saturday. Vaguely expecting to be given a clipboard and stopwatch to manage one of the courses for a few hours I was instead given the task of judging the Technical Merit category. Luckily, instead of having to chase down all the teams myself, it was decided that this year it would make more sense for the judges to be in one spot and the teams to instead go visit them.

    To keep things streamlined I was joined by both the Artistic Merit judge (Hannah) and the Funniest Robot robot judge (Jim) at a table up in the 'quiet area' where we could all view each team's robot as it arrived and not make each team repeat the same answers three times! Over the two hours we saw 19 different robots, slightly less than expected, which ranged from the relatively basic (an ice cream tub with wheels) all the way up to the complicated (robot arm attachments, musical robots, motion controlled robots). The teams them selves varied quite a bit as well,  with a couple where the adults did most of the talking, to those where the kids explained every single detail of their robot, usually accompanied by extreme amounts of enthusiasm.

    With the judging out of the way it was time for a late lunch and then a look around the rest of the area, browse the shops and stalls, visit the 'show and tell' type areas and watch a few of the robots tackling the challenges.
    View over the stalls and golf.Views over the obstacle course and show and tell.

    Eventually I drifted over to the Pi Noon area, along with a growing crowd, to watch (and recorde) the finals (including the quarter and semi finals). Pi Noon had a few minor changes for this year, instead of a single balloon to pop each robot was adorned with three balloons, with the winner being the robot which popped the most (or all ) of the balloons in three minutes
    With Pi Noon complete it was on to the prize giving before a bunch of us headed out to dinner until late.

    Sunday started at around 3am, as several people ran through the corridor of the Travel Lodge I was staying at, and I would be competing with my robot 'PiSquared' in the Pros/Veterans category . At the previous Pi Wars events I had dressed up, so this year I did so again turning up as a Fallout 4 'Vault Dweller', complete with Vault Boy bobble head for my robot and a Raspberry Pi powered PipBoy. The PipBoy was actually part of my 'robot' solution, forming a Bluetooth network that tied together the Pi Zeros connected to the motor drivers and the sensors, allowing them to communicate amongst themselves.
    Why do I subject myself to this?!The  Cambridge Computer Laboratory seems to be missing from the map.
    My first event was Pi Noon, so no time for warm ups, just straight into the action. Last Pi Wars I made it to the finals, this time I didn't even make it into the first round, losing all three of my balloons to one of my opponents.

    Next up was the Obstacle Course, which turned out to be my best event of the day, completing it in just under 1 1/2 minutes to finish 2nd in my group and third overall. My first attempt around the sharks had PiSquared falling into the pit, but I was able to reverse out, limit my max speed down to 25% and making it around the pit on my second try. Unfortunately I didn't manage to get a video of my attempt, instead finding I had a short recording of me setting up the camera...

    As soon as the Obstacle Course was completed it was over to skittles, with a couple of practice runs showing that the servo controller hoop mechanism just wasn't coping with moving the wooden ball around, slipping off the servo, so I changed over to just pushing the ball.  This didn't go all that well as the hoop mechanism was now catching on the ball, stopping me from getting a clean hit, and I ended up with a total score of 2 skittles knocked down!

    I ended up skipping the next two challenges, Line following and the Minimal Maze, as I just didn't have the sensors working well enough to compete. This left me with an hour or so break to grab lunch and recharge batteries... Unfortunately the battery I was charging decided to give up the ghost, getting rather hot and swelling to a large size. Luckily I had been charging it in a fireproof bag and I took it outside to cool down for the next few hours (Of course if it hadn't been in the bag I may have seen it start to expand and stopped it earlier).
    At least it didn't catch fire!
    Golf was up next and this time I completely forgot the camera! The little cage attachment I had created worked mostly okay. The ball did escape when heading down the initial incline, and the size of my robot made it a little hard to recapture on the bend, but I got the ball around the course on both attempts. The first time getting it in the hole, and in the second attempt it rolled behind the windmill.

    The final event for me (As there would be no more Pi Noon battles) was the straight line speed test. This year the challenge was autonomous only, as opposed to either in previous attempts. So I sent PiSquared trundling down the track, requiring several rescues to reach the end. I even manage to repeat my PiWars 2014 trick of finishing a run with one less wheel than I started with... I suspect that run didn't count in the end.

    With all my challenges completed I packed up most of my stuff and headed on down to watch the rest of Pi Noon. This time remembering my camera and tripod! Sunday didn't seem quite as busy as Saturday, despite there being an extra 16 teams competing. I guess the overall team size was higher on the Saturday, with lots of school kids and parents around.

    So how did I get on? Well not so great in the end... My best result was in the Obstacle course, but this was balanced out by doing rather poorly in the skittles. My worst event was, technically, the line following and minimal maze as I ended up not even attempting them :( For the other events I was kinda middling and, despite getting into the Pi Noon finals last time, this year I got knocked out in the first round!

    So what happened? To a degree I think this was down to my inexperience in 3D design, having only previously designed very simple components I had a lot to learn, and plenty of trial and error, to design the robot chassis, interchangeable front wing, rear wing and other accessories. Added to this was the sheer amount of time it took to print, the main chassis itself coming in at just over 20 hours, the rear wing 5 hours and the front wing 2+ hours. My 3D printer was running almost constantly for the month leading up to Pi Wars itself and I still had stuff being printed as I was packing up ready to leave.
    Normal and PiNoon wingsGolf and skittles attachments.Distance and line sensors.

    With all the time spent on getting the hardware ready it left very little time to actually work on the software, the main reason I didn't try the line following and minimal maze challenges. So how to improve? Well having a second printer up and running would have helped, and I started using the 'cut' functionality of my slicer to only print out the part of the model I'm currently working on. There were several accessories that I had the parts for but not the time to assemble and test (I had several plans for skittles, one involving a drill, another a mallet), which if completed would made my robot more competitive.

    Being a totally new design there was quite a lot of work and time spent before having something that could actually move around, so if there was a Pi Wars 2018, and I was competing, then I'd be looking at doing an improved/finished version of this design. I do want to finish getting the sensors and so on working, hopefully getting stuff to a stage where I can release the STLs and software for other people to use. Possible even have it slightly improved for the Egham Raspberry Jam later this month.

    Other than that there are several projects that I've had on hold whilst working on Pi Wars that I'd like to get back to, as well as some blog posts I need to write (Like how I finally got a bluetooth network up and running!).


    Friday, 24 March 2017

    Pi Wars 2017 - Scaling things up

    Whilst the robot I posted about in my last blog entry is reasonably compact and contains most of the components I'll be needing for the PiWars 2017 challenges, in practice it feels a little bit sluggish and under powered, and not something I'd be confident entering into the Pi Noon challenge. So I decided what was need was a slightly bigger robot.

    Now as the robot is 3D printed I can just scale it up to the size I want yes?  Well, unless you have a fully working replicator, its not quite that easy. The plastic parts scale up nicely the motors and other electronics don't. The weight increases, so you need bigger motors, then bigger, however the batteries, and possibly a higher rated motor controller. Then you need to make all these bigger components fit on the robot and suddenly it feels like you have less space than you did before!

    I stripped all the parts from my PiWars 2015 entry and went through several revisions of the scaled up chassis, trying to work out how to make everything fix together.  Eventually I did a spot of rewiring on the controller, cut off some pins and finally came up with the following.

    Old vs New

    The new Pi Squared chassis is considerably larger than the previous variant, as well as gaining a rear wing, just fitting inside the maximum dimensions allowed for PiWars. The front wing is now removable, allowing the chassis a bit more space on my 3D printer, and can be swapped out for the various different challenges, although the only one I have prepped so far is for Pi Noon.
    Removable front wings
    The downside to the increased size is it takes a lot longer to print. The chassis takes just over 20 hours to print, the rear wing 5 and the front wing another 2...So my printer has been running almost constantly for the past week!

    The control method is my usual PS3 controller, with a simple python script driving the motors, making use of pygame and the GPIOZero library to keep everything simple. In fact the entire code is rather small.

    import pygame
    import os
    import time
    import gpiozero
    os.environ["SDL_VIDEODRIVER"] = "dummy"
    # Wait for a joystick
    while pygame.joystick.get_count() == 0:
      print 'waiting for joystick count = %i' % pygame.joystick.get_count()
    j = pygame.joystick.Joystick(0)
    print 'Initialized Joystick : %s' % j.get_name()
    from gpiozero import OutputDevice
    from gpiozero import Robot
    EN1 = OutputDevice(17)
    EN2 = OutputDevice(6)
    r = Robot(left=(27,5), right=(13,4))
        # Only allow axis and button events
        pygame.event.set_allowed([pygame.JOYAXISMOTION, pygame.JOYBUTTONDOWN])
        left = 0.0
        right = 0.0
        while True:
            events = pygame.event.get()
            for event in events:
              UpdateMotors = 0
              if event.type == pygame.JOYAXISMOTION:
                left = j.get_axis(1)
                right = j.get_axis(3)
                r.value = (left, right)
    except KeyboardInterrupt:
        # Turn off the motors

    Finally here's a quick view of the new and improved Pi Squared running around.

    With only a week left until PiWars I still have a lot to do, sensors to attach, code to write, practising driving.. So its going to be a busy weekend and evenings for the rest of the month!


    Wednesday, 1 March 2017

    Pi Wars 2017- How to build robot?

    Having considered the various challenges that will be present at Pi Wars 2017 next step is to give some thought on what type of robot I'll be needing to tackle them. Now the sensible approach would be to use my Pi Wars 2015 entry as a starting point, after all its a fairly solid base, improve on the returning challenges (e.g. the line following) and add additional functionality to handle the new challenges.

    Of course that isn't the approach I'll be taking, although it will be the backup plan, instead I'm looking at starting afresh and putting together a new robot for Pi Wars 2017. To a degree this is because I have new ideas and new components I want to try out, as well as the fact that my Pi Wars 2015 entry didn't turn out to be all that interesting.

    There are various components you need to put together a robot and, fortunately, in the run up to PiWars 2017 the MagPi Magazine has run a few articles, starting in Issue 51, on how to build a remote controlled robot suitable for Pi Wars.

    Lots of wheels and motors.
    So what do we need? Well I will be going for a wheeled robot once more, either a two or four wheeled variety, and I'll be aiming to reuse some of the motors and wheels from previous robots. At last PiWars I took a selection of wheels but ended up not swapping them out for specific events as the motor connections were a little fragile, so that's an area I want to improve this year.

    As far as the motors go I want to investigate using stepper motors to try and get a bit more precision in some of the autonomous challenges. I have a set of four from a 3D printer, as well as a couple of larger ones salvaged from an old Laser printer.

    Motor drivers

    Next up is the motor controller. Here I have a choice of reusing the motor driver from last year as well as using some of the other's I've purchased over the years. The final choice is liable to be determined by the motors/wheels I end up using, and indeed I may need more than one motor driver, especially if I want something to propel the skittle or golf ball at a high speed.

    A robot won't move without power, and once more I'll be going with Lithium Polymer ones for their high power in a small package. I've not yet had one explode on me... however there have been a few sparks, so you need to be careful handling these.


    Next is the brains of the robot, last time I used a Raspberry Pi A+ for its mix of smaller size, reduced power consumption and camera connector. This year I'm currently using a RPi 3B for its additional power (In case I do image processing) and its built in WiFi and bluetooth. Although I'm also planning on using some PiZero for supporting roles.

    Boxes and containers

    Next up on the list is the chassis, something to fit all the above components into, along with the connecting wires as well as any extra sensors or components required. My first Raspberry Pi robots were based around the BigTrak toy and other people have has success with other large plastic toys (preferably ones that already have motors in them!).

    Cheaper alternatives are empty food or packaging boxes (e.g. ice cream tubs, the CamJam EduKit box) as well as various project boxes available at Maplins or similar places. I used a project box for PiWars 2015, but ended up finding it to be a little restrictive in getting all the components connected to it, and overall ended up with a fairly plain looking robot (especially when compared to my Pirate ship from the first PiWars!).

    Luckily I have a much more flexible option this year, a 3D printer! Allowing me to, in theory, print out the exact shaped chassis I want.  Of course that is entirely dependant on me being able to design it in the first place....

    I've only created fairly basic objects to print before, so I thought I'd have a little practice by creating a chassis for a simple ZeroBorg based robot using 4 of the little micro metal gear motors to drive around. This took a few iterations but I generated a simple chassis that looked like it was going to work... apart from one small detail I missed.
    Yes... I forgot to allow space for batteries to drive the motors.... I ended up balancing a 9V battery pack on top of the PiZero, but that wasn't exactly ideal...

    So it was back to the drawing board to come up with something a little better looking for PiWars and, after quite a few more iterations I've come up with the following (Which takes over 4 hours to print if I want it good quality!).

    Still needs more work but its a Raspberry Pi 3, with camera, along with 2 motors, a LiPo battery and an AdaFruit PowerBoost 1000C to allow the LiPo battery to be charged without having to remove it, or interrupt power to the Pi3. There are liable to be many more iterations (It needs sensors/attachments for some challenges, maybe bigger motors/batteries too), but I'm hoping to keep to this general shape for the final event (only a month away now!).

    So that is how I'm planning on building my robot! More or less.. Obviously I have a lot more work to do, but already its looking nicer than my last attempt!.