Pi Wars Week -25: Tagliatelle
The story of the last week has mostly been soldering the breakout board for the I2C multiplexer and realising how atrocious my soldering skills are.
No photo because I'm exercising my right not to self-incriminate for crimes against electrical safety. This is definitely a "for testing purposes only" item.
My soldering job on the I2C multiplexer breakout board... it's pretty grim.
I've also been connecting all the various peripherals together with multi-conductor ribbon cables, turning my spaghetti wiring into tagliatelle. It's a slight improvement
Last night, duly invigorated and inspired by the PiWars mini conference, and chastened by some of the stunning work I've seen other entrants put in, I bit the bullet and started working on a task I'd been putting off for a while: encapsulation and threading. It's a pain to do now but it would be a much bigger pain to start doing in several months when I'd written a lot more code.
Firstly, encapsulation: breaking up related bits of code into separate classes/files to keep them from becoming a big tangled mess. While prototyping I just had one giant .py file which held all the code to interface with peripherals: it was reading the controller input, getting distance values from the TOF sensors, printing stuff to the display, making decisions about where to drive and commanding the motor controllers. The controller input and talking to the motors will remain the responsibility of the core module, but I'm putting the display driver and TOF sensors in their own classes.
I'm also borrowing a technique from previous years: the decisions about where to actually drive are the responsibility of a Challenge object. The R/C "challenge" just reads stick input from the controller and sets the motor speeds accordingly, the speed test challenge will aim to drive as fast as possible while not hitting a wall, and there will be similar classes for all the autonomous challenges. Starting a given challenge will involve instantiating an object of that type and passing control to its run() function. The robot will have a menu which lets me pick a given challenge and kick off that challenge's control loop so I don't have to SSH in to tell it "now do the maze thing".
Threads. Very important.
The other big structural pattern is threading. I alluded to this in a previous post: if you want multiple tasks going on at once these can be made to happen in parallel by putting them in threads. At the very least I'm going to have a thread for updating the display, a thread for reading the distance sensors, a thread for the core business of reading controller input and managing the robot's state. My display uses I2C which is quite a slow bus, and means it can only update about once every 0.5 seconds; having this happen in its own thread means that I don't have to wait for each new frame to be pushed out to the display before the robot will update its distance sensor readings and motor speeds. Yes, I did make this mistake while testing, causing the robot to nearly drive off a table because I wasn't obeying rule 1: don't drive the robot around on a table.
Anyway, that's enough words: here's a video of the duly chastened R3L14NT navigating the wheelchair ramp between the two sides of Hitchin Hackspace. The doormat is there because it can't handle the 1 inch step up the bottom of a wheelchair ramp.... I'm sure it'll be fine, when have Pi Wars robots ever had to climb over obstacles?