micro:bit Morse code transmitter

Here’s a pretty simple, and I think fun, way to introduce some quite sophisticated computing concepts with a few lines of Python, 2 BBC micro:bits and a crocodile clip lead or two (as you’d find in a Makey Makey box).

With a few trivial lines of code you can teach:

  • drawing an image on the LED screen
  • variables
  • if/else conditional branching
  • infinite loops
  • controlling GPIO pins
  • physical networking and protocols

This takes the excellent Morse code program included with the micro:bit Python documentation and makes a simpler transmitter that is compatible with it. My simple code only works as a transmitter but:

  • it’s easier for children to type in
  • it’s easier for them to understand
  • it makes it physically easier to send the Morse code by standardising the duration of dots and dashes, using the A button to send a dot, the B button to send a dash.

Here’s what you might do in a lesson:

Get the class into pairs. Using Mu or the online Python editor, Child 1 (who will be the receiver) copies and pastes the original Morse code program onto her micro:bit and tests it – or uses my simpler receiver code at the foot of this blog post. Child 2 (the transmitter) types in my transmitter code below and flashes it onto her micro:bit.

Unplug them both and carefully connect pin 1 on the transmitter to pin 2 on the receiver using wire with crocodile clips. If both microbits are powered off the same computer’s USB sockets, you can probably stop there. If, however, you are using battery packs attach another wire joining the two microbits’ GND pins together to complete the circuit:

Children will have to be very careful not to short pins when they do this, so it might be wise to physically inspect them before they plug them back in.

Now power them back up. Child 2 should be able to send a Morse code message to child 1 using combinations of A and B button presses – A for dot, B for dash. It takes a bit of practice but my hunch is this is easier than holding down a button for the right length of time. The sender has to be pretty snappy and pay attention to what she’s doing, sending the next dot or dash as quickly as she can otherwise the decoder will think it’s the end of a letter.

There’s no sound, alas – perhaps someone can suggest a way round this. Making a beep of the appropriate duration slows the code down too much. I don’t think this is too much of a drawback as I think wiring up headphones or speakers is a step too far in a lesson anyway.

There’s lots of scope to pick apart my script – and the much more sophisticated original which encodes AND decodes, makes sound AND stores messages. And you could see how far you can send a message this way – perhaps join loads of croc clip leads together. Mmm, I may have to try that later…

See if you can send and decode this message:

.  -    .--.  ....  ---  -. .   ....  ---  -- .

Here’s the Python transmitter code…

# @blogmywiki's simplest microbit Morse code transmitter
# Press A for .       Press B for -

from microbit import *

DOT = Image("00000:"
            "00000:"
            "00900:"
            "00000:"
            "00000:")

DASH = Image("00000:"
             "00000:"
             "09990:"
             "00000:"
             "00000:")

# durations made a bit shorter than 250ms for a dot
# durations made a bit shorter than 500ms for a dot
DOT_DURATION = 230
DASH_DURATION = 470

while True:
    if button_a.is_pressed():
        display.show(DOT)
        pin1.write_digital(1)
        sleep(DOT_DURATION)
        pin1.write_digital(0)
        sleep(50) # little sleep added to debounce
    elif button_b.is_pressed():
        display.show(DASH)
        pin1.write_digital(1)
        sleep(DASH_DURATION)
        pin1.write_digital(0)
        sleep(50) # little sleep added to debounce
    else:
        display.show(Image.ASLEEP)

…and here’s my simplified receiver code:

# simple microbit Morse receiver based on
# http://microbit-micropython.readthedocs.io/en/latest/tutorials/network.html

from microbit import *

