顯示具有 I2C 標籤的文章。 顯示所有文章
顯示具有 I2C 標籤的文章。 顯示所有文章

2026年8月3日 星期一

[水井村USR] EP03|ESP32 讀取 I²C 感測器實戰

智慧生活科技專業社群|IoT 入門系列|適合大一新生
EP01 認識 I²C,EP02 認識四種水質感測器;EP03 則進入真正的程式實作。本文以 Atlas Scientific Aquaponics Kit 為例,帶領學生完成接線、掃描位址、送出讀取命令、解析回傳資料與序列埠監看。

請先將 EP03 主圖上傳 Blogger,再把 EP03_MAIN_IMAGE_URL 換成圖片網址。

圖:ESP32 讀取四種 I²C 水質感測器的完整流程。

一、這一篇要完成什麼?

任務 1|接線確認 ESP32、SDA、SCL、3.3V 與 GND。
任務 2|掃描找出所有 I²C 裝置位址。
任務 3|讀取向指定感測 IC 傳送 R 指令。
任務 4|解析將字串轉成可使用的水質數值。

二、系統接線

ESP32 SDA/SCL Bus RTD、pH、DO、EC
ESP32功能本案接腳
SDA資料線GPIO23
SCL時脈線GPIO22
3.3V供電依板卡設計
GND共地所有模組共地

圖:四顆 EZO IC 共用 SDA 與 SCL。

三、第一步:啟動 I²C

程式碼 1:初始化 Wire
#include <Wire.h>

void setup() {
  Serial.begin(115200);

  // SDA = GPIO23,SCL = GPIO22
  Wire.begin(23, 22);

  // 使用 100 kHz
  Wire.setClock(100000);
}
重點:Wire.begin(SDA, SCL) 必須符合實際開發板與 PCB 配線,不能直接套用別張 ESP32 開發板的預設值。

四、第二步:使用 I²C Scanner 找出所有裝置

程式碼 2:掃描 1~126 位址
void scanI2C() {
  for (uint8_t address = 1; address < 127; address++) {
    Wire.beginTransmission(address);
    uint8_t error = Wire.endTransmission();

    if (error == 0) {
      Serial.print("找到位址:0x");

      if (address < 16) {
        Serial.print("0");
      }

      Serial.println(address, HEX);
    }
  }
}

圖:掃描成功後,可以確認四顆 EZO IC 是否真的存在。

本系統實際掃描結果:

序列監控結果
找到 0x61 → EZO DO
找到 0x63 → EZO pH
找到 0x66 → EZO RTD
找到 0x69 → EZO EC
實務經驗:EC 原本常見預設位址是 0x64,但本機實際位址為 0x69。Scanner 能快速避免「程式正確、位址卻錯誤」的問題。

五、第三步:向感測 IC 傳送讀取命令

Atlas EZO IC 使用字串命令。最常見的讀取命令是:

送出 R 命令
Wire.beginTransmission(address);
Wire.write("R");
Wire.endTransmission();

感測 IC 收到命令後,需要時間完成量測,因此不能立刻讀回。

送出 R 等待約 900~1100 ms requestFrom() 接收資料

六、第四步:讀回感測器資料

程式碼 3:讀取單顆 EZO IC
String readEzo(uint8_t address, unsigned long waitMs) {
  String result = "";

  Wire.beginTransmission(address);
  Wire.write("R");

  if (Wire.endTransmission() != 0) {
    return "ERROR";
  }

  delay(waitMs);

  Wire.requestFrom((int)address, 20);

  while (Wire.available()) {
    char c = Wire.read();

    if (c == '\0') {
      break;
    }

    result += c;
  }

  return result;
}
為什麼使用 String?因為 EZO IC 回傳的是字元資料,例如 6.80,先用字串接收,再轉成 float。

七、第五步:讀取四顆感測器

