micro:bits and raspberry pis


whoami
Luke Spademan
0) Student
1) GCSEs
3) gave a lightening talk last year
2) @lukespademan: [twitter, github, etc]
Project
Project
Connect 4 Game
Micro:bits have 5x5 led matrix
Connect 3 Game
micro:bits
micro:bits
2 micro:bits play connect 3
They use the radio module to communicte
import radio
radio.config(channel=10)
radio.on()
data = radio.receive()
print(data)
radio.send("Hello World")and raspberry pis
and raspberry pis
It then sends the data over serial to a raspberry pi
Another micro:bit listens in on the game play
The raspberry pi then displays that data using a sense hat with RGB LED matrix
print("Hello World")and tensor flow
and tensor flow
I was going to have AI play you at connect 3
But reaslised with the hardware I was using it wasn't going to work
The lessons learnt part of the title, is the lesson that neural networks and raspberry pis are difficult to get talking
Especially because I wanted to do the training on the RPi
microbits = 3  # for game play and sending data to RPi
raspberrypis = 1  # for displaying game
tensorflow = 0  # sorryPlan
Plan
- 2 micro:bits play connect 3
- Your turn and you update the display, you also send the data using the radio 	
                - Opponent to see board
- 3rd micro:bit to see board
- 3rd micro:bit sends data over serial
- raspberry pi displays that data on an RGB LED matrix
 
Let's do this
Step 1
moving the counter along the top
Step 1.0
from microbit import *
board = "00000:" \
        "00000:" \
        "00000:" \
        "00000:" \
        "00000"
x = 0
while True:
    if button_a.is_pressed():
        x += 1
        if x == 5:
            x = 0
            board = board[:4] + "0" + board[5:]
        else:
            board = board[:x-1] + "0" + board[x:]
        board = board[:x] + "9" + board[x+1:]
        print(board)
        display.show(Image(board))Step 1.1
from microbit import *
board = "00000:" \
        "00000:" \
        "00000:" \
        "00000:" \
        "00000:"
x = 0
while True:
    if button_a.is_pressed():
        x += 1
        if x == 5:
            x = 0
            board = board[:4] + "0" + board[5:]
        else:
            board = board[:x-1] + "0" + board[x:]
        board = board[:x] + "9" + board[x+1:]
        display.show(Image(board))
        sleep(250)  # allows recognition on one pressStep 1.2
from microbit import *
def set_board_pixel(x, y, board, colour):
    pos = get_pos(x, y)
    board = board[:pos] + str(colour) + board[pos+1:]
    return board
def get_pos(x, y):
    pos = (6*y) + x
    return pos
board = "00000:" \
        "00000:" \
        "00000:" \
        "00000:" \
        "00000:"
x = 0
while True:
    if button_a.is_pressed():
        x += 1
        if x == 5:
            x = 0
            board = set_board_pixel(4, 0, board, "0")
        else:
            board = set_board_pixel(x-1, 0, board, "0")
        board = set_board_pixel(x, 0, board, "9")
        print(board)
        display.show(Image(board))
        sleep(250)Step 2
send data to the other micro:bit
Step 2
# player1.py
from microbit import *
import radio
radio.on()
radio.config(channel=27)
def show_board(board):
    display.show(Image(board))
    radio.send(board)
# more functions and setup
while True:
    if button_a.is_pressed():
        x += 1
        if x == 5:
            x = 0
            board = set_board_pixel(4, 0, board, "0")
        else:
            board = set_board_pixel(x-1, 0, board, "0")
        board = set_board_pixel(x, 0, board, "9")
        print(board)
        show_board(board)
        sleep(250)# player2.py
from microbit import *
import radio
radio.on()
radio.config(channel=27)
board = "00000:" \
        "00000:" \
        "00000:" \
        "00000:" \
        "00000"
while True:
    data = radio.recive()
    if data:
        board = data
        display.show(Image(board))Step 3
dropping the counter
Step 3
# player1.py
# imports, radio setup, functions
def get_board_pixel(x, y, board):
    pos = get_pos(x, y)
    value = board[pos]
    return valueStep 3
# player1.py
# imports, radio setup, functions
def get_board_pixel(x, y, board):
    # code