# A lookup table of morse codes and associated characters.
MORSE_CODE_LOOKUP = {
    ".-": "A",
    "-...": "B",
    "-.-.": "C",
    "-..": "D",
    ".": "E",
    "..-.": "F",
    "--.": "G",
    "....": "H",
    "..": "I",
    ".---": "J",
    "-.-": "K",
    ".-..": "L",
    "--": "M",
    "-.": "N",
    "---": "O",
    ".--.": "P",
    "--.-": "Q",
    ".-.": "R",
    "...": "S",
    "-": "T",
    "..-": "U",
    "...-": "V",
    ".--": "W",
    "-..-": "X",
    "-.--": "Y",
    "--..": "Z",
    ".----": "1",
    "..---": "2",
    "...--": "3",
    "....-": "4",
    ".....": "5",
    "-....": "6",
    "--...": "7",
    "---..": "8",
    "----.": "9",
    "-----": "0"
}

DOT = Image("00000:"
            "00000:"
            "00900:"
            "00000:"
            "00000:")

DASH = Image("00000:"
             "00000:"
             "09990:"
             "00000:"
             "00000:")             

def decode(buffer):
    # Attempts to get the buffer of Morse code data from the lookup table. If
    # it's not there, just return a question mark.
    return MORSE_CODE_LOOKUP.get(buffer, '?')

# detetct a DOT if incoming signal is less than 250ms.
DOT_THRESHOLD = 250
# detect a DASH if incoming signal is less than 500ms.
DASH_THRESHOLD = 500

# Holds the incoming Morse signals.
buffer = ''
# Holds the translated Morse as characters.
message = ''
# The time from which the device has been waiting for the next event.
started_to_wait = running_time()

while True:
    # Work out how long the device has been waiting for a signal.
    waiting = running_time() - started_to_wait
    # Reset the timestamp for the key_down_time.
    key_down_time = None
    # If pin2 (input) is getting a signal, start timing
    while pin2.read_digital():
        if not key_down_time:
            key_down_time = running_time()
    # Get the current time and call it key_up_time.
    key_up_time = running_time()
    # If there's a key_down_time (created when signal detected)
    if key_down_time:
        # ... then work out for how long it was pressed.
        duration = key_up_time - key_down_time
        # If the duration is less than the max length for a "dot" press...
        if duration < DOT_THRESHOLD:
            # ... then add a dot to the buffer containing incoming Morse codes
            # and display a dot on the display.
            buffer += '.'
            display.show(DOT)
        # Else, if the duration is less than the max length for a "dash"
        # (but longer than that for a DOT ~ handled above)
        elif duration < DASH_THRESHOLD:
            # ... then add a dash to the buffer and display a dash.
            buffer += '-'
            display.show(DASH)
        # Otherwise, any other sort of keypress duration is ignored (this isn't
        # needed, but added for "understandability").
        else:
            pass
        # The button press has been handled, so reset the time from which the
        # device is starting to wait for a signal.
        started_to_wait = running_time()
    # check there's not been a pause to indicate an end of the
    # incoming Morse code character. The pause must be longer than a DASH
    # code's duration.
    elif len(buffer) > 0 and waiting > DASH_THRESHOLD:
        # There is a buffer and it's reached the end of a code so...
        # Decode the incoming buffer.
        character = decode(buffer)
        # Reset the buffer to empty.
        buffer = ''
        # Show the decoded character.
        display.show(character)
        # Add the character to the message.
        message += character
    # Finally, if button_b was pressed while all the above was going on...
    if button_b.was_pressed():
        # ... display the message,
        display.scroll(message)
        # then reset it to empty (ready for a new message).
        message = ''
Posted in computers, education, ICT | Tagged , , , | Leave a comment

Roundup of micro:bit resources

If you are lucky enough to have your class sets of BBC micro:bits for your Year 7s (and it seems plenty of schools are still waiting, mere weeks from the end of the academic year), here’s summary of some resources I made which you may find useful…

Posted in BBC, computers, education, ICT | Tagged , | Leave a comment

Happy Scratch Day!

To mark Scratch Day, here are some teaching resources I made – mostly, but not all, to do with ICT / Computing:

The MakeyMakey Visual Piano

Designed to use easily-accessible keys to play tunes on an 8-note scale, with keys that light up in appropriate colours.

