2022年振り返り

2022年も残り少なくなりました。

今年は、以下のようなブログ記事を書きました。

  1. micro:bitの基本に関する記事(電源、センサー、モーター)
  2. 応用的な作例に関する記事(ETCゲート、MQTT通信)
  3. 開発環境に関する記事(Python新エディタの紹介)

また、ブログに掲載した他に、次のようなことを試しています。

  • センサー類を利用したプログラム
  • v2のlogモジュール(makecodeとpython両方)
  • micro:bitモジュールからのMQTT通信
  • micro:bitのHID拡張機能を利用したScratchのコントローラー
  • micro:bitと段ボール工作(もぐら叩きや的当てゲーム)
  • micro:bitLEGOの組み合わせ(リモコンカー)
  • 放課後プログラミングクラブのScratchレシピをそのまま試す、アレンジしてみる

来年ものんびり、micro:bitやscratchで遊んで行きます。

micro:bit MicroPython新エディタ

0. はじめに

以前の記事でも少し触れましたが、micro:bit用にMicroPythonでプログラミングする方法は複数あります。

その中でも、主なものとして、オフラインエディタのMuと並んで、オンラインエディタがあるところ、そちらがメジャーアップデートされ、Version 3になりました(これまでのアップデート履歴)。

URLは、これまで同様にhttps://python.microbit.org/です。ここにアクセスするとhttps://python.microbit.org/v/3にリダイレクトされます。英語版が表示されますが、日本語化できます。

python.microbit.org

新エディタは以前から開発が進められており、個人的には2月4日のdeveloper community newsでAlphaバージョンの公開を知った段階で一度試してみていましたが、10月3日に正式公開され、各ウェブサイトの紹介やサポートページも更新されているようですので、改めて各種操作を行って、簡単なコードを書いてみました。

1. 新エディタの公式情報

新エディタについてmicrobit.orgの主な関連ページは以下のとおりです。

micro:bit MicroPythonのドキュメンテーションについても、micro:bit V2と新エディタの組み合わせで使用可能なrun_everyデコレータ/関数やlogモジュールなどの記載が拡充されていました。

2. ファーストインプレッション

新エディタは、旧エディタ1と比べると、テキストコーディング初心者にとって、格段に馴染みやすいインターフェイスになっている印象です。

日本語版

画面左下の歯車マーク>Language>日本語を選ぶと、おおよそ全体が日本語化されます。以降は、同じURLにアクセスしても、日本語版となるようです。旧エディタでは地球儀マークで言語設定できましたが日本語がなく、このメニューがあるのは素晴らしいのですが、新エディタももう少しアイコンがわかりやすいと、助かりそうです。

画面構成

詳細は、上記1.の公式情報で動画も交えて説明されていますが、画面構成に着目すると、大きく3つの領域に分かれている点が特徴的です。Scratchの画面構成になぞらえるのは少し正確性を欠きますが、次のような対応関係をイメージすると分かりやすそうです。

  1. 左側のサイドバーメニュー(Scratchの左側のブロックパレット相当)
  2. 中央の編集ウィンドウ&ボタン類(Scratchの中央のスクリプトエリア相当)
  3. 右側のシミュレーター(Scratchの右側のステージ相当)

シミュレーター

旧エディタと比べてパッと目につくのはシミュレーターがある点です。MakeCodeエディタでは以前から、実機がなくても、シミュレーターで動作確認ができましたが、新エディタの登場によりMicroPythonでも同様のことが可能になりました。 加速度、磁気、無線送信2、さらにはlogモジュールでの記録内容まで対応しており、実機がなくとも幅広い機能を試すことができます。
なお、シリアルもシミュレータのところにあります。

サイドバーの「リファレンス 」

また、特徴的なのは、左側のサイドバーメニューです。ここにはいくつかのタブがありますが、テキストコーディング初心者がまずお世話になりそうなのが「リファレンス」タブです。

micro:bitの各種機能、また、Pythonの基本事項などが、コンパクトに解説されており、さらにサンプルコードも提供されています。サンプルコードの方は、ドラッグ&ドロップして、編集ウィンドウに挿入することもでき、この動き自体はブロックコーディングにイメージが似ています(あくまで、サンプルコードがコピーされるだけであるため、意図するプログラムを作ろうとすると、ドラッグ&ドロップでは足りないことになります)。

上記1.の公式情報でもご紹介したmicro:bit MicroPythonのドキュメンテーションチュートリアルに近いイメージですが、サイドバーでの表示ということもあり、要点に絞られているようですので、必要に応じてドキュメンテーションにも遡ることになります。例えば、新機能でrun_everyとlogを組み合わせた定期ログ記録がかなり手軽になりましたが、電池を持たせるためにpowerモジュールとの組み合わせで使うサンプルコードはドキュメンテーション内のみのようです。欲を言えば、ドキュメンテーションの対応箇所へのリンクもあるとありがたいです。

初めてのテキストコーディングでも、何をして良いか分からず固まってしまう、ということにならないように、配慮されている印象です。

サイドバーの「アイデア

いまのところ、感情バッジ、歩数計、アクティビティピッカー、スマイルを送ろう、サイコロ、拍手でライト、グーチョキパーでなにつくろ、の7つのアイデアが紹介されています。

これらについてサンプルコードとその説明を見ることができ、また「開く」ボタンを押すだけで、コードがコピーされてシミュレーターで試すことができます。さらに「チャレンジ」の項目には、アイデアを発展させるためのヒントがあり、「リファレンス」へのリンクが貼られています。

出来上がったコードを見るとそれを動かして終わり、になってしまいそうですが、発展系を示すことで、そこから創意工夫が広がっていきそうです。

なお、末尾の「他のアイデア」のリンクから、microbit.orgのProjectページに移動することができ、MicroPythonのコードがあるプロジェクトが一覧表示されます。プロジェクトのページ内で”Open in Python"をクリックして、新エディタでコードを開くこともできます。

サイドバーの「API

