Skip to content

第4回 データ処理・micro:bit 連携

Pd でデータを処理する方法を学び、micro:bit のセンサデータを Pd で受信して音に変換する方法をマスターします。

今回のゴール

  • 閾値処理・分岐処理でデータを判定できるようになる
  • micro:bit とPd をシリアル通信(OSC)で接続できるようになる
  • センサデータのマッピング・スムージングができるようになる

Part 1: データ処理

センサから受け取ったデータを「どう判定するか」がインタラクティブ作品の鍵です。ここでは、値の判定に使う基本的なテクニックを学びます。


閾値処理 1: sel, else/above

閾値(しきいち) とは、「ある値を超えたかどうか」を判定する境界値のことです。

sel(select)

sel は入力が指定した値と 一致したとき に bang を出力します。

sel 100
  • 左アウトレット: 値が 100 のとき bang を出力
  • 右アウトレット: 100 以外のとき、その値をそのまま出力

else/above

else/above は入力が指定した値を 超えたとき に bang を出力します。

else/above 50

値が 50 を超えた瞬間に bang が出力されます。

閾値処理1


閾値処理 2: 範囲内の判定

値が 特定の範囲内にあるかどうか を判定するには、2つの比較演算を組み合わせます。

>= 30   (30以上か?)
<= 70   (70以下か?)

両方の条件を &&(AND)で組み合わせると、「30〜70 の範囲内」を判定できます。

閾値処理2: 範囲内


閾値処理 3: change

change は入力値が 変化したとき だけ出力します。同じ値が連続して入力されても、出力しません。

change

センサデータは同じ値が連続することが多いため、change を使って「値が変わったときだけ処理する」ことで、不要な処理を減らせます。

閾値処理3: change


分岐処理 1: sel による分岐

sel に複数の値を指定すると、値に応じた 分岐 ができます。

sel 1 2 3
  • 1番目のアウトレット: 値が 1 のとき bang
  • 2番目のアウトレット: 値が 2 のとき bang
  • 3番目のアウトレット: 値が 3 のとき bang
  • 最後のアウトレット: どれにも一致しないとき、値をそのまま出力

分岐処理1


分岐処理 2: 値の範囲による分岐

値の範囲に応じて異なる処理をする場合は、複数の比較演算を組み合わせます。

例: センサの値を3段階に分ける

  • 0〜30: 「弱い」
  • 31〜70: 「中くらい」
  • 71〜100: 「強い」

分岐処理2: 値の範囲


分岐処理 3: change + 分岐

change と分岐を組み合わせると、「状態が変わったときだけ処理する」パターンが作れます。

例: センサ値が閾値を超えた瞬間に音を鳴らし、下回った瞬間に音を止める。

分岐処理3: change+分岐


データ処理 練習問題

問題1

ナンバーボックスの値が 50 以上 のとき「bang」を出力するパッチを作ってください。

ヒント

>= 50 オブジェクトと sel 1 を組み合わせます。>= 50 は条件が真なら 1、偽なら 0 を出力します。

問題2

V. Radio (縦に並んだスイッチ。クリックすると0~(スイッチの数-1)の値を出力。選択状態で画面右側Optionsからスイッチの数を変更可能)の値に応じて3種類の減衰音(220Hz・440Hz・880Hzで1秒間)を鳴らし分けるパッチを作ってください。

ヒント

V. Radiosel 0 1 2 と接続し、sel 0 1 2の各アウトレットを3種類の減衰音を生成するvline~に接続された各メッセージに接続します。3種類の減衰音は第3回 練習問題6で作成したパッチを参考にしましょう。

問題3

問題2で作成したパッチに対して、V. Radioの値が 変化したとき だけ、3種類の減衰音が再生されるパッチを作ってください。

ヒント

V. Radiochangesel 0 1 2と接続します。


Part 2: micro:bit との連携

micro:bit のセンサデータを Pd に送信し、リアルタイムに音を制御する方法を学びます。


シリアル通信の仕組み

micro:bit と PC は USB ケーブル を通じてシリアル通信でデータをやり取りできます。この授業では、シリアルデータを OSC(Open Sound Control) というプロトコルに変換して Pd に送ります。

データの流れ:

micro:bit → USB(シリアル通信)→ SerialOSCConverter → OSC → Pd

OSC とは

OSC(Open Sound Control) は、音楽・メディアアート用に設計された通信プロトコルです。

  • ネットワーク(UDP)を使ってデータを送受信する
  • アドレスパターン(例: /microbit/accelerometer/x)でデータを識別する
  • 数値、文字列などのデータを送れる

SerialOSCConverter の使い方

SerialOSCConverter は、micro:bit のシリアルデータを OSC に変換するアプリケーションです。

