IoT・電子工作

Python × Arduino シリアル通信入門!センサーデータをリアルタイム可視化する方法

「Arduinoでセンサーは動かせるけど、データをパソコンでうまく扱う方法がわからない…」

そんな悩みを持っている方、けっこう多いんじゃないでしょうか。😊

Arduinoは手軽にハードウェアを動かせる最高のツールですが、データの記録・分析・可視化となると、やっぱりPythonの出番です。

今回はArduinoとPythonをシリアル通信でつなげて、センサーのデータをリアルタイムにグラフ表示するところまで、一緒にやってみましょう!

📋 この記事の対象者・難易度

Arduino sensor
Arduino sensor / Photo by Lisha Dunlap via Pexels
  • ✅ Arduinoで「Lチカ」やセンサー読み取りを試したことがある方
  • ✅ Pythonの基本的な書き方がわかる方
  • ✅ ハードウェアとソフトウェアを連携させてみたい方

難易度:★★★☆☆(初中級者向け)

電子工作もPythonも「なんとなくわかる」レベルであれば、十分ついてこられます。ぜひ最後まで読んでみてください!

🔌 シリアル通信ってそもそも何?

まずざっくり説明しておきます。

シリアル通信とは、データを1ビットずつ順番に送受信する通信方式のことです。イメージとしては、「細い一本道をデータが一列になって通る」感じですね。

ArduinoはUSBケーブルでパソコンに接続すると、このシリアルポート(COMポート)を通じてデータをやり取りできます。Arduinoの開発環境(IDE)に「シリアルモニタ」という機能がありますよね。あれがまさにシリアル通信を使っているんです。

Pythonからこのシリアル通信を扱うには、pyserialというライブラリを使います。これがめちゃくちゃ便利で、数行のコードでArduinoとデータをやり取りできるようになります。

🛠️ 必要なものを準備しよう

ハードウェア

  • Arduino(UnoやNanoなど)
  • アナログセンサー(今回は可変抵抗(ポテンショメータ)を使います)
  • USBケーブル
  • ブレッドボード・ジャンパワイヤ

ソフトウェア

  • Arduino IDE
  • Python 3.x
  • pyserial(`pip install pyserial`)
  • matplotlib(`pip install matplotlib`)

pyserialとmatplotlibは事前にインストールしておきましょう。ターミナルで以下を実行すればOKです。

pip install pyserial matplotlib

⚙️ STEP 1:Arduinoのコードを書く

まずはArduino側の準備です。可変抵抗をA0ピンに接続して、アナログ値をシリアルに送り続けるシンプルなスケッチを書きます。

回路は以下のとおりです。

  • 可変抵抗の左端 → 5V
  • 可変抵抗の中央(ワイパー)→ A0
  • 可変抵抗の右端 → GND
// アナログ値をシリアルで送信するArduinoスケッチ

void setup() {
  // シリアル通信を9600bpsで開始
  Serial.begin(9600);
}

void loop() {
  // A0ピンのアナログ値を読み取る(0〜1023)
  int sensorValue = analogRead(A0);

  // 読み取った値をシリアルポートに送信
  Serial.println(sensorValue);

  // 100ミリ秒待つ(10Hz)
  delay(100);
}

ポイントをまとめるとこんな感じです。

  • Serial.begin(9600):通信速度(ボーレート)を9600bpsに設定。Python側と必ず合わせること!
  • analogRead(A0):0〜1023の整数値が返ってくる
  • Serial.println():末尾に改行を付けて送信。Python側で1行ずつ読み取る前提

このスケッチをArduinoに書き込んだら、ArduinoのCOMポート番号を確認しておきましょう。Arduino IDEの「ツール → ポート」で確認できます(例:Windows は `COM3`、Mac/Linux は `/dev/tty.usbmodem…`)。

🐍 STEP 2:Pythonでシリアルデータを受信する

次はPython側です。pyserialを使ってArduinoからデータを受け取ってみましょう。

import serial
import time

# ポート名とボーレートを設定(環境に合わせて変更してください)
PORT = 'COM3'        # Macの場合は '/dev/tty.usbmodem...' など
BAUD_RATE = 9600     # Arduino側と同じ値にすること

# シリアルポートを開く
ser = serial.Serial(PORT, BAUD_RATE, timeout=1)
time.sleep(2)  # Arduino起動を待つ(重要!)

print("データ受信を開始します...")

try:
    for _ in range(20):  # 20回分のデータを受信
        # 1行読み取って文字列に変換
        line = ser.readline().decode('utf-8').strip()

        if line:  # 空行でなければ表示
            value = int(line)
            print(f"センサー値: {value}")

except KeyboardInterrupt:
    print("受信を停止しました")
finally:
    ser.close()  # 必ずポートを閉じる
    print("ポートをクローズしました")

ここが重要です 🎯

  • time.sleep(2):ArduinoはUSB接続時にリセットがかかるため、2秒待たないとゴミデータを拾いやすい
  • decode(‘utf-8’).strip():バイト列を文字列に変換し、改行文字を除去する
  • ser.close():finallyブロックでポートを確実に閉じる。これを忘れると次回接続できなくなることがある

このコードを実行すると、ターミナルにセンサーの値がどんどん表示されるはずです。可変抵抗をくるくる回しながら確認してみてください!

📊 STEP 3:matplotlibでリアルタイムグラフ表示


