IoT・電子工作

PythonとArduinoで作るリアルタイムデータ可視化ダッシュボード!センサーデータをグラフ表示する方法

「Arduinoで取ったセンサーデータ、数字だけじゃなくてグラフで見たい!」

そう思ったことはありませんか?😊

Arduinoで温度や湿度、照度などのデータを取れるようになったのはいいけれど、シリアルモニタに流れる数字を眺めているだけでは、なんとなくもったいない感じがしますよね。

実は、PythonとArduinoを組み合わせるだけで、リアルタイムにデータが更新されるダッシュボードを比較的かんたんに作ることができます。しかも、専用のサーバーやクラウドサービスは不要。手元のPCだけで完結します。

今回は、ArduinoからPythonへシリアル通信でデータを送り、それをリアルタイムでグラフ表示する仕組みをゼロから作っていきます。電子工作とアプリ開発が”つながる”瞬間、ぜひ一緒に体験してみてください!

📋 この記事でできるようになること

Arduino sensors dashboard
Arduino sensors dashboard / Photo by Lisha Dunlap via Pexels
  • ArduinoからPCへシリアル通信でデータを送る
  • PythonでArduinoのデータをリアルタイムに受信する
  • MatplotlibでリアルタイムグラフをPC上に表示する
  • Dashライブラリを使ってブラウザ上のダッシュボードを作る

対象読者・難易度

  • ✅ Arduinoを触ったことがある方(センサーの読み取りができる程度)
  • ✅ Pythonの基本文法がわかる方(ループ・関数・ライブラリのインポートができる程度)
  • 🔰 難易度:初級〜中級

「むずかしそう」を「できそう」に変えるのが目標です。一緒に進めていきましょう!

🔧 必要なもの(事前準備)

まず、手元に以下が揃っているか確認しておきましょう。

ハード・ソフトウェア

  • Arduino(Uno / Nano / Mega など何でもOK)
  • センサー(今回は温度センサー DHT11 を使用)
  • USBケーブル(ArduinoとPCをつなぐもの)
  • Arduino IDE(スケッチの書き込みに使用)
  • Python 3.8以上

Pythonライブラリのインストール

以下のコマンドでまとめてインストールしておきましょう。

pip install pyserial matplotlib dash plotly

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

  • pyserial:PythonからArduinoのシリアルポートに接続するために必須
  • matplotlib:Pythonの定番グラフ描画ライブラリ
  • dash / plotly:ブラウザベースのインタラクティブダッシュボードを作るライブラリ

STEP 1:ArduinoからセンサーデータをPCへ送る

まずArduino側の準備です。DHT11センサーで温度と湿度を取得して、シリアル通信でPCへ送り続けるシンプルなスケッチを書きます。

イメージとしては、Arduinoが「体温計」役で、1秒ごとに測定結果をPCへ報告し続けるような感じです。

// Arduino スケッチ:DHT11センサーのデータをシリアル送信する
#include <DHT.h>

#define DHTPIN 2      // DHT11を接続するデジタルピン番号
#define DHTTYPE DHT11 // センサーの種類を指定

DHT dht(DHTPIN, DHTTYPE);

void setup() {
  Serial.begin(9600); // シリアル通信を9600bpsで開始
  dht.begin();        // DHT11センサーを初期化
}

void loop() {
  delay(1000); // 1秒ごとに計測

  float humidity    = dht.readHumidity();    // 湿度を取得
  float temperature = dht.readTemperature(); // 温度を取得(℃)

  // センサーのエラーチェック
  if (isnan(humidity) || isnan(temperature)) {
    Serial.println("ERROR"); // 読み取り失敗時はERRORと送信
    return;
  }

  // 「温度,湿度」の形式でCSV送信
  Serial.print(temperature);
  Serial.print(",");
  Serial.println(humidity);
}

ここが重要です👇

  • データを 「温度,湿度」のCSV形式(カンマ区切り)で送っています。Python側でパースしやすくするためです
  • DHT.hライブラリはArduino IDEのライブラリマネージャーから「DHT sensor library」を検索してインストールしてください
  • 送信速度(ボーレート)は 9600 に統一。Python側と必ず合わせましょう

スケッチを書き込んだら、Arduino IDEのシリアルモニタを開いて「25.50,60.20」のような数字が流れてくればOKです!✅

STEP 2:PythonでArduinoのデータを受信する

次はPython側です。pyserialライブラリを使ってArduinoに接続し、データを受け取ります。

まず、Arduinoが接続されているポートを確認しておきましょう。

  • Windows:デバイスマネージャーで「COM3」や「COM4」など
  • Mac / Linux:/dev/tty.usbmodem〇〇〇〇/dev/ttyUSB0 など
import serial
import time

# --- 設定 ---
PORT = 'COM3'      # ← 自分の環境に合わせて変更してください
BAUD_RATE = 9600   # Arduino側と同じボーレートを指定

# シリアルポートに接続
ser = serial.Serial(PORT, BAUD_RATE, timeout=1)
time.sleep(2)  # Arduino起動待ち(これを入れないと最初のデータが化けることがあります)

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