程式碼 4:依序讀取
constexpr uint8_t DO_ADDR  = 0x61;
constexpr uint8_t PH_ADDR  = 0x63;
constexpr uint8_t RTD_ADDR = 0x66;
constexpr uint8_t EC_ADDR  = 0x69;

void loop() {
  String temperature = readEzo(RTD_ADDR, 1100);
  String ph = readEzo(PH_ADDR, 1100);
  String dissolvedOxygen = readEzo(DO_ADDR, 1100);
  String conductivity = readEzo(EC_ADDR, 1100);

  Serial.print("T=");
  Serial.print(temperature);

  Serial.print("  pH=");
  Serial.print(ph);

  Serial.print("  DO=");
  Serial.print(dissolvedOxygen);

  Serial.print("  EC=");
  Serial.println(conductivity);

  delay(3000);
}

圖:RTD、pH、DO 與 EC 的讀取結果。

八、完整入門版程式

ESP32+四顆 I²C 感測 IC
#include <Wire.h>

constexpr uint8_t SDA_PIN = 23;
constexpr uint8_t SCL_PIN = 22;

constexpr uint8_t DO_ADDR  = 0x61;
constexpr uint8_t PH_ADDR  = 0x63;
constexpr uint8_t RTD_ADDR = 0x66;
constexpr uint8_t EC_ADDR  = 0x69;

String readEzo(uint8_t address, unsigned long waitMs) {
  String result = "";

  Wire.beginTransmission(address);
  Wire.write("R");

  uint8_t error = Wire.endTransmission();

  if (error != 0) {
    return "ERROR";
  }

  delay(waitMs);

  Wire.requestFrom((int)address, 20);

  while (Wire.available()) {
    char c = Wire.read();

    if (c == '\0') {
      break;
    }

    result += c;
  }

  return result;
}

void setup() {
  Serial.begin(115200);

  Wire.begin(SDA_PIN, SCL_PIN);
  Wire.setClock(100000);

  Serial.println("I2C Sensor Reading Start...");
}

void loop() {
  String temperature = readEzo(RTD_ADDR, 1100);
  String ph = readEzo(PH_ADDR, 1100);
  String dissolvedOxygen = readEzo(DO_ADDR, 1100);
  String conductivity = readEzo(EC_ADDR, 1100);

  Serial.print("T=");
  Serial.print(temperature);

  Serial.print("  pH=");
  Serial.print(ph);

  Serial.print("  DO=");
  Serial.print(dissolvedOxygen);

  Serial.print("  EC=");
  Serial.println(conductivity);

  delay(3000);
}

九、常見錯誤如何判斷?

現象可能原因先做什麼
Scanner 找不到裝置SDA/SCL 錯誤、供電、Enable、位址改變確認接線並重新掃描
endTransmission() 不等於 0裝置沒有 ACK確認位址是否存在
No Data等待時間不足或感測 IC 尚未完成延長至 1100 ms
數值明顯不合理探棒未浸水、未校正、缺少溫度補償確認探棒與校正狀態
只有某一顆失效位址錯誤或單一模組問題單獨讀取該模組

十、從感測器到 Dashboard

I²C 感測 IC ESP32 Wi-Fi JSON Django REST API Dashboard
完成本篇後,學生已經能把「I²C 理論」轉換成「真正可執行的感測器程式」。下一篇可進一步介紹如何把資料上傳 Django REST API。

十一、本篇重點

  1. 先用 I²C Scanner 確認裝置是否存在。
  2. 每顆 IC 都使用不同 Address。
  3. 送出 R 指令後要等待感測器處理。
  4. 回傳資料通常是字串,需要解析。
  5. 硬體、位址、等待時間與校正,是除錯的四個重點。

結語

ESP32 讀取 I²C 感測器的核心流程並不複雜:指定 Address、送出命令、等待處理、讀回資料。真正的工程能力,來自能否用 Scanner、錯誤碼與序列監控快速定位問題。透過 Atlas Aquaponics Kit 的實際案例,大一新生可以把 IC 通訊、感測器、Arduino 程式與智慧養殖應用連結起來。