サイドバーの「API 」は、機能的にmicro:bit MicroPythonのドキュメンテーションAPIの短縮版のイメージです(一部、ドキュメンテーションへのリンクもあります)。「リファレンス」より定数や関数が多く紹介されていますが、全体を通した説明はなく、関数などが羅列されていて(ドラッグ&ドロップ可能)、あと、短いサンプルがあるという構成です。「リファレンス」を使って慣れた人が使うことを想定されているのでしょうね。

編集ウィンドウ&ボタン類

コーディングについては、補完やエラーハイライトの機能が備わっています。旧エディタにはなかった機能であり、初心者にはこれがかなり助かります。細かい比較はしていませんが、オフラインエディタMuの同等の機能より、使いやすいように感じました。

ボタン類は、旧エディタを使っていればそれぞれの機能は迷わず使えそうです。なお、同一プロジェクトにmain.py以外のスクリプトを追加したり、プロジェクトをリセットなどしたい場合は、サイドバーの「プロジェクト」から行うことになります。

キーボードショートカット

こちらにキーボードショートカットの一覧があります。

3. 試しにコード(Trick or Treat)

MicroPythonならではのSpeechモジュールと、外付けの人感センサを使って、人の動きを感知したら、trick or treatとしゃべるプログラムを書いてみました。基本的に、新エディタのサイドバーの「リファレンス」や「API」を見て書くことができましたが、speechモジュールの詳細は、ドキュメンテーションまで遡っています。

from microbit import *
import speech

# 通常の顔
pumpkin_normal =   Image('00000:'
                         '77077:'
                         '00000:'
                         '70707:'
                         '77777')
# しゃべるときの顔
pumpkin_speaking = Image('99099:'
                         '09090:'
                         '90909:'
                         '99999:'
                         '90909')

# まばたき
def display_blinking():
    sleep(1000)
    for i in range (2):
        display.set_pixel(1, 1, 9)
        display.set_pixel(3, 1, 9)
        sleep(100)
        display.set_pixel(1, 1, 0)
        display.set_pixel(3, 1, 0)
        sleep(100)

# (低めの声でしゃべる)
def speech_low(words):
    speech.say(words, pitch=128, speed=100, mouth=50, throat=128)

# しゃべる(通常の顔としゃべる顔を交互に表示しながら、怖い声でしゃべる)
def display_speaking():
    display.show(pumpkin_speaking)
    speech_low("trick?")
    sleep(400)
    display.show(pumpkin_normal)
    speech_low("or")
    sleep(100)
    display.show(pumpkin_speaking)
    speech_low("treat!")
    sleep(400)   
    display.show(pumpkin_normal)

# 人感センサー関連
sensor=0
threshold=900

# 最初に通常の顔の表示
display.show(pumpkin_normal)
    
# まばたきを繰り返す、人感センサが反応したらしゃべる
while True:
    display_blinking()
    sensor=pin0.read_analog()
    if sensor>threshold:
        display_speaking()

人感センサ

人感センサは、AM312を使っています。

micro:bitとの接続方法や、検出方法(デジタルではうまくいかず、アナログで読み取る必要があること)については、こちらのブログを参考にしています。

しゃべる様子

Speechモジュールは、実機を使わないで、新エディタのシミュレータでしゃべる様子を確認することもできます。シミュレータでは、赤外線センサの動作までは試せないので、上記コードのif sensor>threshold:を、if button_a.was_pressed():と置き換えています。


  1. Python Editor(Version 2)(https://python.microbit.org/v/2)も2023年9月までは利用可能です。なお、Version 2にアクセスすると、新エディタの紹介がポップアップされますが、リンク先は新エディタのベータバージョンとなっているようです。

  2. ただし、MakeCodeの2画面エディタのような機能はないようですので、無線の送信と受信のプログラムを別に作って動作を試すには、実機が必要となりそうです。

micro:bitで気象情報・天気予報のMQTT通信

0. アイディア

気象情報・天気予報の作例

これらをみて、なんとか上りと下り両方でIoT(らしきもの)をやってみたい、と思い立ちました。意図した通りに動くものはできましたが、電力消費が激しく、モバイルバッテリーで常時使用は難しい状況であり、こういうこともできる、ということに過ぎません。

micro:bitの限界について

そしてやはり、慣れ親しんだmicro:bitを使いたいと考えましたがそこでネックになるのは、ネットワークへの接続です。micro:bitは単体でWifi接続はできないという限界があり、外部モジュールもWifiに接続できるものは(国内での正規利用を考えると)限られています1。単体でもBluetoothやシリアル通信は可能であるため、micro:bitを使う場合、上記作例も含め、Bluetoothやシリアル通信でラズパイ(Raspberry Pi)、M5シリーズ又はPCに接続、ラズパイ等をゲートウェイにして、インターネットに繋ぐ作例が多いようです。

(今回もそうですが)ゲートウェイ側のラズパイ等のプログラムも必要となってしまうので、そうすると最初からラズパイ等だけでやる(micro:bit不要で、ラズパイ等に直接センサを繋いだり表示したりする)、というのが本来は素直です。。

やりとりするデータについて

やりとりするデータのうち、上り通信の方の気象情報については、micro:bitは、 以前ご紹介したとおり、そのままでもセンサーが充実しており、温度や明るさであれば単体でも計測できます。実際、これまでも、温度と明るさを計測するプログラムを、MakeCode EditorのブロックプログラミングMicroPythonで作成してみたことがあります。他方、これ以外の気象情報、例えば、湿度や気圧の計測となると、外部センサーに頼る必要があります。

なお、下り通信の方の天気予報について、これは、micro:bitだからどうこうという話ではありませんが、今は気象庁の天気予報JSONが手軽でしょうか(気象庁の天気予報JSONファイルをWebAPI的に利用したサンプルアプリ | サンプルアプリ一覧 | あんこエデュケーション)。これを使って、改造Scratchでネコに天気予報をしゃべってもらうプログラムを作ったことはありました。もっとも、今回は楽をして別の方法をとっています。

今回の仕組み

今回の具体的な仕組みは、次の図のようになります。青色矢印が上り通信、オレンジ色矢印が下り通信です。

  • ネックとなるmicro:bitからのネットワークへの接続ですが、

  • データについては、

    • 上り通信のデータとして、気象情報は、BME280という外部センサで、気温・湿度・気圧を測ることにしました。
    • 下り通信の、天気予報については、本来は気象庁のウェブサイトから取得したりしたいのですが、簡略化して、スマートフォンiOS)で天気予報アプリから得た情報を、MQTT接続アプリを使って送信する、というショートカットを作成、それをオートメーション機能で定期実行しています。
  • micro:bitでの表示については、

    • 気象情報は、Aボタンを押すと、外部のOLEDに表示されるようにし、
    • 天気予報は、Bボタンを押すと、micro:bit本体のLEDで降水確率に応じたアイコン表示する形です。

