ArduinoとPCを組み合わせたインタラクション作品を作る


今回は、マイコンボードであるArduinoを使ったプログラミングの話の続きです。以前、シリアルポートを用いてArduinoと通信する方法を紹介しましたが、それを応用してセンサーとキャンバス部品を用いたちょっとしたインタラクション作品を作ってみようと思います。

前回の記事では分かりづらい所があったようでご質問をいくつか頂いていましたので、具体的な例を交えてご紹介できればと思います。なお今回もStuduinoを使ってテストしていますが、プログラムはArduino互換機での利用を前提にしているので、そのまま利用できるはずです。必要なセンサー部品などはご用意下さい。

ArduinoとPCとで通信する

Arduinoのセンサーで受け取った値をPCへ送るためには、常にUSBケーブルでArduinoとPCを接続しておく必要があります。Arduinoとは、指定したCOMポートからシリアル通信で情報を送受信できます。Arduino側ではArduino言語でプログラムを作ります。一方、PC側ではプロデルの「シリアル通信」種類を使います。

また、Studuinoのような一部のArduino互換機では、Bluetoothなどを使って無線でシリアル通信が可能なものもあります。この場合もペアリングした上でシリアル通信で情報を送受信する点は同じです。

すべてのセンサーの値を常時受け取る

まずはじめにArduinoに接続したセンサーからの情報をPCへ送るプログラムを作ってみます。センサーから受け取った値をCOMポートを通じてPCの画面上に表示するようにしてみます。

Arduino IDEを起動して、次のようなスケッチを作成します。このプログラムでは、A0からA7までに接続されたセンサーの値を取得した順番にPC側へ100ミリ秒間隔で送信します。各センサーの値は0~255までです。アナログ値で取得するため、値には若干の誤差もあるようです。

void setup(){
  Serial.begin(19200);
}

void loop(){
  if (Serial.available() > 0) {
	int value = Serial.read();
	Serial.write(analogRead(A0));
  	Serial.write(analogRead(A1));
  	Serial.write(analogRead(A2));
  	Serial.write(analogRead(A3));
  	Serial.write(analogRead(A4));
  	Serial.write(analogRead(A5));
  	Serial.write(analogRead(A6));
  	Serial.write(analogRead(A7));
  }
  delay(100);
}

プロデルでは、次のようなプログラムを作ります。実行すると、ArduinoのセンサーポートA0~A7までの測定値が報告されます。

// Arduinoセンサー //
Arduinoポートというシリアル通信を作る
ポート一覧は、Arduinoポートのポート名一覧
もしポート一覧の個数が0なら「接続してください」というエラーを発生させる
Arduinoポートのポート名は、ポート一覧(1)
Arduinoポートのボーレートは、19200
Arduinoポートを開く
Arduinoポートから{1}をバイナリ形式で送信する

タイマー1というタイマーを作る
タイマー1の時間になった時の手順は、時間になった
タイマー1の間隔を100に変える
タイマー1を開始する
待機

Arduinoポートが受信した時の手順
	A0=Arduinoポートから一字だけ受信したもの
	A1=Arduinoポートから一字だけ受信したもの
	A2=Arduinoポートから一字だけ受信したもの
	A3=Arduinoポートから一字だけ受信したもの
	A4=Arduinoポートから一字だけ受信したもの
	A5=Arduinoポートから一字だけ受信したもの
	A6=Arduinoポートから一字だけ受信したもの
	A7=Arduinoポートから一字だけ受信したもの
	Arduinoポートから{1}をバイナリ形式で送信する
終わり
時間になった手順
	「A0:[A0]」を報告する
	「A1:[A1]」を報告する
	「A2:[A2]」を報告する
	「A3:[A3]」を報告する
	「A4:[A4]」を報告する
	「A5:[A5]」を報告する
	「A6:[A6]」を報告する
	「A7:[A7]」を報告する
終わり

なおプログラムをよく見ると、プロデルからも1を送り、Arduinoで受け取っています。これは、プロデルのプログラムが起動していることを示す信号であり、プロデルのプログラムが実行されていない時にはシリアルポートへセンサー値を送信しないように工夫しています。

Studuinoのセンサーを用いたインタラクション

A0~A3センサーボタンを使う

Studuinoの基板には、A0~A3のセンサーとして十字キーのように配置されたボタンがあります。このボタンを十字キーに見立てて、キャンバス部品上の図形を動かすプログラムを作ってみます。Arduinoの場合はA0~A3にボタンスイッチのセンサーを接続して下さい。

