| ESP32 教學 | MicroPython | I2C LCD1602 | 207 |

I2C 的應用與 SPI 很類似,差別在於 I2C 只需要兩支線路 SDA 與 SCL 即可完成訊息通訊,在 ESP32 平台的 micropython 語言也已建立 I2C 的類別,當然也分了硬體與軟體的 I2C 機制,所以今天就來看看相關的語法如何使用,文末會用一個 I2C LCD1602 來實際操作顯示文字或數字。

1. I2C 原理

關於 I2C 的架構與原理,JIMI 哥在之前分享這篇 Arduino Uno I2C 時有提到過,有興趣的朋友可以再點擊該篇的第 2 節參考,這邊我們就快速講一下重點,I2C 的主要透過兩條資料線進行傳輸– SCK 與 SDA,架構上會分 Master 與 Slave,為了能夠辨別在這個 I2C 網路上的所有裝置,所以每個裝置(或設備),必須內建一個I2C 位置(Address),在訊息的封包上就會包含這個 Address,確認通訊的雙方對象為何,其完整的架構如下圖:

2. Micropython I2C 類別

Micropython I2C 跟 SPI 類似,都有硬體與軟體 I2C 的區別,硬體的 I2C 就是直接使 mcu 內部 I2C 控制器進行通訊,軟體的 I2C 則可以搭配任意的 GPIO,利用軟體模擬出通訊協定,雖然軟體 I2C 使用彈性較大,但 JIMI哥建議直接使用硬體 I2C 即可,因為在 ESP32 內,硬體 I2C 已可以搭配任意 Output 的 GPIO,較不會浪費 mcu 的執行效能,這邊我們先來看一下如何建立 Micropython 硬體 I2C 物件的簡單範例:

from machine import Pin, I2C
hw_i2c = I2C(1, freq=200000)

Hardware I2C 的第一個參數為 id 可以填入 0 或 1,第 2 個參數指定頻率,如果各位使用的是預設腳位去操作 I2C 通訊,就可以省略腳位的設定,每個 id 都有一個預設的腳位,其設定如下:

id 0 1
SCL GPIO 18 GPIO 25
SDA GPIO 19 GPIO 26

但想要使用其他 Output 腳位的話,就得使用下面的建構子:(一樣是 Hardware I2C)

hw_i2c=I2C(1,scl=Pin(27),sda=Pin(26),freq=200000)

初始化 I2C 物件後,可以操作的方法就有很多,下面為列出幾個基本的操作:

1.接收訊息

hw_i2c.readfrom(0x10, 2)   #接收來自裝置位址 0x10 的兩個byte資料

2. 傳送訊息

hw_i2c.writeto(0x10, 'JR') #寫資料"JR"到裝置位址 0x10 

當然也可以是用 python 內建的 bytes 資料型態定義好再傳送訊息

buf=['J','R']
hw_i2c.writeto(0x10, bytes(buf))

知道怎麼建立 I2C 物件與基本操作方法後,就來直接用 I2C 介面的 LCD1602 顯示文字看看。

3. I2C lcd1602 實驗

* 電路接法

這個實驗就用 ESP32 id1 的 I2C 來進行操作,所以 LCD I2C 腳位對應 ESP32 開發板分別為 SCL=GPIO25、SDA=GPIO26,LCD1602 VCC 與 GND 連接 ESP32 開發板上的 3.3V 與 GND 即可(要記得找 3.3V 可用的 LCD1602),完整的接法如下:

i2c lcd1602

* 上傳 I2cLcd 模組到 ESP32

由於 micropython 沒有內建 lcd1602 的模組,所以 JIMI 哥這邊推薦大家可以下載在 Github上 Dave Hylands 作者的 python_lcd 專案,在 lcd 資料夾中找到其中兩個檔案 esp8266_i2c_lcd.py 跟 lcd_api.py 這兩個檔案,下載到電腦,後續上傳到 ESP32 開發板內,此時就可以開始撰寫我們自己的程式碼。

小提醒:忘記如何上傳檔案到 ESP32 板,可以參考這篇 205-micropython spi 內的說明

* 完整程式碼

我們簡單的利用此 I2cLcd 模組來顯示文字資訊,程式碼如下:

from machine import I2C, Pin
from esp8266_i2c_lcd import I2cLcd

DEFAULT_I2C_ADDR = 0x27
hw_i2c0 = I2C(1, freq=200000)
lcd = I2cLcd(hw_i2c0, DEFAULT_I2C_ADDR, 2, 16)
lcd.putstr("Hello World ~~")
while 1:
    pass

