2学期開始!体験授業 受付中 →
ROBO SCIENCE

Processing のはじめ方 ―
マイコンの値を、絵にする

2026.10.30
R3 PE(Pre-expert) ES(Expert-soccer) ER(Expert-rescue)
MacBook の画面に Processing のプログラムと、針の出た窓。手前の手が、ブレッドボードに載せたセンサーを持っている
Processing で描いた針。手に持ったセンサーを回すと、同じように回る。

センサーの値を眺めていても、何が起きているかはなかなかつかめません。Processing を使うと、マイコンから送られてくる値を、そのまま絵にできます。

Processing とは ― Arduino IDE の絵を描く版

Processing は、絵を描くためのプログラミング環境です。画面は Arduino IDE によく似ています。

似ているのは偶然ではありません。Arduino IDE は Processing から生まれました。だから書き方もほとんど同じで、違うのは「どこで動くか」です。

Arduino IDEProcessing
動く場所マイコンの上パソコンの上
得意なことセンサーを読む、モーターを回す絵を描く、音を出す
言語C++Java(書き方はほぼ同じ)

ダウンロードして入れる

無料です。processing.org から、自分のパソコンに合うものを選びます。

インストーラーはありません。ダウンロードしたものを開いて、中の Processing を好きな場所へ置くだけです。Mac なら「アプリケーション」フォルダへ、Windows なら解凍してできたフォルダを、そのまま置きます。

はじめて起動すると、書いたプログラムを置く場所(書類の中の Processing フォルダ)が自動で作られます。

最初の1枚 ― 数行で円を描く

新しいスケッチに、これを貼ります。

void setup() {
  size(640, 480);          // 窓の大きさ
}

void draw() {
  background(250);         // ぬりつぶす
  ellipse(320, 240, 100, 100);   // 円
}

▶ を押すと別の窓が開き、まん中に円が出ます。止めるときは ■ です。

setup と draw ― Arduino の setup と loop

Arduino を書いたことがあれば、覚えることは1つだけです。

ArduinoProcessingいつ動くか
setup()setup()最初に1回だけ
loop()draw()繰り返す(1秒に60回)

loop() が draw() になっただけと思えば、だいたい合っています。

background() は、窓を一色でぬりつぶす命令です。draw() の先頭に置くことで、前の絵が消えます。置かないと、描いたものが残り続けます。消さないでおくと通った跡が線になって残るので、わざと置かないこともあります。

画面の座標 ― 下に行くほど y が大きい

ここが、はじめに引っかかるところです。

(0, 0) x が増える y が増える (240, 95) 窓の中
原点は左上。y は下に行くほど大きくなる。数学のグラフと上下が逆。

数学のグラフは上がプラスですが、画面は下がプラスです。だから「真上に140の線を引く」は、マイナスで書きます。

line(0, 0, 0, -140);   // 真上に140伸ばす

覚える命令は、これだけで足ります

描く
size(640, 480)窓の大きさ。setup() の一番最初に書く
background(250)ぬりつぶす(=消す)
ellipse(x, y, 幅, 高さ)円
rect(x, y, 幅, 高さ)四角
line(x1, y1, x2, y2)線
text("あ", x, y)文字
色
fill(255, 0, 0)中の色(赤・緑・青を 0〜255 で)
stroke(0)線の色
strokeWeight(4)線の太さ
noFill() / noStroke()中を塗らない/線を描かない

数字を1つだけ書くと灰色の濃さになります。fill(0) が黒、fill(255) が白です。

絵を回す ― 紙のほうを回す

針やメーターを描くときに使います。考え方はひとつだけです。ペンを斜めに動かすのではなく、紙を回してからまっすぐ引きます。

pushMatrix();              // ① しおりを挟む
translate(320, 200);       // ② 原点をここへ動かす
rotate(radians(30));       // ③ 紙を30度まわす
line(0, 0, 0, -140);       // ④ まっすぐ線を引くだけ
popMatrix();               // ⑤ しおりの場所へ戻す