for _ in range(10):  # 試しに10回分受信してみる
    line = ser.readline().decode('utf-8').strip()  # バイト列を文字列に変換
    if ',' in line:  # CSV形式のデータだけ処理
        temp, hum = line.split(',')
        print(f"温度: {float(temp):.1f}℃  湿度: {float(hum):.1f}%")

ser.close()  # 最後はポートを閉じる

実行するとこんな出力が得られるはずです👇

データ受信を開始します...
温度: 25.5℃  湿度: 60.2%
温度: 25.6℃  湿度: 60.1%
温度: 25.5℃  湿度: 60.3%
...

ちゃんとデータが取れていますね!😄 これ、実行せずに「ちゃんと動くかな?」と不安になってしまう方も多いと思いますが、ぜひそのまま試してみてください。

STEP 3:Matplotlibでリアルタイムグラフを表示する

データが受信できたら、次はグラフ化です。Matplotlibの アニメーション機能(FuncAnimation) を使うと、グラフをリアルタイムで更新することができます。

つまり、グラフ全体を毎回描き直すのではなく、一定間隔でデータを追加しながらグラフを”生きた状態”に保つイメージです。

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

# --- 設定 ---
PORT = 'COM3'
BAUD_RATE = 9600
MAX_POINTS = 60  # グラフに表示するデータ点数(60秒分)

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

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

# グラフの初期設定
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(10, 6))
fig.suptitle('Arduino リアルタイム センサーダッシュボード', fontsize=14)

def update(frame):
    """FuncAnimationから定期的に呼び出されるグラフ更新関数"""
    line = ser.readline().decode('utf-8').strip()
    if ',' in line:
        try:
            temp, hum = map(float, line.split(','))
            temps.append(temp)  # 新しいデータをキューに追加
            hums.append(hum)
        except ValueError:
            pass  # パースに失敗した場合はスキップ

    # 温度グラフを更新
    ax1.clear()
    ax1.plot(list(temps), color='tomato', linewidth=2)
    ax1.set_ylabel('温度 (℃)')
    ax1.set_ylim(0, 50)
    ax1.grid(True, linestyle='--', alpha=0.5)
    ax1.set_title(f'現在の温度: {temps[-1]:.1f}℃')

    # 湿度グラフを更新
    ax2.clear()
    ax2.plot(list(hums), color='steelblue', linewidth=2)
    ax2.set_ylabel('湿度 (%)')
    ax2.set_ylim(0, 100)
    ax2.grid(True, linestyle='--', alpha=0.5)
    ax2.set_title(f'現在の湿度: {hums[-1]:.1f}%')

    plt.tight_layout()

# 1000ms(1秒)ごとにupdate関数を呼び出す
ani = animation.FuncAnimation(fig, update, interval=1000)
plt.show()

ser.close()

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

  • deque(デック)は、最大個数を超えたデータを自動で捨ててくれる便利なリスト。固定幅のスクロールグラフを作るのに最適です
  • FuncAnimationinterval を変えれば更新頻度を自由に調整できます
  • ax.clear()でグラフをいったんリセットしてから再描画することで、シンプルにリアルタイム更新を実現しています

STEP 4:Dashでブラウザ上のダッシュボードにグレードアップ!


Matplotlibのグラフでも十分きれいですが、Dashを使うとブラウザ上で動くインタラクティブなダッシュボードに仕上げることができます。

Dashはもともとデータ分析ダッシュボードを作るためのフレームワークで、PlotlyのグラフをWebアプリとして公開できるのが特徴です。フロントエンドの知識がなくてもPythonだけで完結するのがうれしいところですよね。

import serial
import threading
from collections import deque
from datetime import datetime
import dash
from dash import dcc, html
from dash.dependencies import Input, Output
import plotly.graph_objs as go

# --- 設定 ---
PORT = 'COM3'
BAUD_RATE = 9600
MAX_POINTS = 60

# 共有データストア
temps = deque(maxlen=MAX_POINTS)
hums  = deque(maxlen=MAX_POINTS)
times = deque(maxlen=MAX_POINTS)

# ---- シリアル受信スレッド ----
def read_serial():
    """バックグラウンドでArduinoデータを受信し続ける関数"""
    ser = serial.Serial(PORT, BAUD_RATE, timeout=1)
    import time; time.sleep(2)
    while True:
        line = ser.readline().decode('utf-8').strip()
        if ',' in line:
            try:
                temp, hum = map(float, line.split(','))
                temps.append(temp)
                hums.append(hum)
                times.append(datetime.now().strftime('%H:%M:%S'))
            except ValueError:
                pass

# シリアル受信をバックグラウンドで起動
thread = threading.Thread(target=read_serial, daemon=True)
thread.start()

# ---- Dashアプリの定義 ----
app = dash.Dash(__name__)