1. 使用したもの

ハード

ソフト

  • 「ショートカット」アプリ(iOS標準)
  • 天気アプリ(iOS標準)
  • MQTT Analyzer(iOSのMQTTクライアント、「ショートカット」からも利用可能)

→「ショートカット」で天気予報アプリの取得情報(降水確率)をMQTT Analyzerでpublishする設定は次のとおり

  • MQTT dashboardAndroidのMQTTクライアント、こちらはJSONの読み込みに加えて、受信した数値のグラフ表示も可能であり、使い勝手がよいです。)

2. 上り通信の雰囲気(気象情報のPublish)

配線は特殊な点はありませんが、外部センサ・外部ディスプレイと、micro:bitを、(M5:Bit経由で)I2C接続する際、繋ぎ間違えないようにするくらいでしょうか。M5:Bitは、エッジコネクタとの接続部を上にしたとき右側に2セットのI2C接続端子があり、DA/CL/V/Gの表示もされているので分かりやすいです。

3. 下り通信の雰囲気(天気予報のSubscribe)

4. コード

micro:bit

  • 初期設定(「最初だけ」)

    • シリアル通信は、TXをP8、RXをP12としています。これは、M5:BitのGroveコネクタ経由での接続の割り当てがデフォルトでこのようになっているためです。
    • LCDディスプレイはこちら、センサ(BME280)はこちら拡張機能を使っており、I2Cのアドレスについて、LCDは60、センサは76を指定しています。
  • ループ(「ずっと」)

    • 1時間ごとに、センサでの気象情報の読み取り(変数への格納)と、読み取った気象情報のM5Cameraへのシリアル通信(上り通信)を行っています。この気象情報は、MQTTブローカーを経由してスマホでsubscribeします。
    • MQTTのクライアント(スマホ)での表示を考慮して、JSON形式にしています。JSON形式にするための拡張機能は見当たらなかったのですがmakecodeのdocsのData Analysis > Remote Data の最後の箇所を参考にして書いています。
  • シリアル通信で受信した時(下り通信)

    • スマホ側でpublishした天気予報の降水確率を、MQTTでsubscribeしているM5Camera経由で受信した時に、変数に格納します。
  • ボタン操作

    • Aボタンが押されると、センサで読み取った気象情報をOLEDディスプレイで表示します。

    • Bボタンが押されると、下り通信で取得した天気予報の降水確率に応じて、晴れ・雨・曇りマークをmicro:bit本体のLEDに表示しています。

MakeCodeの画面でJavaScriptに切り替えたコードは以下のとおりです。

input.onButtonPressed(Button.A, function () {
    OLED12864_I2C.showString(
    0,
    0,
    "Temp: " + convertToText(temperature),
    1
    )
    OLED12864_I2C.showString(
    0,
    1,
    "Humi: " + convertToText(humidity),
    1
    )
    OLED12864_I2C.showString(
    0,
    2,
    "Pres: " + convertToText(pressure),
    1
    )
    basic.pause(5000)
    OLED12864_I2C.clear()
})
serial.onDataReceived(serial.delimiters(Delimiters.NewLine), function () {
    weather = parseFloat(serial.readUntil(serial.delimiters(Delimiters.NewLine)))
})
input.onButtonPressed(Button.B, function () {
    if (weather < 0) {
        basic.showIcon(IconNames.Asleep)
    } else if (weather < 40) {
        basic.showLeds(`
            # . # . #
            . # # # .
            # # # # #
            . # # # .
            # . # . #
            `)
    } else if (weather > 60) {
        basic.showIcon(IconNames.Umbrella)
    } else {
        basic.showLeds(`
            . . . . .
            . # # # .
            # # # # #
            . # # # .
            . . . . .
            `)
    }
    basic.pause(5000)
    basic.clearScreen()
})
let pressure = 0
let humidity = 0
let temperature = 0
let weather = 0
basic.showIcon(IconNames.Giraffe)
basic.pause(500)
basic.clearScreen()
weather = -1
temperature = 0
humidity = 0
pressure = 0
serial.redirect(
SerialPin.P8,
SerialPin.P12,
BaudRate.BaudRate115200
)
OLED12864_I2C.init(60)
BME280.Address(BME280_I2C_ADDRESS.ADDR_0x76)
basic.pause(10000)
basic.forever(function () {
    temperature = BME280.temperature(BME280_T.T_C)
    humidity = BME280.humidity()
    pressure = BME280.pressure(BME280_P.hPa)
    serial.writeString("{")
    serial.writeString("\"temperature\":" + temperature + ",")
    serial.writeString("\"humidity\":" + humidity + ",")
    serial.writeString("\"pressure\":" + pressure)
    serial.writeLine("}")
    basic.pause(3600000)
})

M5Camera側

M5Camera側は、Arduino IDE上で、以下のコードを作成して書き込んでいます。

  • MQTTクライアントは、Arduino Client for MQTTを使用しています。
  • WifiSSIDとパスワードやMQTTのIPアドレスやポート番号の設定はそれぞれの環境にあったものを入力する必要があります。MQTTのユーザやトピックは任意ですが、トピックは同じものをスマホのMQTTクライアントで設定することになります。

  • micro:bitとのシリアル通信(前述の通り、GroveコネクタとM5:Bit経由)は、Serial2.begin()の箇所で初期設定しており、ボーレートはmicro:bitの設定と合わせ、TXは4、RXは13としています(M5Cameraの場合。他のM5シリーズを利用する場合などは異なります)。Serial2.begin()のパラメーターについてはこちらを参考にしました。

  • その他のコードの説明は、簡単なものですがコメントを入れています。定期処理はこのままですとかなり電力を消費するため、間隔を開けて実行するなど省電力化の工夫が必要となりそうです。

