Friday, 30 November 2018

Designing a Rocker Bogie Raspberry Pi Rover

When the Pi Wars robotics competition announced the 2019 event with a space theme, it was clear that the various NASA mars rovers would be a source of inspiration for many potential competitors. I saw a few mentions of Rocker Bogie suspension on Twitter in connection with the competition. I had not heard this term before so I looked it up online. Wikipedia had an article with an animated graphic which had a caption saying it was not actually correct. I was intrigued, but still not sure what it was. I had my balance bot idea and felt that submitting an entry which was just saying I would build a mars rover inspired robot probably wouldn't make the cut for Pi Wars 2019. So I dismissed the idea at the time.

What changed my mind was the publication by JPL of an open source educational model of the Mars Curiosity rover with full build instructions. Their website has a nice animation of their model rover which shows how the rocker bogie suspension really works using a differential pivot (link above: click on the rover to switch to the engineering model and then click the hotspots on the model). It looked like a really interesting build, and felt more likely to succeed in the Pi Wars competition than my balance bot idea. So I based my application on the idea of shrinking the design down to fit within the Pi Wars competition limit stated in the rules.

In the month leading up to the submission deadline, I had started to learn CAD software for the first time. By the entry deadline I had modelled a steering leg from parts which could be cut from 3mm acrylic sheet.

I included this picture in my application. This is what I wrote on my application form:

My plan is to design and build a 6 wheel drive rover with full rocker-bogie suspension. The design should be able to turn on the spot, and drive over uneven terrain while keeping all 6 motor driven wheels in contact with the terrain.

I have seen that the most common good performing design for a Pi Wars robot is a standard 4 wheel drive rectangular chassis, but I saw so many of them at the event last year I felt there should be more variety. So I was looking for ideas for something that would be more visually and mechanically interesting. After several months of trying to build a 2 wheeled balancing robot, I have learned a great deal, but also realised this is probably too big a step for my first entry attempt. I’ll never have the time to learn all the computer vision and autonomous driving code if I stick with that plan. So I decided to embrace the Space Exploration theme. After discovering the JPL Mars Rover open source design I am working on designing a scaled down A4 footprint version which I plan to build from acrylic, using the micrometal gear motors and moon buggy wheels as used on the Coretec Robotics Tiny 4WD robots. My aim is to build something visually exciting and mechanically interesting using affordable components. Other components I have bought (but not learned how to use yet!) include a PixyCam2, and a brushless motor and ESC with a view to build a Nerf dart firing mechanism.

To my delight I got a place in the 2019 competition. Now I had a lot of learning to do. I joined Cambridge Makespace in order to learn how to use a laser cutter and start working on turning this idea into reality.

Friday, 23 November 2018

Self Balancing Robot - Part 2

In my previous post I described the problems my initial attempt at coding a balance bot ran into. Specifically the vibrations or shockwaves from the motors turning on and off swamp the accelerometer readings in noise. So instead of measuring the direction of gravity acting on my robot, the accelerometer is measuring the accerleration forces of these shock waves through the chassis. The robot just vibrated noisily and fell over because I could not measure angle of tilt of the chassis this way. Then it shot off across the room lying down. This second aspect was more concerning initially as it risked damaging my robot. So I dealt with that first.

Once the robot had toppled over, the motors are not able to right it again. There is an angle of tilt beyond which gravity wins over the power of the motors I have. At less steep angles of tilt the robot tries to drive at speed across the room, attempting to get the wheels back underneath the centre of gravity of the robot. I did not know exactly what angle the robot was unable to recover balance beyond, so I just picked 45 degrees from vertical as a starting point (I can tune this value later when I have the fundamentals working). If the robot was tilted at an angle of over 45 degrees from upright, then I set the code to keep the motors off. That way the drive is automatically off if the robots is lying down, and turns off pretty quickly when it falls over.

