Showing posts with label microbit. Show all posts
Showing posts with label microbit. Show all posts

Tuesday, 20 September 2016

Microbit making Minecraft Earthquakes

In this tutorial you are going to connect your Microbit up to your Raspberry Pi and program them so that when your Microbit is shaken it creates an earthquake in Minecraft.

Image

This is part of a workshop I delivered at PyConUK 2016 - download the complete worksheet.

You are going to connect your micro:bit’s pins to the Raspberry Pi gpio pins using some cables and crocodile clips; programs on the micro@bit and Raspberry Pi will make Steve shake in Minecraft.

Install mu
To put you python program on your Micro:bit you will need the editor mu.

Open a Terminal (Menu > Accessories > Terminal) and type:
sudo apt-get update
sudo apt-get install mu
Angry micro:bit
The first task is to program your micro:bit so it gets angry when it's shaken.
  • Connect your micro:bit to the Raspberry Pi using the USB cable.
  • Open mu to create a new Python program for your micro:bit by clicking on Menu > Programming > mu.
  • Click New and type the following code into the editor.
from microbit import *
while True:
    if accelerometer.current_gesture() == "shake":
        display.show(Image.ANGRY)
    else:
        display.show(Image.HAPPY)
  • Click Flash to put your program on your micro:bit.
When the yellow light on the back of your micro:bit stops flashing your program will run.
You should see a happy face on your micro:bit - until it’s shaken!

Image

Any errors will be scrolled on your micro:bit’s leds; if you get an error check your code carefully.

Pins
Now you need to finish your micro:bit program so that it turns pin 0 on and off when it's shaken
  • Go back to Mu and modify your program so that it turns pins 0 on (1) and off (0) when shaken.
from microbit import *
while True:
    if accelerometer.current_gesture() == "shake":
        display.show(Image.ANGRY)
        pin0.write_digital(1)
    else:
        display.show(Image.HAPPY)
        pin0.write_digital(0)
  • Click Flash to put your program on your micro:bit.
Connect it up
Next you will use a jumper cable and a crocodile clip to connect your micro:bit to the Raspberry Pi.
  • Connect the jumper cable to GPIO17 on the Raspberry Pi
  • Clip the crocodile clip to the end of the jumper cable
  • Clip the other end of the crocodile clip to pin0 on the micro:bit
ImageImage

Shake Steve
You now need to create your Minecraft program to shake Steve when the micro:bit is shaken and pin0 is set to 1.
  • Click Menu > Games > Minecraft: Pi Edition to run the game.
  • Click Start Game, then click Create New (or choose an existing one) to enter a world:
  • Press ESC to go back to the Minecraft menu but leave the game playing.
  • Open Python IDLE by clicking Menu > Programming > Python 3.
  • Use File > New Window to create a new program and save it as ‘mc_micro.py’.
  • Type the following code into the program to import the modules you will need
from mcpi.minecraft import Minecraft
from gpiozero import DigitalInputDevice
from time import sleep
  • Create a connection to Minecraft using the code.
mc = Minecraft.create()
  • Post a message to the chat window.
mc.postToChat("Micromine bitcraft earthquake")
  • Run your program by clicking Run > Run Module.
You should see your message appear in the Minecraft chat window.

Any errors will be displayed in the Python Shell in red.

Update your program to shake Steve, by adding the following code at the bottom of your program.
  • Create a pin which is connected to Pi GPIO 17 and micro:bit pin 0.
pin0 = DigitalInputDevice(17)
  • Create a loop which constants gets Steve’s position.
while True:
    sleep(0.1)
    pos = mc.player.getPos()
  • If pin0 is on (1) it adds 0.5 to Steve’s height (y).
    if pin0.value == 1:
        pos.y = pos.y + 0.5
        mc.player.setPos(pos)
  • Run your program by clicking Run > Run Module.
Shake your micro:bit and Steve will be shaken in Minecraft.

Challenges
Can you change the program so that it creates a more realistic earthquake by adding random values to the x, y, z values.

Complete the worksheet from PyConUK 2016 which includes using the micro:bit buttons to makes blocks disappear and appear.

Friday, 25 March 2016

Microbit - get data from USB

As part of my Minecraft, a Microbit and an X-Wing project, I used the USB to read data from the Microbit's accelerometer and buttons to make the X-Wing move.

