「水槽の水温、ちゃんと測って記録しておきたいんですよね…」

熱帯魚の水槽、水耕栽培、ぬか床、お風呂の温度チェック。水の温度を測りたい場面って、意外と多いですよね。でも、よく使われるDHT11やDHT22は空気用のセンサーなので、水には沈められません。

そこで今回使うのが、防水プローブタイプの温度センサー「DS18B20」です。ステンレス管に封入されたタイプが数百円で手に入り、1本の信号線に何個もぶら下げられるのが大きな特徴です。

難易度は初級〜中級(★★☆☆☆)。ArduinoでLチカをしたことがあれば大丈夫です。最後はPythonで測定値をCSVに自動記録するところまで、一緒に作っていきましょう!

DS18B20ってどんなセンサー?

aquarium water temperature
aquarium water temperature / Photo by arnaud audoin via Pexels

DS18B20は、1-Wire(ワンワイヤー)という通信方式を使うデジタル温度センサーです。ざっくり言うと「1本の線で、電源以外の通信を全部まかなう」仕組みです。

  • 測定範囲:−55〜+125℃(−10〜+85℃の範囲で精度±0.5℃)
  • 電源電圧:3.0〜5.5V(Arduino UNOの5Vでも、ESP32などの3.3Vでも使える)
  • 分解能:9〜12bitで設定可能(12bitなら0.0625℃刻み)
  • センサー1個ずつに64bitの固有アドレスが焼き込まれている

最後の「固有アドレス」がポイントです。イメージとしては「全員が同じ廊下(信号線)につながっていて、名札(アドレス)で呼び分ける」感じです。だから信号線1本でセンサーを複数つなげるんですね。

準備するものと配線

準備するもの

  • Arduino UNO(互換機でもOK)
  • DS18B20 防水プローブ(1〜数本)
  • 4.7kΩの抵抗(プルアップ用・1本でOK)
  • ブレッドボード・ジャンパーワイヤー

配線

防水プローブの線の色は、一般的に次のようになっています(製品によって白・黄が違うことがあるので、購入先の説明も確認してください)。

  • 赤(VDD)→ Arduinoの 5V
  • 黒(GND)→ Arduinoの GND
  • 黄(DATA)→ Arduinoの D2
  • DATAと5Vの間に4.7kΩの抵抗を入れる

ここが一番の落とし穴です⚠️ プルアップ抵抗を忘れると、センサーがまったく見つからない、または値が不安定になります。1-Wireは信号線を抵抗で「普段はHIGH」に保っておく仕組みなので、この抵抗は必須です。センサーを複数つなぐ場合も、抵抗は信号線全体で1本で大丈夫です。

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

Arduino IDEのライブラリマネージャで、次の2つをインストールします。

  1. OneWire(1-Wire通信を担当)
  2. DallasTemperature(DS18B20の温度読み取りを担当)

DallasTemperatureをインストールするとき、依存ライブラリとしてOneWireも一緒に入れるか聞かれることがあります。その場合は「全てをインストール」を選べばOKです。

STEP1:まずは1本で水温を測る

#include <OneWire.h>
#include <DallasTemperature.h>

const int ONE_WIRE_PIN = 2;  // DS18B20のDATA線(黄色)をつなぐピン

OneWire oneWire(ONE_WIRE_PIN);
DallasTemperature sensors(&oneWire);

void setup() {
  Serial.begin(9600);
  sensors.begin();
  Serial.print("見つかったセンサー数: ");
  Serial.println(sensors.getDeviceCount());
}

void loop() {
  sensors.requestTemperatures();             // 測定開始(12bitだと最大750msかかる)
  float tempC = sensors.getTempCByIndex(0);  // 1個目のセンサーの温度を取得

  if (tempC == DEVICE_DISCONNECTED_C) {      // 読み取りに失敗すると -127 が返る
    Serial.println("エラー: センサーが応答しません(配線とプルアップ抵抗を確認)");
  } else {
    Serial.print("水温: ");
    Serial.print(tempC, 2);  // 小数点以下2桁で表示
    Serial.println(" C");
  }
  delay(2000);
}
シリアルモニタの表示例
シリアルモニタの表示例

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

  • requestTemperatures() で測定を開始し、getTempCByIndex(0) で1個目の値を読む
  • 読み取りに失敗すると -127(DEVICE_DISCONNECTED_C)が返るので、必ずチェックする
  • 起動時にセンサー数を表示しておくと、配線ミスにすぐ気づける

シリアルモニタ(9600bps)を開くと、2秒ごとに水温が表示されます。コップのお湯にプローブを入れると、数値がぐんぐん上がっていくのが見えるはずです😊

STEP2:複数のセンサーを同時に読む

次は、信号線にセンサーを2本以上つないでみましょう。配線は、2本目以降の赤・黒・黄を1本目と同じ列に並列でつなぐだけです。