Now I just needed to work out how to effectively measure the angle of tilt using the IMU when the motor vibrations mask this information read from the accelerometers alone. My IMU is a 9dof chip (that's 9 degrees of freedom). These come from 3 sets of sensors each of which is measuring along 3 orthogonal vectors (x, y and z axes). We've already talked about the accelerometer (measuring changes in directional forces acting on the chip). The other 2 types of sensor are magnetic field strength, and gyroscopic. The gyros measure the rate of rotation around each axis. If we know how fast something is rotating and we measure this for a short enough time interval (so that the reading we take represents the average over the whole time period) then we can work out how many degrees we have rotated during that time. This allows us to work out the change in tilt angle of our robot since we last knew the angle of tilt, so we can update the angle in our code.

I found example code doing this where the time interval was stored in a constant for their program, based on how long their code loop took between readings. But this appeared flawed to me as what if the code in my loop varied in how long it took to run? So instead I just captured the time just after taking a reading, and then on the next reading I could work out how long had elapsed since the last reading. If you mount your IMU chip so that one of the 3 axes is parallel to the axle of your balance bot wheels then you only need to read one of the 3 axes of the IMU gyros. So with this code we can determine how much our robot tilt angle has changed in the last loop cycle. To work out the actual angle of tilt we also need to know what angle we started at. The gyros cannot tell us this, so we need to use the angle calculated from the accelerometers first. This is OK as long as we read this when the robot motors are off and the robots is not being knocked about. The perfect time is when the robot is being tilted upright to start with, or it is lying down with the motors off not moving at all.

My code design so far is structured as follows.

  1. The loop is timed at the start. This means the first time around the loop the calculated time elapsed will be wrong, but we don't use it on the first pass round the loop so that does not matter. By the time we start reading the gyro we will know now long we have been in the loop. 
  2. We start in accelerometer mode, and stay in that mode until we get stable tilt readings. This ensures we know the true tilt angle read from the accelerometers while the robot is stationary.
  3. Once we know the tilt we can switch to gyro mode. By this time we have been round the loop more than once, so the time elasped calculation is correct for the current loop iteration. We use it to work our how much we rotated according to the gyros in that time.
  4. We add/subtract the amount of rotation since the previous loop iteration from the tilt angle we last calculated, to update it to the new tilt angle.
    Set measure mode to Accelerometers
    Initialise last loop time to zero

    Get the time now
    Calculate the time elapsed since last loop iteration
    (time_now - last_loop_time)
    Update last_loop_time = time_now

    If Measure mode is Accelerometers:
        Calculate angle of tilt measured from the accelerometers

        If angle is very close to last measured angle:
            Switch measure mode to Gyros

    Else (measure mode is gyros)
        Read rate of rotation around axis of wheels (using the gyro)
        Calculate how far we rotated since last tilt calc
        (degrees rotated per second * seconds elapsed)

The psuedo-code above hopefully explains the basic approach, but there is a problem with it. Once we switch to gyro mode, we only ever calculate tilt based on the previously calculated tilt. So any inaccuracy in the measurements can result in the calculated value drifting from the actual tilt angle. Only a small amount of drift will cause the robot to try to maintain an angle different to the perfect balancing angle, and the only way to keep that angle is to keep moving. So the robot will quickly start to head off at speed across the room. Now we are driving the motors we cannot rely on a precise reading from the accelerometers, so how do we correct for this drift in the gyro calculated reading?

I get a lot of help from fellow makers on Twitter, and in this case extra credit must go to  for pointing me at the following resources. The problem of determining when something is level against the background vibration of motors is the same for autoleveling flying drones like quadcopters. Keith pointed me to the following website which in turn links to a couple of tutorial videos on YouTube on autoleveling quadcopters. The first video is here and links to part 2 in the comments:

After thinking and playing with these ideas I realised that while the quadcopter example is having to level in 2 directions (pitch and roll), our balance bot case is much simpler. We only need to consider one axis of rotation, the axis of our wheels axle. Our robot only needs to rotate around this one axis to self balance. The technique in summary is to mix a small amount of the tilt angle calculated from the accelerometers alone with the tilt angle calculated from the gyros. The accelerometer calculated tilt values are very noisy, but over time their average represents the constant force of gravity. So mixing in a very small amount (~0.05%) to the gyro readings does not throw off the calculated tilt significantly, but it is enough to correct for the drift in the gyro readings over time.

With this knowledge I was able to get some initial code working which gave me a reliable tilt angle whether the motors were on or off. I was able to start experimenting with PID tuning next, but that will have to be another post. What I had realised was that this was going to take me too long to perfect for my first Pi Wars competition entry, and another idea had come along which looked much more suitable for my submission for a place in the 2019 competition. We'll look at this in my next post.

Saturday, 6 October 2018

Self Balancing Robot - A steep learning curve!

I've always wanted to build a self balancing robot, and I thought it would make a very visually interesting Pi Wars competition entry. Some searching online and some pointers from members of the maker community on Twitter led me to a number of projects on YouTube with links to blog articles and code. But all these examples seemed to be of the 'recipe' format. By this I mean they contained detailed instructions to build the exact same robot as  the author, using the same parts. Then just deploy the provided code (mostly onto an Arduino) and VOILA! A self balancing robot. If only things were that simple.

I didn't just want to build someone else's project. I wanted to understand how it actually worked, and build my own robot using the components I had. I wanted to understand the theory and the code so I could design my own. So I started to dig deeper into one of the examples.  I learned that the feedback from a tilt sensor is generally processed by a PID algorithm to control the power and direction of the motors to try and maintain an upright position for the robot. It all sounded simple in principle. Use a sensor to measure the angle of tilt, feed this value along with the desired angle of tilt into a PID controller library and apply the output to the motor drivers.

So what is PID?

Before you Google it and find the page on Pelvic Inflamatory Disease, we are talking about a PID Controller, or Proportional Integral Derivative controller. You might find the Wikipedia page of interest. There is a PID controller library available for Arduino, and the author Brett Beauregard has written a series of very detailed blog articles about the theory. Here I will just talk about the usage of his library for a balance bot. In simple terms, you keep reading the angle of tilt between your robot and the force of gravity. On each loop through your code you feed in this measured angle, and the PID Controller calculates a power value to apply to the motors to bring this angle closer to the desired angle. For a stationary balancing robot, we want the robot to be upright and the motors off. If the robot is starting to topple over then the angle moves away from this desired upright angle and power is applied to the motors to restore balance. The greater the difference between the actual measured angle and the desired 'upright' angle, the more power is needed to allow the motors to restore balance. But too much power and the robot is tilted over the other way. So the PID controller constantly needs updating with the current tilt, and needs to apply a new correction to the motors.

The PID Controller also takes 3 input values which control the output for different changes in input over time, and these need to be tuned to make a stable robot. These tuning constants are referred to as Kp, Ki, and Kd. I was pointed to this video which demonstrates the effects of different values for these constants.

Most of the example code I came across supplied values for all 3 constants. But I learned that these values depend on the physical characteristics of your robot. How heavy is it, and how the weight is distributed. How fast your motors are and how much torque they generate. So there are no 'magic values' you can just use. You need to tune your own robot once you have built it. So we had better look at what I actually built.

A Self Balancing Robot Development Board

To prototype and build a proof of concept you don't need a bunch of fancy machinery and a workshop. I started with a sheet of plywood from my local DIY store, a hand saw and the patio table in the garden as a workbench (so I didn't need to sweep up my mess!).

