PR

【第1回】ESP-WROOM-02 + DS18B20 で「温度がシリアルに出るまで」— 開発ボードと生チップ、2 つの始め方

環境センサーデータサーバーシステム
記事内に広告が含まれています。

前回 (序章) の続きです。今回は 温度センサー DS18B20 の値を Arduino IDE のシリアルモニタに表示する ところまでを、初めての方が丸ごと真似できる形で書きます。WiFi も Raspberry Pi もまだ関係ありません。「センサーの値をチップに読ませて、USB でパソコンに表示させる」。

生チップ使う前に入門的に

同じ ESP-WROOM-02 (技適取得済モジュール) を使うのに、2 つの始め方があります:

選択肢ハードル材料費特徴
A. 開発ボード (ESPr Developer)★☆☆ 低約 2,500 円Micro-USB 直結、書込み自動、ハンダ不要、電源が確保できる所で運用
B. 生 ESP-WROOM-02 チップ+DIP基盤★★★ 中〜高約 750 円/台手動リセット必要、USB シリアル別途、複数台や電池運用向け

初めての方は迷わず A から。動く経験を先に得てから、コスト最適化として B に進むのが挫折しにくいです。B は電池駆動の本番機を複数台作るときのコスト削減 (1 台あたり ~1,000 円節約) に効いてくる話。

この記事はまず パート A (ESPr Developer 編) で動くところまで案内し、続けて パート B (生チップ編) に進みます。B はステップアップ扱いです。


パート A: ESPr Developer + DS18B20

スイッチサイエンス製 ESPr Developer を使う版。秋月でも同様の物が有ります。ESP-WROOM-02 に必要な電源回路・USB シリアル・自動リセット回路が 既に基板上に載っている ので、生チップ版でハマりがちな「手動 RST タイミング」「プルアップ抵抗忘れ」を気にせず済みます。

ESPr® Developer Type-C
ESPr® DeveloperのUSBコネクタをType-Cにしました。

用意するもの (材料費 3,500 円程度)

部品個数目安価格入手先
ESPr Developer (ESP-WROOM-02 開発ボード)12,500 円スイッチサイエンス
DS18B20 温度センサー (防水プローブ版が便利)1400 円Amazon
ブレッドボード (400 穴)1300 円Amazon
ジャンパー線 (オス-メス、オス-オス各数本)200 円Amazon
4.7kΩ 抵抗 (DS18B20 プルアップ用)110 円秋月電子
Micro-USB ケーブル (データ通信対応)1家に転がっているリンク未設定
ピンヘッダ50Amazon

抵抗器に関してはアマゾンで購入すると割高感があります。秋月電子買うと一袋100本入りで買う事になり、単価はすごく安いが送料がかかるので何かとまとめて購入するのが良いです。おそらくアマゾンは送料を乗っけた価格になっていると思います。ちょっとずつ買い足すのでなく、計画的に作品作りするならば全部秋月から購入するのをお勧めします。秋月電子の梱包に使う箱は「ちょうどいい」大きさで、何かを分類収納して積み上げて置くには最適です。

ESPr Developer に搭載されているるもの:

  • ESP-WROOM-02 本体 (技適マーク付き)
  • 3.3V レギュレータ (LDO)
  • USB シリアル変換
  • 自動書込み回路 (RESET/GPIO0 自動制御)
  • Micro-USB コネクタ(BとCと有るので注意)
  • ピンヘッダはついていないので別途購入必要
ブレッドボードに挿した ESPr Developer(ESP-WROOM-02 開発ボード)

私の手持ちのモジュールはもう8年位目の物なのでUSB microBです。micro Cのモノもあるのでどちらか選んで購入してください。

配線 (5 分)

DS18B20 を ESPr Developer に接続するだけ。ハンダ付け不要、ブレッドボードに挿してジャンパー線で繋ぎます。3.3V、GND、IO4のピンの引き出し場所はモジュールの裏面にプリントしてあるので確認できます。

ESPr Developer と DS18B20 の配線図(3.3V・GND・IO4、4.7kΩ プルアップ)

ポイント:

  • DS18B20 の 4.7kΩ プルアップは 絶対に必要でDATA と 3V3 の間 に入れる (センサーと ESP を繋ぐ線に並列)
  • ESPr Developer 側の他のピン (RST, IO0, IO15 等) は 何もしなくて良い (基板が全部やってくれる)
  • Micro-USB ケーブルを PC に挿すだけで電源供給 + シリアル通信の両方が完了
  • ESPr Developerは幅が広いので3V3とセンサーのDATA線のジャンパー線はいったん別の場所に引き出してそれぞれの線とプルアップ抵抗で接続
ESPr Developer に DS18B20 防水プローブとプルアップ抵抗を配線したブレッドボード
DS18B20 のリード線に圧着した XH コネクタ

今後の事を考えてリード線はHX端子で仕上げています。まだそこまで考えていない場合はリード線とジャンパー線をワニグチクリップで接続してください。

Arduino IDE の準備 (5 分)

1. Arduino IDE をダウンロード

Arduino IDE 公式ダウンロードページ
https://www.arduino.cc/en/software
から Windows 用インストーラを取得 (2.x 系で OK)。

2. ESP8266 ボードマネージャを追加

Arduino IDE → ファイル → 環境設定 → 「追加のボードマネージャの URL」に:

http://arduino.esp8266.com/stable/package_esp8266com_index.json

を貼付け。

Arduino IDE のファイルメニューから「基本設定」を開く
Arduino IDE 基本設定の「追加のボードマネージャの URL」欄

ツール → ボード → ボードマネージャ で「esp8266」を検索、「esp8266 by ESP8266 Community」をインストール (5-10 分)。

Arduino IDE のツールメニューからボードマネージャを開く
ボードマネージャで esp8266 by ESP8266 Community をインストールした状態

3. 必要なライブラリ

ツール → ライブラリを管理 で以下を検索してインストール:

ライブラリマネージャで OneWire・DallasTemperature を検索する画面
  • OneWire (Paul Stoffregen 版)
  • DallasTemperature (Miles Burton 版)

4. ボード設定

ツール メニューで:

  • ボード → Generic ESP8266 Module
  • Flash Size → 実機に合わせる(私の個体は 4MB でした。次の項を読んでください)
  • CPU Frequency → 80MHz
  • Upload Speed → 115200
  • シリアルポート → USB を挿した COM ポート (Windows のデバイスマネージャで確認)
ツールメニューの ESP8266 ボード設定一覧

Flash Size は個体によって違います

ESP-WROOM-02 の Flash ROM は、2016 年に 4MB から 2MB に変更されています(スイッチサイエンスが告知しています)。しかも型番は変わっていないので、同じ「ESPr Developer」でも 4MB の個体と 2MB の個体が混在しています。私の手持ちは 8 年ほど前に買ったもので、実測すると 4MB でした。新しく買った方は 2MB の可能性があります。

確認方法: 以下のスケッチを書き込むと、シリアルモニタに実際の容量が出ます。

void setup() {
  Serial.begin(115200);
  delay(500);
  Serial.println();
  Serial.printf("実チップ容量: %u bytes (%u MB)\n",
                ESP.getFlashChipRealSize(), ESP.getFlashChipRealSize()/1048576);
  Serial.printf("IDE 設定値  : %u bytes (%u MB)\n",
                ESP.getFlashChipSize(), ESP.getFlashChipSize()/1048576);
}
void loop() {}

出力例(筆者の環境):

実チップ容量: 4194304 bytes (4 MB)
IDE 設定値  : 4194304 bytes (4 MB)

実チップ容量 が本当の値です。IDE 設定値 がそれより大きい場合は、ツールメニューの Flash Size を実チップ以下に変更してください。

シリアルモニタに出た実チップのフラッシュ容量と IDE 設定値の比較

迷ったら小さい方を選んでください。実チップより小さい値を指定しても、スケッチは問題なく動きます。使える領域が狭くなるだけで、本連載ではファイルシステムも OTA も使わないので実害はありません。逆に実チップより大きい値を指定すると、存在しないアドレスを指すことになり、「書込みは通るのに起動しない」という分かりにくい不具合の原因になります。

最初のスケッチ

Arduino IDE で新規スケッチを開いて、以下を貼付け:

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

// DS18B20 のデータ線を GPIO4 (ESPr Developer の IO4 ピン) に繋いだ場合
#define ONE_WIRE_BUS 4

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

void setup() {
    Serial.begin(115200);
    delay(500);
    Serial.println();
    Serial.println("=== DS18B20 単体テスト (ESPr Developer) ===");
    sensors.begin();
    Serial.print("検出したセンサー数: ");
    Serial.println(sensors.getDeviceCount());
}

void loop() {
    sensors.requestTemperatures();
    delay(800);   // 12bit 変換完了に約 750ms かかる
    float temp = sensors.getTempCByIndex(0);
    if (temp == DEVICE_DISCONNECTED_C) {
        Serial.println("ERROR: DS18B20 が繋がっていません");
    } else {
        Serial.print("温度: ");
        Serial.print(temp);
        Serial.println(" °C");
    }
    delay(2000);
}

書込み (30 秒)

Arduino IDE の → (書込み) ボタンをクリックするだけ。

Arduino IDE でスケッチの書き込みが完了した画面
  • ESPr Developer は 自動的にリセット して書込みモードに入る
  • 生チップ版のような 手動 IO0/RST 操作は不要
  • 「書き込みが完了しました」表示 → 自動で通常モードに戻る

シリアルモニタで温度を見る

ツール → シリアルモニタ、右下のボーレートを 115200 に。それか画面右上アイコンをクリックしてボーレート変更。

Arduino IDE 右上のシリアルモニタボタン
シリアルモニタのボーレートを 115200 に設定するプルダウン

以下のように出たら成功:

=== DS18B20 単体テスト (ESPr Developer) ===
検出したセンサー数: 1
温度: 26.75 °C
温度: 26.75 °C
温度: 26.81 °C
シリアルモニタに DS18B20 の温度が表示された成功例

センサープローブを指で握ると温度が上がるので、動作確認しやすいです。

センサーの結線プルアップ抵抗を端折ったり、センサーの接続を間違えると以下の表示が出力されます。

センサー未接続時にシリアルモニタへ出る「DS18B20 が繋がっていません」エラー

温度センサーのプローブを指先で温めれば温度が変化します。

サーモスのタンブラーに水と氷を入れて温度プローブを沈めると、とても温度変化が判り易いです。

サーモスは優秀です。

氷水を入れた魔法瓶にプローブを入れて 4.13℃ を表示しているシリアルモニタ
Amazon.co.jp: サーモス 真空断熱タンブラー 400ml ステンレス JDI-400 S : ホーム&キッチン
Amazon.co.jp: サーモス 真空断熱タンブラー 400ml ステンレス JDI-400 S : ホーム&キッチン

パート A のよくある失敗

症状原因対処
シリアルポートに ESPr が出ないCP2102(などのUSBドライバー) ドライバ未導入 or 充電専用 USB ケーブルSilicon Labs CP2102(モジュールに積まれたチップの) ドライバインストール、データ通信対応ケーブルに交換
書込みで「port が使用中」シリアルモニタが開いたままシリアルモニタ閉じてから書込み
検出したセンサー数: 0プルアップ抵抗 (4.7kΩ) 忘れ or DS18B20 の VCC/GND 逆配線再確認、テスターで通電チェック
温度が -127.00プルアップ抵抗の場所間違い (DATA と 3V3 の間に入れる)配線図の位置を再確認
何も表示されないボーレート不一致シリアルモニタ右下を 115200 に