#include <WiFi.h>
#include <PubSubClient.h>

// 各種設定値
const char* ssid = "[SSIDを入力]";
const char* password = "[パスワードを入力]";
const char* mqtthost = "[MQTTブローカーのIPアドレス]";
const int mqttport = "[MQTTブローカーのポート番号]";
WiFiClient  wfClient;
PubSubClient client(wfClient);

const char* userid = "[ユーザIDを入力]";
const char* topic_pub = "[Subscribeするトピック(天気予報)を入力]";
const char* topic_sub = "[Publishするトピック(気象情報)を入力]";
String message;
const int len = 50;
char payload_pub[len];

// Subscribe用の処理(天気予報のトピックをSubscribeしておきスマホのMQTTクライアントからMQTTブローカー経由で受診した場合、micro:bitにシリアル通知で送信する。)
void callback(char* topic, byte* payload, unsigned int length) {
  for (int i=0; i<length; i++) {
    Serial.print((char)payload[i]);
  }
  Serial.println();
  for (int i=0; i<length; i++) {
    Serial2.print((char)payload[i]);
  }
  Serial2.println();
}

void setup() {
  Serial.begin(9600);
  Serial.println();

  //M5CameraのLED
  pinMode(14, OUTPUT);
  
  setup_wifi();
  setup_mqtt();

  //micro:bitとのシリアル通信用の初期設定(M5Cameraの場合、TXは4、RXは13とする。)
  Serial2.begin(115200, SERIAL_8N1, 13, 4);

  //M5CameraのLEDを点滅
  digitalWrite(14, HIGH);
  delay(100);
  digitalWrite(14, LOW);
  delay(100);
}

