ガイド · 読了まで21分

ArduinoのデータをExcelへ:Data Streamer、PLX-DAQ、CSV、Python

ArduinoのデータをExcelに送る4つの方法(シリアルモニタからCSV、Data Streamer、PLX-DAQ、Pythonでの記録)と、タイムスタンプ、グラフ、実験レポート用の測定表の作り方を解説します。

ArduinoのデータをExcelに取り込むとは、Arduinoがセンサーで読み取った値をUSBケーブル経由でパソコンに送り、表計算ソフトに1行ずつためていくことです。Arduinoは測定値を1回ごとにカンマ区切りの1行としてシリアルポートに書き出します。パソコン側でその行をExcelに取り込む一般的な方法は4つあります。シリアルモニタの出力をCSVファイルとして保存する方法、MicrosoftのData Streamerアドイン、PLX-DAQマクロ、そしてPythonによる自動記録です。どの方法でも考え方は同じで、Arduinoが送る1行がExcelの1行になり、カンマごとに新しい列が始まります。

このガイドでは、DHT11温湿度センサーとLDR光センサーを例に使います。まず4つの方法を比べて合うものを選べるようにし、そのあと1つずつステップごとに設定していきます。続いて、測定値にタイムスタンプを付ける方法、Excelで適切なグラフの種類を選ぶ方法、学校の授業や科学コンテストで使える実験レポート用の測定表の作り方を紹介します。最後のセクションでは、同じことをESP32とRaspberry Pi Picoで行う方法と、よくあるエラーの解決方法を説明します。

Arduino UnoのボードとUSBコネクター
Arduino Uno:測定値はUSBケーブル上の仮想シリアルポートを通ってパソコンに届きます。Excelに送るのに追加のモジュールは必要ありません。

ArduinoのデータをExcelに送る仕組み

ArduinoはExcelに直接書き込むことはできません。できるのは、Serial.print()でシリアルポートにテキストを送ることだけです。パソコンはこのポートに、WindowsではCOM3、macOSでは/dev/cu.usbmodem…、Linuxでは/dev/ttyACM0のような名前でアクセスします。ExcelとArduinoの共通の言語はCSV(Comma Separated Values、カンマ区切りの値)で、12.0,23.0,45,78のような1行は4つの列に分かれます。つまりスケッチでは、値の間には常に同じ区切り文字を入れること、測定値の最後は必ずSerial.println()で終えること、の2つのルールを守るだけで十分です。シリアルポートの基本は「Arduinoのシリアルモニタ」のガイドで詳しく解説しています。

方法対応OSリアルタイム転送時刻情報向いている用途
シリアルモニタ+CSVWindows、macOS、Linux不可。測定後にコピーIDEのタイムスタンプ機能短い実験、手早い確認
ExcelのData StreamerWindows、Microsoft 365のデスクトップ版Excel可Arduinoが送るmillis()授業でのリアルタイムのグラフ
PLX-DAQ v2Windows、デスクトップ版Excel(マクロ)可DATE、TIME、TIMERコマンド用意したシートへの長時間の記録
Python(pyserial+openpyxl)Windows、macOS、Linux可(ファイルへ)パソコンの時計レポートの自動作成、何時間もの記録
SDカードモジュールパソコン不要不可。あとでカードを読むRTCモジュール電池で動かす屋外での測定

回路の例:DHT11とLDRの配線

回路例には2つのセンサーを使います。DHT11は温度を1 °C、湿度を1%の分解能で測ります。精度は約±2 °C、相対湿度±5%で、データピンは1本だけで済みます。LDRは、光が強くなるほど抵抗が下がるフォトレジスタです。10 kΩの抵抗と組み合わせて分圧回路を作り、中点をアナログピンにつなぎます。下の配線では、明るくなるほどアナログ値が大きくなります。LDRから得られる数値はルクス単位ではなく相対的な明るさなので、レポートでは「光(%)」と書くのが正確です。本当のルクス値が必要なら、BH1750のような校正済みの光センサーを使ってください。

接続Arduino UnoESP32Raspberry Pi Pico
DHT11 VCC(+)5V3V3内蔵センサーを使用
DHT11 DATA(OUT)D2GPIO 4内蔵センサー(ADC4)
DHT11 GND(-)GNDGND―
LDRの足15V3V33V3(OUT)、36番ピン
LDRの足2+10 kΩA0GPIO 34GP26(ADC0)、31番ピン
10 kΩのもう一方の端GNDGNDAGND、33番ピン
3ピンのDHT11モジュールでは、データ線のプルアップ抵抗がすでにボードに載っています。4本足のセンサー単体を使う場合は、DATAとVCCの間に4.7〜10 kΩの抵抗を自分で追加してください。追加しないと、スケッチはずっとnanを読み続けます。ESP32とPicoでは、LDRの分圧回路には必ず3.3 Vから給電してください。5 Vにつなぐと、ボードが耐えられる以上の電圧がアナログピンにかかります。
DHT11温湿度センサーモジュール
DHT11:1本のデータピンで温度と湿度の両方を送ります。2回の読み取りの間は1秒以上空ける必要があります。

Arduinoのコード:測定値をCSVの行として送る