AI 協作聲明:本文由作者主導教學目標、硬體測試、程式驗證與案例設計,並使用生成式 AI 協助文字整理、程式碼說明、版面配置與教學資訊圖生成;文章中的 ESP32 腳位、I²C 位址、Atlas EZO 讀取流程與除錯經驗,均依本專案實際測試結果整理,並由作者審核修訂。

[水井村USR] EP02|Atlas Scientific 四種水質感測器解析

智慧生活科技專業社群|IoT 入門系列

本篇延續 EP01〈什麼是 I²C?ESP32 如何與 IC 溝通?〉,介紹 Atlas Scientific Aquaponics Kit 中最重要的四種水質感測器,透過實際測試案例,讓大一新生了解智慧養殖系統如何量測水質。


一、智慧養殖需要量測哪些水質?

感測器量測項目用途
RTD水溫所有感測器溫度補償
pH酸鹼值了解水質是否適合養殖
DO溶氧魚蝦是否有足夠氧氣
EC導電度推估鹽度、離子濃度

二、RTD 水溫感測器

RTD(Resistance Temperature Detector)利用金屬電阻隨溫度改變的特性量測水溫。本次系統中,RTD 並不只是量測溫度,更提供 pH、DO、EC 三個感測器進行溫度補償

RTD.send_read_cmd();

PH.send_cmd_with_num("T,", temperature);
DO.send_cmd_with_num("T,", temperature);
EC.send_cmd_with_num("T,", temperature);
沒有正確的水溫補償,pH、DO 與 EC 的量測值都可能產生誤差。

三、pH 感測器

pH 值代表水中酸鹼程度,7 為中性,小於 7 為酸性,大於 7 為鹼性。

pH代表意義
0~6.9酸性
7中性
7.1~14鹼性

本次測試結果:

pH:6.80

四、DO 溶氧感測器

DO(Dissolved Oxygen)代表水中溶解氧濃度,通常以 mg/L 表示。

DO (mg/L)狀況
<3容易缺氧
5~8一般養殖
>8氧氣充足

本次系統曾成功讀得:

DO:31.92 mg/L

提醒:若未浸入水中,DO 數值可能偏高,不代表實際養殖池狀況。

五、EC 導電度感測器

EC(Electrical Conductivity)表示水中離子濃度,以 μS/cm 為單位。

本次實驗最大的收穫,就是利用 I²C Scanner 發現 EC 模組位址已不是預設的 0x64,而是:

0x69
工程實務中,不要假設感測器一定使用原廠預設位址。先掃描 I²C Bus,再開始寫程式,是良好的開發習慣。

六、四個感測器如何一起工作?

請插入:
探棒 → EZO IC → I²C → ESP32 → Wi-Fi → Django REST API → Dashboard

ESP32 的工作流程如下:

  1. 讀取 RTD 水溫。
  2. 將溫度送給 pH、DO、EC。
  3. 讀取三個感測值。
  4. 組成 JSON。
  5. 透過 REST API 上傳 Django。
  6. Dashboard 即時更新。

七、實際測試結果

水溫:30.01 °C
pH:6.80
DO:31.92 mg/L
EC:441 uS/cm

這代表 Atlas Scientific Aquaponics Kit 已完成四項水質量測,並可作為智慧養殖 IoT 系統的資料來源。

結語

四種感測器各自負責不同工作,但真正的重點不是單一感測器,而是它們透過 I²C 匯流排共同合作,再由 ESP32 整合資料、送往 Django REST API,形成完整的智慧養殖資訊系統。


AI 協作聲明

本文由作者規劃教學架構、完成 Atlas Scientific Aquaponics Kit 實際測試與驗證,並使用生成式 AI 協助文章整理、程式碼說明、版面設計與圖片建議;所有技術內容、測試數據與系統架構均由作者確認後發布。