def fall(x, y, board, colour):
    set_board_pixel(x, y, board, colour)
    show_board(board)
    falling = True  # while counter has not hit bottom or other counter
    while falling:
        if y >= 4 or get_board_pixel(x, y+1, board) != "0":
            falling = False
        else:
            y += 1
            board = set_board_pixel(x, y, board, colour)  # moves counter down by one
            board = set_board_pixel(x, y-1, board, 0)  # removes counter from above
            show_board(board)
            sleep(500)  # waits for 0.5 seconds so animation can be seen
    return board
while True:
    if button_a.is_pressed():
        # moving counter code...
    elif button_b.is_pressed():
        board = fall(x, y, board, my_colour)Step 4
taking it in turns to have a go
Step 4
# player1.py
# imports
# functions, setup
my_turn = True
my_colour = "9"
while True:
    if my_turn:
        if button_a.is_pressed():
            # moving counter code...
        elif button_b.is_pressed():
            board = fall(x, y, board, my_colour)
            my_turn = False
            radio.send("YT")
    else:
        data = radio.receive()
        if data:
            if data == "YT":
                my_turn = True
            else:
                board = data
                display.show(Image(data))# player2.py
# imports
# functions, setup
my_turn = False
my_colour = "4"
while True:
    if my_turn:
        if button_a.is_pressed():
            # moving counter code...
        elif button_b.is_pressed():
            board = fall(x, y, board, my_colour)
            my_turn = False
            radio.send("YT")
    else:
        data = radio.receive()
        if data:
            if data == "YT":
                my_turn = True
            else:
                board = data
                display.show(Image(data))
my_turn = True
my_colour = "9"my_turn = False
my_colour = "4"Step 5
stop players placing counters on the top row
Step 5
# imports
# setup
# functons
# more setup
while True:
    if my_turn:
        if button_a.is_pressed():
            x += 1
            while get_board_pixel(x, 1, board) != "0":
                x += 1  # move along.
                if x > 5:  # when your at the end go to the start
                    x = 0
        
                row = ["0", "0", "0", "0", "0"]
                row[x] = my_colour
                for c, pixel_colour in enumerate(row):  # counter acts as x co-ord
                    board = set_board_pixel(c, 0, board, pixel_colour)
# more code...c = 0
for item in list:
    print(c, item)
    c += 1
for c, item in enumerate(list):
    print(c, item)
Step 6
sending data to the raspberry pi
Step 6.0
# viewer.py
from microbit import *
import radio
radio.config(channel=86)
radio.on()
while True:
    data = radio.receive()
    if data:
        if data != "YT":
            display.show(Image(data))
            print(data)# display.py
import serial
from sense_hat import SenseHat
sense = SenseHat()  # setup sense hat (RGB LED matrix)
# copied and adapted from
# projects.raspberrypi.org/en/projects/microbit-game-controller
PORT = "/dev/ttyACM0"
BAUD = 115200
s = serial.Serial(PORT)
s.baudrate = BAUD
s.parity = serial.PARITY_NONE
s.databits = serial.EIGHTBITS
s.stopbits = serial.STOPBITS_ONE
# copy ends
sense.show_letter("~")  # lets me know that it has started
player1 = (0, 0, 255)  # colours to be displayed for
player2 = (255, 0, 0)  # each player
blank = (0, 0, 0)  # for empty spaces
edge = (100, 100, 100)  # and the edge of the board
# ^ because RPi Sense Hat LED matrix is > 5x5 on micro:bit
Step 6.1
# viewer.py
from microbit import *
import radio
radio.config(channel=86)
radio.on()
while True:
    data = radio.receive()
    if data:
        if data != "YT":
            display.show(Image(data))
            print(data)# display.py
# imports, setup
while True:
    data = s.readline().decode("UTF-8").rstrip()
    data_s = data.split(":")
    formatted = []  # will store data to send to LED matrix
    for i in range(8*2):  # top two rows
        formatted.append(edge)
    for row in data_s:
        formatted.append(edge)  # first col is an edge
        for c in row:
            if c == "4":
                formatted.append(player2)
            if c == "9":
                formatted.append(player1)
            if c == "0":
                formated.append(blank)
        formatted.append(edge)  # two thick edge on right side
        formatted.append(edge)
    for i in range(8):
        formatted.append(edge)
    sense.set_pixels(formated)

https://trinket.io/sense-hat
Step 7
win detection
Step 7.0
def detect_win(board):
    """detects is a player has won connect 3"""
    rows = board.split(":")