④の線はいつも「まっすぐ上」でよく、傾きは③が作ります。

⑤を忘れると、次に描くものまで全部傾きます。pushMatrix() と popMatrix() は、かならず対で書きます。

rotate() は度ではなくラジアンで受け取るので、radians() で変換します。

マイコンとつなぐ ― シリアル

ここからが本題です。マイコン側は、1行に1つ、値を送るだけにしておきます。

void loop() {
  Serial.println(値);   // 1行に1つ
  delay(20);
}

Processing 側は、こう受け取ります。

import processing.serial.*;      // 最初に1行

Serial port;
float value = 0;

// マイコンのポートを「名前」で探す
String findBoard() {
  String[] list = Serial.list();
  printArray(list);              // 一覧を下の欄に出す
  for (int i = 0; i < list.length; i++) {
    if (list[i].contains("usbmodem")) return list[i];
  }
  return null;
}

void setup() {
  size(640, 480);
  String name = findBoard();
  if (name == null) { println("見つかりません"); return; }
  port = new Serial(this, name, 115200);
  port.bufferUntil('\n');        // 改行まで待ってから知らせて、と頼む
}

void serialEvent(Serial p) {     // 1行届くたびに呼ばれる
  String raw = p.readStringUntil('\n');
  if (raw == null) return;
  float v = float(trim(raw));
  if (Float.isNaN(v)) return;    // 数字でない行は捨てる
  value = v;
}

作例では Serial.list()[0]、つまり「ポートの1番目」と書かれていることが多くあります。ところが1番目がマイコンとはかぎりません。Bluetooth の機器や別のマイコンが先に並ぶことがあります。そこで名前に usbmodem を含むものを探しています。

serialEvent() は、1行届くたびに自動で呼ばれる場所です。draw() とは別に動くので、ここでは値を受け取るだけにして、絵は draw() で描きます。

数字でない行は捨てています。マイコンが起動時にメッセージを出しても、これで無視できます。

作ってみる ― ジャイロの向きを針で表す

ここまでの道具だけで、実際に使えるものが作れます。ジャイロセンサーの向きを、時計の針のように表すものです。数字を眺めていても、ずれていく様子はなかなかつかめません。

マイコン側は、ジャイロセンサーの記事のプログラムのままです。1行に1つ、角度を送ります。

Processing 側は、受け取った角度で針を回し、同時に記録を線で残します。

import processing.serial.*;

Serial port;
boolean connected = false;      // つながったか
int     rx    = 0;              // 受け取った行数
float heading = 0;              // 届いた角度
float zero    = 0;              // 0 とみなす向き
float[] trail = new float[600]; // ずれの記録
int    head   = 0;

// マイコンのポートを「名前」で探す。番号で決め打ちしない
String findBoard() {
  String[] list = Serial.list();
  printArray(list);                      // 一覧を下の欄に出す
  for (int i = 0; i < list.length; i++) {
    if (list[i].contains("cu.usbmodem")) return list[i];
  }
  for (int i = 0; i < list.length; i++) {
    if (list[i].contains("usbmodem")) return list[i];
  }
  return null;
}

void setup() {
  size(680, 520);
  String name = findBoard();
  if (name == null) return;              // 見つからない。draw() が知らせる
  println("使うポート: " + name);
  port = new Serial(this, name, 115200);
  port.bufferUntil('\n');
  connected = true;
}