シリアルポートにモジュールが認識されている場合は、デバイスドライバーに以下のような表示が出ます。USBを抜くと表示が無くなります。

デバイスマネージャのポート欄に表示された USB シリアル変換の COM ポート

以降のパート B は「更に安く複数台作りたい」、乾電池による駆動です。


パート B: 生 ESP-WROOM-02 チップ

パート A で動作を確認できた方向け。同じことを生 ESP-WROOM-02 チップ + USB シリアル変換モジュール で行います。このパートでは電池駆動で必要な部品は含まれていません。

Wi-Fiモジュール ESP-WROOM-02 DIP化キット: 半導体 秋月電子通商-電子部品・ネット通販
電子部品,通販,販売,半導体,IC,LED,マイコン,電子工作Wi-Fiモジュール ESP-WROOM-02 DIP化キット秋月電子通商 電子部品通信販売
FTDI USBシリアル変換アダプター Rev.2
FTDI USBシリアル変換アダプター(5V/3.3V切り替え機能付き)のRev.2です。基板が少し細くなりました。ジャンパーピンによって供給電圧を5 V/3.3 Vに切り替えられます。USBコネクタはmicro-Bタイプです。

なぜ生チップを使用するのか:

  • 1 台あたり ~1,000 円節約 (ESPr Developer 2,500 円 → 生チップ組 1,000 円)
  • 電池駆動の本番機を 複数台 (5-10 台) 作るときにコスト効果が効く
  • 開発ボード(ESPr Developer等)にはUSB-シリアル変換ICが搭載されているが、常時通電するようになっているので、そこで乾電池が消耗される。
  • 電源が通電中のLEDランプが点灯するのモジュールも有るので、そこで乾電池が消耗される。

はまるところ:

  • 生チップの必須プルアップ/プルダウン配線(信号を安定化させるもの)を忘れると起動しない
  • 書込み時に 手動 IO0 GND 操作 + RST タイミング が必要
  • 初回はここで挫折しやすい

用意するもの (材料費 3,500 円程度)

部品個数目安価格入手先例
ESP-WROOM-02 DIP化キット1750 円秋月電子
USB シリアル変換モジュール11500 円スイッチサイエンス
DS18B20 温度センサー (防水プローブ版が便利)1400 円Amazon
ブレッドボード (400 穴くらい)1300 円Amazon
ジャンパー線 (オス-オス、オス-メス)各 10 本400 円Amazon
4.7kΩ 抵抗 (DS18B20 のプルアップ用)110 円秋月電子
10kΩ 抵抗 (RST プルアップ用)110 円秋月電子
電解コンデンサ 100µF / 16V 以上 (書込み安定化、ほぼ必須)120 円秋月電子
セラミックコンデンサ 0.1µF (あるとなお良い)110 円秋月電子
MB102 ブレッドボード電源モジュール (コンデンサで直らない場合)1400 円Amazon
USB-A ↔ Mini/Micro USB ケーブル (シリアル変換用)1家に転がっている—

購入するときの注意:AmazonでUSB シリアル変換モジュールを購入すると粗悪品をつかまされる。まず3.3V出力出来ると購入ページに記述が有るが、高い電圧で出力される。ESP-WROOM-02は3.3V入力なのでチップが焼損する可能性が有ります(ESPへの書き込みが出来る以前の問題)。

3.3V 端子から規定以上の電圧が出ていた安価な USB シリアル変換モジュール

私が購入したモジュールは3.3V端子から3.7Vと4V以上を出力して書き込みすらできませんでした。

少々お高いが秋月電子かスイッチサイエンスで購入するのが無難だと思います。

全体の配線図

生の ESP-WROOM-02 と USB シリアル変換・DS18B20 の全体配線図

以上のように繋ぎます。まだ WiFi は使わないので、実は電源と GND とデータ線しか繋ぎません。ハンダはESP-WROOM-02 DIP化キットにピンヘッダを付けるだけ。後はブレッドボードに挿すだけです。

注意点:ESP-WROOM-02は3.3V駆動なので生チップには5Vを印加しないように注意してください。

USB シリアル変換モジュールはジャンパーキャップで3.3Vと5Vの切替が出来るので確認してから接続

する事。

3.3V 設定の USB シリアル変換モジュール(書き込み用)