C++ (Arduino IDE)
1// DHT11 + LDR ölçümlerini CSV satırı olarak gönderir / Sends DHT11 + LDR readings as CSV lines
2#include <DHT.h>
3
4const int DHT_PIN = 2;                 // DHT11 veri pini / DHT11 data pin
5const int LDR_PIN = A0;                // LDR + 10k gerilim bölücü / LDR + 10k voltage divider
6const unsigned long ARALIK = 2000;     // ölçüm aralığı, ms (DHT11 için en az 1000) / interval in ms (at least 1000 for DHT11)
7
8DHT dht(DHT_PIN, DHT11);               // DHT22 kullanıyorsan DHT22 yaz / write DHT22 if you use one
9unsigned long sonOlcum = 0;
10
11void setup() {
12  Serial.begin(9600);                  // Data Streamer ve PLX-DAQ varsayılanı / default of Data Streamer and PLX-DAQ
13  dht.begin();
14  Serial.println("zaman_s,sicaklik_C,nem_yuzde,isik_yuzde");   // başlık satırı / header row
15}
16
17void loop() {
18  if (millis() - sonOlcum < ARALIK) return;   // zamanı gelmediyse çık / not time yet
19  sonOlcum = millis();
20
21  float sicaklik = dht.readTemperature();     // santigrat derece / degrees Celsius
22  float nem = dht.readHumidity();             // bağıl nem, % / relative humidity, %
23  int isik = map(analogRead(LDR_PIN), 0, 1023, 0, 100);   // göreli ışık, % / relative light, %
24
25  if (isnan(sicaklik) || isnan(nem)) {
26    Serial.println("HATA,DHT okunamadi");     // sayı olmadığı için kolay ayıklanır / easy to filter out, not a number
27    return;
28  }
29
30  Serial.print(sonOlcum / 1000.0, 1);         // açılıştan beri geçen saniye / seconds since power-up
31  Serial.print(',');                          // sütun ayırıcı / column separator
32  Serial.print(sicaklik, 1);
33  Serial.print(',');
34  Serial.print(nem, 0);
35  Serial.print(',');
36  Serial.println(isik);                       // satır sonu = yeni Excel satırı / line end = new Excel row
37}

スケッチではAdafruitのDHT sensor libraryを使います。ライブラリマネージャからインストールするときは、依存ライブラリのAdafruit Unified Sensorも一緒にインストールしてください。測定は2秒ごとで、delay()ではなくmillis()でタイミングを計るので、loop()が止まることはありません(詳しくはmillis()とdelay()の違いの記事を参照)。各行は時間、温度、湿度、明るさの順に列が並びます。Serial.print(sicaklik, 1)(sicaklikはトルコ語で「温度」)は、数値を小数点以下1桁で、常にドットを使って出力します。センサーを読み取れなかった場合は数値の代わりに「HATA」(トルコ語で「エラー」)と出力するので、表の中の不正な行をすぐに見つけて除外できます。setup()の見出し行は、シリアルモニタとPythonの方法で役に立ちます。Data Streamerを使うなら、この行は削除してかまいません。室温のようにゆっくり変わる値なら、ARALIK(間隔)を60000にして1分に1回測定するようにしましょう。

方法1:シリアルモニタの出力をCSVとして保存する

  1. スケッチを書き込み、「ツール」>「シリアルモニタ」を開いて、速度のメニューで9600ボーを選びます。
  2. 必要ならタイムスタンプをオンにします。Arduino IDE 2ではウィンドウ右上の時計のアイコンを、IDE 1.8では下にあるタイムスタンプのチェックボックスをクリックします。各行の先頭に、14:03:21.512 ->の形でパソコンの時刻が付きます。
  3. 実験が終わったら、行をマウスで選択し、Ctrl+C(macOSではCmd+C)でコピーします。生データを残しておきたい場合は、メモ帳に貼り付け、ファイルの種類をすべてのファイルにしてolcum.csv(olcumはトルコ語で「測定」)という名前で保存します。
  4. Excelで空のシートのセルA1をクリックし、Ctrl+Vで貼り付けます。すべての行がA列に入ります。
  5. A列を選択した状態で「データ」>「区切り位置」を開き、区切り記号付きを選んで、区切り文字としてカンマにチェックを入れます。タイムスタンプをオンにしている場合はスペースにもチェックを入れます。時刻が1列目に、「->」の記号が2列目に入るので、その列はあとで削除します。
  6. 最後のステップで詳細をクリックし、小数点の記号をドットにします。こうすると、小数点にカンマを使う設定のExcelでも、23.5のような値が数値として認識されます。完了をクリックし、ファイルを.xlsxとして保存します。

この方法は数百行くらいまでならとても手軽です。数千行になると選択が面倒になり、IDEのウィンドウも重くなります。何時間も続く記録には、PuTTY(Session > Logging > All session output)や、Windows・macOS・Linuxで動くCoolTerm(Connection > Capture to Text/Binary File)のようなターミナルソフトを使えば、受信したすべての行がそのままファイルに書き込まれます。そのファイルも同じ手順でExcelに取り込めます。注意点として、ターミナルソフトやシリアルモニタがポートを使っている間は、ExcelのアドインもPythonもそのポートに接続できません。

Windowsの地域設定がヨーロッパ大陸の形式(たとえばドイツ語、フランス語、スペイン語、イタリア語、トルコ語)になっていると、ExcelはCSVファイルの列の区切りにセミコロン、小数点にカンマを期待します。そのため、カンマ区切りのCSVをダブルクリックすると、すべてが1列にまとまったり、23.5のような値が日付(5月23日)に変わったりすることがあります。日本語の設定ではカンマ区切り・小数点はドットなので、通常この問題は起きません。対策は、ファイルをダブルクリックで開くのではなく上のように「区切り位置」で分割するか、最初からセミコロンと小数点のカンマでファイルを作ることです。下のPythonスクリプトはまさにそれを行います。

方法2:ExcelのData Streamerでリアルタイムにデータを取り込む

Data Streamerは、Microsoftが教育向けに作った無料のアドインで、シリアルポートから届くCSVの行をワークシートに直接流し込みます。Microsoft 365のデスクトップ版Excel(バージョン1902以降)に含まれているので、有効にするだけで使えます。COMアドインのためWindowsでしか動作せず、macOS版のExcelやブラウザ版のExcelにはありません。Arduino側では何も変える必要はありません。上のスケッチは、アドインの既定の速度である9600ボーのままで動きます。

  1. Excelで「ファイル」>「オプション」>「アドイン」を開き、下にある管理のリストでCOMアドインを選んで設定をクリックします。
  2. Microsoft Data Streamer for Excelにチェックを入れてOKをクリックすると、リボンにData Streamerタブが表示されます。
  3. Arduino IDEのシリアルモニタを閉じます。シリアルポートは同時に1つのプログラムしか開けません。
  4. Connect a Device(デバイスの接続)ボタンでArduinoのCOMポートを選び、Start Data(データの開始)をクリックします。Excelの言語によっては、ボタン名が翻訳されて表示されることがあります。
  5. Excelは3つのシートを作ります。Data In(受信したデータ)、Data Out(Arduinoに送るデータ)、Settings(設定)です。SettingsシートでData Channelsを4にし、表でより多くの履歴を見たい場合はData Rowsを増やします。
  6. 記録を残すにはRecord Dataで記録を始めます。Stop Recordingで止めると、測定値がCSVファイルに保存されます。このファイルは、あとでImport Data Fileで再生できます。