Studuino基板のA0~A3のボタン

Studuino基板のボタンを押すと、センサーの値は0となり、それ以外は別の1以上の値になります。そこでまずは、PC上の画面のパネルを4つ配置して、値が0の時は赤、それ以外は白となるようなプログラムを作ってみます。

// 十字ボタン //
メイン画面を表示する
待機する

メイン画面とは
	ウィンドウを継承する
	+Arduinoポート
	はじめの手順
		初期化する
		ーー貼り付けた部品に対する操作をここに書きます
		Arduinoポートというシリアル通信を作る
		ポート一覧は、Arduinoポートのポート名一覧
		もしポート一覧の個数が0なら「接続してください」というエラーを発生させる
		Arduinoポートのポート名は、ポート一覧(1)
		Arduinoポートのボーレートは、19200
		Arduinoポートを開く
		Arduinoポートから{1}をバイナリ形式で送信する

		タイマー1というタイマーを作る
		タイマー1の時間になった時の手順は、時間になった
		タイマー1の間隔を100に変える
		タイマー1を開始する
	終わり
	初期化する手順
	ーー自動生成された手順です。ここにプログラムを書き加えても消える場合があります
	この実質大きさを{409,368}に変える
	この内容を「センサーの取得」に変える
	初期化開始する
	パネル4というパネルを作る
		その位置と大きさを{76,148,69,24}に変える
		その移動順を3に変える
	パネル3というパネルを作る
		その位置と大きさを{76,118,69,24}に変える
		その移動順を2に変える
	パネル2というパネルを作る
		その位置と大きさを{76,88,69,24}に変える
		その移動順を1に変える
	パネル1というパネルを作る
		その位置と大きさを{76,58,69,24}に変える
		その移動順を4に変える
	初期化終了する
	メイン画面の設計スケール比率を{144,144}に変える
終わり

Arduinoポートが受信した時の手順
	A0=Arduinoポートから一字だけ受信したもの
	A1=Arduinoポートから一字だけ受信したもの
	A2=Arduinoポートから一字だけ受信したもの
	A3=Arduinoポートから一字だけ受信したもの
	A4=Arduinoポートから一字だけ受信したもの
	A5=Arduinoポートから一字だけ受信したもの
	A6=Arduinoポートから一字だけ受信したもの
	A7=Arduinoポートから一字だけ受信したもの
	Arduinoポートから{1}をバイナリ形式で送信する
終わり
	時間になった手順
		もしA0が0ならパネル1の背景色は、赤。そうでなければ、パネル1の背景色は、白。
		もしA1が0ならパネル2の背景色は、赤。そうでなければ、パネル2の背景色は、白。
		もしA2が0ならパネル3の背景色は、赤。そうでなければ、パネル3の背景色は、白。
		もしA3が0ならパネル4の背景色は、赤。そうでなければ、パネル4の背景色は、白。
	終わり
終わり

プロデル側の「Arduinoポートが受信した時の手順」では、変数へセンサーの値を入れるだけにして、パネルの色を変える処理は一定間隔で実行されるタイマーで呼ぶようにしておきます。「Arduinoポートが受信した時の手順」で、一度に画面に関する操作を実行させると、アプリを閉じた際にプロデルがフリーズしてしまうので、それを防止するためです。

キャンバス図形と組み合わせる

十字ボタンのプログラムを改良して、キャンバス図形に描いた図形をボタンによって移動させるプログラムを作ってみます。Studinoの基板にあるボタンセンサーを十字ボタンを見立てると、ゲーム用のちょっとしたコントローラとしても扱えます。

なおArduino側のプログラムは変更ありません。直すこと無く書き込み済みのプログラムのまま利用できます。

// Arduino十字ボタンとボール //
メイン画面を表示する
待機する