起動手順

  1. SerialOSCConverter を起動する
  2. micro:bit を USB ケーブルで PC に接続する
  3. SerialOSCConverter の画面で:
    • Serial Port: micro:bit が接続されているポートを選択する
    • Baud Rate: 115200 を選択する(micro:bit のデフォルト)
    • OSC Port: 8000(デフォルト)を確認する
  4. Connect ボタンをクリックする
  5. micro:bit からデータが届くと、画面にデータが表示される

ポートが見つからない場合

  • micro:bit が正しく USB 接続されているか確認する
  • USB ケーブルがデータ転送対応か確認する(充電専用ケーブルではデータ転送できません)
  • ドライバが必要な場合はインストールする

MakeCode 側の設定

micro:bit のプログラムで シリアル通信 を使ってデータを送信する必要があります。MakeCode の「シリアル通信」カテゴリから「シリアル通信で値を送る」ブロックを使います。


OSC データの受信

Pd で OSC データを受信するには、else ライブラリの osc.receiveosc.route を使います。

手順

  1. else/osc.receive 8000 を配置する(ポート 8000 で受信)
  2. else/osc.route /x /brightness /volume を配置する
  3. osc.route の各アウトレットからセンサデータが出力される

OSC データの受信

トリガーメッセージの送受信

ボタンが押されたときなどの トリガー(瞬間的なイベント) も OSC で送受信できます。

  • micro:bit 側: ボタンAが押されたとき シリアル通信 文字列を書き出す "/ButtonA"シリアル通信 1行書き出す "1"とシリアル送信する
  • Pd 側: osc.route/ButtonA をルーティングして bang として受け取る

センサデータのマッピング

micro:bit のセンサ値(例: 加速度 -1024〜1024)を、Pd で使いたい範囲(例: 周波数 200〜2000 Hz)に変換する必要があります。

cyclone/scale

cyclone/scale は値の範囲を別の範囲にマッピング(変換)します。

cyclone/scale -1024 1024 200 2000
  • 入力範囲: -1024 〜 1024
  • 出力範囲: 200 〜 2000

入力値 0 → 出力値 1100(中間値)

スケールマッピング


クリップ(値の制限)

センサデータは想定外の値が出ることがあります。clipmaxmin を使って値の範囲を制限します。

オブジェクト機能
clip 0 100値を 0〜100 の範囲に制限する
max 0値が 0 未満なら 0 にする(下限)
min 100値が 100 を超えたら 100 にする(上限)

max / min の名前に注意

Pd の max は「最小値を制限する」(下限を設定する)オブジェクトで、min は「最大値を制限する」(上限を設定する)オブジェクトです。一般的な意味と逆に感じるかもしれませんが、「出力の最大値は少なくともこの値」(max)、「出力の最小値は多くともこの値」(min)と覚えましょう。

クリップ


平滑化処理(スムージング)

センサデータは ノイズ(細かな揺れ)を含むため、そのまま使うとガタガタした制御になります。平滑化(スムージング) で値の変化を滑らかにします。

方法1: lop~ でシグナルを平滑化

lop~(ローパスフィルタ)はシグナルの高周波成分を除去するため、結果的に値が滑らかになります。

sig~ → lop~ 5 → snapshot~

カットオフ周波数を低くするほど(例: lop~ 1)滑らかになりますが、反応が遅くなります。

lop~ による平滑化

方法2: else/smooth~

else/smooth~ は平滑化に特化したオブジェクトです。

else/smooth~ 50

引数の値が大きいほど滑らかになります。

smooth~ + s2f~ による平滑化

else/s2f~ — シグナルを値に戻す

平滑化した結果はシグナル(~)のままなので、値(メッセージ)を受け取るオブジェクトに渡すには再び値に変換する必要があります。else/s2f~ を使うと、snapshot~ + metro の組み合わせよりシンプルに値化できます。

平滑化の度合い

平滑化が強すぎると反応が鈍くなり、弱すぎるとノイズが残ります。作品の特性に合わせて調整してください。


【発展】変化量の検出

値そのものではなく、値の 変化量(どれだけ急に変わったか)を検出すると、「素早く動かした」「ゆっくり動かした」といった動きの質を判定できます。

方法

  1. 現在の値と1つ前の値の差分を計算する
  2. 差分の絶対値が閾値を超えたら「急な変化」と判定する

変化量の検出

応用例

  • 加速度の変化量が大きい → 打楽器のように短い音を鳴らす
  • 変化量が小さい → 弦楽器のように持続音を出す
  • 変化の方向(正/負)で異なる効果を与える

micro:bit 連携 練習問題

問題1