[水井村USR] EP01|什麼是 I²C?ESP32 如何與 IC 溝通?

智慧生活科技專業社群|IoT 入門系列|適合大一新生
I²C 是「IC 與 IC 之間的通訊協定」。在智慧養殖系統中,ESP32 並不是直接讀取探棒,而是透過 I²C 與 pH、溶氧、導電度及溫度等智慧感測 IC 溝通。本篇從 Atlas Scientific Aquaponics Kit 的實際案例出發,帶大一新生認識 SDA、SCL、Address、Master/Slave 與 I²C Scanner。


請先將 EP01 教學圖上傳 Blogger,再把 HTML 中的 I2C_EP01_IMAGE_URL 換成圖片網址。
圖:I²C 兩線式通訊、Address、掃描與智慧養殖應用。

一、ESP32 真的直接讀探棒嗎?

很多初學者看到 pH 探棒或溶氧探棒,會直覺認為 ESP32 直接從探棒取得數值。實際上,多數智慧感測系統的結構是:

探棒 感測 IC I²C ESP32

探棒負責感受物理或化學變化;感測 IC 則負責放大訊號、類比數位轉換、校正、補償與資料處理。ESP32 最後只要向感測 IC 詢問:「請把目前數值告訴我。」

重要觀念:真正與 ESP32 溝通的是感測 IC,不是探棒本身。

二、什麼是 IC?

IC 是 Integrated Circuit 的縮寫,中文稱為「積體電路」。一顆看似很小的晶片,裡面可能包含:

MCU執行程式與控制量測流程。
ADC把類比訊號轉換成數位資料。
Calibration保存校正資料與修正係數。
Communication透過 UART、I²C 或 SPI 與其他 IC 溝通。

以 Atlas EZO-pH 為例,ESP32 不需要自己把電壓換算成 pH,而是送出讀取命令,EZO-pH 內部完成計算後再回傳:

概念示例
ESP32:R
pH IC:6.80

三、I²C 是什麼?

I²C 全名為 Inter-Integrated Circuit,意思就是「積體電路與積體電路之間的通訊」。它是一種同步、序列式、多裝置共用的通訊協定。

2 條線SDA、SCL
多裝置共用一條 Bus
Address每顆 IC 有門牌
同步由 Clock 控制節奏

四、I²C 只需要兩條訊號線

訊號全名功能
SDASerial Data傳送位址、命令與資料。
SCLSerial Clock提供時脈,讓所有裝置在相同節奏下交換資料。

多顆感測 IC 可以共用同一組 SDA 與 SCL,因此不用為每一顆感測器都準備一組獨立通訊線。

ESP32 SDA/SCL Bus pH IC、DO IC、EC IC、RTD IC

五、Address 就像每顆 IC 的門牌號碼

所有 IC 雖然共用 SDA 與 SCL,但每顆 IC 都必須有自己的 Address。ESP32 送出某個位址時,只有符合該位址的 IC 會回答。

感測 IC十六進位位址十進位位址
EZO-DO0x6197
EZO-pH0x6399
EZO-RTD0x66102
本系統 EZO-EC0x69105
除錯經驗:不要假設裝置一定維持原廠預設位址。本次智慧養殖系統的 EC 位址已被修改為 0x69,因此一定要先掃描實際 I²C Bus。

六、Master 與 Slave 在做什麼?

入門階段可以先把 ESP32 視為 Master,把各個感測 IC 視為 Slave。

Master:ESP32決定何時開始通訊、要跟哪一個位址對話,以及要讀取或寫入資料。
Slave:感測 IC監聽自己的位址,被點名後回應命令或提供資料。

七、一次 I²C 讀取大致發生什麼事?

  1. ESP32 送出 Start 訊號。
  2. ESP32 傳送目標 IC 的 Address。
  3. 目標 IC 回覆 ACK,表示「我在這裡」。
  4. ESP32 傳送讀取命令,例如 R
  5. IC 完成量測或計算。
  6. ESP32 向 IC 請求資料。
  7. IC 回傳數值。
  8. ESP32 送出 Stop,結束本次通訊。