メイン画面とは
	ウィンドウを継承する
	+Arduinoポート
	はじめの手順
		初期化する
		ーー貼り付けた部品に対する操作をここに書きます
		タイマー1というタイマーを作る
		タイマー1の時間になった時の手順は、時間になった
		タイマー1の間隔を100に変える
		Arduinoポートというシリアル通信を作る
		ポート一覧は、Arduinoポートのポート名一覧
		もしポート一覧の個数が0なら「接続してください」というエラーを発生させる
		Arduinoポートのポート名は、ポート一覧(1)
		Arduinoポートのボーレートは、19200
		Arduinoポートを開く
		Arduinoポートから{1}をバイナリ形式で送信する
		タイマー1を開始する
		キャンバス1へ円を描いてボールとする
			その位置と大きさは、{20,50,50,50}
			その線色をオレンジに変える
			その太さを3に変える
			その背景色を黄色に変える
	終わり
	初期化する手順
	ーー自動生成された手順です。ここにプログラムを書き加えても消える場合があります
	この実質大きさを{409,368}に変える
	この内容を「センサーの取得」に変える
	初期化開始する
	キャンバス1というキャンバスを作る
		その位置と大きさを{0,0,409,368}に変える
		その移動順を5に変える
		そのドッキング方向を「全体」に変える
	初期化終了する
	メイン画面の設計スケール比率を{144,144}に変える
終わり

Arduinoポートが受信した時の手順
	A0=Arduinoポートから一字だけ受信したもの
	A1=Arduinoポートから一字だけ受信したもの
	A2=Arduinoポートから一字だけ受信したもの
	A3=Arduinoポートから一字だけ受信したもの
	A4=Arduinoポートから一字だけ受信したもの
	A5=Arduinoポートから一字だけ受信したもの
	A6=Arduinoポートから一字だけ受信したもの
	A7=Arduinoポートから一字だけ受信したもの
	Arduinoポートから{1}をバイナリ形式で送信する
終わり
	時間になった手順
		もしA0が0なら、ボールの横は、ボールの横+10
		もしA1が0なら、ボールの縦は、ボールの縦-10
		もしA2が0なら、ボールの縦は、ボールの縦+10
		もしA3が0なら、ボールの横は、ボールの横-10
		キャンバス1を更新する
	終わり
終わり

音センサーで音量メーターを作る

続いて、A4ポートに音センサーを付けて、プロデルの画面上に音量メーターを表示するプログラムを作ってみます。Arduinoに接続した音センサーの値をシリアルポートで受けとけ、その値に応じて、キャンバス部品で描いた図形に反映させてみます。

Studuinoの音センサー

メイン画面を表示する
待機する

メイン画面とは
	ウィンドウを継承する
	+Arduinoポート
	はじめの手順
		初期化する
		ーー貼り付けた部品に対する操作をここに書きます
		Arduinoポートというシリアル通信を作る
		ポート一覧は、Arduinoポートのポート名一覧
		もしポート一覧の個数が0なら「Arduinoを接続してください」というエラーを発生させる
		Arduinoポートのポート名は、ポート一覧(1)
		Arduinoポートのボーレートは、19200
		Arduinoポートを開く
		Arduinoポートから{1}をバイナリ形式で送信する

		タイマー1というタイマーを作る
		タイマー1の時間になった時の手順は、時間になった
		タイマー1の間隔を100に変える
		タイマー1を開始する

キャンバス1へ四角形を描いてバーとする
  その位置と大きさは、{100,20,50,100}
  その線色を青に変える
  その太さを3に変える
  その背景色を黄色に変える
	終わり
	初期化する手順
	ーー自動生成された手順です。ここにプログラムを書き加えても消える場合があります
	この実質大きさを{376,330}に変える
	この内容を「音センサー値の取得」に変える
	初期化開始する
	キャンバス1というキャンバスを作る
		その位置と大きさを{0,0,376,330}に変える
		そのドッキング方向を「全体」に変える
	初期化終了する
	この設計スケール比率を{144,144}に変える
終わり

Arduinoポートが受信した時の手順
	A0=Arduinoポートから一字だけ受信したもの
	A1=Arduinoポートから一字だけ受信したもの
	A2=Arduinoポートから一字だけ受信したもの
	A3=Arduinoポートから一字だけ受信したもの
	A4=Arduinoポートから一字だけ受信したもの
	A5=Arduinoポートから一字だけ受信したもの
	A6=Arduinoポートから一字だけ受信したもの
	A7=Arduinoポートから一字だけ受信したもの
	Arduinoポートから{1}をバイナリ形式で送信する
終わり
	+積算量
	+最大高さ=100
	時間になった手順
		積算量を10だけ減らす
		もし積算量が0より小さいなら積算量は、0
		積算量を(A4/255)*最大高さだけ増やす
		もし積算量が最大高さより大きいなら積算量は、最大高さ
		バーの縦を20+(最大高さ-積算量)に変える
		バーの高さを積算量+3に変える
		キャンバス1を更新する
	終わり
