在Raspberry Pi 3 Model B 與 I2C LCD 點矩陣液晶顯示器之應用這篇文章中,我們了解到如何在 Raspberry Pi 3 Model B 上透過 I2C 介面控制 LCD 顯示器 (LCD1602)。文章中同時也提到 I2C 允許多個裝置串接在同一個匯流排之下,達到同時控制多個 I2C 裝置的目的。更厲害的是,一樣只會用到 Raspberry PI 上的四個接腳。在這篇文章中,我們將利用 Raspberry Pi 3 Model B 同時連接兩個 LCD1602,並分別顯示不同的資訊。雖然範例中兩個 I2C 裝置都是 LCD 顯示器,但是其實就算是不同種類的裝置,只要是 I2C 介面就可以用同樣的接法加以連結並控制。
稍微回顧一下該篇文章中的內容,當中提到在跟 I2C 裝置溝通前,必須先知道該 I2C 裝置的位址,如當時使用的 LCM1602 IIC V1 位址為 3f。此外,同一個匯流排上,位址不可以重複使用,也就是每一個 I2C 裝置的位址都要是獨一無二的。問題來了,世界上那麼多 I2C 介面的裝置,要怎麼樣才能確保都不會重複呢?答案是,沒辦法。所以如果我們拿另一個使用完全一樣的 LCM1602 IIC V1 的 LCD 顯示器,I2C 位址往往是重複的。事實上,同一種裝置的 I2C 預設位址幾乎都是固定一樣的。有些裝置可以透過跳線或其他方式設定 I2C 位址,以解決位址衝突的問題。但是如果沒辦法修改裝置的位址,只好另外尋找其他合適的裝置 (使用不同的位址、甚至是非 I2C 介面),或是使用如 I2C 多工器之類的電子零件來解決。
我在這個例子中,使用了另一款的 LCD1602,背後使用的是不一樣的 I2C 介面板,所以擁有不同的 I2C 位址。

