スクラッチくらぶ上級編ーmicro:bit

★★★★★ ★★★★★ ★★★★★

BBC micro:bit は小さなコンピュータデバイスです。このデバイスで使える言語に、よく知られた Python があります。BBC micro:bit で動作する Python は MicroPython というものです。

ここではmicro:bit の持つ豊富な機能と、高度なプログラミング言語 MicroPython の組み合わせについて紹介します。

このページは、BBC micro:bit MicroPython ドキュメンテーションを参照しています。 https://microbit-micropython.readthedocs.io/ja/latest/

★★★★★ ★★★★★ ★★★★★

micro:bit(マイクロビット)は、イギリスの放送局BBCで開発された教育用のマイコンボードです。※micro:bitは、micro:bit教育財団の登録商標です。

★★★★★ ★★★★★ ★★★★★

MicroPythonについて

MicroPython は、制約の厳しい環境、特に CPython3 が実行される「デスクトップ」システムよりも性能とメモリの制約が厳しいマイクロコントローラを対象としてる。つまり、MicroPython は、この制約された環境を念頭に置いて設計しなければならず、ターゲットシステムに適合しない、またはスケールしない機能については除外する必要がある。

Pythonの「関数」とは

「何らかの値を渡すと、その値に応じた何らかの値を返すもの」といえる。関数に渡す値(関数への入力値)のことを「引数」と呼ぶ。そして、「関数に引数を渡して、関数のコードを実行し、その処理結果を得る」ことを「関数を呼び出す」「関数呼び出し」「関数の実行」などと呼ぶ。また、関数を呼び出したときに得られる結果(関数からの出力)のことを「戻り値」とか「返り値」などという。

Pythonが標準で備えている関数には、「組み込み関数」と「ユーザー定義関数」があります。

組み込み関数

関数呼び出しの一般的な形式

print関数など戻り値がないものについては「変数名 =」の部分は必要なく、単に「関数名(引数1, 引数2, ……)」のように記述できる。

ユーザー定義関数

・プログラム中で何度も利用するコードを1つにまとめる
・まとまったコードの塊に名前を付けてコードの意図を分かりやすくする
・プログラムを関数の形で他のプログラムから利用できるようにする

値を返す関数

result = get_ans4ultimateQ()
print(result)

Pythonの「メソッド」とは

「関数」と「メソッド」の違い

・単独で呼び出しできるのが「関数
・変数や値に付けて呼び出すのが「メソッド

Pythonの「モジュール」とは

「モジュール」とは、関連性のある「プログラム部品」を1つのファイルにまとめたものです。

・プログラム中で何度も利用するコードを1つにまとめる
・まとまったコードの塊に名前を付けてコードの意図を分かりやすくする
・プログラムを関数の形で他のプログラムから利用できるようにする

Pythonには、これまでに何度も使ってきた組み込みの関数に加えて、さまざまな機能を提供するモジュールが「標準ライブラリ」として用意されている。「組み込み関数」と「標準ライブラリ」は、Pythonをインストールするだけですぐにでも使える。

一方、これらとは別に配布されているモジュールも多数存在している。それらを「外部モジュール」「外部パッケージ」「外部ライブラリ」「サードパーティーパッケージ」などと呼ぶこともある。これらを使うには、Pythonとは別にインストールを行う必要がある。

オブジェクト(インスタンス)とクラスの違い

「オブジェクト」とは「プログラムの実行時に作成されて、コンピュータのメモリ上に存在する何かしらのデータ」のことだ。これに対して、「クラス」とは「オブジェクトを作成するための設計図」といえる。オブジェクトがどんな値を持ち、どんなメソッドを持ち、どんな演算が可能かを詳細に記したものが「クラス」である。

オブジェクトとは「あるクラスの設計図から作り出され、メモリ上に存在する実体」であることを強調するために「インスタンス」(instance)と呼ぶこともある。「instance」とは「実例」といった意味だが、プログラミングの世界における「インスタンス」とは「何かの概念を具体的に表したもの」のことです。

クラスの定義

class文
class クラス名:
    クラス定義の本体(クラスが持つ属性を定義する)

 「クラス名」という名前を持つ「クラスオブジェクト」を作成する。