In my parts boxes, I already had the following:

  • An Arduino UNO.
  • A pair of Adafruit motor driver breakout boards.
  • A set of PiBorg motors and wheels.
  • A Sparkfun 9dof IMU breakout board

I had no idea what sort of motors I needed so I took the approach of just trying out what I had to hand first, before going out and buying something I possibly didn't need. Here is what I built.

I simply cut a rectangle of plywood, and bolted everything on. I used cable ties to hold the batteries in place. The physical build did not take long at all. You can use any motor driver boards which can handle the stall current of your motors (this is now much current the motors will draw if they are powered but are prevented from turning). I used the example code from the IMU board I had to read the angle of tilt from vertical using the accelerometers. In my case, the angle was 180 degrees when the robot was balancing upright. Using this information I just needed to use the PID library to calculate the motor power needed to maintain balance, in a loop so it constantly updates based on any change in the tilt value. I am not going to give the full code here, but instead try to explain the principles I was using. We'll look at some actual fully working code in a follow up post.

The PID Controller takes the following inputs:

   PID pid(&input, &output, &setpoint, Kp, Ki, Kd, DIRECT);

The variable names with & in front indicate these are pointers to the variables in my Arduino program. So any changes made to their values anywhere in my program will be available to the PID controller code. I wanted my robot to maintain a tilt of 180 degrees, so my setpoint value was 180. Kp, Ki and Kd are the tuning constants I needed to set to appropriate values for my robot. Input is the value of tilt I was reading from my accelerometer, and output is the power and direction I needed to run my motors. The PID library needs to know the range of values I want my output to range between, so I also had to setup the PID controller with this information:

    pid.SetOutputLimits(-100, 100); 