// Wifi接続
void setup_wifi() {
  Serial.println();
  Serial.print("connecting to ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println();
  Serial.print("WiFi connected at ");
  Serial.print(WiFi.localIP());
}

// MQTT接続
void setup_mqtt(){
  Serial.println();
  Serial.print("connecting to mqtthost");
  client.setServer(mqtthost, mqttport);
  //subscribe
  client.setCallback(callback);
  while (!client.connected()) {
    delay(1000);
    Serial.print(".");
    client.connect(userid);
  }
  Serial.println();
  Serial.print("mqtt connected as ");
  Serial.println(userid);
  // Subscribe用の処理
  client.subscribe(topic_sub);
  Serial.print("mqtt subscribed for ");
  Serial.println(topic_sub);
}

// 定期処理
void loop() {
  // Publish用の処理(micro:bitからのシリアル通信を読み取る。読み取ったデータはJSON形式であるが、特にここでは要素の処理はせず、const char[ ]に変換して、Publishするのみ。)
  if (Serial2.available() > 0) {
    message = Serial2.readStringUntil(0x0a);
    message.toCharArray(payload_pub, len);
    client.publish(topic_pub, payload_pub, true);
    // client.publish(topic_pub, (uint8_t*)payload_pub, (uint8_t)len, true);
    Serial.print("published ");
    Serial.print(topic_pub);
    Serial.print(" as ");
    Serial.println(payload_pub);
    delay(500);
  }
  // Subscribe用の処理
  client.loop();
}

  1. 例えば、grove shield for microbit v2を経由したgrove uart wifi v2というモジュールの利用が考えられます。これは既存の拡張機能によりIFTTT 経由でLINEに通知でき、また、ATコマンドを利用してウェブサイトへのアクセスも可能です(サヌキテックネットさんのGroveデバイスに関する一連の記事の15-3〜15-6)。そのため、実は、このモジュールだけで、MQTTブローカーに接続できるかもしれません。MQTTの構造と、ATコマンドをしっかり理解する必要がありそうですが、MQTTで始めるIoTデバイスの作り方 - MONOist参照。

  2. なお、上記で参照した作例中、「IoTをはじめよう 室温管理システムを作る」は、M5シリーズのうちM5Stackとmicro:bitを接続しています。ここでは、M5:Bitは使わずに、通信はGroveケーブル経由でジャンパワイヤ・エッジコネクタ経由で繋ぎ(なお、この方法が実際可能かは、現行機種の使用も含めてご確認ください)、電源もM5Stackの3.3V端子を使っています。M5Cameraでは同じ方法は試していませんが、少なくとも電源については、M5Cameraは3.3V端子がないため、同じ方法ではできないことになりそうです。

micro:bitでサーボモーター

micro:bitサーボモーターを動かそうとするとき、ケーブルと電源がポイントになります。

ケーブル

ケーブルの接続口は、次の通りmicro:bitサーボモーターで異なるため、繋ぎ方を工夫するか、拡張基盤を使う必要があります。

ワニ口〜ジャンパーピン(オス)のケーブル

下記のようなオンラインストアで販売している、ワニ口〜ジャンパーピン(オス)のケーブルを使うと、1本で済むのですっきりします。圧着工具と材料があれば自作もできます。ワニ口ケーブルとジャンパーワイヤを切断して繋ぐ方法もあるようです(Equipping a microservo with Crocodile clips)。

ワニ口ケーブルでジャンパーワイヤを掴む

micro:bitは普通のワニ口ケーブルで、サーボモーターはジャンパーワイヤ(オスーオス)でそれぞれつなぎ、最後にワニ口ケーブルでジャンパーワイヤをつかむと繋ぐことも一応できます。 ただし、ジャンパーワイヤとワニ口の接続部分は露出してしまうので、そこが接触しないかが気になります。

拡張基盤

拡張基盤には、サーボモーターのジャンパーケーブルを刺せる仕様になっているものがいくつかあるため、そちらを利用するのが手軽です。

電源

makecodeで「サーボ 出力する」を使うとシュミレーターに表示されるのは、micro:bitからの出力電圧3.3V(最大)だけで、サーボモーターに電源供給する接続方法です。

しかしながら、例えば、良く使われるサーボモーターのSG-90の動作電圧は4.8~5Vとされており、この接続方法では動作電圧を満たさないことになります。それでも動くことは動くのですが、特にmicro:bitJST Phコネクタに電池ボックスをつなぐ方式で、電池が減ると動作が安定しなかったり動かないこともあります。

外部電源を用意するか、拡張基盤を用意するか、どちらかにした方が安定します。この辺りは、別の記事で、電源供給をまとめたときに触れています。

vivitelaeti.hatenablog.com

作例

サーボモーターは、上記のようなポイントを押さえても、不良個体があったり、想定通りに動かないこともありますが、やはり、モノを動かすのは楽しいです。書籍やウェブサイトでも、いくつか作例が挙げられています。

micro:bitでミニETCゲート

目次

0.アイディア

家にあったミニカー、子供用のブロックであるJOIZ(ABOUT JOIZ | おもちゃ-ピタゴラス・ブロック | 乳幼児玩具メーカー・ピープル)、サーボモーターを使い、次のようなミニETCゲートを作ってみました。ミニETCは、自動モードの他、手動モードでも開閉できます。手動モードには遠隔操作もあります。

  • 自動モード
    • 磁力センサーでミニカーに積まれた磁石を探知(↓動画)
  • 手動モード
    • A/Bボタン
    • Bluetooth
    • モバイルアプリ

クローズ

オープン

1.必要なもの

  • micro:bit 本体
  • 電源(今回は単3x2の電池ボックス)
  • サーボモーター(今回はSG-90)
  • ケーブル(今回はワニ口〜ジャンパーピン(オス))
  • JOIZ(JOIZ Basicの方ですが、JOIZ Firstでも部品は足ります)
    • ETCゲートのバーになる部分(JOIZを利用。 JOIZがない場合、サーボモーター付属のサーボホーンにストローを繋げるなどで代用可能)
    • サーボモーターの土台(JOIZを利用。JOIZがない場合、適当な空き箱)
  • トミカ(今回は2018年発売のトミカ No.85 三菱ふそう スーパーグレート)
  • 磁石

vivitelaeti.hatenablog.com

2.組み立て方

全体の繋ぎ方

電源→micro:bit→モーター→ETCゲートのバーと繋いでいます。ただし、置く順番としてはLEDの表示が見えやすいように、micro:bitを手前(写真右手=ミニカー侵入口側)に持ってきています。

サーボモーターとETCゲートのバー

サーボモーターには、付属のサーボホーンの代わりに、JOIZの細長いブロック1つを繋いでいます(繋ぐ角度は、makecodeで0度に設定したときにクローズ状態すなわち地面と水平になるように調節しています)。
JOIZの穴の大きさが偶々合うのですが、サーボホーンのように穴に細かいギザギザがないため1、繋いだ状態でブロックに少し負荷をかけると外れます。変に負荷に耐えたりしないので、今の所破損などはないようですが、メーカーでこのような繋ぎ方が想定されているわけでは全くないため、不具合が出ない保証はありません。

micro:bitサーボモータ

micro:bitサーボモーターは、makecodeのシミュレーターで出てくる方法で繋いでいますが、サーボモーターのデータシートで要求される電圧未満となります。これでも新品の電池などでは動きますが、電池の容量が低下すると、安定しないことがあります。本来は、モジュールを使うなどしてサーボモーターに十分な電圧を供給する方が安定します。

サーボモーターの土台

サーボモーターの土台は、JOIZのブロックのうち、丸が3個繋がったものを2つ両側に置き、その間を、丸が2個繋がったもの5つで繋いでいます。これも偶々サーボモーターの突起部分が片方の丸3個ブロックの凹の隙間に入り込み(写真左手)、もう片方が丸3個ブロックの凸にあたり(写真右手)、これでおおよそ固定されるようです。

ミニカー

ミニカーには小さい磁石を積んでいますが、小さいお子さんなど誤飲に注意が必要です。

3.プログラム

オープンとクローズ

ETCゲートをオープン・クローズする部分です。モードや遠隔操作方法によって、幾つかのブロックからオープン・クローズするため、関数にしています。

関数の中でサーボモーターを動かす方法としては、「入出力端子」>「サーボ 出力する 端子○ 角度○」ブロックを使って、オープンの角度は90度、クローズの角度は0度としています。単に角度のところにその数値を入力するだけでは、一瞬でゲートがその角度まで動いてしまうため、「ループ」>「変数○を0〜○にかけて繰り返す」を使って、1度ずつ動くようにしています。

また、ゲートが開いているのにオープン、閉じているのにクローズ、という意味のない呼び出しがなされた場合には、不要な動作をしないように、「ゲート」変数でフラグを立てています。

モード切替え

ETCを模すというところからは離れますが、磁力で開閉する自動モードの他に、遠隔操作して動かす手動モードも選択できるようにしています。

切替えそのときの状態が自動と手動のいずれか、区別できるようにしておくため、「オート」変数(0: 手動、1: 自動)でフラグを立てています。 本体のボタン(A+B)で、自動モードと手動モードの切替えを可能にしています。

自動モード

自動モードでは、磁石を積んだミニカーがETCゲートに近づいたときだけ開くようにする(普通のミニカーでは開かないようにする)ため、磁力センサーで磁石の接近による磁力の変化を探知しています。「入力」>「その他」>「磁力(μT)」のブロックを使い、X方向(左右方向)の磁力の絶対値を導いてそれが閾値を上回れば、オープン関数を呼びだしています。

手動モード(ボタン)

本体のA・Bボタンにそれぞれオープン・クローズ関数を割り当てています。

手動モード(標準の無線機能)

本体のボタンだけではなく、遠隔操作もやってみたくなります。
micro:bitを遠隔操作する方法は幾つかあり、標準の無線機能(Radioradio - micro:bit runtime)を用いて、他のmicro:bitから操作することが一番簡単です。

手動モード(Bluetooth

今回は、Bluetoothにより、スマホと接続してスマホアプリからの操作を試してみました。micro:bit v2のプロトコルは、Bluetooth 5.1 with Bluetooth Low Energy(BLE)となります(Hardware)。

micro:bitで、Bluetooth接続を使うためには、次の①②の事前準備を行います。

①No Paring Required

MakeCode Editorの右上の歯車>「プロジェクトの設定」をクリックすると表示される1番上のトグルボタン(No Paring Required)をオンにすることで、ペアリングを不要にすることができます。

この設定をスキップしても、実際に使用する際、スマホとのペアリングを行えばBluetoothを使うことはできます。(A+Bを押し続けたまま、リセットボタンをオンオフして待つ。Pairing via Bluetooth : Help & Support)。

Bluetooth拡張機能の追加

右上の歯車又は左側のメニューから「拡張機能」をクリックし、"Bluetooth"と検索すると、最初に以下の拡張機能が表示されるため、クリックします。

クリックすると、標準の無線機能(radio)を削除する必要があるとのメッセージが出ます 2 。これは、標準の無線機能(radio)もBluetoothも、同じオンボードの2.4GHz帯を使っているためのようです。

micro:bitのコードでは、「最初だけ」ブロックの中で、BluetoothUARTサービスをオンにしておきます。
micro:bitで利用可能なBluetoothのサービスは、センサーの数値などを取得できる特定のサービスと、汎用的なUARTサービスに分かれるところ、今回はスマホアプリから送る文字に応じてETCゲートをオープン・クローズすることを目的とするため、UARTサービスを使っています。

なお、特定のサービスとUARTサービスという分類は、ものものテックさんのウェブサイト(micro:bitで初めてのBLE通信)を参考にしています。このウェブサイトは分かりやすく、また、WebBluetoothを使った多様な作例の紹介もあります。 また、microbit.orgのサポートにも簡単な例が載っています(micro:bit Bluetooth Low Energy serial UART : Help & Support)。

その上で、「Bluetooth データを受信したとき 区切り文字(改行コード)」ブロック内で、「Bluetooth UART次のいずれかの文字の手前まで読み取る(改行コード)」にて、スマホからのデータを読み取っています。
データを変数に格納して、それが"o"であればオープン、"c"であればクローズしています。(途中で文字列を操作しているのは、そのままのデータでは、末尾に余分な文字列が含まれているのか、条件分岐がうまく働かないためです)。

スマホアプリは、Serial Bluetooth Terminalを使っています(Kai Morich's Android Apps)。"o"や"c"の文字を入力して送信するとmicro:bitを通じて、ミニETCゲートを遠隔操作できます。

手動モード(モバイルアプリ)

micro:bitには公式のモバイルアプリ(iOS版/android版)があり、micro:bitとBLEで接続して、プログラムを書き込むことができます。また、iOS版は、micro:bitから情報を受け取ったり、反対に情報を送って操作するためのインターフェースも備えています(monitor&control。Guide to mobile apps | micro:bit

このmonitor&controlには幾つか機能がありますが、そのうちgamepadは2つの十字キーを利用でき、ロボットなどの操作に便利そうです。

今回は、ゲートの上げ下げだけなので、本当は複数ボタンは必要ないのですが。昨年gamepadの利用方法が変わり、「高度なブロック」>「制御」>「イベントが届いたとき」ブロックを使う仕様になったことを、さとやまノート(マイクロビットを使ってみる 〜マイクロビットをスマホでコントロール 2 | さとやまノート)で知り、使ってみたくなりました。

monitor&controlは、BLEイベントサービスの一つであり、詳しい仕様はこちらに記載があります。micro:bit側はBLEを使えるようにしておく必要があります。

monitor&controlからの受信は「イベントが届いたとき」ブロックの発生源をMES_DPAD_CONTROLLER_IDにして、ボタン毎のイベント値で条件分岐しています。一目瞭然ですが、上ボタンを押す(イベントの値: 1)とオープン、下ボタンを押す(イベントの値: 3)とクローズするように設定しています。

条件分岐の箇所で使っているイベントの値ですが、microbit-dalのソースコードのうちMESEvents.hにて定義されています。

#define MES_DPAD_BUTTON_A_DOWN              1
#define MES_DPAD_BUTTON_A_UP                2
#define MES_DPAD_BUTTON_B_DOWN              3
#define MES_DPAD_BUTTON_B_UP                4
#define MES_DPAD_BUTTON_C_DOWN              5
#define MES_DPAD_BUTTON_C_UP                6
#define MES_DPAD_BUTTON_D_DOWN              7
#define MES_DPAD_BUTTON_D_UP                8
#define MES_DPAD_BUTTON_1_DOWN              9
#define MES_DPAD_BUTTON_1_UP                10
#define MES_DPAD_BUTTON_2_DOWN              11
#define MES_DPAD_BUTTON_2_UP                12
#define MES_DPAD_BUTTON_3_DOWN              13
#define MES_DPAD_BUTTON_3_UP                14
#define MES_DPAD_BUTTON_4_DOWN              15
#define MES_DPAD_BUTTON_4_UP                16

条件分岐の箇所では、上記を参照して数値を入力する代わりに、「高度なブロック」>「制御」>「…その他」>「MICROBIT_EVT_ANY」のブロックを取り出し、このブロックの右端▼から「MES_DPAD_BUTTON_UP」等を選ぶ方法も可能であり、こちらの方がコードを見てgamepadのどのボタンに対応した操作なのか一見してわかりやすいです。
もっとも、gamepadの特定のボタンではなく、いずれかのボタンをDOWN/UPしたときにある動作をする、というプログラムを考えると、上記の数値の規則性、DOWNは奇数、UPは奇数、を理解しておいた方が、条件分岐を簡潔に書けるメリットはありそうです。
例えば、前後左右に動くロボットをgamepadをリモコンにして動かすとき、いずれかのボタンUPでロボットの動作を止めるとしたいときには、「イベントの値を2で割ったあまり=0なら」(イベントの値が偶数ならば)という条件分岐だけで処理できそうです。

注意事項

JOIZとサーボモーターの組み合わせはメーカーが想定したものでは当然なく、相互に破損のおそれがあります。また、磁気センサー探知のため、小さい磁石を使用していますが、小さい磁石については誤飲事故が報告されています。

編集履歴

2022/07/14 高度なブロック」>「制御」>「…その他」>「MICROBIT_EVT_ANY」のブロックの利用方法について加筆


  1. このSG-90のギザギザを含めて、サーボホーンの3Dプリンタ用のデータを公開している方がいます(【SG-90サーボモーター】サーボホーンの歯を3Dプリンタで再現出来るってすごいですね! | ぶらり@web走り書き)。これを元に、サーボモーターとしっかり噛み合う部品を自作することもできそうです。が、CADの使い方も知らないため(Tinker CADを少し触っている程度)、私にはハードルが高いです。

  2. 標準の無線機能に戻したい場合、拡張機能で"radio"を検索してクリックすると、今度はBluetoothを削除するメッセージが出ますので先に進むと、標準の無線機能に戻すことができます。

micro:bitと電源

目次

micro:bit 本体への電源入力

micro:bitには、次の4種類の方法で電源を供給できますが、通常はJST Ph コネクタとmicro USB用コネクタの2種類を使うため、以下ではこれらを中心に少し詳しく見ていきます。

micro:bitのコネクタ 一般的な電源の種類など
JST Phコネクタ 電池ボックス
micro USB用コネクタ ①PCのUSBポート(急速充電用除く) ②スマホ用充電器(ただし、公式には非推奨)
エッジコネクタ (モジュールや回路からの電源供給用に使われている)
バッテリーパッド (rounded rectangular padやlogenze power padと呼ばれる。テストポイントと位置付けられている。)

なお、ここでは2020年に発売されたmicro:bitV2を前提にしています。V2は、V1.5以下とは異なり、インターフェイスのKL27とは別に、オンボードのレギュレーター(NCP114を使用)があり、JST Ph コネクタとmicro USB用コネクタの2種類の方法による給電はこれにつながるようです(developer communityのHardwareGitHub - microbit-foundation/microbit-v2-hardware: The schematic and Bill of Material for the BBC micro:bit V2を参照)。

JST Ph コネクタ

JST S2B-PH-SM4-TBが使われており(日本圧着端子製造株式会社参照)、ここに1.5V x 2本(3V)のJST Ph コネクタ付電池ボックスをつなぎます。このコネクタで電池数が多い電池ボックスは見当たらないのかもしれませんが、さらに電池を増やしてしまうと、上限電圧を超えるおそれがあります。

電池ボックスは、各種スターターキットに付属しており、単体でもmicro:bit用、などとして発売されています。 バリエーションは単3/4、フタ有/無、スイッチ有/無などですが、JST Phコネクタは抜き差しが硬く(microbit on scratch - Vivite Laeti.)、繋ぎっぱなしで必要な時だけオンにする使い方をしたくなるため、スイッチはあった方が良いです。(なお、micro:bit V2ではリセットボタンを長押しすると電源オフ(OffMode)にすることができるため、繋ぎっぱなしでこの機能を活用することは考えられます。電源オン(OnMode)にするためにはもう一度リセットボタンを押します。)

なお、エネループ等の充電式電池をこのような電池ボックスに入れると1.2V x 2(2.4V)となり、使い捨て乾電池より電圧が低くなります。下限電圧をクリアしているため、micro:bitを単体で動かすことはできるようですが、出力は低くなりますし、お薦めというわけではありません。やはり一般には使いきりの乾電池が想定されています。

micro USB用コネクタ

PC接続(基本)

micro USB用コネクタは、基本的にPCのUSBポートとの接続用であり、5Vの入力は可能とされています。

王道の上記JST Ph コネクタ付の電池ボックスは、他にあまり転用が効かないため、そちらではなく、スマホ用充電器を使いまわせると便利なのですが、これは、公式サイトでは非推奨、又は、供給電圧の確認を要するとされています。micro:bitが耐えられる電圧の上限を超えてしまう可能性があり、また、充電器に自動オフ機能が付いていると微弱な電流のため電源供給を自動停止してしまうおそれがあるためという理由のようです。

Iftinyのマイクロビット (micro:bit) v2の扱い方と注意事項 | iftiny: docsも、以下のとおり警告しています。

micro:bit(マイクロビット)の仕様は 1.8V〜3.6V となっています。 携帯電話等急速充電用途のバッテリーに接続しないでください。出力が高い場合多いため、故障の原因となります。 同じ理由で、PCの急速充電対応USBポートへの接続もしないでください。

乾電池タイプのスマホ用充電器

しかしながら、主要な書籍では、少なくとも、1.5Vx2本の乾電池タイプのスマホ用充電器は、選択肢とされているようです。書籍毎に次のとおりです。

今回は、乾電池タイプを2種類試してみました。

エッジコネクタ・バッテリーパッド

エッジコネクタやバッテリーパッドは、回路に直結しているため、上限電圧(developer communityのPower Supplyによればアプリケーションプロセッサ、インターフェイス、モーションセンサーの上限電圧は3.6V)を超えないようにするなど特に取り扱い注意とされています(以下もdeveloper communityのPower Supplyの引用)。

When powering from the 3V ring or the rounded rectangular pads on the PCB, you should take appropriate best practice precautions:
1. Fit an external protection diode (preferably with a low Vf rating) to prevent damage due to the power supply being connected the wrong way round.
2. If powered from a voltage source that could generate a voltage higher than the maximum operating voltage of the micro:bit, fit some form of over voltage protection, or proper regulation.

micro:bit単体からの電源出力

エッジコネクタからの電源出力は、V2については、3.3V・190mmとされています(厳密には、電池残量や逆流防止用のダイオードによる電圧降下により、この値より低くなり得る)。

5V付近の電圧が必要なアクチュエーター(お馴染みのサーボモーターSG-90など)やセンサーには本来不足するため、①別途、5V外部電源をモーター等にだけ付けるか(これをエッジコネクタに繋がないよう注意)、②拡張基板を使うのが本来のやり方です。

Using a servo with the micro:bit : Help & Support

なお、仕組みをシンプルにするため、定格に満たないことを分かりつつ、エッジコネクタからの出力3.3Vだけで動かすこともあります。例えばSG-90の場合、動作電圧は4.8~5Vとされているにもかかわらず、それで動くこともありますが、特にJST Phコネクタから電池ボックスで給電していると、電池の減りに応じて動きが鈍り、最後は停止するなど、やはり安定しません。LEDテープも同様です(光る刀の作り方(micro:bitの加速度センサーで音と光を制御) - TFabWorks(ティーファブワークス)では、定格未満なので新品の電池を使うようにと注記しています)。

厳密に検証しておらず、また手元にある機器の限りでの感想ですが、このような無理のある使い方をする場合、V2より、V1.5の方が、安定する様に思います。前述のレギュレーターの違いのためかもしれません(出力電流はV2の方が多いのですが)。

拡張基板への電源供給

Ks0360 Keyestudio Sensor Shield V2 for BBC micro:bitは、micro:bitを差し込むことで、本体だけでは接続が難しかったエッジコネクタの入出力端子を引き出して、ジャンパーワイアでの接続を可能にしているだけでなく、引き出したピンに対応するVCC/GND/S の3端子を分かりやすく色分けし、並列しているため、モーターや外部センサーを使いやすく、VCCからの供給電圧も3V/5Vの選択が可能であり、またSPIやI2C、シリアルの接続もできます。
このようにとても取り回しが良いのですが、電源入力が、(1) black DC jack (DC 7-9V) か (2) micro USB port (DC 5V)の2択であり、端子台がないのが玉に瑕です。

この拡張基板の(2)のmicro USBに、 5V で接続できそうなモバイルバッテリーとして、乾電池タイプとリチウムイオンタイプを試しました。

なお、 USB入出力付急速充電器 BQ-CC87L 商品概要 | ニッケル水素電池&充電器 | Panasonicは手に入りやすいのですが、こちらも試したところ、自動オフが働いてしまうためか、短時間しか電源供給されませんでした。

編集履歴

2022/03/19 micro:bit v2 の電源オン・オフ機能の追記。なお、micro:bit v2のパワーモードについては、以下参照。

micro:bitのセンサー

0. はじめに

micro:bit事始めとして、前回・前々回の投稿では、micro:bit単体でセンサーを使った測定と記録を試しました。 vivitelaeti.hatenablog.com vivitelaeti.hatenablog.com

前回・前々回の投稿から1年半以上が過ぎてしまいましたが、その間に発売されたv2も含めて、オンボードのセンサー関連の情報を簡単にまとめておきたいと思います。単体で使えるセンサーのほか、エッジコネクタを通じて外部センサーに接続することもできますが、それはまたどこかでまとめたいです。

1. v1.5のセンサー

micro:bitはセンサーが充実しており、v1.5でも標準で以下が使えるのは魅力的です。

  • 温度(プロセッサーの表面温度)
  • 光 (表示用の5x5のLEDマトリックス兼用)
  • 動き(モーションセンサーLSM303AGR)
  • 磁気(同上)
  • タッチ(エッジコネクタのP0/P1/P2)

2. v2のセンサー

さらに、前回・前々回の投稿後に販売開始されたv2には以下が追加されました。

  • 音 (マイク Knowles SPU0410LR5H-QB-7 MEMS)
  • タッチ(前面ロゴ)

タッチセンサーについては、静電容量方式の前面ロゴでの検出が追加されました。

また、エッジコネクタのP0/P1/P2での検出方法について、v1.5では抵抗膜方式のみでしたが、v2では、抵抗膜方式がデフォルト、静電容量方式への切り替えも可能となっています。

下記はmakecode blogのv2対応版リリース時の解説です(MakeCode for the micro:bit V2 Release)。

Set Pin To Touch Mode - by default, the logo is set to capacitive touch and the edge connector pins (P0, P1, P2) are set to resistive touch. The Set Touch Mode block enables you to change the current touch mode of the Pins and the Logo to either capacitive or resistive.

MicroPythonのウェブサイトにも分かりやすい説明がありましたので引用します(入出力端子 — BBC micro:bit MicroPython 1.1.0-beta.1 ドキュメント)。

エッジコネクタ端子のデフォルトのタッチモードは抵抗膜方式(resistive)です。 V2 のロゴ端子のデフォルトのタッチモードは静電容量方式(capacitive)です。
抵抗膜方式タッチ このタッチは、端子と接地(GND)の間にどれだけの抵抗があるかを測定することによって行われます。抵抗が少ないと True の判定を返します。指での検出を確実にするには、体の別の部分、たとえばもう片方の手で GND 端子に触れる必要があります。
静電容量方式タッチ このタッチは、指を電導体としてキャパシターの電界の変化を捉えることによって行われます。 静電容量方式タッチ は、回路の一部として接地(GND)に接続する必要がありません。

3. センサーの使い方や仕組み

各センサーの働きについては、microbit.orgの「はじめよう」>「センサー」( センサー | micro:bit)が分かりやすいです。

また、micro:bitを例にしながらも、センサーの仕組みまで解説してくれる動画に、makecode.microbit.orgの下の方にある「makecodeハードウェアの裏側」のリストからアクセスできます。英語のみですが面白いです。場所が分かりにくいのでリンクを貼っています(下記は、温度・光・動きについて。これ以外にもありますのでぜひ。)。

www.youtube.com www.youtube.com www.youtube.com

4. 技術面

技術面は、micro:bit developer communityとifinityのウェブサイトを参照。

今回はここまで。次回は、センサー測定のみの作例から少しステップアップして、センサーをトリガーに、何か「動かす」ことについて書いてみます。

編集履歴

2022/10/21 エッジコネクタの検出方式のデフォルトについて、記載訂正