終わり

音センサーの前で手を叩いたり、声を吹き込んだりすると、PC側のメーターが上昇します。

Arduinoへコマンドを送ってLEDを光らせる

最後は、逆にPCからArduino側へコマンドを送信して、Arduinoを操作するプログラムを作ってみます。

ここでは、Arduino互換機に共通で実装されている13番ピン(D13)のLEDをPCから制御するプログラムを作ってみます。 PC上の画面でチェックボックスをチェックするとLEDが光り、チェックを外すとLEDが消えるようにしてみます。

D13 LEDの場所(Studuino基板のみの場合)

まずは、プロデルでメイン画面を作り、チェックボタンを1つ貼り付けます。チェックされた時に「on;」を送信して、チェックが外されたときに「off;」を送信するようにします。

メイン画面を表示する
待機する

メイン画面とは
	ウィンドウを継承する
	+Arduinoポート
	はじめの手順
		初期化する
		ーー貼り付けた部品に対する操作をここに書きます
		Arduinoポートというシリアル通信を作る
		ポート一覧は、Arduinoポートのポート名一覧
		もしポート一覧の個数が0なら「接続してください」というエラーを発生させる
		Arduinoポートのポート名は、ポート一覧(1)
		Arduinoポートのボーレートは、19200
		Arduinoポートを開く
	終わり
	初期化する手順
	ーー自動生成された手順です。ここにプログラムを書き加えても消える場合があります
	この実質大きさを{409,368}に変える
	この内容を「センサーの取得」に変える
	初期化開始する
	チェックボックス1というチェックボックスを作る
		その位置と大きさを{91,106,165,38}に変える
		その内容を「チェックボックス1」に変える
	初期化終了する
	メイン画面の設計スケール比率を{144,144}に変える
終わり

チェックボックス1がチェックされた時の手順
もしチェックボックス1のチェックなら
	Arduinoポートから「on;」を送信する
そうでなければ
	Arduinoポートから「off;」を送信する
もし終わり
終わり
終わり

次にArduino側のプログラムです。PCから送られた「on;」と「off;」それぞれに応じて、D13のLEDを点滅させます。

「Serial.readStringUntil()」関数を使うことで、PC側から受信したコマンドを受け取れます。この関数で受け取ったコマンドは「cmd」変数に格納します。なお readStringUntil()では文字列の終わりを示す文字を指定します。ここではコマンド文字列の区切りを「;」で表すことにします。

Arduino言語では文字列に日本語を使えませんので、コマンドはASCII文字(半角英数字)である必要があります。

void setup(){
  Serial.begin(19200);
}

void loop(){
  if (Serial.available() > 0) {
    String cmd = Serial.readStringUntil(';');
    if(cmd=="on") {
      digitalWrite(13, HIGH);
    } else if(cmd=="off") {
      digitalWrite(13, LOW);
    }
  }
  delay(100);
}

loop関数では、if文を使って、onの時はLEDを表示、offの時はLEDを消すためにdigitalWrite関数を呼び出します。

それではArduino IDEでinoプログラムをArduinoへ書き込み、プロデルのプログラムを実行してみましょう。チェックボックスが表示されるので、チェックしてみてください。チェックの状態に応じて基板のLEDが点灯したり消灯したりします。

なおコマンドのバリエーションを増やせば、PCからArduinoの複数のLED部品を操作したり、サーボモーターを制御させることもできます。

Studuinoトランスレータを使う

Arduino側のプログラムをStuduinoトランスレータを使ってプロデル言語で書くことも機能的にはできます。ただしシリアル関連に関する機能が揃っていないため、今後トランスレータのバージョンアップで対応する予定です。また改めて記事に出来ればと思います。

まとめ

今回は、Arduinoのセンサーの値をPCへ送る、またPCからの指示でArduinoの部品を動かすプログラムを作ってみました。Arduinoでは様々な部品を取り付けられ、またプロデルではGUI部品や図形、動画音声などの要素と組み合わせたインタラクションを実現できます。工夫次第でより面白い作品作りが出来るかと思います。

また、プロデルとArduinoやStuduinoを組み合わせた活用例を募集しています。簡単な作品例や写真だけでも構いません。よかったらブログやTwitter、Qiitaなどでご報告頂けると幸いです。

  • 続きを読みたい (3)
  • いいね (3)

コメントを残す