Maze Runner

David Rohu
5 min readApr 18, 2021

After lots of weeks of planning and preparation today we find out if the Tumbller can make it through the maze (obstacle course) and if I can manage to net any ping pong balls in the process. This is the final layout from the Tumbller's point of view with the bottles now in place to fire the ping pong balls over.

There have been a few changes I made to the Tumbller though that I want to talk you through before we look at the attempt. First of all I had to rebalance the motor speeds as the Tumbller was drifting left while both motors were set at the same speeds (had the same voltage applied). This is a very common problem and could be simply due to slight variations within the motors or an uneven mass distribution. Although it is very difficult to get this perfect, I was able to improve it a lot through assigning slightly different values to each motor within the code. This is shown in the drive function code segment below.

Drive Function Code Segment

It is really important to get details like this right when the position of the robot needs to be closely monitored (like when completing an obstacle course). Any small discrepancies will only accumulate as the course continues unless this can be compensated for. I also had to do this when the robot reached specific obstacles to avoid it over or under shooting the turn.

This is simply part of the process unless more complex coding is done to incorporate encoder readings and measure exactly how much each wheel rotates. These encoders are built into the motors but I decided that it probably wasn’t necessary to use them for this. I could also have made us of the IR sensors which measure distance left and right of the ultrasonic sensor. This might have helped control how far the Tumbller turned at each obstacle and kept it running parallel to the side walls through measuring that distance. Again, although I quite like this idea, I felt the more simple solution was just to compensate for small irregularities through the values assigned to specific turns within the code.

In the last blog post I shared some pseudo code for how I planned on writing the actual code for the course. I decided to change it slightly and use a more simple and elegant method through the use of switch statements. How these work is that a switch statement compares the value of a particular variable to values specified in case statements. When the variable is equal to that of a case statement, the code in that statement is run. This is probably more easily understood through looking at another segment from my code.

Switch Case Code Segment

In principal this is almost the same as the pseudo code shown in my last blog, where a variable, ‘action’ here, is assigned a particular value which is added to as individual cases are run. The Tumbller starts off by simply driving forward without any time constraint, as long as the ultrasonic sensor does not pick up an obstacle closer than 20 cm away. If an obstacle is detected within that range, the first case statement is run. This is as action was initially defined to carry the value 1. After the left turn is competed the ‘action’ variable is added to, giving in the value 2, and the Tumbller starts to drive forward again. This in turn means that once another obstacle is detected, the second case statement will be run and so on.

This allows particular commands to be given to the Tumbller on iteration of it detecting obstacles within a 20cm range, which is exactly want we wanted to achieve.

The functions used within the code were as follows:

Functions Code Segments

These functions are very simple and are almost the same as those shown on a previous blog post. One difference is that I introduced the variables AIN1 and BIN1 linked to specific pins on the motors which determine their rotation direction. These were already defined on the robot when it was shipped out. Adding these allowed me to get the robot to turn on the spot with one motor rotating forwards and the other backwards. This can be seen in the functions left_turn and right_turn. The duration for the turn could be specified by changing the value of ‘time’ in the delay.

The only difference between the drive and forward function is that the drive function does not have any delay with which to determine the time that the function is carried out for. The forward function was used at either end of the obstacle course where the robot needed to move a certain distance forward before performing another maneuver.

As I anticipated in the last blog, the extra length added to the front of the Tumbller through the attachment of the new caster wheel made progressing through the course a bit more difficult. The course was already quite tight for the Tumbller to get around and so the extra length required the robot to get as close to the walls of the course as possible to make the turns. This, because of the slight delayed response of the ultrasonic sensor, made it so that it often touched off the the side walls before making a turn. This is not a problem but it does make the use of the ultrasonic sensors look a bit less impressive. I think of these more as controlled crashes.

That is all I wanted to say before showing you how it all worked out, so here is the clip.

Yes, the launcher did get stuck which is not ideal but I did still manage to land a ping pong ball and get it to the finish. This is definitely a success in my books.

Overall, it was a lot of fun putting this all together even if ironing out some small details in the code was a bit of a nightmare. This is not the end of the road though, there is still one other project I need to get finished before the end of this college year and that is building a Rube Goldberg machine. I have a few ideas for this already and have been working on it a bit in the background. I am looking forward to sharing my progress here.

Thank you all for taking the time to read through this. Hopefully you learned something or at least enjoyed the read.

More to come soon.

--

--