Arduino Wire Library 概念流程
Wire.beginTransmission(0x63);
Wire.write("R");
Wire.endTransmission();

delay(1000);

Wire.requestFrom(0x63, 20);

八、I²C Scanner:工程師的第一個除錯工具

當感測器沒有資料時,不應立刻懷疑探棒故障。第一步應先確認該 IC 是否真的出現在 I²C Bus 上。

I²C Scanner 範例
#include <Wire.h>

void setup() {
  Serial.begin(115200);
  Wire.begin(23, 22);

  for (uint8_t address = 1; address < 127; address++) {
    Wire.beginTransmission(address);
    uint8_t error = Wire.endTransmission();

    if (error == 0) {
      Serial.print("找到 I2C 位址:0x");

      if (address < 16) {
        Serial.print("0");
      }

      Serial.println(address, HEX);
    }
  }
}

void loop() {
}

正常掃描可能得到:

掃描結果
找到 I2C 位址:0x61
找到 I2C 位址:0x63
找到 I2C 位址:0x66
找到 I2C 位址:0x69

九、從 Atlas Aquaponics Kit 看 I²C 的實際應用

在本次智慧養殖系統中,ESP32 透過同一條 I²C Bus 與四顆 EZO 感測 IC 溝通:

RTD 水溫 pH DO 溶氧 EC 導電度 ESP32

ESP32 先讀取 RTD 水溫,再把溫度送給 pH、DO 與 EC 進行溫度補償,最後取得完整水質資料。

溫度補償概念
RTD.send_read_cmd();

PH.send_cmd_with_num("T,", temperature);
DO.send_cmd_with_num("T,", temperature);
EC.send_cmd_with_num("T,", temperature);

十、I²C 只是 IoT 資料鏈的第一段

I²C 解決的是「板子內部 IC 與 IC 的通訊」。當 ESP32 取得資料後,還會經過 Wi-Fi、JSON、REST API、資料庫與 Dashboard。

探棒 感測 IC I²C ESP32 Wi-Fi Django REST API Dashboard
從 I²C 到 REST API,學生可以看到一筆水質資料如何從探棒一路走到雲端,形成完整的 IoT 系統。

十一、大一新生應記住的五個重點

  1. I²C 是 IC 與 IC 之間的通訊協定。
  2. I²C 主要使用 SDA 與 SCL 兩條訊號線。
  3. 多顆 IC 可以共用同一條 Bus。
  4. 每顆 IC 必須有不同的 Address。
  5. 感測器沒有資料時,先用 I²C Scanner 確認裝置是否存在。

十二、課後思考

  • 如果兩顆 IC 使用相同 Address,會發生什麼事?
  • I²C 與 UART、SPI 有什麼不同?
  • 為什麼 SDA 與 SCL 通常需要上拉電阻?
  • 如果 I²C 線太長,通訊會遇到什麼問題?
  • 如何把掃描到的位址轉換成裝置名稱?

結語

I²C 看似只是兩條線,背後卻包含 Address、時脈、ACK、讀寫方向與匯流排共享等重要概念。對大一新生而言,先理解「ESP32 是如何點名某一顆 IC,再讀回資料」,就掌握了 I²C 的核心。從智慧養殖案例出發,也能進一步理解感測、通訊、雲端與 Dashboard 如何串成完整的智慧生活科技系統。

AI 協作聲明:本文由作者主導教學目標、案例選擇、實作測試與內容架構,並使用生成式 AI 協助文字整理、程式碼說明、版面設計與教學圖生成;文章中的 Atlas Aquaponics Kit、ESP32 腳位、I²C 位址與感測流程,均依本專案實際測試結果整理,並由作者審核修訂。