第12章 Raspberry Pi I²C 通訊完整教學:I²C Scanner 與 LCD1602 顯示器

發布日期: |更新日期:
文章主圖:第12章 Raspberry Pi I²C 通訊完整教學:I²C Scanner 與 LCD1602 顯示器

上一章我們完成:

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

Raspberry Pi I²C Pin 對照表
功能 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

第 12 章 I²C LCD1602 與 DHT22 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

只要:

  1. Logic Voltage 相容。
  2. Address 不衝突。
  3. Pull-up 合理。
  4. Bus Capacitance 可接受。
  5. 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 指令

第 12 章常用 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 速查

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. 本章重點整理

完成本章後,應掌握:

  1. I²C 是兩線式同步 Serial Bus。
  2. 主要訊號為 SDA 與 SCL。
  3. 一組 I²C Bus 可以連多個具有不同 Address 的 Device。
  4. Raspberry Pi 標準 SDA 使用 GPIO2 / Physical Pin 3。
  5. Raspberry Pi 標準 SCL 使用 GPIO3 / Physical Pin 5。
  6. GPIO2 / GPIO3 有固定 Pull-up。
  7. Raspberry Pi GPIO 屬於 3.3V Logic。
  8. I²C 使用 Open-drain / Pull-up Bus 架構。
  9. Pull-up 不代表越多越好。
  10. I²C 常使用 7-bit Address。
  11. Linux 通常以十六進位顯示 I²C Address。
  12. Raspberry Pi OS 目前可由 Control Centre 啟用 I²C。
  13. raspi-config 的 I²C 項目為 3 Interface Options > I5 I2C。
  14. i2c-tools 包含 i2cdetect。
  15. i2cdetect -l 可以列出 Bus。
  16. i2cdetect -y 1 可掃描 Bus 1。
  17. -- 表示沒有 Device 回應。
  18. UU 通常代表 Address 已由 Kernel Driver 使用。
  19. i2cdetect 並非對所有 Device 完全無風險。
  20. Scanner 應主要作為 Diagnostic Tool。
  21. LCD1602 是典型 16×2 Character Display。
  22. I²C Backpack 可以大幅減少 LCD 所需 GPIO。
  23. PCF8574 是 8-bit I²C I/O Expander。
  24. PCF8574 7-bit Address Range 是 0x20~0x27。
  25. PCF8574A Range 是 0x38~0x3F。
  26. 0x27 不是所有 LCD 的固定 Address。
  27. 0x3F 也不是所有 LCD 的固定 Address。
  28. A0/A1/A2 可以改變 PCF8574 Address。
  29. 同一 Bus 的 Device Address 不應衝突。
  30. LCD Backlight 亮不等於 I²C 通訊成功。
  31. PCF8574 可在約 2.5~6V VCC 工作。
  32. PCF8574 VIH 最低規格為 0.7×VCC。
  33. PCF8574 若在 5V,VIH(min) 為 3.5V。
  34. Raspberry Pi 約 3.3V HIGH 不滿足 3.5V Worst-case Threshold。
  35. 5V LCD Backpack 不能無條件視為 3.3V-safe。
  36. SDA/SCL 如果被 Pull-up 到 5V,對 Pi 3.3V GPIO 不安全。
  37. 3.3V / 5V I²C 系統可使用 Bidirectional I²C Level Shifter。
  38. Level Shifter Pi Side Pull-up 應為 3.3V。
  39. 5V Device Side 可維持其 5V Domain。
  40. 兩側需要 Common Ground。
  41. RPLCD 也提醒 5V Backpack 與 Raspberry Pi 可能需要 I²C Level Shifter。
  42. 本章 Python 使用 RPLCD。
  43. RPLCD I²C Mode 支援 PCF8574。
  44. RPLCD 支援 16×2、20×4 等 Character Display Config。
  45. RPLCD 可使用 smbus2。
  46. smbus2 目前持續維護並支援 Python 3。
  47. write_string() 可寫入 LCD。
  48. cursor_pos=(row,col) 可以定位文字。
  49. clear() 可以清除畫面。
  50. 本章已完成 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 硬體介面能力再往前跨一大步。

下一步學習

不要停在這一篇,接著把內容做成自己的實作

目前主題:Raspberry Pi。從完整學習路線、免費資源、會員下載,再接到實作所需材料。

同系列:Raspberry-Pi |  已是會員?直接前往 Getfile
相關資源與會員文章下載
文章可免費閱讀;下載完整 DOCX 或 PDF 需登入免費基本會員。
會員免費下載 DOCX 會員免費 PDF/列印

← 回文章列表