Robot Tour was a Science Olympiad Event that I competed in from 2024 through 2026. These are monthly blog posts about my experience with Robot Tour.
I began with a starter’s kit from Ward’s Science. It used a BBC Micro:bit, two DC motors, and an Inksmith k8 motor driver. I programmed it primarily with Microsoft Make Code. I experimented with some other MicroPython editors like Mu, but ultimately stuck with Make Code. The Inksmith k8 motor driver was at first hard to figure out because I could find very little documentation. I primarily used an extension for Make Code that was made by Inksmith. I grew rather frustrated with the limited control I had over the motors so I dug into how the library was made. I found the Github project and was able to figure out what pins to write to to control the motors. This gave the control I was looking for however it did not produce the intended results. Probably the biggest issue was that it would not go straight. A secondary issue was that since it used plain old DC motors I had no way of tracking movement. My first invitational did not go well so I returned to the drawing board.
Discouraged by the capabilities of the Inksmith motor driver and the kit motors, I decided to use an Encoder Motor from what I had learned while working on another event, Electric Vehicle.
I at first tried an Arduino Uno R4 and an L298N motor driver with the encoders but landed on using the same Micro:bit paired with a Keystudio motor driver with the encoder motors: This is the design I maintained for the rest of the 2024-2025 season.
The chassis changed slightly ending with this design:
The biggest issue with this new design was that while now I could successfully track the distance traveled I was unable to move in a straight line. Performance of the robot was also largely dictated by the voltage levels of the batteries making consistency hard to achieve. I continued to tinker with it but this design is what stuck for the remainder of the 2024-2025 season.
The new season of robot tour introduced a new bonus (object manipulation done by the robot) but was relatively similar to the 2024-2025 season. One big difference was that I was no longer soloing the project. My good friend Kaladin was now working with me on the project. We initially wanted to use something like a stepper motor instead of the encoders I had used last year. Since steppers seemed too difficult we landed on continuous servos. The components we used were an Arduino R4 with the Arduino Rev3 motor driver, two continuous servos, a buck converter, and 2 four-battery packs wired in series:
The idea with the buck converter was that we would regulate the voltage to the motors and thus end the unpredictable nature of the robot’s movement. However we misunderstood the behavior of the continuous servos. We thought that we could write a value (the change in orientation) e.g 720 degrees, to make the servo turn 2 rotations. This is not how continuous servos work. Continuous Servos have easily adjustable speeds so you can speed control without a motor driver. These obviously did not suit our needs.
Also this was actually the second chassis design of the season. The first one which has remained unpictured was destroyed after a battery incident. One of the batteries began leaking during testing and melted/corroded the aluminum frame. We treated the acid with a base to hopefully neutralize it, but the damage was done so we moved to the mostly 3d printed chassis you see above.
We replaced the continuous servos with my old encoders, but needed a new chassis as our current one was now too small. I resurrected my previous design from the 2024-2025 season. Here is a picture with the chassis outfitted with the components:
Additionally we have added the MPU6050. The MPU is a gyrometer and accelerometer. We used it to check the orientation of the robot to make sure we were turning 90 degrees and moving in a straight line. It was largely successful due to the finicky reading of the MPU. It drifted a lot when trying to read. We also were unable to read the MPU and the encoder motors at the same time due to the limited abilities of the Arduino. Without reading the encoders we attempted to just try and have the robot move in a straight line using readings from the MPU but it was not fruitful.
We made several major changes to the robot in December. First we upgraded the MPU to a BNO055. Secondly we had been using code that read both encoder pins and attempted to discern the direction of the movement and update a count of how far we had traveled ever since I had used it in Electric Vehicle back in 2024. We wanted to read the BNO while also being able to read the encoder motors. Since the Arduino cannot multi-thread, we explored the possibility of using an ESP32 but were reluctant to abandon our faithful Arduino. Instead we found out about interrupts. Using interrupts to read the encoders in the background the Arduino was freed up to respond to feedback from the BNO. This was our first successful implementation of a feedback loop. It is quite laughable that it took me a year and a half to finally reach this point. However we unfortunately found that one of the pins needed to read the encoders was also used by the Arduino rev3 motor driver for some other function. This meant that we would be only able to read one encoder. This was not a viable situation so as you can see from the image above we resorted to using a L298n motor driver to free up the Arduino’s Interrupt Pins. This was our new circuit:
The BNO055 was both a life saver and the single one component that broke our brains. It behaved erratically at first. We were able to use an Adafruit Library to read most of our information from the BNO. Initially we could not read any values from it except for zeros. At some point we discover a small copper pad at the back of the breakout board intended to be optionally used to change the I2C address from 0x28 (the default) to 0x29. We thought that somehow we were connecting the copper pad by mistakenly and changing the address making it impossible for the Arduino to receive data. Our theory was incorrect but we didn’t realize this for quite a while. We explored several possibilities for why it was malfunctioning:
We rewired the SCL and SDA jumpers like so:
Now our use procedure is to:
At this point the Arduino does not need code reuploaded. Seems to work consistently from this point on. Even after powering the system down. With the BNO functioning we were able to successfully implement a feedback loop that allows us to course correct to a straight line. Also used in turning until we had reached a certain orientation. We finished the month with this design:
The regional competition we attended was on March 7th. Unfortunately due to some misplaced confidence we were unable to complete a single successful run. The primary issues that held us back from medaling where:
Some secondary issues that came up were that the proctor found it difficult to measure the distance from the pencil to the target point due to the chassis obscuring a clear view. Thankfully among other things we did not get tiered and the team was able to make it to the State competition. To address the issues we have created a new chassis that allows an easier line of sight of the pencil for the proctor, and are still developing a competition checklist and manual testing for the BNO055 to mitigate any human error.
State competition is in a couple weeks. We have made a new chassis and have pin pointed the issue with the BNO055. Turns out the i2c bus was locking up because of pullup resistors stretching the clock. This can be solved by completing the transmission via the scl cable and therefore releasing the slave which opens the sda cable back up. We have developed a checklist for use when testing and running the competition. As we dug deeper into the BNO055 issue we found that there are some pretty big timing problems that are exacerbated by using the Arduino r4. These can be ameliorated slightly by stretching the clock and constantly testing the connection and recovering. However we found that this would interfere with running the course in the manner we intended coupled with the fact that we lose points for stalling (recovering the BNO055 is timely and could be interpreted as stalling). Thus instead of implementing these changes we chose to switch the r4 out for the r3 model which doesn’t have these timing issues. So far in testing we have observed no issues when running with some minor clock stretching.
Code Overview In our code we implement a basic feedback loop. We read information from our sensors (the encoders and BNO055). We take this information or feedback and use that to dictate the decisions made by the robot. Functions used in code:
If you have never made a robot then you may not know the frustration of putting time and effort into a buggy or car and when you turn it on it literally cannot move in a straight line. I mean how hard can it be? Actually it is really hard. At least for me… Course correction uses the BNO055 to tell us whether we are in a straight direction or have started to veer off to the side. With this feedback we can adjust the tilt of the robot in motion. This looks like speeding up one motor over the other. The robot begins to turn back into the correct orientation. Once we have reached our original heading we stop correcting. However due to the imperfect nature of the motors once we start course correcting we do not stop correcting until we have reached our target distance.
Reading the BNO055 was a long and difficult process. We used the breakout board from Adafruit and subsequently used the Stemma QT connection provided. We also used the Adafruit library for the Arduino to read the values. However after frequent use the BNO055 would only return zeros. It was incredibly frustrating. We were using an Arduino R4. Supposedly this microcontroller has something different about it that messes with the setup and rise timing on the I2C bus when reading the SCL and SDA pins. The Adafruit breakout board has default 10k resistor pullups. By increasing the resistance on the pullups we can lengthen the setup and rise times for the BNO055. We added a 3k resistor to the SCL and a 2k resistor to the 2k pullup on the SDA line. This fixed our issue with the BNO055. We give it around 2 seconds of setup time and then begin reading almost immediately. Reading Encoders Reading the Encoders accurately is really important. You don’t want to miss anything because it can cause you to go too far or too short. Since we are giving most of our attention to reading the BNO055 to course correct we can’t really read the encoders at the same time. We have two processes or loops that need to be followed in parallel. The Arduino R4 unfortunately cannot run tasks in parallel. Well not in the way that you would conventionally. Using what are called interrupts we can use minimal processing power to read the encoder values. Every time the encoder tracks movement it sends a signal to the arduino. We have them connected to pins 2 and 3. These pins are interrupt pins and can perform simple math in the background. We can use the interrupt pins to update a global volatile integer. Now while we are course correcting as we move though the loop we can check the number of movements we have made and figure out how far we have moved without having to divert our attention between two processes.
The hardware we used on the robot is fairly easy to come by. We use the Arduino Rev 4 microcontroller. This is the brain of the robot. It holds our instruction set and tells the other components what to do. Our motor driver or the translator from microcontroller to motors is the L298n. It is a widely produced motor driver that is very cheap. You can actually make your own at home if you have the patience! We use rotary encoders that make use of the Hall effect to measure distance. I have seen the encoders that work with a photogate. I think that the Hall effect motors are more precise, but if you don’t have the budget the photogate style encoders are great too. We picked rather slow motors for our project at only 150 rotations per minute max speed. This is advantageous to us because as we increase in speed we become less accurate however as our robot becomes more adaptable we are beginning to feel the need for faster motors. If you buy high RPM motors (for example most hobby motors are ~1000 RPM) you will notice that when you have low voltage levels the motor will struggle or even burn out. The crowning jewel of the robot is our BNO055. This is really what makes the robot able to even be competitive. In combination with the rotary encoders they are the eyes and hands of the robot. Without them our robot would move blindly without knowing where it was. Our power supply is from an 8 pack of AA batteries as per the regulations in the rules. The chassis is 3D printed. To manipulate the water bottle we have a pair of prongs that fit closely around the bottle that extend from the chassis. Besides this we have a breadboard installed on the chassis to allow us to use a small push button and experiment with the pullup resistors for the Stemma QT connection with the BNO055.