Data Inシートの上部には最新の値(Current Data)が、その下には過去の測定値が流れていく表(Historical Data)があります。この表を選択して「挿入」>「おすすめグラフ」で折れ線グラフか散布図を追加すると、新しい値が届くたびにグラフが自動で更新されます。センサーの前に手をかざした瞬間に光の曲線が下がる様子をクラスに見せるのにぴったりです。SettingsシートのData Interval (ms)はシートを更新する間隔を、Data Orientationは最新のデータを表の上と下のどちらに表示するかを決めます。Data Outシートに入力した値も、CSVの行としてArduinoに送られます。ArduinoはSerial.parseInt()でそれを読めるので、たとえばアラームのしきい値をExcelから設定することもできます。

Data Streamerタブがまったく表示されない場合は、Microsoft 365以外のOfficeか、macOSを使っている可能性が高いです。その場合はPLX-DAQかPythonの方法に切り替えてください。スケッチで9600以外の速度を使っているなら、Advanced(詳細)ウィンドウの設定でボーレートを同じ値にしてください。そうしないと、表が文字化けした文字で埋まります。

方法3:PLX-DAQマクロでExcelに1行ずつ書き込む

PLX-DAQ(Parallax Data Acquisition)は、Excelの中で動くVBAマクロで、シリアルポートから届く特別なコマンドをExcelのセルに変換します。Parallax社のオリジナル版は32ビット版Excelでしか動かないため、現在はArduinoのコミュニティが開発したPLX-DAQ v2が使われています。64ビット版Excelに対応し、1つの.xlsmファイルとして配布されています。このマクロもWindows APIに依存しているため、Windowsでしか動きません。Data Streamerとの違いは、ArduinoがExcelを操作する点です。見出しを書き込み、シートを消去し、Excelに日付と時刻を追加させます。

C++ (Arduino IDE)
1// PLX-DAQ v2: Excel'e tarih, saat ve ölçüm satırı yazar / PLX-DAQ v2: writes date, time and readings into Excel
2#include <DHT.h>
3
4DHT dht(2, DHT11);                     // DHT11 veri pini D2 / DHT11 data pin D2
5const int LDR_PIN = A0;
6
7void setup() {
8  Serial.begin(9600);                  // PLX-DAQ'ta da 9600 seç / choose 9600 in PLX-DAQ too
9  dht.begin();
10  Serial.println("CLEARDATA");         // eski ölçümleri sil / clear old readings
11  Serial.println("LABEL,Tarih,Saat,Sure (s),Sicaklik (C),Nem (%),Isik (%)");   // 1. satır başlıkları / row 1 headers
12  Serial.println("RESETTIMER");        // TIMER sayacını sıfırla / reset the TIMER counter
13}
14
15void loop() {
16  float sicaklik = dht.readTemperature();
17  float nem = dht.readHumidity();
18  int isik = map(analogRead(LDR_PIN), 0, 1023, 0, 100);
19
20  if (!isnan(sicaklik) && !isnan(nem)) {
21    Serial.print("DATA,DATE,TIME,TIMER,");   // DATE, TIME, TIMER'ı Excel doldurur / Excel fills in DATE, TIME, TIMER
22    Serial.print(sicaklik, 1);
23    Serial.print(',');
24    Serial.print(nem, 0);
25    Serial.print(',');
26    Serial.println(isik);
27  }
28  delay(2000);                         // DHT11 saniyede en fazla 1 ölçüm verir / DHT11 gives at most 1 reading per second
29}
コマンド働き
CLEARDATAシート上の古い測定値を消去する
LABEL,Tarih,Saat,...1行目に列の見出しを書き込む(Tarihはトルコ語で「日付」、Saatは「時刻」)
DATA,...次の空いている行に新しい測定値を書き込む
DATEとTIMEDATA行の中でパソコンの日付と時刻に置き換えられる
TIMER記録開始またはRESETTIMERからの経過秒数
RESETTIMERTIMERのカウンターをリセットする
ROW,SET,2次のデータを書き込む行を指定する
CELL,SET,G2,25 / CELL,GET,G2セルに値を書き込む、またはセルの値をArduinoに送り返す
SAVEWORKBOOKExcelファイルを保存する
  1. PLX-DAQ v2のファイルをダウンロードし、zipから展開します。.xlsmファイルを右クリックし、プロパティで許可するにチェックを入れます。Officeは、インターネットから入手したファイルのマクロを既定でブロックします。
  2. ファイルを開き、上部の黄色いバーでコンテンツの有効化をクリックします。
  3. Arduino IDEのシリアルモニタを閉じ、シート上のOpen PLX DAQ UIボタンをクリックします。
  4. 開いたウィンドウのPort欄にはCOMの番号だけを入力し(COM5なら5)、Baudで9600を選んでConnectをクリックします。
  5. 見出しが表示されない場合は、Arduinoのリセットボタンを押します。setup()がもう一度実行され、CLEARDATAとLABELのコマンドがExcelに届き、行が流れ込み始めます。
  6. 終わったらDisconnectをクリックし、必要ならデータを別の.xlsxファイルとして保存します。

方法4:PythonでCSVとExcelのファイルを自動作成する

