ArduinoとProcessingでスイッチ製作

お久しぶりです。今回はArduinoとPCを通信させてデータの受け渡しをさせてみようと思います。

使用するものは次の2つ

Arduino側は何秒かに1回文字列を送るプログラムを組んでもよかったのですが、今回は前回の記事で作ったスイッチ用のスケッチを使おうと思います。

Arduino用のスイッチの回路の作り方は難しくないので過去記事もご一読ください。一般的なタクトスイッチ用にソースコードを書き換える箇所の説明もpart3で紹介しています。

動作の仕様(Arduino側)

  1. スイッチを押す
  2. 数値の1がArduinoからPCにシリアル通信を使って送信される

動作の仕様(Processing側)

  1. 特定のポート(通信用の門のようなもの)をProcessingで監視
  2. シリアル通信が発生する(Arduinoから文字列が送られてくる)とProcessingのserialEvent()関数を読み込み何かしらのアクションを起こす

前回記事で紹介したArduinoのスケッチを次に挙げておきます

int state = 0;

void setup() {
  pinMode(2,INPUT);
  Serial.begin(115200);
}

void loop() {
  if(digitalRead(2) == HIGH && state == 0){
    delay(100);
    Serial.write("1");
    state = 1;
  }
  else if(digitalRead(2) == LOW && state == 1){
    delay(100);
    state = 0;
  }
}

スイッチが押されると、Serial.write()関数で”1″を送信していることが分かります。

次にProcessing側のコードを見てみます

import processing.serial.*;
Serial ser;
int state = 0;

void setup() {
  ser = new Serial(this, "yourCOMport", 115200);
}

void draw() {
  if (state == 1) {
  //何かの処理
  }
}


void serialEvent(Serial port) {
  println(port.read());
  if (state == 0) { 
    state = 1;
  } else {
    state = 0;
  }
}

Processing側のserialEvent()関数がシリアル通信を監視する関数です。スイッチを押されるたびに状態を示すstate変数が1,0,1,0,1,…と順番に切り替わってい行きます。

そして、draw()関数の中のif文state=1のとき(もしくはstate=0のとき)の動作を記述しておけば、スイッチを押すたびにProcessingがdraw()関数内のif文の中の処理を行ってくれます。

ソースコードはざっとこんなものですが、忘れてはいけないポイントがいくつかあるのでまとめておきます。

  • processing.serial.*のインポート
import processing.serial.*;

上の記述を忘れてはいけません。シリアル通信用の関数を読み込むことができなくなります。

  • yourCOMportの設定
ser = new Serial(this, "yourCOMport", 115200);

シリアル通信を扱える構造体を宣言する(Serialクラスのインスタンスを作成する)時に2つめの引数である”yourCOMport”の部分はシリアル通信に使うポートを指定してやる必要があります。

ここで指定したポートをProcessingで監視するため、異なるポートを指定すると通信ができなくなります。

今回シリアル通信に使っているポートとはつまりArduinoが刺さっているUSBの差込口のことです。

Windowsならばコマンドプロンプト、Macならターミナルでポートを確認する方法があるのですが、私はいつもArduino IDEを起動してポートを確認しています(Arduinoにスケッチをアップロードするときに設定するCOM5とか書いてあるアレです)。

以前はポートの名前は”dev.tty~なんたらかんたら”みたいなのを書いていたのですが単純に”COM~”と書くだけでいいみたいです。

ちなみに私は”COM10″に接続したので、私の環境だとこう書けますね。

ser = new Serial(this, "COM10", 115200);
  • 通信速度を合わせる

Processing側

ser = new Serial(this, "yourCOMport", 115200);

3つめの引数に115200という数値が入っています。これは通信速度を表しています(正確にはBaudRate:ボーレート)。送信側の速度と受信側の速度を通信ができていても文字列を正確に読み取ることができなくなります。

今回Processingは受信側で通信速度115200bpsに設定しています。

Arduino側

Serial.begin(115200);

送信側となるArduinoの通信速度はsetup()関数内のSerial.begin()関数の引数で指定します。よく分からないまま習慣的に9600bpsで指定している人もいると思うので気を付けてください。

基本的にはこの部分を抑えておけばArduinoとPC(Processing)で通信ができます。

 

雑記1

ちなみに今回のサンプルスケッチでは実は通信速度の設定を間違えていても動作します。Processing内のserialEvent()関数は指定されたポートでシリアル通信が行われたときに実行される関数なのでデータの中身が読み取れなくても何かしら通信が行われると実行されます。

今回は1ボタンしかなく、ON/OFFの判別さえできればよいため通信の中身まで読み取る必要はありませんが、もしも、ゲームのコントローラーなど2つ以上のボタンを持つ機器を今回紹介した方法でArduinoで作るときは設定しないといけません。

 

雑記2

あと気になったのは、Arduinoで送信した文字列をProcessingでPrintしてみると”1″を送ったはずなのに、うろ覚えですがたしか”49″を受け取ってしまうところですね。

”0”を送信すると”48″、”1″を送信すると”49″という風に規則的にずれているため一つ一つ確認しつつ処理していけば大した問題ではないのですが、うっかり忘れるなんてこともあるので気を付ける必要があります。

原因についてはきちんと確かめていませんが、文字列として”1″を送っているはずなのに勝手にint型にキャストされているような気がします。

たしか、数値以外の文字列(アルファベット)ならこのようなことが起きていなかったような気がしたのですが…(うろ覚え)。とりあえず確認する必要がありそうです。

 

雑記3

今回紹介したArduino用スケッチは通信をする部分以外にもいろいろ余分なものがあったので単純に動作するものも作成しました。

1秒ごとに文字列の”ON”と”OFF”を交互に送るというスケッチです。

このスケッチはもともと、”ON”と”OFF”の部分は”1″と”0″だったのですが雑記2で書いたこともあり少し修正しました。

雑記2で書いた部分の検証ができれば、また補足を書きたいと思います。

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

void loop() {
    Serial.write("ON");
    delay(1000);
    Serial.write("OFF");
    delay(1000);
}

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Scroll to top