@NCSComputing on twitter has started re-using the code to make other things happen, so thought it would be a good idea to write up how it works, so others can do the same.

Image

To make this work you need one program which runs on the Microbit and prints data and a second runs on your computer (a Raspberry Pi, PC, Mac, anything with a USB port) which reads the data via a serial connection.

Image

See github.com/martinohanlon/microbit-serial for the code for both of these programs.

The Microbit
The microbitreaddata.py python program runs on the Microbit, gets the data and prints it to the output, which in this case is the USB serial connection, and should be flashed to your computer using the Python editor:
from microbit import *

REFRESH = 500

def get_data():
    x, y, z = accelerometer.get_x(), accelerometer.get_y(), accelerometer.get_z()
    a, b = button_a.was_pressed(), button_b.was_pressed()
    print(x, y, z, a, b)

def run():
 while True:
  sleep(REFRESH)
  get_data()

display.show('M')
run()

Your Computer
The clientreaddata.py python program runs on the computer and reads the data using pyserial:
import serial

#the port will depend on your computer
#for a raspberry pi it will probably be /dev/ttyACM0
#PORT = "/dev/ttyACM0"
#for windows it will be COM(something)
PORT = "COM3"

BAUD = 115200

s = serial.Serial(PORT)
s.baudrate = BAUD
s.parity   = serial.PARITY_NONE
s.databits = serial.EIGHTBITS
s.stopbits = serial.STOPBITS_ONE

try:
    while True:
        #read a line from the microbit, decode it and
        # strip the whitespace at the end
        data = s.readline().rstrip()

        #split the accelerometer data into x, y, z
        data_s = data.split(" ")
        x, y, z = data_s[0], data_s[1], data_s[2]
        a, b = data_s[3], data_s[4]
        print(x,y,z)
        print(a,b)

finally:
    s.close()
The values of the accelerometer will be put into the variables x, y, z and the buttons in a & b.

Setting the PORT
You will have to change the PORT variable in the clientreaddata.py program to the comm port that the Microbit is connected to on your computer.

For a Raspberry Pi it is probably "/dev/ttyACM0", in the event it isn't, unplug the Microbit and run:
ls /dev/tty*
Image

Then plug the Microbit and run the command again, the new device which appears will be the port of your Microbit.

For Windows it will be "COM#", the # being a number, the easiest way is to look in Device Manager for the "mBed Serial Port (COM#)"

Image

Tuesday, 2 February 2016

Microbit - a Bop-it game in Python

I wanted to create a simple game for the Microbit and after bring brought an R2D2 Bop-it game I thought I would make one whereby you have to press the A and B buttons in time.

Lets start by importing the microbit and random libraries:
from microbit import *
import random
Create some constants, one for the SPEED which is the amount of time in between each bop for each level, and one for the LEVELUP's which is the amount of points at each level:
SPEED = {0: 1000, 1: 750, 2: 650, 3: 600, 4: 550, 5: 500}
LEVELUP = (5, 10, 15, 20, 25, 30)
Create 4 functions which when caused will show A, B, a tick and a cross:
def show_a():
    display.clear()
    display.show("A")

def show_b():
    display.clear()
    display.show("B")

def show_tick():
    display.clear()
    display.set_pixel(0, 3, 9)
    display.set_pixel(1, 4, 9)
    display.set_pixel(2, 3, 9)
    display.set_pixel(3, 2, 9)
    display.set_pixel(4, 1, 9)
    
def show_cross():
    display.clear()
    display.show("X")
Create a function which will wait for the button to be pressed, returning True if it is and False if it isn't:
def wait_for_button(rightbutton, wrongbutton):
    rightpressed = False
    wrongpressed = False
    
    started = running_time()
    now = running_time()
    
    while now - started < SPEED[level]:
        if rightbutton.is_pressed():
            rightpressed = True
        if wrongbutton.is_pressed():
            wrongpressed = True
        now = running_time()
        
    if rightpressed == True and wrongpressed == False:
        return True
    else:
        return False