getTempCByIndex(i) でも読めますが、センサーを付け外しすると番号がずれることがあります。そこで今回は固有アドレスを覚えておき、アドレス指定で読む方法にします。

#include <OneWire.h>
#include <DallasTemperature.h>

OneWire oneWire(2);
DallasTemperature sensors(&oneWire);

const int MAX_SENSORS = 4;
DeviceAddress addrs[MAX_SENSORS];  // センサーごとの固有アドレス(8バイト)
int count = 0;

// アドレスを16進数で表示する
void printAddress(const DeviceAddress addr) {
  for (int i = 0; i < 8; i++) {
    if (addr[i] < 0x10) Serial.print("0");
    Serial.print(addr[i], HEX);
  }
}

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

  count = sensors.getDeviceCount();
  if (count > MAX_SENSORS) count = MAX_SENSORS;

  for (int i = 0; i < count; i++) {
    if (sensors.getAddress(addrs[i], i)) {
      sensors.setResolution(addrs[i], 12);  // 分解能12bit(0.0625℃刻み)
      Serial.print("# sensor ");            // 「#」で始まる行はPython側で読み飛ばす
      Serial.print(i);
      Serial.print(": ");
      printAddress(addrs[i]);
      Serial.println();
    }
  }
}

void loop() {
  sensors.requestTemperatures();  // 全センサーに一斉に測定を指示
  Serial.print(millis());
  for (int i = 0; i < count; i++) {
    Serial.print(",");
    Serial.print(sensors.getTempC(addrs[i]), 2);  // アドレス指定で読むので順番が入れ替わらない
  }
  Serial.println();
  delay(5000);
}
  • getAddress() で各センサーの固有アドレスを取得して配列に保存
  • setResolution() で分解能を12bitに設定(細かく測れる分、変換に時間がかかる)
  • 測定値は 経過ミリ秒,温度1,温度2,... というCSV形式で出力(次のPythonで扱いやすくするため)

「どのアドレスが水槽用で、どれが室温用か」は、1本ずつ手で握って温度が上がるものを確認すると簡単に見分けられます。

STEP3:PythonでCSVに自動記録する

Arduinoのシリアル出力をPCのPythonで受け取り、日時つきでCSVに追記していきます。事前に pip install pyserial でライブラリを入れておきましょう。

import csv
from datetime import datetime

import serial  # pip install pyserial

PORT = "COM3"  # Macなら "/dev/cu.usbmodem1101" のような名前(Arduino IDEで確認)

with serial.Serial(PORT, 9600, timeout=10) as ser, \
        open("water_temp_log.csv", "a", newline="", encoding="utf-8") as f:
    writer = csv.writer(f)
    print("記録を開始しました(Ctrl+Cで終了)")
    while True:
        line = ser.readline().decode("utf-8", errors="ignore").strip()
        if not line or line.startswith("#"):
            continue  # 空行・センサーアドレスの表示行は読み飛ばす

        temps = line.split(",")[1:]  # 先頭の millis() は捨てて温度だけ使う
        if "-127.00" in temps:
            print("読み取り失敗のセンサーがあります。配線を確認してください")
            continue

        now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        writer.writerow([now, *temps])
        f.flush()  # 途中で止めてもデータが残るよう、毎回ファイルに書き出す
        print(now, temps)
Pythonでの記録の表示例
Pythonでの記録の表示例
  • PORT はArduino IDEの「ツール → ポート」に表示される名前に合わせる
  • Arduino IDEのシリアルモニタは閉じておく(開いたままだとポートが使用中になり接続できません)
  • f.flush() で毎回書き出しているので、途中で止めてもそれまでのデータは残る

できあがったCSVはExcelやpandasでそのまま開けるので、1日の水温変化をグラフにするのも簡単です。

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

  • センサー数が0/-127が出る → プルアップ抵抗の有無、DATA線のピン番号、線の色の取り違えを確認
  • 85.00が出る → 85℃は電源投入直後の初期値です。測定が完了する前に読んでいるか、電源が不安定な可能性があります。配線の接触と電源を見直しましょう
  • ケーブルを長く延長したら不安定になった → プルアップ抵抗を少し小さく(例: 2.2kΩ前後)すると改善することがあります

まとめ

DS18B20は、防水・安価・1本の線で複数つなげるという、水温測定にぴったりのセンサーです。今回のポイントは3つだけです。

  • DATAと電源の間に4.7kΩのプルアップ抵抗を忘れない
  • 複数センサーは固有アドレスで呼び分ける
  • −127や85が出たら、まず配線と電源を疑う

ここまでできれば、水温が一定以上になったら通知する、ファンやヒーターをリレーで制御する、といった応用にもすぐ進めます。ぜひ手を動かしながら試してみてください🚀

📡 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を用いたアプリ開発、ウェブアプリケーションの開発で業務の効率化をサポートしています。