★★★★★ ★★★★★ ★★★★★

1.チュートリアル

Hello, World!イメージボタン入出力
ミュージックランダム動きの検知ジェスチャー
方角の検知ストレージ音声ネットワーク
無線通信

2.APIリファレンス

Microbit モジュール加速度センサーオーディオBluetooth
ボタンコンパスディスプレイローカル永続ファイルシステム
I2CイメージミュージックNeoPixel
入出力端子無線通信乱数生成音声
SPIUARTutime

APIリファレンスのページへ飛ぶ

★★★★★ ★★★★★ ★★★★★

1.チュートリアル

■Hello,World!

新しい言語を始める伝統的な方法は、コンピュータに “Hello, World!”と言わせることです。

from microbit import *
display.scroll("Hello, World!")

★★★★★ ★★★★★ ★★★★★

■イメージ

MicroPython は、5×5 グリッドの赤色 LED を使って、ディスプレイに表示できる多くの組込みピクチャがあります。

たとえば、デバイスがハッピーに見えるようにするには、次のように入力します。

from microbit import *
display.show(Image.HAPPY)

組み込みイメージ一覧表

Image.HEARTImage.HEART_SMALLImage.HAPPYImage.SMILEImage.SAD
Image.CONFUSEDImage.ANGRYImage.ASLEEPImage.SURPRISEDImage.SILLY
Image.FABULOUSImage.MEHImage.YESImage.NOImage.CLOCK12
Image.CLOCK11Image.CLOCK10Image.CLOCK9Image.CLOCK8Image.CLOCK7
Image.CLOCK6Image.CLOCK5Image.CLOCK4Image.CLOCK3Image.CLOCK2
Image.CLOCK1Image.ARROW_NImage.ARROW_NEImage.ARROW_EImage.ARROW_SE
Image.ARROW_SImage.ARROW_SWImage.ARROW_WImage.ARROW_NWImage.TRIANGLE
Image.TRIANGLE_LEFTImage.CHESSBOARDImage.DIAMONDImage.DIAMOND_SMALLImage.SQUARE
Image.SQUARE_SMALLImage.RABBITImage.COWImage.MUSIC_CROTCHETImage.MUSIC_QUAVER
Image.MUSIC_QUAVERSImage.PITCHFORKImage.XMASImage.PACMANImage.TSHIRT
Image.ROLLERSKATEImage.DUCKImage.HOUSEImage.TORTOISEImage.BUTTERFLY
Image.STICKFIGUREImage.GHOSTImage.SWORDImage.GIRAFFEImage.SKULL
Image.UMBRELLAImage.SNAKE

自作イメージ

自分で作成したイメージを micro:bit に表示します。

物理ディスプレイ上の各 LED ピクセルは 、0 〜 9の数値で明るさの設定ができます。ピクセルを 0 (ゼロ)に設定するとオフになります。ピクセルを 9 に設定すると最も明るいレベルになります。1 〜 8 は明るさのレベルを表します。

from microbit import *

boat = Image("05050:"
             "05050:"
             "05050:"
             "99999:"
             "09990")

display.show(boat)

boat の箇所を下図のように書くことも出来ます。

boat = Image("05050:05050:05050:99999:09990")

アニメーション

静止したイメージの他に、それを移動させることが出来ます。イメージのリストを使うだけです!

①. 文字列の場合

shopping = ["Eggs", "Bacon", "Tomatoes" ]
from microbit import *

shopping = ["Eggs", "Bacon", "Tomatoes" ]

display.show(shopping)

②. 数値の場合

primes = [2, 3, 5, 7, 11, 13, 17, 19]
from microbit import *

primes = [2, 3, 5, 7, 11, 13, 17, 19]

display.show(primes)

【注釈】

数値は(文字列ではなく)単一の値を表すため、引用符で囲む必要はありません。2(数値の2) と"2"(数字の 2を表す文字)は違うものです。

③. 文字列と数値の混在の場合

mixed_up_list = ["hello!", 1.234, Image.HAPPY]
from microbit import *

mixed_up_list = ["hello!", 1.234, Image.HAPPY]

display.show(mixed_up_list)

高度なアニメーション

from microbit import *

