ArduinoとDS18B20防水温度センサーで水温を測る!複数センサー同時計測とPythonでCSV記録
「水槽の水温、ちゃんと測って記録しておきたいんですよね…」
熱帯魚の水槽、水耕栽培、ぬか床、お風呂の温度チェック。水の温度を測りたい場面って、意外と多いですよね。でも、よく使われるDHT11やDHT22は空気用のセンサーなので、水には沈められません。
そこで今回使うのが、防水プローブタイプの温度センサー「DS18B20」です。ステンレス管に封入されたタイプが数百円で手に入り、1本の信号線に何個もぶら下げられるのが大きな特徴です。
難易度は初級〜中級(★★☆☆☆)。ArduinoでLチカをしたことがあれば大丈夫です。最後はPythonで測定値をCSVに自動記録するところまで、一緒に作っていきましょう!
DS18B20ってどんなセンサー?

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つをインストールします。
- OneWire(1-Wire通信を担当)
- 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)

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ロボット入門のおすすめコース・部品を見る →📚 関連商品・おすすめ書籍
※本記事にはアフィリエイトリンクが含まれます。





