上一章我們完成:
DHT22
│
├── Temperature
└── Humidity
↓
Raspberry Pi
↓
Python
資料目前主要顯示在:
Terminal
但真正的獨立式電子設備,不一定會接:
- HDMI Monitor
- Keyboard
- SSH Terminal
因此這一章,我們要增加:
LCD1602
讓 Raspberry Pi 可以直接顯示:
Temp: 27.5 C
Humi: 63.2 %
而 LCD1602 如果使用傳統 Parallel Interface,可能需要很多 GPIO。
加入:
I²C Backpack
之後,主要通訊只需要:
SDA
+
SCL
兩條 Signal Line。
I²C 的重要優點之一,就是一個 Controller 能透過兩條 Bus 線和多個具有不同位址的 Peripheral 通訊。
1. I²C 是什麼?
I²C:
Inter-Integrated Circuit
是一種同步式序列通訊 Bus。
典型架構:
Raspberry Pi
I²C Controller
│
├──── SDA ───────────────┐
│ │
└──── SCL ───────────────┤
│
┌──────────────────┼─────────┐
│ │ │
Sensor LCD RTC
0x76 0x27 0x68
多個裝置可以共用同一組 SDA / SCL,只要位址設計沒有衝突。TI 的 I²C 說明文件也以單一 Controller 加多個 Target Device 的兩線架構說明 I²C 的主要優點。
2. Master / Slave 和 Controller / Target
較舊的 I²C 文件常使用:
Master
Slave
現代技術文件也常改稱:
Controller
Target
本章主要使用:
Raspberry Pi
=
Controller
LCD / Sensor
=
Target Device
閱讀舊 Datasheet 時看到 Master / Slave,概念基本上仍對應同一類角色。
3. I²C 只有兩條主要訊號線
兩條核心 Signal:
SDA
SCL
SDA
Serial Data。
負責:
Address
Data
ACK / NACK
等資料。
SCL
Serial Clock。
由通訊時序控制端產生 Clock,協調資料傳輸。
I²C 是雙線式 Bidirectional Bus;TI 的 I²C 官方說明也將 SDA 與 SCL 視為主要的兩條 Bus 線。
4. Raspberry Pi 標準 I²C Pin
Raspberry Pi 40-pin Header 的主要 I²C:
SDA
=
GPIO2
=
Physical Pin 3
以及:
SCL
=
GPIO3
=
Physical Pin 5
Raspberry Pi 官方 GPIO 文件確認 GPIO2 / GPIO3 是標準 I²C Data / Clock Pin,並且這兩支腳位具有固定 Pull-up。
5. 本章 Pin Table
| 功能 | BCM GPIO | Physical Pin |
|---|---|---|
| I²C SDA | GPIO2 | Pin 3 |
| I²C SCL | GPIO3 | Pin 5 |
| 3.3V | — | Pin 1 / 17 |
| 5V | — | Pin 2 / 4 |
| GND | — | Pin 6 等 |
Raspberry Pi GPIO 的一般邏輯電壓為 3.3V;GPIO2 與 GPIO3 的 I²C Pull-up 也屬於 Raspberry Pi 的 3.3V Domain。
6. I²C 和 UART 有什麼不同?
UART:
TX
RX
通常屬於 Point-to-point Serial Communication。
I²C:
SDA
SCL
可以在同一個 Bus 上掛:
Device A
Device B
Device C
Device D
靠:
I²C Address
辨識要和哪一個裝置通訊。
7. I²C 和 SPI 有什麼不同?
SPI 常見:
MOSI
MISO
SCLK
CS
每個 Target 通常還需要 Chip Select。
I²C 則主要共用:
SDA
SCL
並使用:
Address
識別裝置。
因此大量低速 Sensor、RTC、GPIO Expander 很常使用 I²C。Raspberry Pi 官方目前也將 I²C 描述為適合 Sensor、RTC 等低速 Peripheral 的硬體通訊介面。
8. I²C Address 是什麼?
假設:
LCD = 0x27
RTC = 0x68
Sensor = 0x76
Controller 可以送:
Address = 0x27
表示:
接下來我要和 LCD 通訊。
所以同一個 Bus:
SDA + SCL
能掛很多裝置的核心原因就是:
Addressing
9. I²C 常見使用 7-bit Address
Linux 與大部分 Raspberry Pi Python Library,通常使用:
7-bit I²C Address
例如:
0x20
0x27
0x3F
0x68
PCF8574 Datasheet 有時也會列出包含 R/W Bit 的 8-bit Read / Write Address,因此閱讀 Datasheet 時要注意不要把 8-bit Address 直接當 Linux 的 7-bit Address 使用。TI PCF8574 資料表的 Address Reference 就同時呈現了 Write/Read 形式。
10. 0x27 是十六進位
例如:
0x27
其中:
0x
表示:
Hexadecimal
也就是十六進位。
I²C Tool 與 Datasheet 通常用 Hex 顯示 Address。
所以:
27
和:
0x27
不是在所有情況下都表示同一個數字。
11. 為什麼 I²C 需要 Pull-up?
I²C SDA / SCL 使用 Open-drain 類型的 Bus 概念。
裝置主要會:
主動拉 LOW
或:
Release Bus
Bus 回 HIGH 需要 Pull-up Resistor 完成。TI 的 I²C 原理文件專門將 Open-drain 與 Pull-up 說明為 I²C 雙向通訊的核心電氣特性。
12. I²C 不是一般 Push-pull HIGH
可以想成:
Device
│
├── 拉 LOW
│
└── 放開
而:
Pull-up
│
▼
Bus HIGH
這就是為什麼:
I²C Level Shifter 必須適合 Open-drain Bidirectional Bus。
不能隨便拿只適合單方向 Push-pull Signal 的轉換方式套上去。
13. Raspberry Pi GPIO2 / GPIO3 已有 Pull-up
Raspberry Pi 官方文件指出:
GPIO2
GPIO3
具有固定 Pull-up Resistor。
因此在簡單 3.3V I²C Device Lab 中,通常不需要再盲目增加一堆強 Pull-up。
不過完整 I²C Bus 的 Pull-up 設計仍需考慮:
- Device 內建 Pull-up
- Bus Capacitance
- Wire Length
- Clock Frequency
- Parallel Pull-up
TI 也有專門文件討論 I²C Pull-up Resistor 的計算與速度/功耗取捨。
14. 多塊 Module 都有 Pull-up 會怎樣?
假設:
Module A
4.7kΩ
Module B
4.7kΩ
Module C
4.7kΩ
全部平行接在同一 Bus。
等效 Pull-up Resistance 會下降。
所以:
有 Pull-up
不代表:
越多越好。
大型 I²C Project 應該檢查整條 Bus,而不是只看單一 Module。I²C Pull-up 值本來就需依 Bus 電容與時序條件設計。
15. Raspberry Pi OS 預設要先啟用 I²C
目前 Raspberry Pi OS 可從:
Preferences
→ Control Centre
→ Interfaces
→ I2C
開啟 I²C。
也可以使用:
sudo raspi-config
目前官方 raspi-config 路徑為:
3 Interface Options
↓
I5 I2C
↓
Yes
啟用後,Raspberry Pi OS 會開啟 ARM I²C Interface 並在開機時載入相關 Kernel Module。
16. 使用 raspi-config 啟用 I²C
執行:
sudo raspi-config
選:
3 Interface Options
再:
I5 I2C
回答:
Yes
完成:
OK
Finish
這是目前 Raspberry Pi 官方提供的標準方法。
17. 也可以檢查 config.txt
Raspberry Pi Device Tree 支援:
dtparam
來啟用 I²C、SPI 等 Interface。官方 config.txt 文件仍將 I²C 列為 dtparam 可控制的硬體功能。
一般初學者建議優先使用:
Control Centre
或:
raspi-config
而不是手動亂改 Boot Configuration。
18. 安裝 i2c-tools
在 Raspberry Pi OS:
sudo apt update
然後:
sudo apt install -y i2c-tools
Debian Trixie 目前提供 i2c-tools Package,其中包含 i2cdetect、i2cget、i2cset、i2ctransfer 等 Linux I²C Utility。
19. 先列出 I²C Bus
推薦先:
i2cdetect -l
而不是立即假設 Bus Number。
i2cdetect 官方 Manpage 明確說明 Bus Number 應該對應 i2cdetect -l 所列出的 Adapter。
20. Raspberry Pi 40-pin 通常使用 Bus 1
現代 Raspberry Pi 的主要 40-pin GPIO2 / GPIO3 I²C 介面通常會以:
i2c-1
出現在 Linux。
RPLCD 的 Raspberry Pi I²C 使用文件也將預設 I²C Port 設為:
port=1
並以 Bus 1 為一般 Raspberry Pi I²C 範例。
但正式程式仍推薦:
先用 i2cdetect -l 確認。
21. 查看 Device Node
可以:
ls -l /dev/i2c-*
若 I²C Interface 正常啟用,通常會看到類似:
/dev/i2c-1
Linux Python 的 SMBus Binding 正是透過 /dev I²C Interface 存取 Kernel I²C Bus。
22. I²C Scanner
確定 Bus 為:
1
後,可以:
sudo i2cdetect -y 1
i2cdetect 會掃描指定 I²C Bus,並顯示有回應的 Target Address。
23. Scanner 輸出範例
假設 LCD Address:
0x27
可能看到:
0 1 2 3 4 5 6 7 8 9 a b c d e f
00:
10:
20: 27
30:
40:
50:
60:
70:
表示:
I²C Device found at 0x27
24. -- 是什麼?
i2cdetect 表格中:
--
表示該 Address 被 Probe,但沒有 Device 回應。
25. UU 是什麼?
如果看到:
UU
表示 Scanner 沒直接 Probe 該 Address,通常是因為該位址已被 Kernel Driver 使用。
Debian i2cdetect Manpage 說明 UU 強烈暗示該地址確實存在 Device,只是目前已由 Driver Claim。
26. i2cdetect 不是完全無風險
這一點很重要。
i2cdetect 並沒有一個所有 I²C Device 都能安全回答的標準「Who are you?」命令。
它會使用不同 SMBus Probe 操作偵測 Device;官方 Manpage 甚至直接警告,對某些裝置掃描可能:
- Confuse Device
- Cause Data Loss
- 產生更嚴重結果
因此 Scanner 應該當:
Diagnostic Tool
而不是高頻率一直掃 Bus。
27. 本章簡單 LCD Lab 可以掃嗎?
對只有:
PCF8574 LCD Backpack
的教學 Bus,我們會使用:
sudo i2cdetect -y 1
確認 Address。
但未來如果同一 Bus 掛有:
- EEPROM
- PMIC
- 特殊 Controller
- 已由 Kernel Driver 控制的 Device
不要隨意反覆掃描。
28. LCD1602 是什麼?
LCD1602 表示典型 Character LCD:
16 Characters
×
2 Lines
例如:
Raspberry Pi 5
Temp: 27.5 C
RPLCD 支援常見 HD44780-compatible Character LCD,並可透過 GPIO Parallel 或 I²C Port Expander 控制。
29. 傳統 LCD1602 有很多 Pin
一般 Parallel LCD 需要:
- RS
- E
- D4
- D5
- D6
- D7
以及:
- Power
- Contrast
- Backlight
如果直接接 GPIO,會占用很多 Pin。
30. I²C Backpack 做什麼?
I²C Backpack 在:
Raspberry Pi
和:
LCD Parallel Interface
之間增加:
I²C I/O Expander
典型使用:
PCF8574
架構:
Raspberry Pi
│
│ SDA / SCL
▼
PCF8574
│
│ Parallel GPIO
▼
LCD1602
PCF8574 本身就是 8-bit I²C I/O Expander。
31. PCF8574 是什麼?
TI 目前 PCF8574 為:
8-bit
2.5V~5.5/6V class
I²C I/O Expander
它透過 SDA / SCL 提供 8 個 Quasi-bidirectional I/O,可用來把兩條 I²C Bus 轉換成 LCD 所需的 Parallel Control Signal。
32. 為什麼 LCD Backpack 常看到 0x27?
PCF8574 的 7-bit Address 由:
A2
A1
A0
決定。
TI 的 PCF8574 / PCF8574A Address Map 為:
PCF8574
0x20 ~ 0x27
PCF8574A
0x38 ~ 0x3F
所以:
0x27
只是 PCF8574 Address Range 的其中一個位址。
33. 0x3F 又是什麼?
如果 Backpack 使用:
PCF8574A
Address Range 為:
0x38 ~ 0x3F
因此很多教學也會看到:
0x3F
34. LCD Address 不一定是 0x27 或 0x3F
不要直接把程式固定成:
address=0x27
然後 LCD 不動就以為 Raspberry Pi 壞掉。
正確方式:
sudo i2cdetect -y 1
實際掃描。
RPLCD 官方 Getting Started 也要求先找出實際 LCD I²C Address,再建立 CharLCD。
35. Address 焊盤可以修改
很多 PCF8574 Backpack 有:
A0
A1
A2
Solder Jumper。
透過:
Open
Short
改變 Address。
因此同樣外觀的兩塊 LCD:
可能不是同一 Address。
PCF8574 本身就是透過 A2/A1/A0 三個 Hardware Address Input 產生八個可選地址。
36. 同一 Bus 可以接兩個 LCD 嗎?
可以,只要:
LCD1
Address A
與:
LCD2
Address B
不同。
例如:
0x26
0x27
PCF8574 支援八個 Address,PCF8574A 也另有八個 Address。
37. Address Conflict 是什麼?
假設:
LCD1 = 0x27
LCD2 = 0x27
接在:
同一 SDA / SCL
Controller 送:
0x27
兩個 Device 可能同時回應。
這就是:
I²C Address Conflict
通常要:
- 改 Address
- 使用 Multiplexer
- 換 Bus
處理。
38. LCD1602 電壓是一個大陷阱
很多 LCD1602 + Backpack 設計以:
5V
驅動 LCD 與 Backlight。
但 Raspberry Pi GPIO:
3.3V Logic
因此不能只看到:
VCC
GND
SDA
SCL
四個 Pin 就毫不檢查直接接。
39. PCF8574 本身可以 5V 工作
PCF8574 的 Supply Voltage 支援大約:
2.5V ~ 6V
範圍。
問題在於:
I²C Logic Threshold 會跟 VCC 有關。
40. PCF8574 在 5V 時的 HIGH Threshold
TI Datasheet 規定:
VIH(min)
=
0.7 × VCC
如果:
VCC = 5V
則:
VIH(min)
=
3.5V
但 Raspberry Pi HIGH:
約 3.3V
因此:
5V PCF8574 並不能在 Datasheet 規格上保證 3.3V HIGH 一定被判定為 HIGH。
41. 這就是為什麼「我的 LCD 直接接也能用」不等於設計正確
某些 Module:
實際上可能能工作。
但:
能亮
和:
符合 Worst-case Electrical Specification
不是同一件事。
正式教學應避免把:
可能工作
寫成:
保證安全穩定。
PCF8574 的 Datasheet Threshold 就顯示出這個設計餘裕問題。
42. 另一個更危險的問題:Pull-up 到 5V
I²C 是 Open-drain Bus。
如果 Backpack 上 SDA / SCL 的 Pull-up Resistor 被拉到:
5V
那 Bus Release 後 SDA / SCL 就可能往:
5V
上升。
但 Raspberry Pi GPIO 是 3.3V Logic。
因此:
必須確認 Backpack 的 Pull-up 接到哪個電壓。
43. 最安全的 5V LCD I²C 架構
如果 LCD / PCF8574 Backpack 要 5V 運作,本系列推薦:
Raspberry Pi 3.3V Side
GPIO2 SDA ─────┐
GPIO3 SCL ─────┤
│
Bidirectional
I²C Level Shifter
│
├──── SDA → LCD Backpack
└──── SCL → LCD Backpack
Pi side pull-up
→ 3.3V
LCD side pull-up
→ 5V
這樣:
Raspberry Pi Side
=
3.3V
LCD Side
=
5V
兩邊分開。
44. 為什麼必須是 Bidirectional I²C Level Shifter?
因為:
SDA
本身是雙向資料線。
SCL 在某些情況也可能涉及 Clock Stretch 等雙向 Open-drain 行為。
因此 Level Shifter 必須適合:
I²C Open-drain Bidirectional Bus。
RPLCD 文件也明確提醒 3.3V Raspberry Pi 與 5V I²C Backpack 之間可能需要支援 I²C 的 Level Shifter,以避免可靠度甚至硬體損壞問題。
45. 本章不推薦的接法
不要直接教學成:
Pi 5V
│
LCD VCC
Pi GPIO2
│
LCD SDA
Pi GPIO3
│
LCD SCL
卻完全不檢查:
Backpack Pull-up Voltage
PCF8574 Supply
Logic Threshold
這種「四條線直接插」雖然網路上非常常見,但缺少重要的電氣安全條件。
46. 如果 Backpack 已確認 3.3V Compatible 呢?
如果製造商明確標示:
Raspberry Pi compatible
3.3V logic
並且:
SDA/SCL 不會被 Pull-up 到 5V
就可以依該 Module 的官方 Wiring 使用。
關鍵不是:
所有 LCD 都一定要 Level Shift
而是:
先確認電氣規格,再接。
47. 本章建議硬體架構
為了教材安全,本章採:
Raspberry Pi 5
│
│ 3.3V I²C
▼
Bidirectional
I²C Level Shifter
│
│ 5V I²C
▼
PCF8574 Backpack
│
▼
LCD1602
這樣後續程式不會因為硬體電壓設計而模糊。
48. Level Shifter 接線概念
Pi Side:
LV
→ 3.3V
GND
→ Pi GND
LV1
↔ SDA GPIO2
LV2
↔ SCL GPIO3
LCD Side:
HV
→ 5V
GND
→ Common GND
HV1
↔ LCD SDA
HV2
↔ LCD SCL
實際模組 Label 可能不同:
LV1/HV1
TXS...
A/B
請依 Level Shifter Datasheet 接線。
49. 一定要 Common Ground
Raspberry Pi、Level Shifter、LCD:
GND
必須有共同 Reference。
架構:
Pi GND
│
├── Level Shifter GND
│
└── LCD GND
否則兩側 Signal Voltage 沒有共同參考基準。
50. LCD Backlight 亮不代表 I²C 成功
這也是初學常見誤判。
如果:
LCD Backlight ON
只代表:
Power
可能有供電。
不代表:
SDA
SCL
Address
Python Library
都正確。
51. 第一個測試永遠先跑 Scanner
在寫 Python 前:
i2cdetect -l
確認 Bus。
然後:
sudo i2cdetect -y 1
確認 LCD Address。
如果 Scanner 都看不到:
0x20~0x27
或:
0x38~0x3F
先不要 Debug Python。
PCF8574 / PCF8574A 的 7-bit Address Range 就位在上述範圍。
52. Scanner 完全沒有 Device
例如全部:
--
先檢查:
I²C enabled?
SDA?
SCL?
GND?
Power?
Level Shifter?
LCD Backpack?
而不是先:
pip install 5 個 LCD Library
53. SDA / SCL 接反會怎樣?
如果:
GPIO2 SDA
接到:
LCD SCL
而:
GPIO3 SCL
接:
LCD SDA
Bus 通常不會正常通訊。
所以記:
SDA → SDA
SCL → SCL
不像 UART:
TX → RX
RX → TX
I²C 不交叉。
54. Python 選用 RPLCD
本章 LCD Python Library 使用:
RPLCD
目前 PyPI 的 RPLCD 1.4.0 支援 Python 3,支援 HD44780-compatible Character LCD,而且 I²C Mode 支援 PCF8574、MCP23008、MCP23017 等 Port Expander。
55. 為什麼 RPLCD 適合 Pi 5 I²C?
I²C Mode 使用:
Linux SMBus / I²C
而不是依賴 Raspberry Pi 5 不相容的舊 Direct GPIO Register Access。
RPLCD I²C Source 會優先使用 smbus,找不到時使用 smbus2,並透過指定 I²C Port 開啟 Bus。
56. smbus2
smbus2 是 Pure Python SMBus / Linux I²C Library,目前 PyPI 最新版為 0.6.1,發布於 2026 年 4 月,支援 Python 3 並提供 SMBus 與完整 I²C transaction API。
本章使用:
RPLCD
+
smbus2
57. 建立 Chapter 12 Project
cd ~
建立:
mkdir -p raspberrypi-course/chapter12
進入:
cd raspberrypi-course/chapter12
58. 建立 Virtual Environment
現代 Raspberry Pi OS 使用 pip Package 時,延續前面章節的 Project venv:
python3 -m venv .venv \
--system-site-packages
啟動:
source .venv/bin/activate
59. 安裝 Python LCD Library
在:
(.venv)
中:
python -m pip install \
--upgrade \
RPLCD \
smbus2
RPLCD 官方目前支援使用 smbus2 作為 I²C Backend,而 smbus2 官方 PyPI 安裝方式就是 pip。
60. 再確認 Scanner Address
假設:
sudo i2cdetect -y 1
結果是:
27
則:
LCD_ADDRESS = 0x27
如果是:
3f
則:
LCD_ADDRESS = 0x3F
不要硬套別人的 Address。
61. 第一支 LCD1602 Python 程式
建立:
nano lcd_hello.py
程式:
from RPLCD.i2c import CharLCD
LCD_ADDRESS = 0x27
lcd = CharLCD(
i2c_expander="PCF8574",
address=LCD_ADDRESS,
port=1,
cols=16,
rows=2,
auto_linebreaks=False
)
try:
lcd.clear()
lcd.write_string(
"Raspberry Pi 5"
)
lcd.cursor_pos = (
1,
0
)
lcd.write_string(
"I2C LCD Ready"
)
finally:
lcd.close(
clear=False
)
RPLCD 官方 I²C API 使用 CharLCD 建立 PCF8574 LCD,並支援指定 Address、Port、Columns、Rows;文字使用 write_string(),游標則使用 (row, col) 格式的 cursor_pos。
62. 執行程式
python lcd_hello.py
預期:
Raspberry Pi 5
I2C LCD Ready
63. lcd.clear()
lcd.clear()
會清除畫面並讓 Cursor 回到開始位置。這是 RPLCD 官方提供的 Display Method。
64. write_string()
lcd.write_string(
"Hello"
)
就是向 Character LCD 寫入文字。
RPLCD 官方 API 以 write_string() 寫 Unicode String 到顯示器。
65. cursor_pos
例如:
lcd.cursor_pos = (
1,
0
)
表示:
Row 1
Column 0
也就是第二行第一個 Character Position。RPLCD 的 Cursor Position 使用 (row, col) Tuple。
66. 為什麼第二行是 Row 1?
Python / RPLCD Index:
第一行
=
Row 0
第二行
=
Row 1
所以:
(1, 0)
代表:
第二行第一格。
67. LCD1602 每行只有 16 個字元
例如:
1234567890123456
就是:
16 Columns
所以設計 UI 時應該儘量控制字串長度。
不要直接把很長 Terminal Message 全塞進 16×2 LCD。
68. 顯示器通常不能直接顯示任意中文字
HD44780-compatible Character LCD 使用固定 Character ROM / Character Map,不是一般 Unicode Graphic Display。
RPLCD 支援 A00、A02、ST0B 等 Character Map,另外 HD44780 類顯示器也只有少量自訂 Character Slot。
因此本章 LCD 顯示採:
英文
數字
符號
比較可靠。
69. 溫度符號 ° 可能受 Character Map 影響
不同 LCD Clone:
A00
A02
ST0B
Character Map 可能不同。
如果:
°
顯示錯誤,最簡單做法就是:
27.5 C
而不是硬依賴某個特殊 Character。
RPLCD 官方也提醒 Character Map 必須配合實際 LCD Controller。
70. LCD 只有 Backlight、沒有文字
這是非常常見的情況。
先檢查:
Contrast Potentiometer
PCF8574 Backpack 通常有一顆:
Blue Potentiometer
調整 LCD Contrast。
如果 Contrast 太低或太高:
Backlight 亮
但是看不到正常文字
71. 一排黑方塊代表什麼?
如果 LCD:
有電
有 Contrast
但 Controller 尚未正確初始化,常會看到:
████████████████
這通常應優先檢查:
I2C Communication
Address
Backpack Pin Mapping
Library
而不是認為 LCD Glass 已經壞掉。
72. RPLCD 的 PCF8574 Pin Mapping 不一定適合所有 Backpack
RPLCD 預設 PCF8574 Mapping 為:
P7 D7
P6 D6
P5 D5
P4 D4
P3 BL
P2 EN
P1 RW
P0 RS
如果你的 Backpack PCB 使用完全不同 Wiring,可能:
i2cdetect 看得到
但 LCD 還是不顯示。
這時需要查 Backpack Schematic。
73. Scanner 找得到代表哪一層成功?
如果:
i2cdetect -y 1
看到:
27
代表大致:
Raspberry Pi
→ I²C Bus
→ PCF8574
已能通訊。
但尚未證明:
PCF8574
→ LCD1602
Mapping、Contrast、LCD 初始化一定正確。
74. 分層 Debug 非常重要
LCD 不顯示時應拆成:
Layer 1
Power
Layer 2
SDA / SCL
Layer 3
I²C Address
Layer 4
PCF8574
Layer 5
LCD Pin Mapping
Layer 6
Contrast
Layer 7
Python UI
不要所有問題都歸咎:
Python。
75. 不要使用 i2cset 亂寫未知 Device
i2cset 可以直接寫 I²C Device Register / Data。
Debian 官方 Manpage 明確警告,強制或錯誤寫入可能混亂 Kernel Driver 或對裝置寫錯資料。
所以初學:
i2cdetect
用來找 Address,
LCD 控制交給:
RPLCD
即可。
76. 更新 LCD 不要每次都亂 clear()
例如每 0.1 秒:
lcd.clear()
lcd.write_string(...)
可能造成:
Flicker
更好的方法:
固定 Cursor
+
寫固定 16 字元
避免畫面不斷全清除。
77. 固定寬度文字
例如:
line1 = (
f"Temp:{temperature:5.1f} C"
)
line2 = (
f"Humi:{humidity:5.1f} %"
)
再補到 16 字元:
line1 = line1.ljust(16)[:16]
line2 = line2.ljust(16)[:16]
這可以把舊字元覆蓋乾淨。
78. 建立 LCD Helper Function
def write_line(
lcd,
row,
text
):
text = (
text.ljust(16)[:16]
)
lcd.cursor_pos = (
row,
0
)
lcd.write_string(
text
)
使用:
write_line(
lcd,
0,
"Raspberry Pi 5"
)
write_line(
lcd,
1,
"I2C Ready"
)
79. 顯示 IP Address
前面 Network Chapter 學過:
hostname -I
Python 也可以取得系統網路資訊,再顯示:
IP:
192.168.1.120
這讓 Headless Raspberry Pi 很方便,開機後就能從 LCD 看 IP。
80. 現在整合第 11 章 DHT22
架構:
DHT22
GPIO4
│
▼
Python
│
├── Terminal
│
└── I²C LCD1602
│
▼
Temperature
Humidity
I²C LCD 使用:
GPIO2
GPIO3
DHT:
GPIO4
所以 Pin 不衝突。
81. Chapter 12 Pin Assignment
| 功能 | BCM | Physical |
|---|---|---|
| LCD SDA | GPIO2 | Pin 3 |
| LCD SCL | GPIO3 | Pin 5 |
| DHT22 DATA | GPIO4 | Pin 7 |
| GND | — | Pin 6 等 |
| 3.3V DHT | — | Pin 1 |
| 5V LCD side | — | Pin 2 / 4 |
| Level Shifter LV | 3.3V | Pi Side |
| Level Shifter HV | 5V | LCD Side |
Raspberry Pi I²C Pin 與 3.3V GPIO Domain 皆來自官方 GPIO 定義。
82. Python Package
如果延續第 11 章:
adafruit-blinka
adafruit-circuitpython-dht
再增加:
RPLCD
smbus2
可以在同一 Project venv:
python -m pip install \
adafruit-blinka \
adafruit-circuitpython-dht \
RPLCD \
smbus2
smbus2 與 RPLCD 目前皆提供 Python 3 支援。
83. DHT22 + LCD1602 完整程式
import time
from datetime import datetime
import adafruit_dht
import board
from RPLCD.i2c import CharLCD
LCD_ADDRESS = 0x27
LCD_PORT = 1
DHT_PIN = board.D4
READ_INTERVAL = 2
lcd = CharLCD(
i2c_expander="PCF8574",
address=LCD_ADDRESS,
port=LCD_PORT,
cols=16,
rows=2,
auto_linebreaks=False
)
dht = adafruit_dht.DHT22(
DHT_PIN,
use_pulseio=False
)
def write_line(
row,
text
):
text = (
text.ljust(16)[:16]
)
lcd.cursor_pos = (
row,
0
)
lcd.write_string(
text
)
def show_environment(
temperature,
humidity
):
line1 = (
f"Temp:{temperature:5.1f} C"
)
line2 = (
f"Humi:{humidity:5.1f} %"
)
write_line(
0,
line1
)
write_line(
1,
line2
)
try:
lcd.clear()
write_line(
0,
"Raspberry Pi 5"
)
write_line(
1,
"Sensor starting"
)
time.sleep(2)
while True:
try:
temperature = (
dht.temperature
)
humidity = (
dht.humidity
)
now = datetime.now()
print(
now.strftime(
"%Y-%m-%d %H:%M:%S"
)
)
print(
f"Temperature: "
f"{temperature:.1f} C"
)
print(
f"Humidity: "
f"{humidity:.1f} %"
)
print(
"-" * 30
)
show_environment(
temperature,
humidity
)
except RuntimeError as error:
print(
"Temporary DHT error:",
error
)
write_line(
0,
"Sensor read err"
)
write_line(
1,
"Retrying..."
)
time.sleep(
READ_INTERVAL
)
except KeyboardInterrupt:
print(
"\nMonitor stopped."
)
finally:
dht.exit()
lcd.close(
clear=True
)
RPLCD 的 CharLCD、write_string()、cursor_pos、clear() 與 close() 都屬官方 Library API。
84. LCD 畫面
正常時:
Temp: 27.5 C
Humi: 63.2 %
如果 DHT 暫時失敗:
Sensor read err
Retrying...
下一次成功讀取後:
Temp: 27.6 C
Humi: 63.1 %
就會恢復。
85. 不要每次 Sensor Error 就關掉整個 LCD
DHT 偶發讀取失敗在前一章已經設計成:
Retry
所以 LCD 也應該:
顯示 Error
↓
等下一次 Sensor Read
↓
自動恢復
這比整支 Python Script Crash 更適合長期 Monitor。
86. 加入 Normal / Warning 狀態
可以把第二行改成:
T:32.5 H:68%
WARNING
但 LCD1602 只有:
16 × 2
所以 UI 必須精簡。
例如:
def get_status(
temperature
):
if temperature >= 35:
return "DANGER"
if temperature >= 30:
return "WARNING"
return "NORMAL"
87. 狀態 LCD
line1 = (
f"T:{temperature:4.1f} "
f"H:{humidity:4.1f}"
)
line2 = (
f"State:{status}"
)
例如:
T:32.4 H:68.2
State:WARNING
這就是一個真正獨立的小型環境監測器。
88. LCD 顯示不要當歷史資料庫
LCD 適合:
Current Value
Current Status
不適合保存:
昨天
上週
一個月
歷史資料。
歷史記錄留給後面:
SQLite
處理。
89. 多個 I²C Sensor 可以一起使用
未來可以在同一 SDA / SCL 增加:
RTC
Pressure Sensor
ADC
OLED
I/O Expander
只要:
- Logic Voltage 相容。
- Address 不衝突。
- Pull-up 合理。
- Bus Capacitance 可接受。
- Software Driver 正確。
I²C 的兩線多 Peripheral 架構正是該 Bus 的核心優點。
90. I²C Bus 太長會有問題嗎?
會。
I²C 並不是設計成:
幾十公尺 Sensor Network
的長距離 Bus。
線越長:
Capacitance
Noise
Rise Time
越容易影響 Signal Integrity。
Pull-up Resistance、Bus Capacitance 與 Clock Speed 本來就共同決定 I²C Rise Time。
91. 長距離環境監測怎麼辦?
更適合考慮:
- RS-485
- CAN
- Ethernet
- Wi-Fi
- MQTT
- Industrial Fieldbus
而不是把 I²C 線一路拉到另一個房間。
92. Remote I/O Error 是什麼?
Python 若出現類似:
OSError:
[Errno 121]
Remote I/O error
通常表示 Linux I²C Transaction 沒有得到預期 Device 回應。
優先檢查:
Address
Power
SDA
SCL
GND
Logic Level
Device State
而不是先重灌 Python。
93. Address 錯誤
如果 Scanner:
3f
程式:
LCD_ADDRESS = 0x27
當然找不到正確 Device。
所以遵守:
Scanner Result
↓
Program Address
不要:
網路文章 Address
↓
直接 Copy。
94. Scanner 找得到但 Python Permission Denied
確認:
ls -l /dev/i2c-1
以及:
groups
不同 Raspberry Pi OS / 安裝環境可能有不同 Device Permission Policy。
不要第一步就把:
/dev/i2c-1
改成世界可寫:
chmod 777
那不是正確權限管理方式。
95. LCD 出現亂碼
檢查:
- Address
- PCF8574 Pin Mapping
- Character Map
- Power Stability
- I²C Signal
- Level Shifter
- LCD Controller Compatibility
RPLCD 支援 A00、A02 與 ST0B Character Map,可依實際 LCD Controller 選擇。
96. LCD 一直閃
可能原因:
程式一直 clear()
例如:
while True:
lcd.clear()
每次 Update 都 Clear 整個 Display。
更好的方式:
固定 Cursor
+
覆寫 16 Characters
97. I²C Debug 標準流程
建議順序:
1. Power
↓
2. Voltage Compatibility
↓
3. Common GND
↓
4. SDA / SCL
↓
5. I²C Enabled
↓
6. i2cdetect -l
↓
7. i2cdetect -y BUS
↓
8. Address
↓
9. Python Library
↓
10. LCD Mapping / Contrast
這樣效率最高。
98. 本章常用 Linux 指令
| 指令 | 功能 |
|---|---|
| sudo raspi-config | 啟用 I²C |
| sudo apt install i2c-tools | 安裝 I²C Utility |
| i2cdetect -l | 列出 I²C Bus |
| sudo i2cdetect -y 1 | 掃描 Bus 1 |
| ls -l /dev/i2c-* | 查看 I²C Device Node |
| python -m pip install RPLCD smbus2 | 安裝 LCD Python Library |
Raspberry Pi 官方目前的 I²C Enable 項目位於 3 Interface Options > I5 I2C,Debian Trixie 也持續提供 i2c-tools。
99. RPLCD API 速查
| API | 功能 |
|---|---|
| CharLCD() | 建立 LCD |
| address= | I²C Address |
| port=1 | I²C Bus |
| cols=16 | 16 Columns |
| rows=2 | 2 Rows |
| clear() | 清畫面 |
| write_string() | 寫文字 |
| cursor_pos | 游標位置 |
| home() | 回原點 |
| backlight_enabled | Backlight 控制 |
| close() | 關閉 LCD Object |
這些功能皆由 RPLCD I²C CharLCD API 提供。
100. 本章重點整理
完成本章後,應掌握:
- I²C 是兩線式同步 Serial Bus。
- 主要訊號為 SDA 與 SCL。
- 一組 I²C Bus 可以連多個具有不同 Address 的 Device。
- Raspberry Pi 標準 SDA 使用 GPIO2 / Physical Pin 3。
- Raspberry Pi 標準 SCL 使用 GPIO3 / Physical Pin 5。
- GPIO2 / GPIO3 有固定 Pull-up。
- Raspberry Pi GPIO 屬於 3.3V Logic。
- I²C 使用 Open-drain / Pull-up Bus 架構。
- Pull-up 不代表越多越好。
- I²C 常使用 7-bit Address。
- Linux 通常以十六進位顯示 I²C Address。
- Raspberry Pi OS 目前可由 Control Centre 啟用 I²C。
- raspi-config 的 I²C 項目為 3 Interface Options > I5 I2C。
- i2c-tools 包含 i2cdetect。
- i2cdetect -l 可以列出 Bus。
- i2cdetect -y 1 可掃描 Bus 1。
- -- 表示沒有 Device 回應。
- UU 通常代表 Address 已由 Kernel Driver 使用。
- i2cdetect 並非對所有 Device 完全無風險。
- Scanner 應主要作為 Diagnostic Tool。
- LCD1602 是典型 16×2 Character Display。
- I²C Backpack 可以大幅減少 LCD 所需 GPIO。
- PCF8574 是 8-bit I²C I/O Expander。
- PCF8574 7-bit Address Range 是 0x20~0x27。
- PCF8574A Range 是 0x38~0x3F。
- 0x27 不是所有 LCD 的固定 Address。
- 0x3F 也不是所有 LCD 的固定 Address。
- A0/A1/A2 可以改變 PCF8574 Address。
- 同一 Bus 的 Device Address 不應衝突。
- LCD Backlight 亮不等於 I²C 通訊成功。
- PCF8574 可在約 2.5~6V VCC 工作。
- PCF8574 VIH 最低規格為 0.7×VCC。
- PCF8574 若在 5V,VIH(min) 為 3.5V。
- Raspberry Pi 約 3.3V HIGH 不滿足 3.5V Worst-case Threshold。
- 5V LCD Backpack 不能無條件視為 3.3V-safe。
- SDA/SCL 如果被 Pull-up 到 5V,對 Pi 3.3V GPIO 不安全。
- 3.3V / 5V I²C 系統可使用 Bidirectional I²C Level Shifter。
- Level Shifter Pi Side Pull-up 應為 3.3V。
- 5V Device Side 可維持其 5V Domain。
- 兩側需要 Common Ground。
- RPLCD 也提醒 5V Backpack 與 Raspberry Pi 可能需要 I²C Level Shifter。
- 本章 Python 使用 RPLCD。
- RPLCD I²C Mode 支援 PCF8574。
- RPLCD 支援 16×2、20×4 等 Character Display Config。
- RPLCD 可使用 smbus2。
- smbus2 目前持續維護並支援 Python 3。
- write_string() 可寫入 LCD。
- cursor_pos=(row,col) 可以定位文字。
- clear() 可以清除畫面。
- 本章已完成 DHT22 + Raspberry Pi + I²C LCD1602 環境監測系統。
FAQ:Raspberry Pi I²C 與 LCD1602 常見問題
Q1:Raspberry Pi 5 的 I²C SDA 是哪一支 Pin?
GPIO2
=
Physical Pin 3
Q2:I²C SCL 是哪一支?
GPIO3
=
Physical Pin 5
Q3:如何啟用 Raspberry Pi I²C?
sudo raspi-config
選:
3 Interface Options
→ I5 I2C
→ Yes
這是目前 Raspberry Pi 官方方式。
Q4:如何掃描 I²C Device?
先:
i2cdetect -l
找到正確 Bus。
再例如:
sudo i2cdetect -y 1
i2cdetect 是 Debian i2c-tools 提供的 I²C Bus Scanner。
Q5:LCD1602 一定是 0x27 嗎?
不是。
如果 Backpack 使用 PCF8574:
0x20~0x27
如果使用 PCF8574A:
0x38~0x3F
所以應該用 Scanner 確認。
Q6:為什麼有人是 0x3F?
PCF8574A 的 7-bit Address Range 為:
0x38~0x3F
0x3F 是其中一個可能位址。
Q7:可以直接把 5V LCD I²C 接 Raspberry Pi 嗎?
不能無條件這樣做。
Raspberry Pi I²C 是 3.3V GPIO,而 PCF8574 如果以 5V 供電,其 Datasheet 規定 VIH 最低為 0.7×VCC,也就是 3.5V;另外還必須確認 Backpack 的 SDA/SCL Pull-up 是否會拉到 5V。
若無法確認電氣相容性,使用:
Bidirectional I²C Level Shifter
是較安全的設計。
Q8:為什麼 LCD Backlight 有亮但沒有字?
先檢查:
- Contrast
- I²C Address
- SDA
- SCL
- PCF8574 Mapping
- Python Library
Backlight 有電並不能證明 I²C 已經正常。
Q9:LCD 出現黑方塊怎麼辦?
先調 Contrast,再確認:
sudo i2cdetect -y 1
是否看得到 Backpack Address。
如果 Address 看得到,再檢查 Library 與 PCF8574-to-LCD Pin Mapping。
Q10:RPLCD 如何建立 LCD1602?
例如 Address 為 0x27:
from RPLCD.i2c import CharLCD
lcd = CharLCD(
i2c_expander="PCF8574",
address=0x27,
port=1,
cols=16,
rows=2
)
這符合 RPLCD I²C API。
Q11:如何寫第二行?
lcd.cursor_pos = (
1,
0
)
lcd.write_string(
"Second line"
)
RPLCD Cursor Position 使用 (row, col)。
Q12:LCD 可以顯示中文嗎?
一般 HD44780-compatible LCD 不是 Unicode Graphic Display,主要使用內建 Character ROM;RPLCD 支援 A00、A02、ST0B 等有限 Character Map。
所以一般 LCD1602 教學建議使用:
ASCII 英文
數字
少量符號
Q13:為什麼 LCD 一直閃?
很可能是程式:
lcd.clear()
呼叫得太頻繁。
建議固定 cursor_pos 後覆寫整行。
Q14:I²C 可以接多個 Sensor 嗎?
可以。
I²C 本來就是讓多個不同 Address Device 共用 SDA / SCL 的 Bus。
Q15:兩個 Device Address 一樣怎麼辦?
需要:
- 修改其中一個 Address
- 使用 Address Jumper
- 使用 I²C Multiplexer
- 使用另一組 Bus
否則會產生 Address Conflict。
Q16:i2cdetect 可以一直跑嗎?
不建議。
Debian 官方 Manpage 警告它使用 Probe Command 掃描,對部分 Device 可能造成混亂甚至資料損失。
把它當:
安裝
接線
故障排除
時使用的診斷工具即可。
Q17:I²C 可以拉很長的線嗎?
不建議直接把一般 I²C 當長距離 Field Bus。
Bus Length 增加會提高 Capacitance,進而影響 Rise Time 與可用 Clock Speed;I²C Pull-up 設計本來就必須考慮 Bus Capacitance。
Q18:什麼是 Remote I/O error?
通常表示 Linux I²C Transaction 沒有得到 Target 的正常回應。
優先檢查:
Address
Power
SDA
SCL
GND
Voltage Level
Q19:DHT22 可以和 LCD1602 一起用嗎?
可以。
本章:
DHT22
→ GPIO4
LCD I2C
→ GPIO2 / GPIO3
Pin 不衝突。
因此可以建立完整:
Temperature
Humidity
↓
LCD1602
環境監測器。
Q20:下一步 I²C 還能接什麼?
常見可以加入:
BME280
BMP280
RTC DS3231
OLED
ADC
GPIO Expander
EEPROM
只要確認:
- Address
- Voltage
- Driver
- Pull-up
- Bus Loading
即可逐步擴充。
結語
完成第 12 章後,我們的 Raspberry Pi 已經從:
Sensor
↓
Terminal
進化到:
DHT22
│
├── Temperature
└── Humidity
↓
Raspberry Pi
│
├── Terminal
│
└── I²C
↓
LCD1602
更重要的是,我們真正學會了:
I²C
│
├── SDA
├── SCL
├── Pull-up
├── Address
├── Scanner
├── Level Shifting
└── Multi-device Bus
其中最重要的工程觀念不是:
記住 LCD 是 0x27
而是:
永遠先掃描實際 Address。
也不是:
四條杜邦線接上就好。
而是:
先確認 3.3V / 5V I²C 電氣相容性。
現在我們已經學會一個非常重要的低速 Peripheral Bus。
下一章則要進入另一個完全不同的 Serial Bus:
SPI
SPI 不再依靠 Device Address,而會使用:
MOSI
MISO
SCLK
Chip Select
並且具有較高的資料傳輸能力。
更重要的是,Raspberry Pi 本身沒有 Arduino UNO 那種一般用途 Analog Input。
所以第 13 章我們會用:
MCP3008 ADC
把:
Potentiometer
Analog Sensor
的類比電壓轉成 Raspberry Pi 可以讀取的 Digital Value。
下一章
第 13 章 Raspberry Pi SPI 通訊入門:MCP3008 ADC 讀取類比訊號
下一章將完整學習:
- SPI 是什麼
- MOSI
- MISO
- SCLK
- CE0
- CE1
- Controller / Peripheral
- Full Duplex
- SPI 與 I²C 差異
- Raspberry Pi SPI0 Pin
- GPIO10 MOSI
- GPIO9 MISO
- GPIO11 SCLK
- GPIO8 CE0
- GPIO7 CE1
- raspi-config
- 啟用 SPI
- /dev/spidev*
- Raspberry Pi 為什麼沒有一般 Analog Input
- ADC 是什麼
- Resolution
- 10-bit ADC
- 0~1023
- Reference Voltage
- MCP3008
- MCP3008 CH0~CH7
- 8-channel ADC
- MCP3008 3.3V 接線
- Potentiometer
- Python spidev
- GPIO Zero MCP3008
- 讀取 0.0~1.0
- 取得 Raw ADC Value
- Voltage Conversion
- Moving Average
- 類比電位器控制 LED Brightness
- Analog Sensor Data Logging
- SPI Device Not Found
- Wiring Debug
- 3.3V Analog Input Safety
完成第 13 章後,我們的 Raspberry Pi 就會同時具備:
Digital Input
Digital Output
PWM
Digital Sensor
I²C
Analog Input via ADC
讓整套 Raspberry Pi 硬體介面能力再往前跨一大步。