display.show(Image.ALL_CLOCKS, loop=True, delay=100)

単一の画像と同様に、デバイスのディスプレイに表示するには display.show を使います。しかし、MicroPython には Image.ALL_CLOCKS の利用を伝えています。また、イメージのリストをループするよう(アニメーションが永遠に続くよう) MicroPython に伝えるために loop=True を指定しています。さらに、各イメージ間の表示間隔を 100 ミリ秒 (0.1 秒)とするために引数 delay=100 を指定しています。

最後に、自前のアニメーションを作成する方法について説明します。この例では、ボートをディスプレイの底に沈めます。

from microbit import *

boat1 = Image("05050:"
              "05050:"
              "05050:"
              "99999:"
              "09990")

boat2 = Image("00000:"
              "05050:"
              "05050:"
              "05050:"
              "99999")

boat3 = Image("00000:"
              "00000:"
              "05050:"
              "05050:"
              "05050")

boat4 = Image("00000:"
              "00000:"
              "00000:"
              "05050:"
              "05050")

boat5 = Image("00000:"
              "00000:"
              "00000:"
              "00000:"
              "05050")

boat6 = Image("00000:"
              "00000:"
              "00000:"
              "00000:"
              "00000")

all_boats = [boat1, boat2, boat3, boat4, boat5, boat6]
display.show(all_boats, delay=200)

★★★★★ ★★★★★ ★★★★★

■ボタン

micro:bit で入力を行う最も当たり前の手段は、「A」と「B」のラベルのついた2個のボタンです。ボタンが押されたことを通知します。

from microbit import *

sleep(10000)
display.scroll(str(button_a.get_presses()))

このスクリプトの全貌は、1万ミリ秒(すなわち10秒)スリープしている間にボタン「A」を押した回数をスクロール表示するというものです。

①.sleep 関数は micro:bit を指定のミリ秒数だけスリープさせます。プログラムの実行を一時停止させたいなら、この関数を使うとよいです。
②.button_a というオブジェクトがあり、その get_presses メソッドで押した回数を得られます。

イベントループ

何かが起こるのを待つプログラムが必要になることがよくあります。これを行うには、ボタンを押すなどの特定のイベントにどう反応するかを定義するコードの周りにループを作ります。

from microbit import *

while running_time() < 10000:
    display.show(Image.ASLEEP)

display.show(Image.SURPRISED)

あなたのデバイスは 10 秒間眠ってから、驚いた顔で目を覚まします。

イベントの処理

ボタンを押すイベントに反応するようにしたい場合、ボタンが押されたかをチェックする is_pressed を無限ループの中に入れます。

A」ボタンを押している場合を除き、常に悲しい顔をします。「B」ボタンを押すと死にます。

from microbit import *

while True:
    if button_a.is_pressed():
        display.show(Image.HAPPY)
    elif button_b.is_pressed():
        break
    else:
        display.show(Image.SAD)

display.clear()

★★★★★ ★★★★★ ★★★★★

■入出力

端子のいくつかは他の端子よりも大きいので、ワニ口クリップを取り付けられます。大きい端子には 0, 1, 2, 3V, GND のラベルが付いています。デバイスにエッジコネクタボードを取り付けると、他の(より小さい)端子にワイヤを結線できるようになります。

大きい端子は、0(pin0), 1(pin1), 2(pin2) というオブジェクトで表します。

くすぐったがりな Python (Ticklish Python)

端子を介した入力の最も単純な例は、それに触れているかどうかをチェックすることです。デバイスをくすぐって笑わせてみましょう。

from microbit import *

while True:
    if pin0.is_touched():
        display.show(Image.HAPPY)
    else:
        display.show(Image.SAD)

片手でデバイスの GND 端子を持ちます。次に、もう一方の手で 0 (ゼロ)の端子を触れてください。ディスプレイが心配顔から笑い顔に変わるのを見てください!

ブーピー音

デバイスに取り付けられる最も簡単なものは圧電ブザーです。

圧電ブザーはデバイスを回路に接続すると高音域のブザー音が鳴ります。BBC micro:bit に取り付けるには、ワニ口クリップを使って端子 0 と GND に接続します。

from microbit import *

while True:
    pin0.write_digital(1)
    sleep(20)
    pin0.write_digital(0)
    sleep(480)