void draw() {
  background(250);

  if (!connected) {
    fill(200, 60, 40);
    textSize(17);
    text("マイコンが見つかりません。", 24, 60);
    fill(90);
    textSize(14);
    text("・USB を挿す\n・Arduino IDE のシリアルモニタを閉じる\n・▶ を押し直す", 24, 95);
    return;
  }

  float h = wrap(heading - zero);

  // ---- 方位の針 ----
  pushMatrix();
  translate(width/2, 200);
  noFill();
  stroke(215);
  strokeWeight(1);
  ellipse(0, 0, 300, 300);
  line(0, -165, 0, -140);        // 正面の目印
  rotate(radians(h));
  stroke(30);
  strokeWeight(4);
  line(0, 0, 0, -140);
  popMatrix();

  // ---- 数字 ----
  fill(30);
  noStroke();
  textSize(30);
  text(nf(h, 0, 1) + "°", 24, 46);
  fill(130);
  textSize(13);
  text("c キー … いまの向きを 0 にする", 24, 72);
  text("受信 " + rx + " 行", 24, 92);

  // ---- ずれの記録 ----
  stroke(225);
  line(24, 420, width - 24, 420);
  noFill();
  stroke(215, 95, 35);
  strokeWeight(2);
  beginShape();
  for (int i = 0; i < trail.length; i++) {
    int k = (head + i) % trail.length;
    vertex(map(i, 0, trail.length, 24, width - 24), 420 - trail[k] * 1.5);
  }
  endShape();
  fill(130);
  noStroke();
  textSize(12);
  text("静止させたまま、この線が傾いていけばドリフト", 24, 462);
}

float wrap(float d) {
  while (d >  180) d -= 360;
  while (d < -180) d += 360;
  return d;
}

void serialEvent(Serial p) {
  String raw = p.readStringUntil('\n');
  if (raw == null) return;
  String s = trim(raw);
  if (s.length() == 0) return;
  float v = float(s);
  if (Float.isNaN(v)) return;   // 数字でない行は捨てる
  heading = v;
  rx++;
  trail[head] = wrap(heading - zero);
  head = (head + 1) % trail.length;
}

void keyPressed() {
  if (key == 'c') {
    zero = heading;
    for (int i = 0; i < trail.length; i++) trail[i] = 0;
  }
}

動かすと、こうなります。

基板を手で回すと、画面の針がついてくる。下の線は、通った跡。

ポートを番号ではなく名前で探しているのと、受信した行数を画面に出しているのには理由があります。前者は前の項のとおりで、後者は切り分けのためです。針が動かないとき、原因が「マイコンが送っていない」のか「受け取り方が違う」のかを、ここで切り分けられます。0 行のままならマイコン側、数字が増えるのに針が止まっていれば Processing 側です。

センサーを机に置いて、動かさずにおいてみます。BNO055 なら、針も下の線もほとんど動きません。止まっているあいだに、センサーが自分でバイアスを引いているからです。

ずれを見たいときは、止めずに回し続けてから、はじめの向きに戻します。針が 0 に帰ってこなければ、そのぶんがずれです。

ロボサイエンスでは、こうして部品の素の性質を測ってから、プログラムの設計を決めます。どのくらいずれるのかを知らないと、ハーフの10分を持たせられるのかどうかも決められません。

センサーの側の話は ジャイロセンサー BNO055 と BNO055 のキャリブレーション にあります。

動かないときに見るところ

症状見るところ
ポートが開けないArduino IDE のシリアルモニタを閉じる。シリアルポートは1つのプログラムしか開けません
絵が線だらけになるbackground() を draw() の先頭に書いているか
何も届かない先に Arduino IDE のシリアルモニタで、値が流れているか確かめる
上下が逆に動くy は下がプラス
size() でエラーsetup() の一番最初に書く

いちばん多いのは1つめです。Arduino IDE でマイコンの様子を見たあと、閉じずに Processing を動かすと、ここで止まります。

「何も届かない」ときは、Processing を疑う前にマイコンを確かめます。Arduino IDE のシリアルモニタに値が流れていなければ、原因はマイコン側です。

ロボサイエンスについて

ロボカップジュニア2027 に向けて、レスキュー(災害救助)とサッカーの2種目に取り組みます。プログラミングと電子工作の経験は問いません。

ロボサイエンスのコース紹介 →
これまでの大会成績 →
体験授業・お問い合わせ →

← ロボサイエンスの記録一覧へ戻る