MacやLinuxを使っている場合や、何時間も記録する予定がある場合、毎回手作業でレポートを作るのが面倒な場合は、Pythonがいちばん柔軟な方法です。まずターミナルでpython -m pip install pyserial openpyxlを実行し、2つのパッケージをインストールします。下の1つ目のスクリプトはArduinoからの受信を待ち受け、測定値をパソコンの時刻と一緒にdeney_olcumleri.csv(トルコ語で「実験の測定値」)というファイルに書き込みます。ポートの見つけ方、自動リセット、リアルタイムのグラフ表示などは、ArduinoとPythonのシリアル通信のガイドで詳しく説明しています。

Python
1import csv
2import time
3from datetime import datetime
4
5import serial
6
7PORT = "COM3"               # macOS: /dev/cu.usbmodem…, Linux: /dev/ttyACM0
8BAUD = 9600                 # Arduino'daki Serial.begin ile aynı / same as Serial.begin on the Arduino
9DOSYA = "deney_olcumleri.csv"
10AYIRICI = ";"               # Türkçe Excel ; bekler, İngilizce Excel , / Turkish Excel expects ;, English Excel ,
11ONDALIK = ","               # Türkçe Excel ondalık virgül, İngilizce nokta / decimal comma in Turkish Excel, dot in English
12
13
14def sayi(x):
15    return f"{x:.1f}".replace(".", ONDALIK)   # 23.5 -> "23,5"
16
17
18with serial.Serial(PORT, BAUD, timeout=3) as ser, \
19        open(DOSYA, "w", newline="", encoding="utf-8-sig") as f:   # BOM: Excel Türkçe harfleri doğru gösterir / BOM keeps accents readable
20    time.sleep(2)                       # Uno port açılınca resetlenir / the Uno resets when the port opens
21    ser.reset_input_buffer()            # yarım kalmış satırları at / drop partial lines
22    yazici = csv.writer(f, delimiter=AYIRICI)
23    yazici.writerow(["Zaman", "Süre (s)", "Sıcaklık (°C)", "Nem (%)", "Işık (%)"])
24    print("Kayıt başladı, durdurmak için Ctrl+C / logging, press Ctrl+C to stop")
25    try:
26        while True:
27            satir = ser.readline().decode("utf-8", errors="ignore").strip()
28            parca = satir.split(",")
29            if len(parca) != 4:
30                continue                # boş, hata ya da başlık satırı / empty, error or header line
31            try:
32                sure, sicaklik, nem, isik = (float(p) for p in parca)
33            except ValueError:
34                continue                # sayı olmayan satır / non-numeric line
35            simdi = datetime.now()
36            yazici.writerow([simdi.strftime("%Y-%m-%d %H:%M:%S"),   # bilgisayar saati / PC clock
37                             sayi(sure), sayi(sicaklik), sayi(nem), sayi(isik)])   # süre Arduino'dan gelir / elapsed time comes from the Arduino
38            f.flush()                   # satırı hemen diske yaz / write the row to disk now
39            print(simdi.strftime("%H:%M:%S"), sicaklik, nem, isik)
40    except KeyboardInterrupt:
41        print("Kayıt bitti / logging stopped:", DOSYA)

このスクリプトでは、3つの工夫でExcelとの互換性を保っています。utf-8-sigエンコーディングは、ファイルの先頭に見えないBOMを追加します。BOMがないと、Excelは「°C」やアクセント付きの文字を文字化けして表示します。AYIRICI(区切り文字)とONDALIK(小数点)の定数は、ヨーロッパ大陸の多くの地域設定でExcelが期待する形式、つまりセミコロンと小数点のカンマに設定してあります。米国や英国の設定なら、カンマとドットに変えるだけです。日本語の設定のExcelもこちらと同じなので、カンマとドットにしてください。f.flush()は各行をすぐにディスクに書き込むので、パソコンの電源が落ちたりケーブルが抜けたりしても、失うのは最大で最後の測定値1つだけです。Ctrl+Cでスクリプトを止めたら、ファイルをダブルクリックするだけで、列が正しく分かれた状態で開きます。記録中にファイルを確認したい場合は、コピーを開いてください。Excelは開いたファイルをロックすることがあるからです。

Python
1import csv
2from datetime import datetime
3
4from openpyxl import Workbook
5from openpyxl.chart import Reference, ScatterChart, Series
6
7GIRIS = "deney_olcumleri.csv"
8CIKIS = "deney_raporu.xlsx"
9
10wb = Workbook()
11ws = wb.active
12ws.title = "Olcumler"
13
14with open(GIRIS, encoding="utf-8-sig", newline="") as f:
15    okuyucu = csv.reader(f, delimiter=";")
16    ws.append(next(okuyucu))                               # başlık satırı / header row
17    for satir in okuyucu:
18        zaman = datetime.strptime(satir[0], "%Y-%m-%d %H:%M:%S")
19        degerler = [float(x.replace(",", ".")) for x in satir[1:]]   # "23,5" -> 23.5
20        ws.append([zaman] + degerler)                      # .xlsx sayıyı sayı olarak saklar / .xlsx stores real numbers
21
22son = ws.max_row
23for hucre in ws["A"][1:]:
24    hucre.number_format = "hh:mm:ss"                       # zaman sütunu biçimi / time column format
25ws.column_dimensions["A"].width = 12
26
27# Özet tablo: formüller İngilizce yazılır, Excel kendi diline çevirir
28# Summary: formulas are written in English, Excel shows them in its own language
29ws["G1"], ws["H1"], ws["I1"], ws["J1"] = "Özet", "Sıcaklık (°C)", "Nem (%)", "Işık (%)"
30for i, (ad, fonk) in enumerate([("Ortalama", "AVERAGE"), ("En düşük", "MIN"),
31                                ("En yüksek", "MAX"), ("Std. sapma", "STDEV")], start=2):
32    ws.cell(row=i, column=7, value=ad)
33    for sutun, harf in ((8, "C"), (9, "D"), (10, "E")):
34        ws.cell(row=i, column=sutun, value=f"={fonk}({harf}2:{harf}{son})")
35
36# Her ölçüm için süre-değer (XY dağılım) grafiği / one time-value (XY scatter) chart per reading
37x = Reference(ws, min_col=2, min_row=2, max_row=son)       # Süre (s) sütunu / elapsed time column
38for sutun, baslik, konum in ((3, "Sıcaklık (°C)", "G8"), (5, "Işık (%)", "G24")):
39    grafik = ScatterChart()
40    grafik.title = baslik + " - süre"
41    grafik.x_axis.title = "Süre (s)"
42    grafik.y_axis.title = baslik
43    grafik.x_axis.delete = False                           # yeni Excel'de eksenler görünsün / keep axes visible
44    grafik.y_axis.delete = False
45    y = Reference(ws, min_col=sutun, min_row=1, max_row=son)
46    grafik.series.append(Series(y, x, title_from_data=True))
47    grafik.width, grafik.height = 18, 8                    # cm
48    ws.add_chart(grafik, konum)
49
50wb.save(CIKIS)
51print(son - 1, "ölçüm yazıldı / readings written:", CIKIS)

