MicroPython “powered”, micro:bit based bicycle brake light (science for kids)

The background story and why yet another post for kids:

A while back, I took my kid and a couple of her friends for a bicycle run, and what I noticed on that particular occasion was that a pair of them (one being my daughter the other one her girl friend) could not keep their heads straight and concentrate on the traffic around them. It was a dedicated bicycle path after all. Therefore, when riding one after the other, each time the one riding in front braked hard the other one riding in the back would almost slam into the first one. Not good!

As a temporary safety measure, I had ask them each time the one in the front breaks, to shout ‘breaking’ and alert the other in case she was ‘star gazing’ at that moment and break on time herself :). But this ended up annoying the c7@p out of their other boy friend who was kinda embarrassed by their constant shouting.

So I began thinking what would be the simplest way to alert the rider in the back the one in front was breaking – especially breaking abruptly!? By simple, I meant – as little fiddling as possible, as clean as possible i.e. the less wiring the better, and so on.

At the time, we were already working (my daughter and I) on preparing our line follower robot which is based on the BBC micro:bit, so the idea literally just popped: the micro:bit already has an onboard accelerometer, so why not use that and in the process teach my kid something new – and by something new, I didn’t mean programming only, but basic physics concepts that surround and affect us all the time.

How about inertial forces? 😉 See the topics of inertia and inertial force or fictitious force.

It’s the force that kicks us back in the seat whenever the car is accelerating. Is’s the force that propels us forward whenever that same cars starts breaking.

Well, we could definitely use that principle here and do something with the BBC micro:bit.

As mentioned before, the micro:bit features an on-board accelerometer which measures acceleration in Cartesian space (i.e. along the x, y and z axis) expressed (and calibrated) in mg’s (‘milli gees‘) or thousands of a 1g (Earth’s gravity). It can also be (and in fact it’s precisely how it’s used in mobile phones and tablets) – to detect orientation.

The nice thing about the BBC micro:bit is that it features a 5×5 LED matrix which could be used for displaying (appropriate) signals when accelerating, decelerating or when abruptly breaking.

So, in short, this would be the feature list:

  • display an UP arrow when accelerating
  • display a DOWN arrow when decelerating
  • display a STOP sign (well, it actually turned out to be the ONE WAY sign, but who cares…) when abruptly stopping
  • display a NEUTRAL sign when riding with a constant speed
  • beep as you start breaking (with a variable frequency or rather the increasing the frequency of beeping as the deceleration increases (and vise versa)
  • detect an abrupt stop and continuously beep for a set time

This is conceptually how I imagined the entire gadget to function (a plastic case carrying the micro:bit):

The working principle we decided to employ to solve our problem

The batteries would function as weights shifting the center of mass downwards and away from the pivoting axis, therefore each time the rider accelerates/decelerates the bicycle, the PCB holding the micro:bit would swing. The springs are there to bring back the entire thing back into “neutral” position as quickly as possible. Now, this is just on paper and whether it would function as intended, remains to be seen. I am though, expecting some oscillations due to the springs which, but those could easily be filtered out through code.

At the same time, I am fully aware there are other ways to accomplish something similar and in a more straightforward way – especially if deceleration is the only thing we are interested in, but see – this was never intended to be turned into a commercial product :). There are plenty of products already out there – and dirty cheap too!

It was merely a fun and quick way of demonstrating a basic principle and how the technology that already surrounds us, could help us measure it. It was also an excellent opportunity to spend more time with my kids and broaden their horizons.

We wrote the code in MicroPython and as always, hosted in my BitBucket repository, but here it is as well – in it’s entirety:

from microbit import *
import math

def main():
    IMG_ACCEL   = Image("00900:09990:00900:00900:00900")
    IMG_DECEL   = Image("00900:00900:00900:09990:00900")
    IMG_NEUTRAL = Image("00000:00000:09990:00000:00000")
    IMG_STOP    = Image("09990:90009:99999:90009:09990")

    TRESHOLD_POS = 100
    TRESHOLD_NEG = -100
    HARSH_STOP   = 250

    BEEP_FOR_MS      = 3000
    SAMPLING_TIME_MS = 100

    while True:
        x = accelerometer.get_x()
        y = accelerometer.get_y()
        z = accelerometer.get_z()

        accel = math.sqrt(x**2 + y**2 + z**2)
        print("({}, {})".format(z, accel))

        if z >= TRESHOLD_NEG and z <= TRESHOLD_POS:
            display.show(IMG_NEUTRAL)
        else:
            if z < 0:
                display.show(IMG_ACCEL)
            else:
                pin0.write_digital(1)
                if z > HARSH_STOP:
                    display.show(IMG_STOP)
                    sleep(BEEP_FOR_MS)
                else:
                    display.show(IMG_DECEL)

        sleep(SAMPLING_TIME_MS)
        display.clear()
        pin0.write_digital(0)

main()

Yes, it may not really be ‘Pythonic’ – but not everything needs to follow a certain pattern – especially not when solving simple problems and when the code itself is short as this one.

The code itself is pretty straightforward: one main function is defined and executed at startup. Inside this function, we define the patterns we wish to display on the LED matrix. We use the Image class for this purpose by passing a string containing the 5 LED rows of the matrix separated by a column (:). Each row digit represents a column, where a 0 represents zero LED intensity (basically LED OFF) and 9 represents maximum LED intensity – and anything in between.

At lines 10 and 11 we define the positive and negative threshold values of the accelerometer at which later on we start the detection and decision process, and at line 12 the threshold value at which we detect a harsh/hard stop.

Then inside a continuous while loop we measure the values of the acceleration in all 3 axis (x, y & z) – lines 18, 19 & 20. We’re only interested in the z-axis (because of the principle we had decided to employ), but I was curious to see what I will get if I hold the micro:bit perfectly straight facing me. Finally we calculate and print the resulting acceleration and the z component at lines 22 & 23.

At line 25 we start making decisions: if the z-component falls within the threshold values – we consider that a zero acceleration – i.e. the rider moves at a constant speed. Anything outside of that, the rider either accelerates (line 28) or decelerates (line 30). Once decelerating, we activate the piezo buzzer connected to digital pin P0 of the micro:bit (line 31) and while decelerating, we determine if we are measuring a harsh stop (line 32) or a gradual deceleration (line 35).

It would be nice to turn this into a fully fledged project with a design of the plastic case and a freely downloadable model to 3D print. I just have try and see if manage to convince a friend to do that (and possibly propose an alternative solution because as much as I believe I am mechanically literate – mechanics is his thing really 🙂 ).