Set 3 variables for the level, the score and one which will be set to True when the game is over:
level = 0
score = 0
gameover = False
Scroll "BopBit" on the screen to show its the start of the game:
display.scroll("BopBit")
Loop until the game is over:
while gameover == False:
Randomly pick an action (either A or B), show it on the screen and wait for a button to be pressed:
    success = False
    
    #randomly pick an A or B button
    action = random.randint(0, 1)
    
    #wait for the button to be pressed
    if action == 0:
        show_a()
        success = wait_for_button(button_a, button_b)
    elif action == 1:
        show_b()
        success = wait_for_button(button_b, button_a)
If the player pressed the right button in time show a tick and increase the score or show a cross:
    if success:
        show_tick()
        score = score + 1
        #if the score is a levelup score increase the level 
        if score in LEVELUP:
            level = level + 1
    else:
        show_cross()
        gameover = True
Wait for a small amount of time (half the current speed):
    sleep(int(SPEED[level] / 2))
After the game is over, sleep for 1 second, and display the players score on a loop:
sleep(1000)
while True:
    display.scroll("{} points".format(score))
You can view the complete code in my Microbit MicroPython examples repository on github.

How about taking it further by adding new actions such as shaking or a connecting up a speaker and adding a sound track,

Friday, 18 December 2015

Minecraft, a Microbit and an X-Wing

I was having a chat with David Whale, my co-author of Adventures in Minecraft and he remarked that wouldn't it be cool if you could control something in Minecraft using the Microbit. (Btw - you should definitely check out David's virtual Minecraft Microbit.)

I settled on the idea of using the Microbit's accelerometer to control an object flying through Minecraft. What object, well it had to be the X-Wing, from my previous Minecraft - Star Wars project.

Image

The A button starts and stops the X-Wing, by tilting the Microbit left and right you can turn and the B button drops blocks of TNT which create craters where they land.


There are 2 python programs:
  1. microbitreaddata.py - this runs on the Microbit and reads the status of the buttons and accelerometer 
  2. mcfly.py - this runs on your computer (I used a Windows PC running Raspberry Juice and full Minecraft, but it would work on a Raspberry Pi as well) which reads the data from the Microbit and makes all the calls to move the X-Wing in Minecraft.
You will find the full code and my other Microbit MicroPython examples at github.com/martinohanlon/microbit-micropython.

Monday, 30 November 2015

MicroBit Magic 8 Ball with MicroPython

I wanted to create something with the MicroBit which used the on-board accelerometer and I settled on a Magic 8 Ball, the fortune-telling pool ball which when shaken and asked a question it provides, a, often cryptic, response.


The program works out whether the MicroBit has been shaken by:
  • Reading the x, y, z values from the accelerometer in a loop and adding them together to get a total force exposed
  • Getting the difference between the last reading and the current reading
  • If the difference is greater than a threshold, you assume the MicroBit has been shaken
I wrapped this into a function wait_for_shake, which perhaps not unsurprisingly blocks until the MicroBit is shaken!
import microbit

TOLERANCE = 3000

def get_accel_total():
    x = microbit.accelerometer.get_x()
    y = microbit.accelerometer.get_y()
    z = microbit.accelerometer.get_z()
    return x + y + z

def wait_for_shake():
    shaken = False
    last = get_accel_total()
    while not shaken:
        this = get_accel_total()
        diff = last - this
        if diff < 0: diff = diff * -1
        if diff > TOLERANCE:
            shaken = True
        last = this
        microbit.sleep(50)
Its not 'very' sophisticated but it works.

Once I had this working it pretty simple to add a loop which waited for the MicroBit to be shaken and scrolled a random message on the LED screen.
MESSAGES = ["It is certain", "Dont count on it", "Ask again"]
while True:
    microbit.display.print("8")
    wait_for_shake()
    microbit.display.clear()
    microbit.sleep(2000)
    message = microbit.random(len(MESSAGES))
    microbit.display.scroll(MESSAGES[message])
If you want to add your own messages, just add them to the MESSAGES list.

You can find the code here and other examples in my microbit-micropython GitHub repository.

Image

Thursday, 26 November 2015

Snake on MicroBit using MicroPython

ImageI got my hands on one of the BBC's Microbit's as part of ntoll's Micro World Tour.

I used ntoll's upyed website to create my code and download the .hex file which I uploaded to the Microbit.

After a few tests to see if everything was working I decided to see if I could port the code I wrote to make Snake for Minecraft and Raspberry Pi Sense Hat.


I was pretty pleased. If you want to have a go yourself you will find the code here.

The code
import microbit

import random