app.layout = html.Div([
    html.H1('🌡️ Arduino センサーダッシュボード',
            style={'textAlign': 'center', 'fontFamily': 'Arial'}),

    # 現在値カードエリア
    html.Div([
        html.Div(id='temp-card', style={
            'background': '#ff6b6b', 'color': 'white',
            'padding': '20px', 'borderRadius': '12px',
            'textAlign': 'center', 'width': '200px'
        }),
        html.Div(id='hum-card', style={
            'background': '#4dabf7', 'color': 'white',
            'padding': '20px', 'borderRadius': '12px',
            'textAlign': 'center', 'width': '200px'
        }),
    ], style={'display': 'flex', 'gap': '20px',
              'justifyContent': 'center', 'margin': '20px'}),

    # グラフエリア
    dcc.Graph(id='temp-graph'),
    dcc.Graph(id='hum-graph'),

    # 1秒ごとに自動更新するインターバル
    dcc.Interval(id='interval', interval=1000, n_intervals=0)
])

@app.callback(
    Output('temp-card', 'children'),
    Output('hum-card', 'children'),
    Output('temp-graph', 'figure'),
    Output('hum-graph', 'figure'),
    Input('interval', 'n_intervals')
)
def update_dashboard(n):
    """1秒ごとにダッシュボード全体を更新するコールバック"""
    t_list = list(temps)
    h_list = list(hums)
    t_axis = list(times)

    # 現在値カードの内容
    temp_now = f"{t_list[-1]:.1f}℃" if t_list else "--"
    hum_now  = f"{h_list[-1]:.1f}%"  if h_list else "--"
    temp_card = html.Div([html.H3("🌡️ 温度"), html.H2(temp_now)])
    hum_card  = html.Div([html.H3("💧 湿度"), html.H2(hum_now)])

    # 温度グラフ
    temp_fig = go.Figure(
        go.Scatter(x=t_axis, y=t_list, mode='lines+markers',
                   line=dict(color='tomato', width=2)),
        layout=go.Layout(title='温度の推移', yaxis=dict(range=[0, 50]),
                         paper_bgcolor='#f8f9fa')
    )

    # 湿度グラフ
    hum_fig = go.Figure(
        go.Scatter(x=t_axis, y=h_list, mode='lines+markers',
                   line=dict(color='steelblue', width=2)),
        layout=go.Layout(title='湿度の推移', yaxis=dict(range=[0, 100]),
                         paper_bgcolor='#f8f9fa')
    )

    return temp_card, hum_card, temp_fig, hum_fig

if __name__ == '__main__':
    app.run(debug=False)  # debug=Trueにするとスレッド二重起動に注意!

ここが重要です👇

  • threadingでシリアル受信をバックグラウンドに分離しているのがポイントです。Dashのメインスレッドとシリアル受信を同時並行で動かすために使っています
  • dcc.Intervalという部品が「1秒ごとにコールバックを呼び出してね」という命令を出してくれます
  • 実行後、ブラウザで http://127.0.0.1:8050 を開くとダッシュボードが表示されます

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


詰まりやすいポイントをまとめておきます。途中で止まった方はここを確認してみてください!

  • ☑️ ポートが合っているか確認:Arduino IDEの「ツール → ポート」で表示されるCOMポートとPythonコードが一致しているか
  • ☑️ Arduino IDEのシリアルモニタは閉じているか:シリアルモニタを開いたままだとPythonからポートを開けません
  • ☑️ ボーレートが一致しているか:Arduino側の Serial.begin(9600) とPython側の BAUD_RATE = 9600 が同じ値になっているか
  • ☑️ time.sleep(2)を入れているか:Arduinoはシリアル接続直後にリセットがかかるため、2秒の待機がないと最初のデータが文字化けすることがあります
  • ☑️ DHT.hライブラリがインストールされているか:Arduino IDEのライブラリマネージャーで「DHT sensor library」を確認

💡 応用アイデア:もっと発展させるには?

ここまでできたら、あとは応用するだけです。ざっくりとした流れがつかめるはずなので、こんなアイデアにも挑戦してみてください!

  • 🌱 センサーを追加する:照度センサー(CdS)や土壌水分センサーを足して、植物管理ダッシュボードにする
  • 📊 CSVに記録する:Pythonの csvモジュールを使ってデータをファイルに保存すれば、あとから集計・分析できます
  • 🔔 しきい値アラートを追加:温度が30℃を超えたらメール・LINE通知を送るといった機能も比較的シンプルに実装できます
  • 📱 スマホからアクセスする:DashアプリをPC上で動かしたまま、同じWi-Fiに接続したスマホのブラウザからIPアドレスで開けます

まとめ

今回は、ArduinoとPythonを連携させてリアルタイムデータ可視化ダッシュボードを作る方法を紹介しました。

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

  1. ArduinoでセンサーデータをCSV形式でシリアル送信
  2. Pythonの pyserial でデータを受信
  3. Matplotlib でリアルタイムグラフを表示
  4. Dash でブラウザ上のインタラクティブダッシュボードに昇華

「電子工作とアプリ開発はなんか別の世界…」と感じていた方も、今回の組み合わせで一気に解決できるかもしれません! 😊

センサーの種類を変えたり、グラフのデザインをカスタマイズしたり、自分だけのダッシュボードに育てていくのがとても楽しいですよ。ぜひ手を動かして試してみてください。一緒に学んでいきましょう!🚀

📡 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

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