2つ目のスクリプトは、CSVを本物の.xlsxファイルに変換します。.xlsxの中では数値がテキストではなく数値として保存されるので、区切り文字と小数点の問題は完全になくなり、英語版、ドイツ語版、トルコ語版のExcelでも、もちろん日本語版でも同じように開けます。スクリプトは、平均、最小値、最大値、標準偏差をまとめた集計表と、温度と明るさの2つの散布図も追加します。数式は英語の名前(AVERAGE、MIN、MAX、STDEV)でファイルに書き込まれ、Excelはファイルを開くときにそれを自分の言語に置き換えます。日本語版のExcelでは、関数名は英語のまま表示されます。delete = Falseの行は、最近のバージョンのopenpyxlで作ったグラフに軸のラベルが表示されない問題を防ぐためのものです。

タイムスタンプを付ける:millis()、パソコンの時計、RTC

時刻の取得元取得方法長所短所
millis()Arduinoのスケッチでmillis() / 1000.0追加のハードウェア不要、ミリ秒単位の分解能リセットのたびに0に戻る、実際の日付ではない、49.7日でオーバーフローする
パソコンの時計Pythonのdatetime、PLX-DAQのDATEとTIME、シリアルモニタのタイムスタンプ実際の日付と時刻、設定不要パソコンをずっと接続しておく必要がある
RTCモジュール(DS3231、DS1307)RTClibのrtc.now()パソコンなしで動き、電池で時計が動き続ける追加のモジュールが必要。DS1307は1日に数秒ずれることがある
インターネットの時刻(NTP)ESP32のconfigTime()設定なしで秒単位まで正確な時刻Wi-Fi接続が必要

パソコンにつないで行う実験なら、パソコンの時計がいちばん簡単で、このPythonスクリプトも各行にそれを書き込みます。Arduinoが送る経過時間も一緒に残しておくのはよい習慣です。測定の実際の間隔がわかり、行が抜けたときにもすぐ気づけます。Arduinoからmillis()の生の値を送る場合は、Excelで=B2/1000とすれば秒に、=B2/60000とすれば分に変換できます。たとえばSDカードに記録するなど、Arduinoをパソコンから切り離して動かす場合は、日付と時刻をRTC時計モジュールから取得してください。SDカードへのCSVの記録についてはSDカードモジュールのガイドで詳しく説明しています。ESP32ならインターネットから時刻を取得することもできます。詳しくは「ESP32のNTP」を参照してください。

Excelでグラフを作る

  1. 時間と温度の列を見出しごと選択します。列が隣り合っていない場合は、Ctrlキーを押しながら2つ目の列を選びます。
  2. 「挿入」>「グラフ」>「散布図(X、Y)」から、線の付いた散布図の種類を選びます。
  3. グラフの横にある+ボタンで軸ラベルをオンにし、軸に単位付きの名前を付けます。「時間(s)」と「温度(°C)」のようにします。
  4. 明るさの系列を追加するには、グラフを右クリックして「データの選択」>「追加」で明るさの列を追加します。目盛りの範囲が大きく違うので、系列を右クリックして「データ系列の書式設定」>「第2軸」を選びます。
  5. 縦軸を右クリックし、軸の書式設定で最小値と最大値を固定します。こうすると、1 °Cの変化が大きな変動のように見えなくなります。

なぜ折れ線グラフではなく散布図なのでしょうか。Excelの折れ線グラフは、横軸の値を等間隔のラベルとして扱います。測定値が1つ抜けたり、測定間隔を変えたりすると、時間軸が知らないうちにゆがんでしまいます。散布図(X、Y)なら、各点が実際の時刻の位置に置かれます。科学的なグラフに求められるのはこちらです。3つの部屋の平均温度のように、いくつかの決まった値を比べるだけなら、縦棒グラフのほうが読みやすくなります。センサーのノイズが多い場合は、系列を右クリックして「近似曲線の追加」>「移動平均」で曲線をなめらかにできます。

実験レポートの例:測定表

実験の問いを「デスクライトをつけると、近くの空気の温度、湿度、明るさはどう変わるか?」としてみましょう。センサーをライトから約15 cmの位置に置き、スケッチのARALIKを60000、つまり1分に1回の測定にしました。1分の時点でライトをつけ、6分の時点で消しました。下の値は、この装置で得られる典型的な値の例です。最後の2行はExcelの数式で計算した集計です。

時間(分)温度(°C)湿度(%)光(%)状態
0234614ライト消灯
1234681ライト点灯
2244582点灯中
3254482点灯中
4264383点灯中
5264283点灯中
6264215ライトを消した
7254314ライト消灯
8244514ライト消灯
平均24.744.052.0―
最小 / 最大23 / 2642 / 4614 / 83―

