Arduino 資料一覧

ArduinoとProcessingを連携させてシリアルデータをやり取りする

2019/07/24更新

対応バージョン: Arduino IDE 1.8.9 + Processing 3.5.3

Arduinoと母艦のOSとの間でやり取りするシリアルデータに対して母艦側でProcessingを使って制御すると、例えばマウスやタッチパネル式ディスプレイを使ってArduinoを操作したり、逆にArduino側のセンサーで取得したデータの可視化をリッチにしたりすることができる。

ここではProcessingからの入力をArduinoに連携する方法と、Arduinoからの入力をProcessingに連携する方法をそれぞれ簡単なサンプルで示す。

それぞれの開発環境は公式サイトで入手できる。

また言語リファレンスもしっかり整備されている。

Processing → Arduino

まずProcessingからの入力をArduinoに連携する方法を示す。

例としてProcessingでマウスクリックの状態を取得してArduinoの内蔵LEDを点灯/消灯させる簡単なプログラムを書いてみる。

尚、この例ではArduinoボードはUno(Rev3)を使い、シリアルポートは/dev/ttyACM0、通信速度は9600bpsとする。

流れとしてはまずArduinoでシリアルポートから受け取ったデータによってLEDに加える電圧を高くしたり(点灯)、低くしたり(消灯)するプログラムをArduinoに書き込んでおく。

#define led LED_BUILTIN		// 内蔵LED

void setup() {
  Serial.begin(9600);
  pinMode(led, OUTPUT);		// LEDを出力用に
}

void loop() {
  // シリアルポートからデータを受け取ったら
  if (Serial.available() > 0) {

    // 受信したデータを読み込む
    char data = Serial.read();

    // データが'1'ならLED点灯
    if (data == '1') {
      digitalWrite(led, HIGH);
    }

    // データが'0'ならLED消灯
    if (data == '0') {
      digitalWrite(led, LOW);
    }
  }
}

次にProcessingでマウスの左と右のクリックに応じてシリアルポートにデータを送信するプログラムを書いて実行する。

import processing.serial.*;

Serial port;

void setup() {
  size(300, 300);
  port = new Serial(this, "/dev/ttyACM0", 9600);
}

void draw() {
  // マウスの左クリックボタンが押されたらシリアルポートに'1'を送信
  if (mousePressed && (mouseButton == LEFT)) {
    port.write('1');
    println("left");
  }

  // マウスの右クリックボタンが押されたらシリアルポートに'0'を送信
  if (mousePressed && (mouseButton == RIGHT)) {
    port.write('0');
    println("right");
  }
}

これでマウスを左クリックするとArduinoの内蔵LEDが点灯し、右クリックすると消灯する。

CLIで実行したい場合は以下のようにする。

$ tree .
.
├── p2a_a
│   └── p2a_a.ino
└── p2a_p
    └── p2a_p.pde

$ arduino --board arduino:avr:uno --port /dev/ttyACM0 --upload p2a_a/p2a_a.ino

$ processing-java --sketch=$(pwd)/p2a_p --run

Arduino → Processing

今度は逆にArduino側で取得したデータをProcessingに連携する方法を示す。

例としてArduinoに光センサー(CdSセル)を接続し、取得した値をProcessingに連携して可視化する。

流れとしてはまずArduinoで光センサーの値を取得する簡単な回路を作っておく。(CdSセルはGL5528、抵抗は10kΩ)

次にこの回路を使って光センサーから取得したデータをシリアルポートに送信する。

送信するデータは一度に1byte分(0〜255)しか送れないが、光センサーから取得した値は0〜1023なので2bytesに分けて送ってもよいが、作りを簡単にするためにmap()関数を使って0〜255に丸める。このプログラムをArduinoに書き込んでおく。

int val = 0;

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

void loop() {
  // センサーの値を取得
  val = analogRead(0);

  // 一度に送れるデータ(1byte)に変換
  map(val, 0, 1023, 0, 255);

  // シリアルデータ送信
  Serial.write(val);

  delay(50);
}

Processing側ではこの値を取り出して円の直径がリアルタイムに変わるような描画を行う。

import processing.serial.*;

Serial port;

float x;
float y;

int in_data;

void setup() {
  size(300, 300);
  port = new Serial(this, "/dev/ttyACM0", 9600);
  background(0, 0, 0);
}

void draw() {
  // 描画エリア設定
  fill(255, 10);
  noStroke();
  rect(0, 0, width, height);

  // シリアルポートからデータを受け取ったら
  if (port.available() > 0 ) {
    // シリアルデータ受信
    in_data = port.read();

    // 描画
    x = width  / 2 + random(-3, 3);
    y = height / 2 + random(-3, 3);

    noFill();

    stroke(random(255), random(255), 255);

    ellipse(x, y, in_data, in_data);
  }
}

CLIで実行したい場合は以下のようにする。

$ tree .
.
├── a2p_a
│   └── a2p_a.ino
└── a2p_p
    └── a2p_p.pde

$ arduino --board arduino:avr:uno --port /dev/ttyACM0 --upload a2p_a/a2p_a.ino

$ processing-java --sketch=$(pwd)/a2p_p --run

実行結果は以下のようになる。

ArduinoとProcessingの組み合わせでリッチな表現が簡単に実現できるのでインタラクティブコンテンツやメディアアートなどにも応用できる。

参考サイト