rows = [
    ["00000"],
    ["00000"],
    ["00000"],
    ["00000"],
    ["00000"]
]Formatting the board
Step 7.1
def detect_win(board):
    # setup
    """detects win on x axis"""
    for row in rows:
        for i in range(3):
            colour = row[i]
            if colour != "0":
                if row[i] == row[i+1] == row[i+2]:
                    return colour
rows = [
    ["00000"],
    ["00000"],
    ["00000"],
    ["00000"],
    ["00999"]
]Detecting in in a row
Step 7.2
def detect_win(board):
    # setup and x axis detection
    
    """"detects win on y axis"""
    for col in range(3):
        for row in range(5):
            colour = rows[col][row]
            if colour != "0":
                if rows[col][row] == rows[col+1][row] == rows[col+2][row]:
                    return colour

rows = [
    ["00000"],
    ["00000"],
    ["00009"],
    ["00009"],
    ["00009"]
]Detecting a win in a column
Step 7.3
def detect_win(board):
    # setup x axis and y axis detection
    
    """"detects win on y = -x + c"""
        for col in range(3):
            for row in range(3):
                colour = rows[col][row]
                if colour != "0":
                    if rows[col][row] == rows[col+1][row+1] == rows[col+2][row+2]:
                        return colour

rows = [
    ["00000"],
    ["00000"],
    ["00900"],
    ["00090"],
    ["00009"]
]Detecting a win in a y=-x+c diagonal
Step 7.4
def detect_win(board):
    # setup, x axis, y axis and y=-x+c detection
    
    """"detects win on y = x + c"""
        for col in range(4, 1, -1):
            for row in range(3):
                colour = rows[col][row]
                if colour != "0":
                    if rows[col][row] == rows[col-1][row+1] == rows[col-2][row+2]:
                        return colour

rows = [
    ["00000"],
    ["00000"],
    ["00009"],
    ["00090"],
    ["00900"]
]Detecting a win in y=x+c diagonal
Step 7.5
def detect_win(board):
    """detects is a player has won connect 3"""
    # [:-1] is needed as board ends with :
    # causing an emtpy list at the end or rows
    rows = board.split(":")[:-1]
    """detects win on x axis"""
    # code
    """"detects win on y axis"""
    # code
    """detects win on y=-x+c"""
    # code
    """detects win on y=x+c"""
    # code
    return None
Overview
Step 7.6
# player1.py & player2.py
# imports
# functions, setup
def detect_win(board):
    # code
# setup
while True:
    if my_turn:
        # code
        elif button_b.is_pressed():
            board = fall(x, y, board, my_colour)
            my_turn = False
            winner = detect_win(board)
            if winner == my_colour:
                congradulate()
            else:
                radio.send("YT")
    else:
        data = radio.receive()
        if data:
            if data == "YT":
                my_turn = True
            elif data == "IW":
                defeat()
            # code...Implementing win_detection
Step 7.7
# player1.py
# imports
import music
# functions, setup
def detect_win(board):
    # code
def congradulate():
    radio.send("IW")
    display.show(Image.HAPPY)
    music.play(music.BA_DING)
def defeat():
    display.show(Image.SAD)
    music.play(music.DADADADUM)
Congradulating the winner
Step 8
ending game after win/loss
Step 8
# player1.py & player2.py
# imports
# functions, setup
def detect_win(board):
    # code
# setup
while True:
    if my_turn:
        # code
        elif button_b.is_pressed():
            board = fall(x, y, board, my_colour)
            my_turn = False
            winner = detect_win(board)
            if winner == my_colour:
                congradulate()
                break
            else:
                radio.send("YT")
    else:
        data = radio.receive()
        if data:
            if data == "YT":
                my_turn = True
            elif data == "IW":
                defeat()
                break
            # code...That's it
so far
What have I learnt?
What have I learnt?
- Don't be confined by the specifications of a device, or what other people tell you a device can be/do.
- If I have an issue, search the web, and see if anyone else has solved your issue before / can help you.
- Python programmers are the nicest out there.
Thank you for listening
- project code is available at github.com/lukespademan/connect3
- @lukespademan
	- github
- conference slack
 
- here until Sunday afternoon
Copy of micro:bits and raspberry pis
By Luke
Copy of micro:bits and raspberry pis
- 946
 
  