データが受信できたら、いよいよグラフとして可視化してみましょう。matplotlibの`animation`機能を使うと、リアルタイムに更新されるグラフが作れます。

import serial
import time
import matplotlib.pyplot as plt
import matplotlib.animation as animation
from collections import deque

# 設定
PORT = 'COM3'
BAUD_RATE = 9600
MAX_DATA_POINTS = 100  # グラフに表示するデータ数

# データを保持するキュー(古いデータは自動で削除)
data_queue = deque([0] * MAX_DATA_POINTS, maxlen=MAX_DATA_POINTS)

# シリアルポートを開く
ser = serial.Serial(PORT, BAUD_RATE, timeout=1)
time.sleep(2)

# グラフの初期設定
fig, ax = plt.subplots(figsize=(10, 5))
line, = ax.plot(list(data_queue), color='steelblue', linewidth=2)

ax.set_title('Arduinoセンサーデータ リアルタイムモニタ', fontsize=14)
ax.set_xlabel('経過時間(サンプル数)')
ax.set_ylabel('アナログ値(0〜1023)')
ax.set_ylim(0, 1023)  # Arduinoのアナログ読み取り範囲
ax.grid(True, alpha=0.3)

def update(frame):
    """アニメーション更新関数:新しいデータを読んでグラフを更新"""
    try:
        line_data = ser.readline().decode('utf-8').strip()
        if line_data:
            value = int(line_data)
            data_queue.append(value)  # 新しい値をキューに追加
            line.set_ydata(list(data_queue))  # グラフを更新
    except (ValueError, serial.SerialException):
        pass  # 変換エラーは無視して続行
    return line,

# アニメーション開始(100ミリ秒ごとに更新)
ani = animation.FuncAnimation(
    fig, update, interval=100, blit=True, cache_frame_data=False
)

try:
    plt.tight_layout()
    plt.show()
finally:
    ser.close()
    print("ポートをクローズしました")

ポイントをまとめるとこんな感じです。

  • deque(デック):`maxlen`を指定すると、データが溢れたとき古いものを自動削除してくれる。スライディングウィンドウ表示に最適!
  • FuncAnimation:指定した間隔(`interval`)でupdate関数を繰り返し呼ぶ仕組み
  • blit=True:変更のある部分だけ再描画するので、描画が軽くなる

実行すると、可変抵抗を回すたびにグラフがリアルタイムで動くのが見えます。「むずかしそう」が「できた!」に変わる瞬間ですね 🎉

🔍 うまく動かないときのチェックリスト

詰まりやすいポイントを先にまとめておきます。確認してみてください。

  • COMポート番号は合っている?(Arduino IDEで確認)
  • ボーレートはArduinoとPythonで一致している?(両方9600など)
  • ArduinoのシリアルモニタはOFFになっている?(同時接続はできない)
  • time.sleep(2)を入れている?(起動待ちは意外と重要)
  • Pythonのポートが前回の実行でクローズされている?(ser.close()を忘れずに)

まとめ


今回はPython × Arduino のシリアル通信を使って、センサーデータをリアルタイムでグラフ表示する方法を解説しました。

流れをおさらいするとこんな感じです。

  1. Arduinoで Serial.println() を使ってデータを送信
  2. Pythonの pyserial でデータを受信・文字列に変換
  3. matplotlib の FuncAnimation でリアルタイムグラフ表示

一度この仕組みが理解できると、温度センサー・照度センサー・加速度センサーなど、どんなセンサーにも応用できます。データをCSVに保存したり、異常値を検知してアラートを出したりと、応用範囲は無限大ですよ。😄

ぜひ手元のArduinoで試してみてください。「センサー → Python → グラフ」のパイプラインが動いた瞬間、電子工作の楽しさがひとつ上のステージに上がると思います!

次回は、受信したセンサーデータをCSVファイルに保存してあとから分析する方法も取り上げる予定です。お楽しみに 🚀

📡 Arduinoをもっと深く学ぼう!

Arduino・ラズパイ・ロボットプログラミングを体系的に学びたい方へ。おすすめのUdemyコースや電子部品もまとめています。

Arduinoロボット入門のおすすめコース・部品を見る →

📚 関連商品・おすすめ書籍

スッキリわかるPython入門 第2版 (スッキリわかる入門シリーズ)

もしも

スッキリわかるPython入門 第2版 (スッキリわかる入門シリーズ)

初心者に定番のPython入門書

Amazonで見る

Arduinoをはじめよう 第4版 (Make: PROJECTS)

もしも

Arduinoをはじめよう 第4版 (Make: PROJECTS)

Arduino公式推薦の定番入門書

Amazonで見る

徹底攻略! 電子工作&プログラミング Arduinoで学ぶ電子工作完全ガイド

もしも

徹底攻略! 電子工作&プログラミング Arduinoで学ぶ電子工作完全ガイド

電子工作とプログラミングを同時に学べる

Amazonで見る

※本記事にはアフィリエイトリンクが含まれます。

ABOUT ME
やまちゃん
これまで学生と社会人を合わせて5000人以上にプログラミング学習を指導。 ゼロからイチをわかりやすく解説する専門家として活動しており、本業ではArduinoを用いたIoT開発とロボットプログラミングが専門。 Pythonを用いたアプリ開発、ウェブアプリケーションの開発で業務の効率化をサポートしています。

COMMENT

メールアドレスが公開されることはありません。 が付いている欄は必須項目です