Binary Maths Cards

Designed to work with the Computer Science Unplugged binary cards, I use this a tool when teaching and revising binary – a big hit with students who can come up and slap the interactive whiteboard to convert decimal to binary and back.

Checksum Game

Another one to get your students using on the big screen – introduce parity bits with this CS Unplugged card trick.

Bubble sort

A simple and pleasingly noisy bubble sort that allows students to see a bubble sort run in real time – and pick apart the code that makes it work.

Scaredy Squirrel Turns

I made this for a Year 2 class to help them learn about quarter turns (we didn’t do degrees in Year 2 then, though they probably do radians now). I got the children up to the board and asked questions like ‘how should we get Scaredy to face the bees?’ or ‘if Scaredy makes a half turn, what will he see?’ in a cross-curricular link with our literacy topic.

Scaredy Squirrel Game

People told me they were too young, but I wanted to get Year 2 coding, and invented this game with a familiar character to show them what Scratch could do. You have to guide Scaredy back to the safety of his tree, avoiding the various perils on the way. The results were, I think, a big success.

Posted in computers, education, ICT | Tagged | Leave a comment

BBC micro:bit – handle with care

Here’s the TL/DR version of this blogpost: if you are using the BBC micro:bit, especially with children, make sure they heed the advice on these panels in the middle of the back of the ‘Getting Started’ leaflet. In effect this means you can’t easily use the micro:bit buttons when it’s plugged in to a computer, as the natural way of holding it is to put a finger behind the A button to support it as you push:

Still interested? Here’s the background.

I’ve had 3 preview teacher micro:bits for a few months, and they all worked swimmingly… until I started using them with children. One unit got warm but still worked, another got incredibly hot (dangerously so) and failed. I sent it back to the BBC and got a replacement unit, which worked fine again – until I started using them with children. The new unit also started getting warm, but it still worked.

The BBC told me the chances of having multiple failures were ‘billions’ to one, so there must be an environmental factor. They sent me 5 more micro:bits to test in the same ICT room, on the same computers: HP Chromebooks. I spent about an hour testing them – and they were all perfectly fine. Must have been a fluke. A billion-to-one fluke.

Then I tried them out with my Year 5 computer club – and 2 of the new 5 micro:bits also now started getting warm. Not dangerously so, but noticeably warmer than normal.

Logically the only explanation for the mystery of the micro:bits was: children. I toyed with the idea of positing a new particle called a childon. Children must emit childons which have the effect of frying integrated circuits.

It turns out that my experience with the micro:bit is reproducable, and is, I am told, caused by 3 things happening at the same time:

  • The micro:bit must be plugged into a USB socket that can deliver enough current to charge a phone
  • The user must be touching the metal test pads on the back of the device
  • The user must cause an electrostatic charge to go into the device

Now this is a bit of a problem, because I think these 3 things will happen really quite often indeed. Firstly, most children test code, upload it, tweak it, upload it again. Combine that with the need for batteries, I think most micro:bits will be plugged into computers most of the time. Our HP Chromebooks are not unusual devices in schools, they have USB 3 sockets, and apparently these provide enough current to be a problem.

Secondly, it’s hard to avoid touching the test points on the back, especially as the ones in question are immediately behind the A button. It’s natural to hold it there as you push the button. Is it reasonable to expect children always to remember to hold them by the edges?

Thirdly, electrostatic shocks. My problems were in a room where I’d never noticed static shocks, but the floor is covered in carpet tiles, presumably nylon, so it’s a possibility. In my main ICT room I get shocks all the time, so when we use the class sets with Year 7 we will all have to keep earthing ourselves on something – not quite sure what. Do I need to run an earth to every desk?

I write all this with a heavy heart. I like the device, I love the microPython on it, I’ve written Python games for it, I’ve re-made the ‘happy plant‘ physical computing project, I’ve planned lessons for it.

