Pi Wars week -30: Coding Practice
So, now that the hardware is capable of moving itself around, it's time to turn our focus towards the software side. The first thing we need is an R/C mode to drive it around using the sticks on my controller. That isn't the most exciting task to talk about, but testing it immediately raised a point of good coding practice which I thought might be worth sharing.
A failsafe is not, as I thought when I was younger, something which prevents a failure. If something fails safe, it means in the event of a failure it will enter a safe state. Electronic door locks will unlock if the building loses power in a fire, failing safe, meaning people won't be trapped inside. A tyre swing fails dangerous: if the rope snaps, you enter the "falling" state.
Why is this relevant to my robot? Well, as soon as I started testing my robot, I pushed the stick forward and the wheels turned forward. Then I pushed it backwards and the code promptly crashed because it wasn't set up to handle negative numbers... and the wheels kept turning. I restarted the code and it stopped the wheels. I needed a fail safe to make sure the motors would stop if the code crashed, to prevent the robot from literally crashing.
try, catch, finally
Python (like many languages) deals with errors like this with the try-catch-finally construction. You tell the code to try to do something, and if an error crops up you
have an opportunity to catch the exception (called except in Python), but even if you don't, the finally block will always execute before the program stops.
My code needs to look roughly like this:
try: do startup stuff while (alive): read the joystick position set the motor speeds sleep(0.1) finish up, play a fanfare finally: set motor speeds to 0
Then, when the "set the motor speeds" line throws an exception because you can't give a negative number to a PWM controller, it will tidy up after itself and not drive uncontrollably into the nearest wall.
The missing part here is the catch: if you expect a certain type of exception and know how to deal with it, you can catch it and continue. In a previous year we had some sensors which would occasionally fail to connect to the Pi. They would throw a predictable exception when this happened, which we could catch and show a message on the robot's display telling us we needed to restart the code (because the solution is always "turn it off and on again"). Including this, the code might look more like:
try: connect sensors while (alive): read distance from sensor set the motor speeds sleep(0.1) finish up, flash flashy lights except SensorNotConnected: show "sensor not connected" message finally: set motor speeds to 0
No, not that kind (unless you're Faceplant, that is)
This kind of bug can happen to anyone, and fortunately for me it happened while I had the robot up on blocks (well, a tub of hair gel) on my desk with the wheels spinning freely. The rules state:
All robots must remain powered down or ‘on blocks’ in the workrooms.
Do yourself a favour and make a nice stand that you can pop the robot on and let it spin its wheels for testing so you don't have to prop it up with random junk!
Now that my flashy LEDs have arrived, perhaps next week's random code diversion will talk about threading (or possibly "why I should have ordered a level shifter at the same time I bought Neopixels").