非常に簡単なメトロノームを作りました!

★★★★★ ★★★★★ ★★★★★

■ミュージック

BBC micro:bit の MicroPython には、強力な音楽とサウンドのモジュールがあります。 スピーカーを接続すれば 、デバイスから音を鳴らすのは非常に簡単です。ワニ口クリップを使用して、端子 0 と GND をスピーカーの正と負の入力に接続します。

import music

music.play(music.NYAN)

MicroPython には多くのメロディが内蔵されています。

music.DADADADUMmusic.ENTERTAINERmusic.PRELUDEmusic.ODE
music.NYANmusic.RINGTONEmusic.FUNKmusic.BLUES
music.BIRTHDAYmusic.WEDDINGmusic.FUNERALmusic.PUNCHLINE
music.PYTHONmusic.BADDYmusic.CHASEmusic.BA_DING
music.WAWAWAWAAmusic.JUMP_UPmusic.JUMP_DOWNmusic.POWER_UP
music.POWER_DOWN

各音符には音階名(C#F など)、オクターブ(音の高さ)、持続時間(鳴らす時間)があります。オクターブは数字で示します ~ 0 は最低のオクターブ、4は中位の C を含み、8 は犬のための音楽を作っていない限りは必要ないぐらいに高くなります。持続時間も数字で表されます。持続時間の値が高いほど音を鳴らす時間が長くなります。持続時間の値はお互い関連しています ~ たとえば、持続時間 4 は 持続時間 2 の 2 倍の長さです。音階名 R を使用すると、MicroPython は指定された持続時間だけ、休符(つまり無音)を再生します。

各音符は次のような文字列で表されます。

NOTE[octave][:duration]

たとえば 、"A1:4"は音階名がA、オクターブが1、持続時間が4 である音符を指します。

音符のリストを作成してメロディーを作成しましょう。たとえば、MicroPython が "Frere Jaques" (フランス民謡)の冒頭を演奏するようにする方法は次のとおりです。

import music

tune = ["C4:4", "D4:4", "E4:4", "C4:4", "C4:4", "D4:4", "E4:4", "C4:4",
        "E4:4", "F4:4", "G4:8", "E4:4", "F4:4", "G4:8"]
music.play(tune)

【注釈】

上記のメロディを簡単にできます。オクターブと持続時間は次に変更するまで値をおぼえています。結果として、上記の例は次のように書き直すことができます。

import music

tune = ["C4:4", "D", "E", "C", "C", "D", "E", "C", "E", "F", "G:8",
        "E:4", "F", "G:8"]
music.play(tune)

音響効果

MicroPython では、音符ではないトーンを作成できます。たとえば、警察のサイレン効果を作成する方法は次のとおりです。

import music

while True:
    for freq in range(880, 1760, 16):
        music.pitch(freq, 6)
    for freq in range(1760, 880, -16):
        music.pitch(freq, 6)

この例で music.pitch メソッドがどのように使われているかに注目してください。このメソッドは周波数の指定を期待しています。たとえば、周波数 440 は、交響楽団がチューニングするために使用する調律音 A と同じです。

上記の例では range 関数を使用して数値の範囲を生成しています。これらの数字は音色のピッチを定義するために使用されます。range 関数の3つの引数は、開始値、終了値、間隔幅です。したがって、range 関数を最初に使っているところを日本語で言うと「880 から 1760 までの範囲の数字を 16 間隔で作成する」となります。2 番目に使っている range では「1760 から 880 の範囲の値を -16 間隔で作成する」となります。これは、サイレンのような音程で上下に変化する周波数の範囲を得る方法です。

★★★★★ ★★★★★ ★★★★★

■ランダム

場合によっては、偶然な要素を入れたい、または少し混ぜたいことがあります。 デバイスをランダムに動作させたいことがあるでしょう。

MicroPython には random モジュールがあり、コードに偶然と少し混乱を導入できます。たとえば、ディスプレイ上でランダムな名前をスクロールする方法は次のとおりです。

from microbit import *
import random

names = ["Mary", "Yolanda", "Damien", "Alia", "Kushal", "Mei Xiu", "Zoltan" ]

display.scroll(random.choice(names))

乱数

乱数は非常に便利です。ゲームでは一般的に使われています。サイコロを使ったりするのも乱数を得るためです。

MicroPython には、いくつかの便利な乱数メソッドがあります。シンプルなサイコロを作る方法は次のとおりです。

from microbit import *
import random

display.show(str(random.randint(1, 6)))

デバイスがリセットされるたびに、1 から 6 までの数字が表示されます。

場合によっては小数点以下の数字が必要になることがあります。これは浮動小数点数と呼ばれ、そのような数値を random.random メソッドで生成できます。これは 0.0 から 1.0 の間の値を返すだけです。より大きなランダムな浮動小数点数が必要な場合は、以下のように random.randrange random.random の結果を加算するとよいです。

from microbit import *
import random

answer = random.randrange(100) + random.random()
display.scroll(str(answer))

混沌の種(Seeds of Chaos)

コンピュータで使われている乱数生成器は本当にランダムではありません。開始シード値を与えられた結果のようにランダム値を生成します。シード値の生成には、現在時刻やチップ内に組み込まれた温度計などのセンサー値のようなランダム性のあるものを使うこと多いです。

反復可能なランダム性、すなわち再現性のある乱数発生が欲しいこともあります。サイコロを投げるたびに同じ5つのランダムな値が必要であるようなことです。

これはシード値を設定することで簡単に実現できます。既知のシードが与えられると、乱数ジェネレータは同じ乱数セットを作成します。シードは random.seed に任意の整数を指定します。以下バージョンのサイコロプログラムは常に同じ結果を生成します。

from microbit import *
import random

random.seed(1337)
while True:
    if button_a.was_pressed():
        display.show(str(random.randint(1, 6)))

このプログラムは最初のサイコロの例のようにデバイスをリセットする代わりに、ボタン「A」を押すようにしています。

★★★★★ ★★★★★ ★★★★★

■動きの検知

BBC micro:bit には加速度センサーがついています。これは 3 軸に沿った動きを測定します。

①.X - 左右の傾き

②.Y - 前後の傾き

③.Z - 上下の動き

各軸についてミリ単位の測定結果を正または負の数を返すメソッドがあります。読み取り値が 0 の場合は、その特定の軸に沿って「水平」になっているということです。

たとえば、X 軸に沿ってどのくらいの動きかを測定するために get_x を使う、非常にシンプルな判定プログラムは以下のようになります。

from microbit import *

while True:
    reading = accelerometer.get_x()
    if reading > 20:
        display.show("R")
    elif reading < -20:
        display.show("L")
    else:
        display.show("-")

デバイスを水平にしておくと「-」を表示します。しかし、左右に傾けるとそれぞれ「L」と「R」を表示します。

Y軸のための get_y メソッドとZ軸のための get_z メソッドもあります。

ミュージカル・メイヘム(Musical Mayhem)

加速度センサーからの値をピッチとして演奏するとどうなりますか? 確認してみましょう。

from microbit import *
import music

while True:
    music.pitch(accelerometer.get_y(), 10)

問題の行は最後にあります。music.pitch メソッドに渡す周波数としてY軸の読込みを入れ子にしています。デバイスが傾けられたときに音色をすばやく変更したいので、10ミリ秒間だけ再生させます。

★★★★★ ★★★★★ ★★★★★

■ジェスチャー

加速度センサーは特定の手段(ジェスチャー)で動かすと、MicroPython はこれを検出できます。

MicroPythonは、次のジェスチャーを認識することが可能です。 up , down , left , right , face up , face down , freefall , 3g , 6g , 8g , shake です。ジェスチャーは常に文字列として表されます。ジェスチャー 3g , 6g , 8g は、デバイスがg を受けたことを検出します。

現在のジェスチャーを取得するには、accelerometer.current_gesture メソッドを使います。以下のプログラムは、デバイスが表向きの場合にのみデバイスがハッピーになります。

from microbit import *

while True:
    gesture = accelerometer.current_gesture()
    if gesture == "face up":
        display.show(Image.HAPPY)
    else:
        display.show(Image.ANGRY)

★★★★★ ★★★★★ ★★★★★

■方角の検知

BBC micro:bit にはコンパスがついています。風向きを調べるのにこのデバイスを利用できます。

コンパス

以下のプログラムは北の方角を教えてくれます

from microbit import *

compass.calibrate()

while True:
    needle = ((15 - compass.heading()) // 30) % 12
    display.show(Image.ALL_CLOCKS[needle])

プログラムは compass.heading の値をとり、 床除算(floor division) //剰余(modulo) % を使って画面に表示するクロックの数字を計算し、おおよその北を指すように表示します。

★★★★★ ★★★★★ ★★★★★

■ストレージ

コンピュータにデータを保存すると、デバイスの電源を入れ直してもデータは保持されます。

ファイルシステムで 利用可能な容量は約 30KB となっています。

開けゴマ(Open Sesame)

with open('story.txt') as my_file:
    content = my_file.read()
print(content)

 上の例では、"story.txt" というテキストファイルを開きます。

with open('hello.txt', 'w') as my_file:
    my_file.write("Hello, World!")

上の例では、"hello.txt" というファイルに、 "Hello、World!" というテキストを書き込んでいます。

★★★★★ ★★★★★ ★★★★★

■音声

コンピュータやロボットが話せれば、より「人間」らしくなるでしょう。

音声シンセサイザを使いましょう。

何か言わせてみる

デバイスが話せるようにする前に、スピーカーを接続する必要があります。

デバイスに話させる最も簡単な方法は、次のように speech モジュールをインポートして、 say 関数を使うことです。

import speech

speech.say("Hello, World")

音声シンセサイザは、この点で非常に強力です。なぜなら、4つのパラメータを変更できるからです。

①.pitch - 音声の高低s (0 = 高, 255 = Barry White)

②.speed - デバイスが話す速度 (0 = impossible, 255 = bedtime story)

③.mouth - 音声の発音の不明瞭または明瞭の程度 (0 = 腹話術師の人形, 255 = Foghorn Leghorn)

④.throat - 声の調子のリラックスまたは緊張の程度 (0 = falling apart, 255 = totally chilled)

import speech

speech.say("I am a DALEK - EXTERMINATE", speed=120, pitch=100, throat=100, mouth=200)

★★★★★ ★★★★★ ★★★★★

■ネットワーク

デバイスの間で互いにメッセージの送受信を行えます。

結線

あるデバイスから別のデバイスに信号を到達するための何らかの方法が必要です。これは無線接続で行われることもありますが、この例では単に2本のワイヤを使用します。

青と赤のマイクロビットはワニ口クリップのリード線で接続します。両方とも出力には端子1を使い、入力の場合は端子2を使います。

信号

この例では、単に I/O 端子を介してワイヤーで送られるデジタルのオン/オフ信号です。

pin1.write_digital(1)  # 信号をオンにする
pin1.write_digital(0)  # 信号をオフにする
input = pin2.read_digital()  # 信号の値(1か0)を読む

プロトコル

最もよく知られているプロトコルは、ワールドワイドウェブによって使用されるハイパーテキスト転送プロトコル(HTTP)でしょう。

メッセージを送信するためのもう1つの有名なプロトコルは(コンピュータが現れる前のからありますが)モールス符号です。これは、長時間または短時間のオン/オフ信号を介して文字ベースのメッセージを送信する方法を定義します。このような信号は、しばしばビープ音として再生されます。長い信号は長点(-)と呼ばれ、短い信号は短点(.)です。長点と短点を組み合わせることで、モールスは文字を送信する方法を定義しています。たとえば、標準のモールスアルファベットがどのように定義されているかを次に示します。

.-    A     .---  J     ...   S     .----  1      ----.  9
-...  B     -.-   K     -     T     ..---  2      -----  0
-.-.  C     .-..  L     ..-   U     ...--  3
-..   D     --    M     ...-  V     ....-  4
.     E     -.    N     .--   W     .....  5
..-.  F     ---   O     -..-  X     -....  6
--.   G     .--.  P     -.--  Y     --...  7
....  H     --.-  Q     --..  Z     ---..  8
..    I     .-.   R

①. 持続時間が 250 ミリ秒未満の信号は短点とします。

②. 250 ミリ秒から 500 ミリ秒未満の持続時間を有する信号は長点とします。

③. 他の持続時間の信号は無視するものとします。

④. 信号のない時間が 500 ミリ秒を超えると、文字の終わりを示します。

明らかに、メッセージを送信するには、短点と長点を入力できる必要があります(これにはボタン「A」を使用できます)。送受信したメッセージを見たい場合は、ディスプレイ上にメッセージをスクロールするよう指示できる必要があります(そのためにボタン「B」を使用できます)。最後に、これはモールス符号であり、スピーカーが接続されている場合は、ユーザーがメッセージを入力している間にビープ音を聴覚フィードバックの一形態として再生する必要があります。

最終結果

from microbit import *
import music

# モールス信号とそれが表す文字のルックアップテーブル
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"
}

def decode(buffer):
    # ルックアップテーブルからモールス信号を探します
    # 該当するものがなければ、終止符を返します
    return MORSE_CODE_LOOKUP.get(buffer, '.')

# 単一の短点を表示する方法
DOT = Image("00000:"
            "00000:"
            "00900:"
            "00000:"
            "00000:")

# 単一の長点を表示する方法
DASH = Image("00000:"
             "00000:"
             "09990:"
             "00000:"
             "00000:")

# 短点を作るには 250 ミリ秒未満でボタンを押す必要あり
DOT_THRESHOLD = 250
# 長点を作るには 250 ミリ秒未満でボタンを押す必要ある
DASH_THRESHOLD = 500

# 入ってくるモールス信号を保持
buffer = ''
# モールス信号から文字に変換したものを保持
message = ''
# 次にボタンが押されるのをデバイスが待ち始めた時間
started_to_wait = running_time()

# デバイスがボタンの押下を待って反応するためのループ
while True:
    # デバイスがボタンの押下を待っている時間を計算
    waiting = running_time() - started_to_wait
    # key_down_time のタイムスタンプをリセット
    key_down_time = None
    # ボタンAが押されたら ...
    while button_a.is_pressed():
        # ビープ音を鳴らす - つまりモールス信号を鳴らします
        music.pitch(880, 10)
        # 端子1 (出力) を "オン" にします
        pin1.write_digital(1)
        # ... そして key_down_time が設定されていない場合はすぐに設定 !
        if not key_down_time:
            key_down_time = running_time()
    # 端子2が信号を受け取っている場合は、ボタンAが押されたかのような
    # ふりをして ...
    while pin2.read_digital():
        if not key_down_time:
            key_down_time = running_time()
    # 現在の時刻を取得して key_up_time に入れます
    key_up_time = running_time()
    # 端子1 (出力)を "オフ" にします
    pin1.write_digital(0)
    # key_down_time に値が入っていた場合
    # ボタンAが押されたときに設定されます
    if key_down_time:
        # ... ボタンが押されていた時間を調べます
        duration = key_up_time - key_down_time
        # 押されていた時間が "短点" の最大長未満であれば ...
        if duration < DOT_THRESHOLD:
            # ... 着信したモールス信号を格納するバッファに短点を追加して、
            # ディスプレイに短点を表示
            buffer += '.'
            display.show(DOT)
        # そうでなく、押されていた時間が "長点" の最大長未満であれば ...
        # (しかし、上で判定した短点よりは長い)
        elif duration < DASH_THRESHOLD:
            # ... バッファに長点を追加し、長点を表示
            buffer += '-'
            display.show(DASH)
        # さもなければ、その他の押下時間は無視します
        # これは必要ではなく、"わかりやすさ" のために追記しています
        else:
            pass
        # ボタン押下を処理したので、ボタン押下をデバイスが
        # 待ち始める時間をリセット
        started_to_wait = running_time()
    # さもなければ、このループのサイクルではボタンAの押下が無かったので、
    # モールス信号文字の終端を示す一時停止が無いかをチェックします
    # 一時停止は長点信号の時間よりも長い必要があります
    elif len(buffer) > 0 and waiting > DASH_THRESHOLD:
        # バッファになにかあり、信号の終端に達したので、
        # バッファにあるものをデコードします
        character = decode(buffer)
        # バッファを空にリセットします
        buffer = ''
        # デコード結果の文字を表示します
        display.show(character)
        # メッセージに文字を追加します
        message += character
    # 最後に、上記すべてが行われている間にボタンBが押されていたら ...
    if button_b.was_pressed():
        # ... メッセージを表示して
        display.scroll(message)
        # メッセージを空にリセットします(新しいメッセージの準備)
        message = ''

★★★★★ ★★★★★ ★★★★★

■無線通信

無線のやりとりはすべて物理学に基づくものです。 電波(可視光に似た電磁波の一種)は、送信機によって変調される特性(振幅、位相、パルス幅など)を持っていて、これを利用して情報をコード化して送信します。電波が電気導体(すなわち、アンテナ)に遭遇すると、波の情報が抽出され、元の形に変換された交流電流が発生します。

バイト

micro:bit に組み込まれた無線機能を使用すると、信号の最小単位が 1 バイトになります。バイトは、(通常) 8 ビットで構成される情報の単位です。ビットは、オンまたはオフの2つの状態しかないので、最小限の情報単位です。

アドレッシング

①. 無線通信を異なるチャンネル(0〜83 の番号)にチューニングすることは可能です。これは、子ども向けのトランシーバーのおもちゃとまったく同じように機能します。誰もが同じチャンネルに同調し、誰もがそのチャンネルを介してブロードキャストするものを聞きます。トランシーバーと同様に、隣接するチャンネルを使っても干渉の可能性はわずかです。

②. 無線モジュールでは、アドレスとグループという2つの情報を指定できます。アドレスは郵便アドレスのようなものですが、グループはアドレスの特定の受信者に似ています。重要なのは、無線通信があなたのアドレスとグループと一致しない受信したメッセージを除外することです。つまり、アプリケーションが使用する予定のアドレスとグループを事前に配置することが重要です。

ホタル

ホタルは生物発光を使って(ワイヤなしで)仲間に信号を送る虫の一種です。

無線モジュール radio を使って、ホタルの群れがお互いに交信するようなものを作ってみましょう。

まず Python プログラムで関数を利用できるように import radio します。次に、無線をオンにする radio.on() 関数を呼び出します。これを行うと radio はパワーを得てメモリを確保するので、もちろん、無効にする radio.off() 関数もあります。

radio.send("a message")
new_message = radio.receive()

radio モジュールは文字列だけでなく任意のタイプのデータを送信することもできます。これについてはAPIドキュメントを参照してください。

# micro:bit ホタル
# 作成者 Nicholas H.Tollervey
import radio
import random
from microbit import display, Image, button_a, sleep

# "発光" (flash)アニメーションフレームを作成(何をしているかわかりますか?)
flash = [Image().invert()*(i/9) for i in range(9, -1, -1)]

# 無線を使うためのスィッチをオンにします
radio.on()

# イベントループ
while True:
    # ボタンAは "flash" メッセージを送ります
    if button_a.was_pressed():
        radio.send('flash')  # a-ha
    # 受信メッセージを読み込みます
    incoming = radio.receive()
    if incoming == 'flash':
        # "flash" メッセージを受信したら、ランダムな短い
        # 一時停止の後にホタルの発光アニメーションを表示
        # します
        sleep(random.randint(50, 350))
        display.show(flash, delay=100, wait=False)
        # 少し休んだ後に、flash メッセージをランダムに
        # 再送信します
        if random.randint(0, 9) == 0:
            sleep(500)
            radio.send('flash')  # それっ

最初に、ボタン「A」が押されたかどうかをチェックし、そうであれば、radioを使用してメッセージ "flash" を送信します。次に、radio.receive() でメッセージキューからメッセージを読み込みます。メッセージがある場合は、短くランダムな時間の休止と display.show() を使って、ホタルの光の点滅を表現します。最後に、物事を少しエキサイティングにするために、誰かに "flash" メッセージを再ブロードキャストするチャンスが 1/10 になるように乱数を選択します。ブロードキャストを決定すると、"flash" 信号を再び送信する前に、0.5秒間待機します。このコードは while True ブロック内にあるため、無限に処理を継続します。

★★★★★ ★★★★★ ★★★★★

2.micro:bit Micropython API(APIリファレンス)

APIリファレンスのページへ飛ぶ

★★★★★ ★★★★★ ★★★★★