集計の行は、Excelで=AVERAGE(B2:B10)、=MIN(B2:B10)、=MAX(B2:B10)を使って計算します。測定値のばらつきを示すには、=STDEV(B2:B10)も追加できます。結果を考察するときは、表に表れた傾向を説明しましょう。ライトをつけた瞬間に光は14%から81%に跳ね上がりましたが、温度は約3分かけてゆっくり3 °C上がりました。これを熱慣性といいます。ライトを消すと光はすぐに下がりましたが、温度はその後数分間高いままでした。温度が上がると相対湿度は下がりました。空気中の水分の量が同じでも、暖かい空気はより多くの水分を含むことができるからです。白熱電球やハロゲンランプではこの効果がはっきり出ますが、LEDランプでは温度の上がり方がずっと小さくなります。

  • 目的:研究の問いと仮説を1文で書きます。
  • 使用したもの:ボードの型番、センサー、抵抗、使ったソフトウェア(Arduino IDE、Excel)。
  • 方法:センサーの設置場所、測定間隔(たとえば60秒)、実験の長さ、Excelにデータを取り込んだ方法。
  • 測定表:各列の見出しには単位を入れます。本文には集計表を使い、生データ全体は付録として添付します。
  • グラフ:軸ラベルと単位が入り、出来事(ライト点灯、消灯)に印を付けた散布図。
  • 結論と誤差の原因:結果を仮説と比べ、DHT11の±2 °Cの精度、校正していないLDR、センサーとライトの距離などの限界を挙げます。

ESP32のデータをExcelに送る

ESP32でも、どの方法も同じように使えます。Data StreamerとPLX-DAQから見れば、ESP32もただのシリアルポートの1つです。変わるのは3点です。アナログの読み取りは12ビット(0〜4095)になり、LDRの分圧回路は3.3 Vから給電し、アナログ入力にはWi-Fiがオンでも動作するADC1のピン(GPIO 32〜39)のどれかを選びます。ESP32のボードは通常115200ボーで使うので、Pythonスクリプト、Data Streamer、PLX-DAQの速度もそれに合わせて変えてください。起動時にシリアルポートに出るブートローダーのメッセージは数値ではないので、Pythonスクリプトは自動的に読み飛ばします。パソコンにまったくつながずに測定値をクラウドに送りたい場合は、「ESP32とGoogleスプレッドシート」のガイドを参考にしてください。

C++ (Arduino IDE)
1// ESP32: aynı CSV çıktısı, 12 bit ADC ve 3,3 V / ESP32: same CSV output, 12-bit ADC and 3.3 V
2#include <DHT.h>
3
4const int DHT_PIN = 4;                 // güvenli bir GPIO / a safe GPIO
5const int LDR_PIN = 34;                // ADC1 pini, Wi-Fi açıkken de okur / ADC1 pin, still reads with Wi-Fi on
6DHT dht(DHT_PIN, DHT11);
7
8void setup() {
9  Serial.begin(115200);                // Python'da ve Data Streamer'da da 115200 / 115200 in Python and Data Streamer too
10  dht.begin();
11  analogReadResolution(12);            // 0-4095
12}
13
14void loop() {
15  float sicaklik = dht.readTemperature();
16  float nem = dht.readHumidity();
17  int isik = map(analogRead(LDR_PIN), 0, 4095, 0, 100);   // göreli ışık, % / relative light, %
18
19  if (!isnan(sicaklik) && !isnan(nem)) {
20    // zaman_s,sicaklik,nem,isik biçimi, Uno koduyla aynı / same zaman_s,temp,hum,light format as the Uno sketch
21    Serial.printf("%.1f,%.1f,%.0f,%d\n", millis() / 1000.0, sicaklik, nem, isik);
22  }
23  delay(2000);
24}

Raspberry Pi PicoでCSVに記録する(MicroPython)

Raspberry Pi PicoでMicroPythonを使うなら、測定値をパソコンに送る代わりに、ボード自身のフラッシュメモリにあるCSVファイルに書き込めます。こうすればパソコンはまったく不要で、モバイルバッテリーで給電したPicoを測りたい場所に置いておけます。下のコードは、追加のハードウェアが要らない内蔵温度センサー(ADC4)と、GP26につないだLDRを使い、ヨーロッパの地域設定のExcelに合うよう、セミコロンと小数点のカンマでファイルを書き込みます。内蔵センサーはチップの温度を測るので、室温より数度高く出ることがあります。正確に測るには外付けのセンサーを使ってください。MicroPythonが初めてなら、「Raspberry Pi Picoとは?」のガイドから始めましょう。

Raspberry Pi Picoマイコンボード
Raspberry Pi Pico:MicroPythonで、測定値を自身のフラッシュメモリにあるCSVファイルに書き込みます。ファイルはThonnyでパソコンにダウンロードします。
MicroPython
1import os
2import time
3
4import machine
5
6ldr = machine.ADC(26)                 # GP26 = ADC0, LDR + 10k bölücü / LDR + 10k divider
7ic_sensor = machine.ADC(4)            # yongadaki sıcaklık sensörü / on-chip temperature sensor
8DOSYA = "olcum.csv"
9ARALIK_S = 10                         # ölçüm aralığı, saniye / interval in seconds
10
11
12def tr(x):
13    return "{:.1f}".format(x).replace(".", ",")   # Türkçe Excel için ondalık virgül / decimal comma for Turkish Excel
14
15
16try:
17    os.stat(DOSYA)                    # dosya varsa silme, sonuna ekle / keep an existing file, append to it
18except OSError:
19    with open(DOSYA, "w") as f:
20        f.write("Sure (s);Sicaklik (C);Isik (%)\n")   # ASCII başlık / ASCII header
21
22baslangic = time.ticks_ms()
23while True:
24    volt = ic_sensor.read_u16() * 3.3 / 65535
25    sicaklik = 27 - (volt - 0.706) / 0.001721       # RP2040 veri sayfası formülü / RP2040 datasheet formula
26    isik = ldr.read_u16() * 100 / 65535             # göreli ışık, % / relative light, %
27    sure = time.ticks_diff(time.ticks_ms(), baslangic) / 1000
28    satir = "{};{};{}".format(tr(sure), tr(sicaklik), tr(isik))
29    print(satir)                                    # Thonny kabuğunda da görünür / also shown in the Thonny shell
30    with open(DOSYA, "a") as f:                     # her satırda aç-kapat / open and close for every line
31        f.write(satir + "\n")                       # elektrik kesilse de veri kalır / data survives a power cut
32    time.sleep(ARALIK_S)