So now the PID controller knows my motor output values need to be in the range -100 (full power reverse) and +100 (full power forwards). In the main program loop, I now just needed to read the tilt from the IMU, run the PID Controller calculation, and apply the output power to my motors. Or so I thought. It turns out there are a number of complications I had not taken into account (and which the example project I was trying to follow did not use). What actually happened when I turned it on was that my robot just vibrated very loudly and fell over. Then once it hit the floor it shot off across the room with the top of the board scraping along the floor!

It turned out that the motors were put into full power forwards, which generated a shock to the IMU making the accelerometer read a very high value. This cause the PID controller to put the motors into full reverse, causing an opposite direction shock to the board. This repeated on every iteration of the loop. So the motors alternated between fast forward and fast reverse. The whole thing was shaking, causing the buzzing sound and the tilt values being calculated were not related to the angle of tilt of my robot at all, but to how hard it was being shaken by the motors.

At the time I did not understand what was wrong, so I posted my failure on Twitter:
Pretty quickly got some great pointers to more information. Clearly I had more reading to do. In my next blog post I will explain how these problems in my initial design were solved.

Monday, 3 September 2018

Mentoring School Teams for Pi Wars

As I already lead a code club and volunteer at youth groups to give Raspberry Pi and robotics workshops, it makes sense for me to get involved with mentoring school team entries for Pi Wars. This may prove to be a distraction from my own plans for a Pi Wars entry, but I expect it will actually focus my thinking on design and building robots. I am sure it will also expose me to a great level of creativity and ideas which will benefit my own entry. My daughter was inspired to enter the Pi Wars 2019 competition after attending the 2018 competition as a spectator, and originally the plan was to encourage her to put in an individual entry. But then she got one of her school friends interested and I had two children wanting to work on an entry. So I contacted their school computing teacher to see if they were interested in running a school team entry (or multiple teams). Their teacher was very interested in the idea, and I am now tasked with preparing and giving a school assembly on Pi Wars early in the new school year (with around 20 days remaining to get entries in).

Over the school Summer holidays I have been working with my daughter to guide her and her friend to start building a robot chassis and writing some Python code. We chose Lego Technic and a tracked tank like design. This enables rapid prototyping and learning a lot about the mechanics of building a working tank chassis.

We had a lot of fun building the chassis over the holidays, and took it all away with us to work on while on our Summer family holiday.
We used a state table to design what she wanted the motor control code to do in response to different positions of controls on a game controller. This was a great success in coaching her to create a design, and then realising that design in code. My daughter was really engaged with the project and it has kindled a desire in her to learn Python. After the holiday we visited our local library and she picked out two childrens 'Learn Python' books which she has started to work through at home. A very successful start and a great example of how a project like a Pi Wars entry generates the drive to learn new skills and overcome challenges.

Now I need to overcome the challenge of giving an assembly at my daughter's school to inspire other children to enter the competition this year.

Friday, 13 July 2018

Ideas for My First Pi Wars Robot

One of the things I noticed at Pi Wars 2018 was that there were a lot of very similar robot designs as far as the basic chassis, drive and steering are concerned. Four wheel drive, fixed mount wheels on a rectangular chassis, with steering done by reversing the direction of the wheels on one side compared to the other. Clearly a winning formula and very effective on the more challenging terrain of the obstacle course.