But I fear that unless teachers and children read the leaflet carefully and heed the advice, an awful lot of micro:bits will fail, some may even get dangerously hot – though I should stress only 1 out of 9 initial units felt hot enough to burn, but a high proportion of the micro:bits I’ve actually allowed children to use run warmer than they should and draw more current than they should. I do wonder what would happen to the warm units if left plugged in for a long time – there is another warning panel about not leaving them unattended and unventilated on the back of the Getting Started leaflet. Where do I stand legally, as a teacher, if I give a child a micro:bit to take home and at home it causes an injury or fire?

The project is already beleaguered by insane delays – we were supposed to get them near the start of the academic year. That was 2015. We finally got our class sets for Year 7 last week, but because of upcoming exams and school trips, I now can’t use them until after half term in the Summer 2016 term. It’s a one-off giveaway, so the current Year 7s will only get a few weeks’ use out of them – and then we may struggle to use them in class. “Right Year 7! Only hold them by the edges! Earth yourself! Don’t use them when they are plugged in to the computer!” I may be an exceptionally poor teacher, but I find children do not always hear, understand and follow instructions in class. And the supplied USB leads are so short, usage will anyway be quite comical given our PC base units are built into the bottom of the desks.

It all just seems like a tragic mess, a wasted opportunity. I wish the BBC had been able to say “we messed up, let’s hold it over a year and you can hand them out next year’s Year 7s, or Year 8s if you already told them they were coming.”

Luckily I have still not told my current Year 7s about the micro:bit. And I am still not sure what to do with them.

How not to handle a micro:bit:

Posted in education, ICT | Tagged , | 3 Comments

Coding as a way of understanding the Monty Hall problem

The other night a maths teacher and I were sharing a few cold drinks and we fell to discussing the Monty Hall Problem.

Now, you may have heard of the Monty Hall Problem even if you don’t know it by that name. It goes like this: you are on a TV game show. There are 3 doors. Behind one door is a car, behind the other two there are goats. Assuming you want to win the car (thank you, Son B), you pick a door; the host then opens a door to reveal a goat and gives you the chance to change your choice. Should you change your choice, stick with the one you have, or does it make no difference?

This problem has infuriated me for ages because I’ve always been firmly of the opinion that it makes no difference. Which is a problem, because, in fact, if you change your choice you are TWICE as likely to win the car as if you stick with your first choice. To most people, this seems utterly mad, certainly counter-intuitive.

My maths teacher friend tried explaining it to me with glove puppets and I still didn’t really get it, so I decided the best thing was for me to write a computer simulation of it in Python. And by golly, not only does it prove him right, it also helped me understand the problem in a way I never had previously.

I think this would make a great combined maths/computing activity, because even just planning out the code helped me see the logic of the problem in a way I never had before because I was forced to confront what happens in every possible scenario. I could then see that being told what one of the wrong doors was actually changes everything – or at least it gives you a whole lot more information and that’s the key to seeing why you should change your choice.

To simplify the coding, I decided that for each game I’d always have the car behind the third door (which is door number 2, of course, Python being a zero-indexed language). I don’t think this makes any difference as long as the door choices the players make are random – an extension activity would be to rewrite the code so in every game the car is behind a different door.

This is how my code works – I’d be very happy to hear more elegant solutions, but it was when I wrote this out that the penny dropped and I finally understood the problem. Here’s how my (possibly flawed) thinking worked:

        |-----------------------|
door no.|   0   |   1   |   2   |
        |-----------------------|
        | goat  |  goat |  car  |
        |-----------------------|

I decided that I’d have two players who both pick the SAME random door in each game; player 1 would stick and player 2 would always change their choice having been ‘shown’ the door with the goat. If the car is always behind the last door, I think the sequence works like this…

If the players choose door 0, the host must open door 1 to reveal a goat, and player 2 must change their choice to door 2 – winning the car!

If the players choose door 1, the host must open door 0 to reveal a goat, and player 2 must change their choice to… door 2 – winning a car again!