兩組不同 I2C 位址的 LCD1602 點矩陣液晶顯示器背面
因為這個範例一樣是控制 I2C 介面的 LCD 顯示器,所以準備工作與Raspberry Pi 3 Model B 與 I2C LCD 點矩陣液晶顯示器之應用一致。如果你還沒有完成相關的準備,請務必先行完成再繼續進行後面的工作。
線路圖
說明如下:
- 在這個範例中,因為要串接兩個 I2C 裝置,所以我們使用麵包板以方便串接。
- 那一大堆的藍色短線一樣因為已經焊在板子上,所以直接無視即可。
- 扣掉新增加的第二個 LCD 顯示器 (藍色),接線方式跟控制單一 LCD 顯示器時完全一樣。也就是
LCM1602 IIC V1 接腳 Raspberry Pi GPIO 腳位 GND 實體編號 6 (接地) VCC 實體編號 4 (+5V) SDA 實體編號 3 SCL 實體編號 5 - 第二個 LCD 顯示器 (藍色) 的接線方式也是一樣。在線路圖以及實際接線時,我使用了同樣的顏色來標示同樣用途的接腳,因此應該很容易看出其規律。
尋找 I2C 裝置的位址
透過指令
1 | i2cdetect -y 1 |
應可看到類似下面的輸出結果
1 2 3 4 5 6 7 8 9 | 0 1 2 3 4 5 6 7 8 9 a b c d e f 00: -- -- -- -- -- -- -- -- -- -- -- -- -- 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 20: -- -- -- -- -- -- -- 27 -- -- -- -- -- -- -- -- 30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 3f 40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 70: -- -- -- -- -- -- -- -- |
我們確實看到兩個非 — 的字串,分別是 27 與 3f。因為在之前的範例中我們已經知道 3f 是原本那個 LCD 顯示器的位址,所以 27 就是藍色 LCD 顯示器的位址。
程式代碼
利用文字編輯器 (如 nano) 新增 Python 程式 double_i2c_lcd.py
1 | nano double_i2c_lcd.py |
內容如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | import sys import os import time import smbus2 sys.modules['smbus'] = smbus2 from RPLCD.i2c import CharLCD def getCPUTemperature(): res = os.popen('vcgencmd measure_temp').readline() return(res.replace("temp=","").replace("\n","")) lcd_green = CharLCD('PCF8574', address=0x3f, port=1, backlight_enabled=False) lcd_blue = CharLCD('PCF8574', address=0x27, port=1, backlight_enabled=False) try: print('按下 Ctrl-C 可停止程式') lcd_blue.clear() lcd_green.clear() while True: lcd_green.cursor_pos = (0, 0) lcd_green.write_string("Date: {}".format(time.strftime("%Y/%m/%d"))) lcd_green.cursor_pos = (1, 0) lcd_green.write_string("Time: {}".format(time.strftime("%H:%M:%S"))) load = os.getloadavg() lcd_blue.cursor_pos = (0, 0) lcd_blue.write_string("L:{},{},{}".format(load[0], load[1], load[2])) lcd_blue.cursor_pos = (1, 0) lcd_blue.write_string("CPU Temp:{}".format(getCPUTemperature())) time.sleep(1) except KeyboardInterrupt: print('關閉程式') finally: lcd_green.clear() lcd_blue.clear() |
程式說明如下:
- 我們在此跳過與之前範例相同的部分,僅針對不同的地方加以說明。
- 第 10 行定義一個用來抓取 Raspberry Pi CPU 溫度的函數。此函數透過命令列指令 vcgencmd 完成目的。
- 第 14, 15 行分別定義兩個用來控制 LCD 的 Python 物件。其中第 14 行使用 I2C 位址 3f,表示是綠色的 LCD 顯示器。而第 15 行使用位址 27,表示是藍色的 LCD 顯示器。
- 第 26 行取得系統負載,回傳為三組數字組成的 Tuple。
- 第 28 行將系統負載資訊顯示至藍色 LCD 顯示器的第一行。
- 第 30 行將 CPU 溫度顯示至藍色 LCD 顯示器的第二行。
程式完成後,輸入下列指令執行程式
1 | python double_i2c_lcd.py |
順利的話,就可以看到綠色的 LCD 顯示器開始顯示目前的日期與時間,而藍色 LCD 顯示器則顯示系統負載以及 CPU 溫度。同樣的,兩個 LCD 顯示器上面所呈現的資訊依舊會每秒持續更新,如以下影片中所示。
問題排除
- 無法取得 I2C 裝置的位址
確認所有接腳皆已正確連結。雖然 I2C 介面僅使用四支接腳,接線上並不複雜,但是因為連結的 Raspberry Pi 四個腳位緊靠在一起,所以很容易造成錯置。請務必使用四種不同顏色的杜邦線加以連結,以方便區分各個接腳。此外,同樣用途的接腳,也應該選用相同顏色的杜邦線,以減少不必要的混亂。 - 沒有出現兩個 I2C 裝置的位址
移除原有的 LCD 顯示器 (綠色),確認藍色 LCD 顯示器的 I2C 位址是否有所重複。 - 程式無法順利執行
依序進行下列確認:
- 如果出現 Remote I/O error 錯誤,請使用指令 i2cdetect -y 1 確認裝置的位址與程式內所使用的位址一致。
- 如果出現無法引入的錯誤,請使用指令 pip list 確認 RPLCD, smbus2 已經正確安裝。
- 如果程式出現錯誤訊息而無法順利執行,請仔細檢查每一行指令。必要時,可以直接複製程式碼並貼進你的編輯器。
- 無法顯示資訊
依序進行下列確認:- 使用後方之旋鈕控制螢幕之亮度,亮度設定太低將造成無法正常顯示。
- 再次確認所有接腳皆已正確連結。雖然 I2C 介面僅使用四支接腳,接線上並不複雜,但是因為連結的 Raspberry Pi 四個腳位緊靠在一起,所以很容易造成錯置。請務必使用四種不同顏色的杜邦線加以連結,以方便區分各個接腳。此外,同樣用途的接腳,也應該選用相同顏色的杜邦線,以減少不必要的混亂。
在這個範例中,我們了解到 Raspberry Pi 如何與多個 I2C 介面的元件互動。與多個 I2C 介面裝置進行互動,其實與單一裝置時並無太大差別 (如果忽略電器特性的限制),唯一需要注意的是是否有位址重複的問題。
如果對文章的內容有任何疑問或建議,歡迎與我聯絡。