A great source of ideas and knowledge are the blogs written by previous entrants (check out the Pi Wars 2018 blogs or others on the 'past years' pages of the website). There were a few rather different entries, many of which really struggled in the challenges. But it was these that I enjoyed watching the most. Some tracked tank like designs worked well and one omni-wheeled robot had some awesome moves.

I am not so much motivated to try to win the competition, as to entertain and inspire. Sure I want to design something that performs well, but not at the expense of individuality. So I came away from the 2018 competition thinking it would be cool to enter something completely different. I had always liked the idea of building a 2 wheeled balancing robot, so my plan was to try and build one capable enough to tackle the challenges at Pi Wars. It turned out I was not alone!

So the learning phase begins. Here are some of the questions I have at the start:

  • What sort of motors are needed for a balancing robot?
  • How do you use an accelerometer sensor?
  • How do you control a pair of motors using the tilt sensor data to keep it balanced?
  • How do you get a balancing robot to move forwards and backwards while the motors are being driven to keep it balanced upright?
  • How big can a 2 wheeled balancing robot be and still qualify for the Pi Wars rules of maximum size?
  • Is this idea completely mad?
I decided to start experimenting with the parts I already had in my boxes of bits I've bought already for robot projects in general. A pair of motors from PiBorg, a SparkFun 9dof sensor breakout board, and some AdaFruit 3.6A motor driver breakout boards. It seems like a good idea to use a dedicated processor to handle the sensor reading, balancing and motor driving aspect of things. I don't want the robot falling over every time the Raspberry Pi is busy doing something else when I start looking at image sensing and autonomous driving challenges. So I started with an Arduino board to attempt to build my first prototype.

This added a couple more questions to my list of things I needed to learn:
  • How do you program an Arduino?
  • How do you communicate between an Arduino and a Raspberry Pi?
This is going to be a very educational journey!

Thursday, 12 July 2018

The Beginning of My Pi Wars Journey

Back in September 2017 as I was starting to engage with people in the Raspberry Pi community on social media, a friend told me I would love Pi Wars and should check it out. A quick Google search brought me to where I learned about this exciting non-destructive robotics competition in Cambridge. Unfortunately the deadline for entries was only about 3 weeks away, and I had only just built my first robot using the CamJam Edukit #3 which started me on these adventures. Looking at the challenges it was clear I had a lot to learn before I could write an entry application. So it would not be for that year. I noted the date of the competition in my calendar and planned to attend.

It was a start, but I was going to need something a bit more sophisticated than this.
Over the next 6 months, I built my first few robots. Mainly as technology demonstrators for kids clubs and workshops I had been volunteering at. As the date of the Pi Wars competition approached, I went to a couple of the excellent meet ups at Cambridge Makespace organised by previous Pi Wars winner Brian Corteil where I got to meet some of the competitors and see some of their robots in development. I registered as a volunteer for the event and when the weekend of the competition came, I did the morning shift judging the obstacle course for the schools entries on the Saturday.

As well as seeing lots of robots over the Pi Wars weekend, I also learned a lot about what went wrong for competitors. Robots which could not grip on slopes, or get over the edge of a piece of plywood. Batteries which came loose and dangled on the ends of their leads as the robots attempted the courses. Controllers which stopped talking to their robots. Robots which stopped when their software crashed each time they took a knock. Robots which arrived at their time slot for a challenge with the wrong version of the code on their SD Card. Operators who struggled with the fine control needed to get their robot to drive where they wanted when they wanted.

Clearly a competition robot needed to be robust, well tested and the driver well practised in operating it. It also helped to have pink unicorn stickers on it (well it should look interesting, not just be functional). I took my kids along on the Sunday to spectate, met a lot of people, bought lots of parts to build bigger and better robots and came away with my daughter saying she wanted to enter, and wanting to have a go myself too.

So now the Pi Wars 2019 dates have been confirmed, and the details of the challenges published. Clearly it is time to start thinking up some ideas!