* 程式講解

from machine import I2C, Pin
from esp8266_i2c_lcd import I2cLcd

這邊除了 import 必須的 I2C 與 Pin 類別外,也導入 I2cLcd module(已事先上傳檔按到 ESP32 板內)。

DEFAULT_I2C_ADDR = 0x27
hw_i2c = I2C(1, freq=200000)
lcd = I2cLcd(hw_i2c, DEFAULT_I2C_ADDR, 2, 16)
lcd.putstr("Hello World ~~")
while 1:
    pass
  1. DEFAULT_I2C_ADDR 這個參數是手邊的 lcd1602 的 I2C 位址,如果不確定可以檢查模組背面是否有標示,最常見的就是 0x27 或 0x20。
  2. hw_i2c 就是新建立 Micropython I2C 物件,採用內建的 id1 與預設腳位。
  3. lcd = I2cLcd(hw_i2c, DEFAULT_I2C_ADDR, 2, 16)這行是建立 I2cLcd 的物件,第1個參數為 I2C 物件,第2個參數為 lcd1602 的位址,第3個參數為 lcd 的行數,第四個參數就是 lcd 的字元數。
  4. lcd.putstr 這個方法源自 lcdapi.py 這個檔案,功能為顯示字串,該模組內還有很多其他的方法,各位如果有興趣可以研究。

4. 結語

Micropython I2C 的使用方法與 SPI 非常類似,各位僅需要知道 I2C 原理,確認傳輸速度上限與位址後,在網路上搜尋對應模組就可以進行操作,當然 LCD1602 只是 I2C 應用的其中一環,還有其他的裝置像 EEPROM 跟很多 Sensor 都有 I2C 的版本,先預告下次的內容就是用 I2C 介面的 OLED 來顯示文字或圖案哦! 今天的內容就到這邊,如果在使用上有遇到任何問題,歡迎在下面留言給我~!!

↓↓↓↓↓↓賣場連結↓↓↓↓↓↓

歡迎大家有需要的話,可以多多支持一下我們的蝦皮賣場喔! 😀 

吉米家官方店-創客機器人材料專賣 https://shopee.tw/jimirobot.tw

Follow JIMI哥 Twitter : https://twitter.com/jimirobot  <–得到最新文章通知

This Post Has 4 Comments

  1. Traceback (most recent call last):
    File “”, line 6, in
    File “esp8266_i2c_lcd.py”, line 25, in __init__
    OSError: [Errno 110] ETIMEDOUT
    在執行後跑出這個錯誤 不知道是哪裡做錯了(使用esp8266,程式碼如下)
    from machine import I2C, Pin
    from esp8266_i2c_lcd import I2cLcd

    DEFAULT_I2C_ADDR = 0x27
    hw_i2c0 = I2C(scl=Pin(5),sda=Pin(4), freq=200000)
    lcd = I2cLcd(hw_i2c0, DEFAULT_I2C_ADDR, 2, 16)
    lcd.putstr(“Hello World ~~”)
    while 1:
    pass

    1. Hi~ 因我手邊沒有esp8266的實驗板,無法直接跑這段程式看看,不過依經驗推斷,這應該跟 i2c 要初始化 lcd1602 時的timeout 有關,也就是可以試著檢查一下 i2c的周邊電路是否連接正確,如scl 或 clk 是否連接相反? pin腳連接是否正確? lcd模組的電壓是否選用3.3V規格的(8266應該是3.3V)?操作電源是否穩定之類的相關問題,先釐清一下是否為硬體的問題,或許這樣就會找出相關的答案,以上答案供您參考一下~

      1. 我也出現了這個問題,請問有舊版的esp8266_i2c_lcd函式庫嗎?新版的好像有地方寫錯

    2. 可能esp8266_i2c_lcd新版函式庫定義有誤
      可以暫時用軟體模擬腳位,就能正常使用
      程式碼如下:

      from machine import I2C, Pin
      from esp8266_i2c_lcd import I2cLcd
      DEFAULT_I2C_ADDR = 0x27
      i2c=I2C(scl=Pin(22),sda=Pin(21),freq=200000)
      lcd = I2cLcd(i2c,0x27, 2, 16)
      lcd.putstr(“Hello World ~~”)
      while 1:
      pass

      互動環境(shell)訊息:
      >>> %Run -c $EDITOR_CONTENT
      Warning: I2C(-1, …) is deprecated, use SoftI2C(…) instead

發佈留言

Close Menu