⚠️ 生 ESP-WROOM-02 の必須プルアップ/プルダウン (これを忘れると起動しません):

  • EN → 3.3V (プルアップ)
  • IO0 → 3.3V (書込み時のみ GNDに一回落とす、通常は 3.3V。
  • GPIO15 → GND (プルダウン)
  • RST → 3.3V (10kΩ でプルアップ)
ブレッドボードに載せた生の ESP-WROOM-02 と USB シリアル変換の配線

⚠️ 一番の落とし穴: USB シリアル変換の 3.3V では電流が足りない

パート B で私が一番時間を溶かしたのがここです。書き込みが成功したり失敗したりする、という症状に悩まされました。同じ配線、同じ操作なのに、通るときと通らないときがある。原因が分からず何日も潰しました。

恐らく電源だと思われます。

USB シリアル変換モジュールの 3.3V 出力約 50mA
ESP-WROOM-02 が起動の瞬間に引く電流200〜300mA

最大6 倍足りません。

これは私が使った古いモジュールが悪かったわけではありません。USB シリアル変換モジュールの 3.3V 出力は、メーカーや価格を問わず数十 mA しかないのが普通です。変換 IC(FT231X、CP2102、CH340 など)に内蔵されたレギュレータから、おまけで出ている電源だからです。高いものを買っても解決しません。

「じゃあなぜ時々成功するのか」というと、ギリギリで足りたり足りなかったりするからです。USB ポートの給電の余裕、ケーブルの太さ、ブレッドボードの接触抵抗、その日の気温。こういうもので勝ったり負けたりします。だから再現性がなく、原因が分かりにくいのです。

パート A の開発ボードでこの問題が起きないのは、基板に専用の 3.3V レギュレータが載っていて、必要な電流を供給できるからです。

対策 1: 電解コンデンサを接続(手持ちが有れば)

ブレッドボードの電源レール(+と−)に 100µF の電解コンデンサを挿します。

  • 極性があります。長い脚が+、短い脚(本体に白い帯がある側)が−
  • 逆に挿すと破裂することがあります。必ず向きを確認してください
  • ESP-WROOM-02 のできるだけ近くに挿します。遠いと効果が落ちます
  • できれば 0.1µF のセラミックコンデンサ(極性なし)も並列に足すとなお良いです

コンデンサは電気を一時的に溜めておく部品です。起動の瞬間だけ大電流が要る、という用途にはこれが効きます。私の環境では、これで書込みの成功率が明らかに上がりました。

電源ラインに電解コンデンサを追加した ESP-WROOM-02 のブレッドボード

対策 2: 電源を別に用意する(それでも不安定なら)

コンデンサだけでは足りない場合、電源そのものを USB シリアル変換から切り離します。電子工作入門者に一番扱いやすいのは、Amazon などで数百円で売っている MB102 ブレッドボード電源モジュールです。ブレッドボードの電源レールにそのまま挿さる形をしていて、3.3V と 5V を出せます。

[USB or ACアダプタ] ──→ [MB102 電源モジュール] ──→ ブレッドボードの電源レール (3.3V)
│
├─→ ESP-WROOM-02 の 3V3
└─→ プルアップ抵抗の 3.3V 側

[PC] ──USB──→ [USB シリアル変換] ──→ TXD / RXD だけを ESP に接続
│
└─→ GND をブレッドボードの GND レールへ ★これが必須
  1. MB102 の 3.3V/5V 切替ジャンパーを 3.3V 側にセットする
  2. テスターで実際に 3.3V が出ているか測る(ここは必ず測ってください。ジャンパーの挿し間違いで 5V が出ていると ESP-WROOM-02 が壊れます)
  3. ESP の 3V3 は MB102 側の電源レールから取る
  4. USB シリアル変換の 3.3V ピンは ESP に繋がない(浮かせておく)
  5. USB シリアル変換の GND を、MB102 側の GND レールに必ず繋ぐ
  6. USB シリアル変換の TXD / RXD は今まで通り ESP の RXD / TXD にクロス接続

5 番が肝心です。電源が別系統になると、GND(基準電位)を共通にしないとシリアル通信の 0 と 1 が判定できません。文字化けするか、そもそも通信できなくなります。「電源を分けたら余計に動かなくなった」の原因は、たいていこれです。

必要なもの: MB102 ブレッドボード電源モジュール(Amazon で 300〜500 円程度)と、その電源(USB-A ケーブル、または 6.5〜12V の AC アダプタ)。

Amazon.co.jp: KKHMF 5個 3.3V 5V MB102ブレッドボード用 電源モジュール パワーモジュール [並行輸入品]: DIY・工具・ガーデン
オンライン通販のAmazon公式サイトなら、KKHMF 5個 3.3V 5V MB102ブレッドボード用 電源モジュール パワーモジュール をDIY・工具・ガーデンストアで、いつでもお安く。当日お急ぎ便対象商品は、当日お届け可能です。アマゾ...

ケーブルが 2 本必要になります。PC → USB シリアル変換 と、電源 → MB102 の 2 系統です。USB ポートが 2 つ空いている PC なら、USB-A ケーブル 2 本で済みます。ただし MB102 ブレッドボード電源モジュールのUSBケーブルは両方オスです。

Amazon.co.jp: Viviber USB-A to USB-A ケーブル 1m弱 USB3.0 オス-オス 5Gbps高速転送 金メッキ端子 ブラック | ナイロン編みで断線しにくい,外付けHDD・DVD機器対応,PC周辺機器の接続に便利,安定したデータ同期,丈夫で絡まりにくい設計 : パソコン・周辺機器
Amazon.co.jp: Viviber USB-A to USB-A ケーブル 1m弱 USB3.0 オス-オス 5Gbps高速転送 金メッキ端子 ブラック | ナイロン編みで断線しにくい,外付けHDD・DVD機器対応,PC周辺機器の接...

AC アダプタを使う場合の注意: MB102 は入力電圧をリニアレギュレータで降圧します。12V を入れて 3.3V を取り出すと、差の 8.7V 分がすべて熱になり、モジュールが熱くなって保護回路で落ちることがあります。USB からの 5V 入力が一番無難です。

電源モジュールから別給電した ESP-WROOM-02 のブレッドボード

Arduino IDE の準備

ボードマネージャ URL と OneWire/DallasTemperature ライブラリは パート A と同じ なので、既にパート A を試している場合はそのまま使えます。注意するのはReset Methodです。生チップには自動書き込み+リセット機能が無いのでこの設定が必要です:

  • ボード → Generic ESP8266 Module (「Generic」= 生 ESP-WROOM-02 のこと)
  • Flash Size → 実機に合わせる(分からなければ 1MB (FS:64KB OTA:~470KB) で動きます。パート A の確認スケッチで実測できます 現時点ではメモリは2MBしか流通していないようです 私の手持ちのモジュールは全て古いようです)
  • CPU Frequency → 80MHz
  • Reset Method → no dtr (aka ck)
  • Upload Speed → 115200
  • シリアルポート → USB シリアル変換をつないだ COM ポート (Windows のデバイスマネージャで確認)
ツールメニューの Reset Method を「no dtr (aka ck)」にした設定

なぜ no dtr (aka ck) なのか

dtr (aka nodemcu) は、USB シリアル変換の DTR / RTS 信号を使って自動的にリセットをかける設定です。パート A の開発ボードはこの配線が基板上にあるので、自動で書込みモードに入れます。

しかしパート B の配線では DTR も RTS も繋いでいません。IO0 と RST を自分の手でジャンパー線で操作する方式です。つまり自動リセットの出番がありません。

no dtr (aka ck) にすると、Arduino IDE は余計なリセット信号を出さず、すでに書込みモードに入っているチップとそのまま通信を始めます。手動操作と設定が噛み合うので、うまくいかないときに疑う場所が 1 つ減ります。

後の方の回で出てきますがこれでも書き込めない事態が発生するので、書き込み用基板を作成しています。

最初のスケッチ (温度をシリアルに出すだけ)

Arduino IDE で新規スケッチを開いて、以下を貼付け (パート A とほぼ同じ、ヘッダのコメントだけ変更):

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

// DS18B20 のデータ線を GPIO4 に繋いだ場合
#define ONE_WIRE_BUS 4

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

void setup() {
    Serial.begin(115200);
    delay(500);
    Serial.println();
    Serial.println("=== DS18B20 単体テスト ===");
    sensors.begin();
    Serial.print("検出したセンサー数: ");
    Serial.println(sensors.getDeviceCount());
}

void loop() {
    sensors.requestTemperatures();
    delay(800);   // 12bit 変換完了に約 750ms かかる
    float temp = sensors.getTempCByIndex(0);
    if (temp == DEVICE_DISCONNECTED_C) {
        Serial.println("ERROR: DS18B20 が繋がっていません");
    } else {
        Serial.print("温度: ");
        Serial.print(temp);
        Serial.println(" °C");
    }
    delay(2000);
}

書込み手順

生 ESP-WROOM-02 は自動書込み回路がないので、書込みモードに手動で入れる 必要があります(とっても大事):

  1. IO0 (GPIO0) を GND に落とす (ジャンパー線を GND レールに挿す)
  2. RST を一瞬 GND に落として離す (リセット = 書込みモード突入)
  3. Arduino IDE の → (書込み) ボタンをクリック
  4. 「書き込みが完了しました」が出たら:
  5. IO0 を GND から外して 3.3V に戻す (もしくは浮かせる)
  6. もう一度 RST を GND に一瞬 → 通常モードで起動

シリアルモニタで温度を見る

ツール → シリアルモニタ、右下のボーレートを 115200 に。

以下のように出たら成功:

=== DS18B20 単体テスト ===
検出したセンサー数: 1
温度: 26.75 °C
温度: 26.75 °C
温度: 26.81 °C
...

センサープローブに温度変化を与えて問題ないか確認してください。

よくある失敗

症状原因対処
書込みが成功したり失敗したりする(再現性がない)電源の電流不足。USB シリアル変換の 3.3V は約 50mA しか出せないが、ESP は起動時に 200〜300mA 引く上の「一番の落とし穴」の節へ。まず 100µF の電解コンデンサ、駄目なら MB102 で電源を分離
書込みで Failed to connect to ESP8266: Timed out waiting for packet headerIO0 が GND に落ちていない、RST タイミングずれ、または電源不足IO0→GND→RST 一瞬 GND の順序を確実に。それでも駄目なら電源対策
途中まで進んで Write timeout / Invalid head of packet書込み途中の電圧降下。電源不足がほぼ確定電源対策(コンデンサ → MB102)
MD5 of file does not match data in flash書込みは通ったがデータが化けた。電源かケーブル品質電源対策。USB ケーブルをデータ通信対応の短いものに交換
シリアルに何も出ない、化けるボーレート不一致、USB シリアル変換の RX/TX 逆結線115200 確認、TX ↔ RX を入替え
書込みは通るのに起動しない・変な文字が出続けるFlash Size を実チップより大きく指定している可能性パート A の確認スケッチで実チップ容量を測り、それ以下の値に設定し直す
検出したセンサー数: 0プルアップ抵抗 (4.7kΩ) 忘れ、DS18B20 の VCC/GND 逆配線再確認、テスターで通電チェック
温度が -127.00プルアップ抵抗の場所間違い (DATA と 3.3V の間に入れる)配線図の位置を再確認
起動と同時にリセット繰返しEN/GPIO15 のプルアップ/プルダウン抜け生チップ必須配線の再確認

それでも動かないとき — 1-Wire ピンスキャナで結線を確かめる

温度が -127 になる、あるいは 検出したセンサー数: 0 のままになる。このとき困るのは、配線・端子の仕上がり・センサー個体のどれが悪いのか区別できないことです。

目で見ても分かりません。ジャンパを挿し直したり、センサーを何本も交換したりして時間を溶かすことになります。筆者は実際にそれをやりました。

そこで、どのピンにセンサーがぶら下がっているか、プルアップが効いているかを総当たりで調べ、さらに見つかったセンサーが生きているかまで判定するスケッチを用意しました。配線を触る前にそのまま書き込んでください。

/**
 * ============================================================
 *  1-Wire ピンスキャナ + センサー健康診断  (v2)
 *
 *  1) DS18B20 がどの GPIO に繋がっているか総当たりで調べる
 *  2) 見つかったセンサーが「生きているか」まで判定する
 *
 *  ボード: Generic ESP8266 Module / Reset Method "no dtr (aka ck)"
 *  シリアルモニタ: 115200 bps
 *  所要時間: センサー 1 個につき 3 秒ほど余分にかかります
 * ============================================================
 */
#include <OneWire.h>
#include <DallasTemperature.h>

// 走査するピン。GPIO1/3 は TX/RX なので除外。
// GPIO16 は RST に配線されている可能性があるため意図的に除外
//   (走査で LOW に落とすと本体がリセットしてしまう)
const uint8_t PINS[] = {0, 2, 4, 5, 12, 13, 14, 15};
const int PIN_COUNT = sizeof(PINS) / sizeof(PINS[0]);

// 見つかったセンサーを覚えておく (走査後にまとめて診断する)
struct Found {
    uint8_t pin;
    uint8_t addr[8];
};
Found g_found[8];
int   g_foundCount = 0;

const int   READ_COUNT   = 3;
const float SPREAD_WARN  = 0.25f;   // これを超えたら △
const float SPREAD_BAD   = 1.00f;   // これを超えたら ×

// プルアップが効いているか (外部 4.7kΩ があれば HIGH で安定する)
const char* idleLevel(uint8_t pin) {
    pinMode(pin, INPUT);          // 内蔵プルアップを切って素の状態を見る
    delay(2);
    int high = 0;
    for (int i = 0; i < 20; i++) {
        if (digitalRead(pin)) high++;
        delayMicroseconds(200);
    }
    if (high == 20) return "HIGH (プルアップ有り)";
    if (high == 0)  return "LOW  (プルアップ無し/GND 短絡)";
    return "不安定 (浮いている)";
}

void scanPin(uint8_t pin) {
    Serial.printf("GPIO%-2d  待機レベル: %-28s ", pin, idleLevel(pin));

    OneWire ow(pin);
    ow.reset_search();
    delay(50);

    uint8_t addr[8];
    int found = 0;
    while (ow.search(addr)) {
        if (OneWire::crc8(addr, 7) != addr[7]) {
            Serial.print("\n        ROM の CRC 不一致 (ノイズを拾っています)");
            continue;
        }
        found++;
        if (found == 1) Serial.println();
        Serial.printf("        ★発見 #%d  ROM=", found);
        for (int i = 0; i < 8; i++) Serial.printf("%02X", addr[i]);

        const char* fam = "不明";
        if      (addr[0] == 0x28) fam = "DS18B20";
        else if (addr[0] == 0x10) fam = "DS18S20";
        else if (addr[0] == 0x22) fam = "DS1822";
        Serial.printf("  family=0x%02X (%s)\n", addr[0], fam);

        // 後で診断するために覚えておく
        if (g_foundCount < (int)(sizeof(g_found) / sizeof(g_found[0]))) {
            g_found[g_foundCount].pin = pin;
            memcpy(g_found[g_foundCount].addr, addr, 8);
            g_foundCount++;
        }
    }
    if (found == 0) Serial.println("→ デバイスなし");
}

void checkSensor(const Found& f) {
    Serial.println();
    Serial.printf("---- GPIO%d  ROM=", f.pin);
    for (int i = 0; i < 8; i++) Serial.printf("%02X", f.addr[i]);
    Serial.println(" ----");

    OneWire ow(f.pin);
    DallasTemperature ds(&ow);
    ds.begin();

    DeviceAddress addr;
    memcpy(addr, f.addr, 8);

    // 給電方式。パラサイトになっていたら VDD の挿し忘れを疑う
    Serial.printf("  給電方式  : %s\n",
                  ds.isParasitePowerMode()
                      ? "パラサイト (VDD 未接続の可能性)"
                      : "外部給電 (VDD 接続)");

    int res = ds.getResolution(addr);
    Serial.printf("  分解能    : %d bit", res);
    if (res == 12)      Serial.println("  (既定値。1 目盛 0.0625℃)");
    else if (res == 0)  Serial.println("  ← 応答なし。この後の測定も失敗するはず");
    else                Serial.println("  ← 既定の 12bit ではありません");

    // 連続して読み、ばらつきと所要時間を見る
    float v[READ_COUNT];
    bool  bad = false;

    for (int i = 0; i < READ_COUNT; i++) {
        uint32_t t0 = millis();
        ds.requestTemperatures();
        v[i] = ds.getTempC(addr);
        uint32_t ms = millis() - t0;

        Serial.printf("  %d 回目    : %9.4f ℃  (%lu ms)", i + 1, v[i], ms);

        if (v[i] == DEVICE_DISCONNECTED_C) {
            Serial.print("  ← CRC 失敗。配線か電源を疑う");
            bad = true;
        } else if (v[i] == 85.0f) {
            Serial.print("  ← 変換が走っていない。電源不足の定番");
            bad = true;
        } else if (v[i] < -55.0f || v[i] > 125.0f) {
            Serial.print("  ← DS18B20 の測定範囲外。故障");
            bad = true;
        }
        Serial.println();
        delay(200);
    }

    float mn = v[0], mx = v[0];
    for (int i = 1; i < READ_COUNT; i++) {
        if (v[i] < mn) mn = v[i];
        if (v[i] > mx) mx = v[i];
    }
    float spread = mx - mn;
    Serial.printf("  ばらつき  : %.4f ℃  (最小 %.4f / 最大 %.4f)\n", spread, mn, mx);

    Serial.print("  判定      : ");
    if (bad) {
        Serial.println("×  異常値が出ています");
    } else if (spread > SPREAD_BAD) {
        Serial.println("×  ばらつきが大きすぎます。センサー不良を疑う");
    } else if (spread > SPREAD_WARN) {
        Serial.println("△  ばらつきがやや大きい。もう一度走らせて再現するか見る");
    } else {
        Serial.println("○  安定しています");
    }
}

void runAll() {
    g_foundCount = 0;

    Serial.println();
    Serial.println("========================================");
    Serial.println(" 1-Wire ピンスキャナ + 健康診断 (v2)");
    Serial.println(" 配線はそのままで実行してください");
    Serial.println("========================================");

    for (int i = 0; i < PIN_COUNT; i++) {
        scanPin(PINS[i]);
        delay(20);
    }

    Serial.println("========================================");
    Serial.printf(" 走査終了。見つかったセンサー: %d 個\n", g_foundCount);

    if (g_foundCount == 0) {
        Serial.println(" 1 個も見つかりません。配線・プルアップ抵抗・電源を確認してください");
        Serial.println("========================================");
        return;
    }

    Serial.println("========================================");
    Serial.println(" センサー健康診断");
    Serial.println("========================================");

    for (int i = 0; i < g_foundCount; i++) checkSensor(g_found[i]);

    Serial.println();
    Serial.println("========================================");
    Serial.println(" ○ が出たピン番号を ONE_WIRE_BUS に設定します");
    Serial.println("========================================");
}

void setup() {
    Serial.begin(115200);
    delay(500);
    runAll();
}

void loop() {
    delay(8000);
    runAll();
}

結果の読み方

正常な個体ではこう出ます。実機の出力です。

========================================
 1-Wire ピンスキャナ + 健康診断 (v2)
 配線はそのままで実行してください
========================================
GPIO0   待機レベル: HIGH (プルアップ有り) → デバイスなし
GPIO2   待機レベル: LOW  (プルアップ無し/GND 短絡) → デバイスなし
GPIO4   待機レベル: HIGH (プルアップ有り) 
        ★発見 #1  ROM=28FF6F5A83160454  family=0x28 (DS18B20)
GPIO5   待機レベル: HIGH (プルアップ有り) → デバイスなし
GPIO12  待機レベル: LOW  (プルアップ無し/GND 短絡) → デバイスなし
GPIO13  待機レベル: LOW  (プルアップ無し/GND 短絡) → デバイスなし
GPIO14  待機レベル: HIGH (プルアップ有り) → デバイスなし
GPIO15  待機レベル: LOW  (プルアップ無し/GND 短絡) → デバイスなし
========================================
 走査終了。見つかったセンサー: 1 個
========================================
 センサー健康診断
========================================

---- GPIO4  ROM=28FF6F5A83160454 ----
  給電方式  : 外部給電 (VDD 接続)
  分解能    : 12 bit  (既定値。1 目盛 0.0625℃)
  1 回目    :   28.3750 ℃  (641 ms)
  2 回目    :   28.3750 ℃  (641 ms)
  3 回目    :   28.3750 ℃  (641 ms)
  ばらつき  : 0.0000 ℃  (最小 28.3750 / 最大 28.3750)
  判定      : ○  安定しています

========================================
 ○ が出たピン番号を ONE_WIRE_BUS に設定します
========================================

GPIO4 で ★発見、family=0x28 (DS18B20)。 これがスケッチの #define ONE_WIRE_BUS 4 と一致していれば、配線は正しいことになります。GPIO15 が LOW なのは、起動用に 10kΩ でプルダウンしているからで、これも正常な姿です。

出方意味次にやること
期待したピンで ★発見配線もプルアップも正常センサー個体か電源を疑う
別のピンで ★発見挿す場所を間違えているそのピンに配線を移すか、ONE_WIRE_BUS を合わせる
どこにも出ない。該当ピンは HIGH (プルアップ有り)4.7kΩ は繋がっているのに応答が無いセンサー個体の不良、または VCC / GND の未接続・逆接。別の個体に交換して比較する
該当ピンが LOWプルアップが無い、または GND に落ちている4.7kΩ を DATA と 3V3 の間に入れる。GND 側ではない
該当ピンが 不安定 (浮いている)どこにも繋がっていないジャンパの抜け、はんだ不良、圧着不良を疑う
ROM の CRC 不一致ノイズを拾っている配線を短くする。電源を安定させる

走査で見つかっても、生きているとは限らない

同じ配線のまま、不良個体に差し替えて走らせた出力です。走査部分は正常個体とまったく同じなので、診断部分だけ載せます。

---- GPIO4  ROM=28593B7300000072 ----
  給電方式  : 外部給電 (VDD 接続)
  分解能    : 12 bit  (既定値。1 目盛 0.0625℃)
  1 回目    : -127.0000 ℃  (3 ms)  ← CRC 失敗。配線か電源を疑う
  2 回目    : -127.0000 ℃  (4 ms)  ← CRC 失敗。配線か電源を疑う
  3 回目    : -127.0000 ℃  (3 ms)  ← CRC 失敗。配線か電源を疑う
  ばらつき  : 0.0000 ℃  (最小 -127.0000 / 最大 -127.0000)
  判定      : ×  異常値が出ています

走査では ★発見 されています。 ROM も読めていて family も 0x28 です。配線は正しい。 それでも温度が読めません。

これが v1 のスキャナでは見抜けなかったものです。 ★発見 が出た時点で「配線 OK」と判断して先へ進み、そこから先で「なぜか -127 が出る」と悩むことになります。筆者は実際にそれで時間を溶かしました。

読みどころは 3 つ

正常個体不良個体意味
走査★発見★発見どちらも見つかる。ここでは区別できない
温度28.3750 ℃-127.0000 ℃-127 は CRC 失敗。断線ではない
所要時間641 ms3 ms12bit 変換には 600〜750ms かかる。3ms は待たずに即エラーが返った証拠
ばらつき0.0000 ℃0.0000 ℃区別できない

一番効いたのは所要時間でした。 正常なら 641ms、不良なら 3ms。桁が 2 つ違います。値そのものを見なくても、時間を見るだけで判別できます。

逆に、ばらつきは役に立ちませんでした。 「壊れかけたセンサーは値が飛ぶだろう」と予想して入れた指標でしたが、実際の不良個体は同じ異常値を安定して返し続けました。どちらも 0.0000℃ です。予想が外れた指標をそのまま残してあるのは、外れたこと自体が読者の役に立つと思うからです。中途半端に壊れた個体なら効くかもしれませんが、少なくとも今回の壊れ方には無力でした。

白状すると、この記事の初版に「正常なときはこう出ます」として載せていた出力の ROM は 28593B7300000072 でした。 つまり上の不良個体そのものです。当時は走査しかしていなかったので、見つかった時点で正常だと思い込んでいました。診断まで走らせて初めて気づいた、というのがこの節ができた経緯です。

DS18B20 は VDD と GND を逆に挿すと一発で死にます。 この個体が最初から不良品だったのか、実験中に逆電圧を掛けて壊したのかは分かりません。原因が特定できなくても、「そういう壊れ方をする部品だ」と知っておけば、次に同じ症状が出たときに配線を疑い続けずに済みます。

ROM アドレスが出るのが効きます。 センサーを交換したときに ROM が変われば「別の個体を認識した」と確実に言えます。変わらなければ挿し替わっていません。目視より速い判定材料です。

筆者はこのスキャナで、結線ミス・端子の圧着不良・センサー個体の不良の 3 つを切り分けられました。最終的に犯人はセンサーの不良で、別の個体に替えたら 28℃ 前後の正常値が出ました。


書き込みモードに入れたか確かめる (74880 bps)

書込みが失敗するとき、そもそも書き込みモードに入れていないのが一番多い原因です。ところが手順どおりボタンを押したつもりでも、入れたかどうかは画面から分かりません。

確認する方法があります。ESP8266 は起動直後だけ 74880 bps という決まった速度で内部ログを出します。スケッチの Serial.begin(115200) とは無関係の、チップ自身のメッセージです。通常このログは 115200 で見ているせいで冒頭数行が文字化けしますが、速度を合わせれば読めます。

手順

  1. Arduino IDE のシリアルモニタを 74880 bps に切り替える
  2. IO0 を GND に落としたまま、RST を一瞬 GND に落として離す
  3. シリアルモニタに出た boot mode を読む

書き込みモードに入れていれば、こう出ます。

ets Jan  8 2013,rst cause:2, boot mode:(1,6)

waiting for host

「waiting for host」が出れば成功です。 書き込み待ちの状態になっています。ここで Arduino IDE の書込みボタンを押します。

IO0 を落とさずに RST だけ押すと、こうなります。

ets Jan  8 2013,rst cause:2, boot mode:(3,7)
load 0x4010f000, len 3424, room 16 
tail 0
chksum 0x2e
load 0x3fff20b8, len 40, room 8 
tail 0
chksum 0x2b
csum 0x2b
v0004a540
~ld

こちらは通常起動です。~ld の後にスケッチの setup() が始まります。

boot mode の読み方

boot mode:(A,B) の A は GPIO15 / GPIO0 / GPIO2 の 3 ビットをそのまま表しています。見るべきは A だけです。

表示GPIO15GPIO0GPIO2意味
boot mode:(1,x)001UART ダウンロードモード (書き込み待ち)
boot mode:(3,x)011通常のフラッシュ起動

A が 1 なら書き込みモード、3 なら通常起動。 GPIO0 の状態がそのまま出ているだけです。手前の rst cause:2 は「外部リセット」、つまり RST ピンを落としたという意味です。

ボタン操作を疑う前にこれを見てください。 boot mode:(3,x) しか出ないなら、押す順番か IO0 の配線の問題です。boot mode:(1,6) と waiting for host が出ているのに書き込めないなら、原因は別 (電源、ケーブル、ポート選択) にあります。切り分けの境界がここで引けます。

確認が済んだら、シリアルモニタの速度を 115200 に戻すのを忘れずに。戻さないとスケッチの出力が文字化けします。

技適マークについて (日本国内で使う場合の重要事項)

日本国内で電波を出す機器は技適マーク (認証番号) 付き である必要があります。

  • ESP-WROOM-02 は Espressif Systems の技適取得済みモジュールです(工事設計認証番号 206-000519。モジュールの金属シールドに刻印されています)
  • Aliexpress で「ESP8266」として売られている ESP-12F/ESP-12E は技適マーク無しで、国内で電波を出すと違法になります
  • 秋月電子・スイッチサイエンス等で「技適マーク付き」と明記されている ESP-WROOM-02 を選んでください
  • ちなみに今回のスケッチはまだ WiFi を使っていない (シリアルに温度を出しているだけ) ので、技適の話は次回以降が本題です。「せっかく作るなら技適付きで揃えよう」の意味で書きました。

AI との会話例

このスケッチを書くとき、Claude にはこんな聞き方をしました:

ESP-WROOM-02 に DS18B20 温度センサーを繋いで、シリアルモニタに温度を出したい。GPIO4 に DATA を繋いだ前提で、Arduino IDE 用の最小スケッチを書いて。

上の文章の青文字部分はこのブログ文章を書いてもらったAIが出力した。これではプルアップやプルダウンや抵抗値もわからない。しかしそこらはAI検索をかければテック系ブログのリンクを探してくれるので、そこらへんは複合的に調査して進めてください。逆に詳細にAIにプロンプトを入れれば必要なパーツも出力してくれます。何が欲しいかを明示する必要があります。どのように聞けば必要十分な情報をくれるかたまに聞いてみても良いです。

しかし返ってきたコードそのままで動くはずです。エラーが出たときはシリアルモニタの出力をコピーして「これ何?」と聞くと、「プルアップ抵抗が違う位置にある可能性」等、原因候補が返ってきます。センサーの信号線の出力をGPIO04にしたのは、基盤の引き出しが一番右下で扱いやすいと思ったからです。しかしながら引き出しピンの中にはデータで入出力の使用をしてはいけないピンもあります。開発ボードになると引き出しピンの名前が違う場合が有るので、利用するボードの型式なども一緒に入力してください。そういう知識を積み重ねていけばはまった時、AIにヒントを出して解決まで短時間になるはずです。

AI に聞くコツ:

  • チップ名を必ず書く (ESP32 と ESP8266 では別コードになる・生チップか開発ボードなら具体的に型式やメーカー名を明示)
  • コードだけでなく必要部品も欲しいなら明確に記述 (利用に問題ないピンをAIに十分確認してもらうことも忘れぬよう)

次回予告

第2回は XIAO ESP32-C3 で同じことをやります。ボードが違うと何が変わって、何が変わらないのか、を体感してください。その次から Raspberry Pi の話に入ります。


この記事のコード:
https://github.com/whiskerpad/sensorserverwithESP/tree/main/ESP8266_DS18B20_Serial

質問・訂正・「もっと詳しく」等あればコメント歓迎します。


← 序章 | 連載目次 | 第2回 →

コメント

タイトルとURLをコピーしました