Thonnyでコードをmain.pyという名前でPicoに保存すると、ボードは電源が入るたびに自動で記録を始めます。ファイルがすでにある場合は削除されず、新しい行が末尾に追加されます。測定が終わったらPicoをパソコンにつなぎ、Thonnyで停止をクリックし、「表示」>「ファイル」パネルでolcum.csvを右クリックしてパソコンにダウンロードし、Excelで開きます。10秒ごとに約20バイトの行を書き込むと、ファイルは1日に約170 KBずつ増えます。Picoのファイルシステムなら、数日分の記録にも十分な余裕があります。日本語の設定のExcelのように小数点にドットを使う場合は、tr()関数の中のreplace()の呼び出しを削除してください。

よくあるエラーと解決方法

症状原因解決方法
ポートが開かない、「アクセスが拒否されました」(Access is denied)シリアルモニタ、シリアルプロッタ、またはほかのプログラムがポートを使っているポートを使っているウィンドウをすべて閉じる。ポートは同時に1つのプログラムしか開けない
すべての値が1つの列に入ってしまうCSVの区切り文字がExcelの地域設定と合っていない「データ」>「区切り位置」でカンマの位置で分割するか、Pythonで区切り文字を「;」にする
23.5が日付(5月23日)になった、またはテキストのままになったヨーロッパの地域設定のExcelは小数点にカンマを期待する「区切り位置」の「詳細」で小数点の記号をドットにするか、「ファイル」>「オプション」>「詳細設定」で「システムの区切り文字を使用する」のチェックを外す
アクセント付きの文字や°の記号が文字化けするCSVがBOMなしのUTF-8で保存されたPythonでencoding="utf-8-sig"を使うか、見出しに特殊な文字を使わない
表が文字化けした文字で埋まるボーレートが合っていないSerial.begin()の速度をData Streamer、PLX-DAQ、Pythonの設定と合わせる
Data Streamerタブがないアドインが有効になっていない、またはExcelのバージョンが対応していない「COMアドイン」で有効にする。macOS版とWeb版のExcelにはこのアドインはない
PLX-DAQのボタンが動かないマクロがブロックされているファイルの「プロパティ」で「許可する」にチェックを入れ、「コンテンツの有効化」をクリックする
PLX-DAQがポートに接続できないCOM番号が違う、または大きすぎるデバイスマネージャーで、そのポートの「ポートの設定」>「詳細設定」からCOM番号を小さい値(たとえばCOM4)に変更する
温度と湿度の代わりに「HATA」や「nan」が出るDHT11の配線、プルアップ抵抗の不足、または読み取りの頻度が高すぎる配線を確認し、2回の読み取りの間は1秒以上空ける
測定間隔は目的に合わせて選びましょう。室温のようにゆっくり変わる量なら1分に1回で十分すぎるほどで、1日分の記録でも1,440行に収まります。Excelのワークシートに入るのは最大1,048,576行で、1秒に10回測定すると約29時間でこの上限に達します。ノイズの多いセンサーでは、Arduinoで何回かの測定値を平均してから1行だけ送ると、ファイルが小さくなり、グラフもなめらかになります。

Excelへのデータ記録を使ったプロジェクトのアイデア

  • 冷却曲線:防水型のDS18B20で、コップのお湯が冷めていく様子を測り、Excelで指数近似の近似曲線を追加して、ニュートンの冷却の法則を調べます。
  • ミニ気象ステーション:BME280で温度、湿度、気圧を1週間記録し、昼と夜の違いをグラフにします。
  • 植物の水やり記録:水やりの前後で土壌水分センサーの値を記録し、土が乾くまでにどのくらいかかるかを調べます。
  • 運動の分析:HC-SR04で距離と時間の表を作り、Excelで連続する行の差から速さと加速度を計算します。
  • 電池の放電曲線:分圧回路で電池の電圧を測って何時間も記録し、時間とともに電圧がどう下がるかを調べます。
  • 科学コンテストのプロジェクト:色の違う箱が日なたでどれだけ温まるかを比べます。ほかのアイデアは「Arduinoの科学コンテスト向けプロジェクトアイデア」のガイドを参照してください。

どの方法を選んでも、基本は同じです。Arduinoできれいで一貫したCSVの行を作り、パソコンで正しい区切り文字を使ってExcelに取り込みます。手早く確認するならシリアルモニタ、授業でリアルタイムに見せるならData Streamer、ArduinoからExcelを操作するならPLX-DAQ、長時間の自動記録ならPythonが最適です。BlueGraysアプリには、「DHT11で温度と湿度を測定」「LDRで光の強さを測定」「ESP32温度データロガー」などのプロジェクトが、回路図とコード付きでステップごとにそろっています。測定したデータは、ここで紹介した方法でExcelに送れます。

よくある質問

ArduinoのデータをExcelに取り込むには?

いちばん簡単なのは、Arduinoから測定値をSerial.println()でカンマ区切りの行として送り、その行をExcelに取り込む方法です。WindowsでMicrosoft 365を使っているなら、Data Streamerアドインでデータをリアルタイムに転送でき、PLX-DAQマクロも同じような働きをします。MacやLinuxでは、PythonとpyserialでCSVファイルに記録するのがいちばん実用的です。

ExcelのData StreamerはMacで使えますか?

いいえ。Data StreamerはCOMアドインで、Windows版のMicrosoft 365デスクトップ版Excelでしか使えません。macOS版のExcelやWeb版には含まれていません。Macでは、PythonでCSVや.xlsxのファイルを作るか、CoolTermのようなターミナルソフトでシリアル出力をファイルに保存できます。

PLX-DAQは64ビット版Excelで使えますか?

Parallax社のオリジナルのPLX-DAQは、32ビット版Excelでしか動きません。Arduinoのコミュニティが開発したPLX-DAQ v2は64ビット版Excelにも対応していて、同じCLEARDATA、LABEL、DATAのコマンドを使います。どちらもVBAマクロなので、Windowsでしか動かず、マクロを有効にする必要があります。