micro:bit の A, B ボタンを押したらそれぞれ /buttonA/buttonB というアドレスに 0/1(0: 押されていない, 1: 押されている)を送信する micro:bit プログラムと、受信する Pd パッチを作ってください。

ヒント

MakeCode でボタンA,ボタンBという変数を用意します。そして、「ずっと」ブロックの冒頭に、もし ボタン A が押されている なら 変数 ボタンA を 1 にする でなければ 変数 ボタンA を 0 にする というブロックを作成します。ボタンBも同様に作成します。 その下に、シリアル通信 文字列を書き出す "/ButtonA"シリアル通信 1行書き出す ボタンAというブロックを作成し、ボタンBも同様に作ります。Pd 側は else/osc.receive 8000else/osc.route /buttonA /buttonB → ナンバーボックス(左と中央の2箇所) と接続します。

問題2

micro:bit の A, B ボタンを押したらそれぞれ 500 Hz, 1000 Hz で正弦波を再生し続ける機能を作ってください。

ヒント

osc.route /buttonA /buttonBsel 1 でボタンが押された瞬間(値が 1 のとき)に bang を出力し、それぞれの周波数をメッセージで osc~ に送ります。ただ、このままだとA, Bを押しっぱなしにした際の挙動が安定しないため、sel 1 の直前にchange を入れることでボタンの状態に変化があった時のみosc~ に周波数を送る形にします。

問題3

四則演算を用いて明るさセンサの最大・最小値が概ね 0〜100 の値になるように変換した数値を表示してください。

ヒント

明るさセンサの値は 0〜255 です。/ 255* 100 の順で接続すると 0〜100 に変換できます(expr $f1 / 255 * 100 でもOK)。ただし、現実の環境では255の値を取ることはないため、実際の環境下での明るさの最大値で割り、100をかけると良いでしょう。

問題4

scaleclip を用いて明るさセンサの最大・最小値が必ず 0〜100 の値になるように変換した数値を表示してください。

ヒント

cyclone/scale (実際のセンサデータの下限値) (実際のセンサデータの下限値) 0 100 でマッピングし、clip 0 100 で範囲を確実に制限します。

問題5

明るさセンサの値を適切に変換し、周波数が変化するテルミンを作成してください。

ヒント

明るさセンサの値を cyclone/scale で適切な周波数範囲(例: 200〜2000 Hz)にマッピングし、osc~ の周波数インレットに接続します。

問題6

スマホのライトを当てると 0 より大きい値になり、当てないと常に 0 の値が表示されるよう(ライトを当てていない時の明るさを 0、当てた時の明るさを 100)に変換してください。

ヒント

cyclone/scale (ライトなしのセンサ値) (ライトありのセンサ値) 0 100 でマッピングします。

問題7

  1. で作成した機能を用いて、micro:bit にスマホのライトを当てると 1000 Hz の正弦波を 1 秒間減衰して再生する機能を作ってください。
ヒント

問題6の出力を > 0sel 1 で bang に変換します。bang → vline~ のエンベロープ(例: 1 0, 0 1000 0)→ *~output~ で減衰音を鳴らします。第3回の練習問題6で作成した減衰音のパッチも参考にしましょう。


【発展】練習問題

発展1

音センサの値を変換し、micro:bit の近くで手を叩いたら 0 より大きい値になり、叩かないと常に 0 の値が表示されるようにしてください。

ヒント

cyclone/scale (叩かない時の音センサ値) (叩いたときのセンサ値) 0 100 でマッピングし、clip 0 100 で範囲を確実に0-100 に制限します。

発展2

  1. で作成したパッチを用いて、手を叩いたら 1000 Hz の正弦波を 1 秒間減衰して再生する機能を作ってください。
ヒント

発展1の出力を > 0sel 1 で bang に変換し、bang → vline~ エンベロープ(例: 1 0, 0 1000 0)→ *~output~ の流れで 1000 Hz の減衰音を鳴らします。

発展3

練習問題2. で作成したパッチに対して、切り替えた際の周波数変化が緩やかになる(だんだん音が高くなる/低くなる)よう平滑化処理を追加してください。

ヒント

周波数の値を else/smooth~ で処理してから osc~ に接続します。else/smooth~ の引数を大きくするほど変化が緩やかになります。

発展4

ホワイトノイズを生成した状態で、音センサの大きさに応じてローパスフィルタのカットオフ周波数が大きくなるよう変化させてください。さらに、音の変化が自然になるようにセンサの値に対して適度なマッピングと平滑化処理を追加してください。

ヒント

noise~lop~output~ と接続します。音センサの値を cyclone/scale で適切な周波数範囲(例: 200〜5000 Hz)にマッピングし、else/smooth~ で平滑化してから lop~ の右インレットに接続します。