class SnakeBit():
    UP = 0
    DOWN = 1
    RIGHT = 2
    LEFT = 3
    
    SNAKEBRIGHTNESS = 9
    APPLEBRIGHTNESS = 5
    SAMPLETIME = 50
    SAMPLESPERMOVE = 10
    
    def __init__(self):
        pass
    
    def startGame(self):
        microbit.display.clear()
        self.direction = self.UP
        self.length = 2
        self.tail = []
        self.tail.insert(0, [2, 4])
        self.createApple()
        self.score = 0
        
        playing = True
        
        samples = 0
        while(playing):
            #keep looping around, if the button is pressed, move the snake immediately, 
            #otherwise move it when the sample time is reached
            microbit.sleep(self.SAMPLETIME)
            buttonPressed = self._handle_buttons()
            samples = samples + 1
            if buttonPressed or samples == self.SAMPLESPERMOVE:
                playing = self.move()
                samples = 0
                
        microbit.display.scroll("Score = " + str(self.score), 100)
        microbit.display.clear()

    def _handle_buttons(self):
        buttonPressed = False
        
        #has a button been pressed
        if microbit.button_a.is_pressed():
            #wait for the button to be released
            while microbit.button_a.is_pressed():
                microbit.sleep(self.SAMPLETIME)
            self.left()
            buttonPressed = True
        
        if microbit.button_b.is_pressed():
            while microbit.button_b.is_pressed():
                microbit.sleep(self.SAMPLETIME)
            self.right()
            buttonPressed = True
            
        return buttonPressed

    def createApple(self):
        badApple = True
        #try and fnd a location for the apple
        while(badApple):
            x = random.randint(0,4)
            y = random.randint(0,4)
            badApple = self.checkCollision(x, y)
        self.apple = [x, y]
        microbit.display.set_pixel(x, y, self.APPLEBRIGHTNESS)

    def checkCollision(self, x, y):
        #is this outside the screen
        if x > 4 or x < 0 or y > 4 or y < 0:
            return True
        else:
            #or in the snakes tail
            for segment in self.tail:
                if segment[0] == x and segment[1] == y:
                    return True
            else:
                return False

    def addSegment(self, x, y):
        #create the new segment of the snake
        microbit.display.set_pixel(x, y, self.SNAKEBRIGHTNESS)
        self.tail.insert(0, [x, y])
        
        #do I need to clear a segment
        if len(self.tail) > self.length:
            lastSegment = self.tail[-1]
            microbit.display.set_pixel(lastSegment[0], lastSegment[1], 0)
            self.tail.pop()

    def move(self):
        #work out where the new segment of the snake will be
        newSegment = [self.tail[0][0], self.tail[0][1]]
        if self.direction == self.UP:
            newSegment[1] -= 1
        elif self.direction == self.DOWN:
            newSegment[1] += 1
        elif self.direction == self.LEFT:
            newSegment[0] -= 1
        elif self.direction == self.RIGHT:
            newSegment[0] += 1

        if self.checkCollision(newSegment[0], newSegment[1]):
            #game over
            snakehead = self.tail[0]
            for flashHead in range(0,5):
                microbit.display.set_pixel(snakehead[0], snakehead[1], self.SNAKEBRIGHTNESS)
                microbit.sleep(200)
                microbit.display.set_pixel(snakehead[0], snakehead[1], 0)
                microbit.sleep(200)
            
            return False
            
        else:
            self.addSegment(newSegment[0], newSegment[1])

            #has the snake eaten the apple?
            if newSegment[0] == self.apple[0] and newSegment[1] == self.apple[1]:
                self.length += 1
                self.score += 10
                self.createApple()

            return True

    def left(self):
        if self.direction == self.RIGHT:
            self.direction = self.UP
        elif self.direction == self.UP:
            self.direction = self.LEFT
        elif self.direction == self.LEFT:
            self.direction = self.DOWN
        elif self.direction == self.DOWN:
            self.direction = self.RIGHT

    def right(self):
        if self.direction == self.RIGHT:
            self.direction = self.DOWN
        elif self.direction == self.DOWN:
            self.direction = self.LEFT
        elif self.direction == self.LEFT:
            self.direction = self.UP
        elif self.direction == self.UP:
            self.direction = self.RIGHT

snake = SnakeBit()
snake.startGame()