If the players choose door 2 (containing the car), it doesn’t matter which of the other 2 doors the host opens, but I have decided they always open door 0 to keep things simple. In this case player 1 actually wins the car, but it’s the only way they can win it – a 1 in 3 chance. With bitter irony, player 2 has actually picked the right door first time but they will be forced to change their choice and win a goat instead – but the crucial thing is that they won in 2 out of the 3 scenarios. The changing player has a 2 in 3 chance of winning, the stick-in-the-mud has only a 1 in 3 chance.

Just sketching this out in a simple flowchart aids understanding of this problem, I don’t think any actual programming is necessary. You can see how the player who changes is twice as likely to win a car:

flowchart of possible simulation of Monty Hall problem

And indeed when I run this code for about 1000 games, player 2 does indeed win about twice as many cars as player 1:

A nice side-bar to this (especially as we teach in a girls’ school) is that it was a woman, Marilyn vos Savant, who proposed the correct solution to this problem, and 1000s of people with PhDs (mostly men, I bet) wrote to say she was wrong. She wasn’t.

Here’s my code, run it yourself in Python3. You can also download it here. It runs an awful lot faster in the OS X command line than it does in IDLE, and I expect I’ll find the same with Windows.

Monty Hall simulation running in OS X terminal and IDLE

If you improve it or use it in school, please let me know! Some bar charts might be nice…

# A computer simulation of the Monty Hall problem,
# a counter-intuitive logic and probability puzzle.
# by @blogmywiki - www.suppertime.co.uk/blogmywiki

print('Welcome to the\n'
'    __  ___            __           __  __      ____\n'
'   /  |/  /___  ____  / /___  __   / / / /___ _/ / /\n'
'  / /|_/ / __ \/ __ \/ __/ / / /  / /_/ / __ `/ / / \n'
' / /  / / /_/ / / / / /_/ /_/ /  / __  / /_/ / / /  \n'
'/_/  /_/\____/_/ /_/\__/\__, /  /_/ /_/\__,_/_/_/   \n'
'                      /____/ show\n'
'        |-----------------------|\n'
'door no.|   0   |   1   |   2   |\n'
'        |-----------------------|\n'
'        | goat  |  goat |  car  |\n'
'        |-----------------------|\n')

while True:

    import random

    print()
    answer = input('How many games do you want to simulate? (q to quit) ')
    if answer == "q":
        break
    else:
        tries = int(answer)

    doors = ['goat','goat','car']
    # door no. 0      1      2

    # I don't think it matters that these are not random
    # and keeping this fixed makes coding easier. 

    # Both players will pick the same door, but
    # when a door is opened with a goat behind it,
    # player1 will always stick with their 1st choice
    # whereas player2 will always change.
    # We will then keep a tally of who won more cars.

    player1_tally = 0
    player2_tally = 0

    for i in range(tries):

        chosen_door = random.randint(0,2)
        # pick a random door number between 0 and 2

        print('Game',i)
        print ('door',chosen_door,'chosen, containing a',doors[chosen_door])
        player1_choice = chosen_door
        if chosen_door == 0:
            player2_choice = 2
            print('Host opens door 1, player2 switches choice to door 2')
        elif chosen_door == 1:
            player2_choice = 2
            print('Host opens door 0, player2 switches choice to door 2')
        elif chosen_door == 2:
            player2_choice = 1
            print('Host opens door 0, player2 switches choice to door 1')

        if doors[player1_choice] == "car":
            print('Player 1 won a car!')
            player1_tally = player1_tally + 1

        if doors[player2_choice] == "car":
            print('Player 2 won a car!')
            player2_tally = player2_tally + 1

        print()

    print('Player 1 who stuck won',player1_tally,'cars.')
    print('Player 2 who changed won',player2_tally,'cars.')

And here’s a Trinket with a Python 2(ish) version of the code which you should be able to run in a web browser:

Posted in computers, education, ICT | Tagged , , , , | Leave a comment