Arduinoのシリアルモニタのデータを保存するには?

シリアルモニタには保存ボタンがありません。行をマウスで選択してCtrl+Cでコピーし、テキストファイルかExcelに直接貼り付けます。タイムスタンプの機能をオンにすると、各行にパソコンの時刻が付きます。長時間の記録には、PuTTYやCoolTermのファイル保存機能か、Pythonのスクリプトを使うほうが確実です。

CSVファイルがExcelで1つの列に入ってしまうのはなぜですか?

ヨーロッパの多くの地域設定では、Excelは列の区切りにセミコロンを期待するため、カンマ区切りのファイルをダブルクリックすると、すべての値がA列に入ったままになります。「データ」>「区切り位置」でカンマの位置で分割するか、「データ」>「テキストまたはCSVから」でファイルを取り込み、区切り記号を自分で選んでください。Pythonでファイルを作るなら、最初からExcelが期待する区切り文字を使うのがいちばん確実な解決策です。

パソコンなしでArduinoのデータを記録するには?

パソコンがない場合は、測定値をSDカードモジュールにCSVファイルとして書き込み、日付と時刻はRTCモジュールから取得します。あとでカードをパソコンに挿し、ファイルをExcelで開きます。Wi-Fi対応のESP32なら、データをGoogleスプレッドシートに直接送れます。Raspberry Pi Picoなら、MicroPythonで自身のフラッシュメモリにCSVファイルを書き込めます。

全プロジェクトを見る
DHT11で温度と湿度を測定
#55中級

DHT11で温度と湿度を測定

部屋の温度は何度で、空気は湿っているでしょうか、それとも乾燥しているでしょうか?DHT11センサーが温度と湿度を測定し、Arduinoが2行のLCDディスプレイに値を表示して、数秒ごとに更新します。センサーに異常があればエラーメッセージが表示されます。自分だけの小さな気象観測装置を作る第一歩です。

4.7(47)
73
LDRで光の強さを測定
#11初級

LDRで光の強さを測定

部屋の明るさを数値で見てみませんか?光に反応する小さな部品、LDRで周囲の光を測定し、Arduinoが0.5秒ごとにその値をコンピューターの画面に表示します。手で覆うと数値が変わる様子を確認できます。自動で点灯する常夜灯などのプロジェクトへの第一歩です。

4.6(81)
139
HC-SR04で距離を測定(シリアルモニタ表示)
#27初級

HC-SR04で距離を測定(シリアルモニタ表示)

HC-SR04センサーは、コウモリが暗闇で道を見つけるのと同じ仕組みで動作します。人には聞こえない音を出し、その反響を捉えて前方の物体までの距離を測ります。Arduinoは0.5秒ごとに距離をセンチメートル単位でコンピューターの画面に表示し、3〜100センチメートルの測定値を示します。駐車センサーや障害物を避けるロボットなどのプロジェクトの基礎になります。

4.6(46)
71
ESP32とLDRモジュールで光の強さを読み取る
#113初級

ESP32とLDRモジュールで光の強さを読み取る

LDRモジュールの生のADC値と、暗い状態・明るい状態の基準値から計算した相対的な明るさの割合を、シリアルモニタでリアルタイムに確認します。この割合はルクスの測定値ではありません。モジュールの校正の仕組みを学べます。しきい値の決定に使うため、プロジェクト10の前に取り組むのが適しています。

4.6(36)
55
ESP32温度データロガー(DHT22 + DS1307 RTC + microSD + OLED)
#144上級
プレミアム

ESP32温度データロガー(DHT22 + DS1307 RTC + microSD + OLED)

ESP32で日時付きの温度・湿度記録システムを作ります!DHT22で1分ごとに温度と湿度を読み取り、DS1307 RTCから取得した日時とともにmicroSDカードへCSV形式で記録します。OLEDには最新の温度を大きな文字で表示し、湿度のパーセント値、日時、総記録数も表示します。SDカードの/temp_log.csvファイルはExcel、Google Sheets、Pythonのpandasで開いて分析できます。温室の監視、家や部屋の温度管理、実験室のデータ収集、食品の保管環境や養蜂箱の監視に適しています。

4.7(7)
12
ESP32 DHT22温湿度計(LCDディスプレイ付き)
#117中級

ESP32 DHT22温湿度計(LCDディスプレイ付き)

DHT22センサーで周囲の温度と湿度を測定し、16x2 I2C LCDにリアルタイムで表示するプロジェクトです。Adafruit DHTライブラリを使い、1本の信号線を使うプロトコルでセンサーからデータを読み取ります。IoT気象観測装置やスマートホームの自動化、温室の環境監視システムの基礎となります。ESP32のGPIO 4ピンを介してDHT22と通信します。

4.8(38)
56
NTCと2x16 LCDディスプレイで温度を測定
#44初級
プレミアム

NTCと2x16 LCDディスプレイで温度を測定

小さなビーズのようなセンサーで周囲の温度を測ります。NTCというこの部品は、温まるほど電気が流れやすくなります。Arduinoがその変化を読み取り、数式で摂氏温度に変換して、2行のLCDディスプレイに0.5秒ごとに表示します。手のひらでセンサーを温めて、数値が上がる様子を見るのも楽しみの1つです。

4.5(33)
44
ESP32とDS1307 RTCのデジタル時計(I2C + LCD)
#120中級
プレミアム

ESP32とDS1307 RTCのデジタル時計(I2C + LCD)

このプロジェクトでは、DS1307リアルタイムクロック(RTC)モジュールを使って16x2 I2C LCDに時刻と日付を表示します。DS1307は電池でバックアップされるRTCで、ESP32の電源を切っても時刻を保持します。両方のモジュールが同じI2Cバス(SDA/SCL)を共有するため、2本の信号線だけで複数の機器を制御する方法を学べます。I2C通信プロトコルやRTCモジュールの動作原理、LCDの表示データを随時更新する方法を実践的に学ぶプロジェクトです。

4.6(26)
40