去年底重做 SSD1306 測試後, 又從零件箱中找出傳統 2*16 的 1602A LCD 顯示器, 趁著元旦假期也重測看看以前的函式庫是否還能用, 參考我在 2017 年寫的這篇 :
本系列全部文章參考 :
參考書籍 :
# 超簡單 Python/MicroPython 物聯網應用 (博碩, 陳會安)
# 超圖解 Python 物聯網 (旗標, 趙英傑)
# Python 感測器大應用 (旗標, 創客自造者)
本篇仍是以 D1 mini 開發板進行測試, 用 ESP8266 驅動 1602A 需要下列兩個函式庫 :
也可以從原作者的 GitHub 下載 :
將此兩個函式庫上傳到 ESP8266 開發板即可開始進行測試.
在這之前要先將 1602A 與 D1 mini 透過 1602 I2C 模組用 I2C 介面連接起來. 也可以直接用 1602A 與 ESP8266 連接, 但那要用掉 ESP8266 八個 GPIO 埠來直接傳送資料給 1602A 的 D0~D7 腳, 而且還有其他接腳須要控制, 連接起來很麻煩, 一般都會用一個 1602 I2C 模組介面板插在 1602A 針腳上, 然後用上面那兩個 I2C 函式庫去控制, 這樣只要用兩個 GPIO 埠即可. 這個 1602 12C 模組其實是利用 PCF8574 多工器 IC 將 IO 埠集縮並轉成 I2C 介面以節省輸出入腳與簡化操作方式, 接線圖重貼如下 :
上圖中 1602 I2C 模組上有 VCC, GND, SCL, 與 SDA 四支腳, VCC 與 GND 分別接到 D1 min 的 3.3V 與 GND 腳, SCL 接到 D1 腳 (GPIO5), 而 SDA 則接到 D2 腳 (GPIO4), 這兩個 GPIO 埠是 ESP8266 的預設 I2C 輸出入埠, 但也可以用其他任何 GPIO 埠, 因為最新版的 MicroPython 韌體已經改用軟體 I2C 類別 SoftI2C 來處理 I2C 通訊, 取代原本的內建 I2C 類別, SoftI2C 可用任何 GPIO 腳模擬為 SCL 與 SDA 腳.
其次要注意的是, 1602A 有 3.3V 與 5V 兩種電壓, 兩種板子的差別在於 3.3V 款的背板有一顆位準轉換 IC 與電容, 圖片重貼如下 :
我使用的是上方的 3.3V 款, 可直接從 D1 mini 的 3.3V 與 GND 腳取得電源. 接好電源後 1602A 的藍色背光就會亮起來, 接著就可匯入函式庫來輸出字串到 1602A 顯示幕, 先使用 I2C 類別 :
>>> from machine import I2C, Pin
>>> from esp8266_i2c_lcd import I2cLcd
然後呼叫內建的 I2C 類別建構函式來建立 I2C 物件 :
>>> i2c=I2C(scl=Pin(5), sda=Pin(4), freq=400000)
>>> type(i2c)
<class 'SoftI2C'>
>>> dir(i2c)
['__class__', 'readinto', 'start', 'stop', 'write', 'init', 'readfrom', 'readfrom_into', 'readfrom_mem', 'readfrom_mem_into', 'scan', 'writeto', 'writeto_mem', 'writevto']
>>>
可見 I2C() 會建立一個 SoftI2C 物件 (新版 MicroPython 韌體), 它提供了低階的讀寫方法. 但通常不會直接使用這些讀寫方法來通訊, 而是使用上面從 esp8266_i2c_lcd 模組匯入的 I2cLcd 類別. 此處 freq 參數設定 I2C 匯流排通訊速率為 400K bps, scl 與 sda 參數設定 GPIO5 與 GPIO4 為 I2C 通訊接腳, 此為 ESP8266 預設的 I2C 埠, 參考 :
板子腳位 | ESP8266 腳位 | 功能 |
D0 | GPIO16 | IO |
D1 | GPIO5 | IO, SCL |
D2 | GPIO4 | IO, SDA |
D3 | GPIO0 | IO, 內建 10K 上拉電阻 |
D4 | GPIO2 | IO, 內建 10K 上拉電阻與 LED |
D5 | GPIO14 | IO, SCK |
D6 | GPIO12 | IO, MISO |
D7 | GPIO13 | IO, MOSI |
D8 | GPIO15 | IO, SS, 內建 10K 上拉電阻 |
TX | TXD | UART 送端 |
RX | RXD | UART 收端 |
A0 | ADC | 類比輸入 (0~3.3V) |
接著呼叫 SoftI2C 物件的 scan() 方法掃描目前 I2C 匯流排上有哪些設備 (I2C 是一對多協定), 它會傳回設備的 10 位址串列 :
>>> i2c.scan()
[39]
此處只有 1601 I2C 模組這一個 I2C 設備, 其位址為 39, 此乃十進制, 須將其轉為二進制 0x27, 因為接下來要呼叫 I2cLcd 類別之建構函式 I2cLcd() 時要傳入此二進制位址做為第二參數, 此函式之參數結構如下 :
第一參數為上面建立之 SoftI2C 物件, 第二參數為 I2C 設備之二進制位址, 第三參數為 LCD 顯示幕列數 (1602A 為 2), 第四參數為 LCD 顯示行數 (1602A 為 16) :
>>> lcd=I2cLcd(i2c, 0x27, 2, 16)
>>> type(lcd)
<class 'I2cLcd'>
可見 I2cLcd() 會建立一個 I2cLcd 物件, 檢視其內容 :
>>> dir(lcd)
[object_link_for_thonny=1073677440]['__class__', '__init__', '__module__', '__qualname__', 'clear', '__dict__', 'i2c', 'i2c_addr', 'num_lines', 'num_columns', 'hal_write_init_nibble', 'LCD_FUNCTION_RESET', 'LCD_FUNCTION', 'LCD_FUNCTION_2LINES', 'hal_write_command', 'hal_backlight_on', 'hal_backlight_off', 'backlight', 'hal_write_data', 'LCD_CLR', 'LCD_HOME', 'LCD_ENTRY_MODE', 'LCD_ENTRY_INC', 'LCD_ENTRY_SHIFT', 'LCD_ON_CTRL', 'LCD_ON_DISPLAY', 'LCD_ON_CURSOR', 'LCD_ON_BLINK', 'LCD_MOVE', 'LCD_MOVE_DISP', 'LCD_MOVE_RIGHT', 'LCD_FUNCTION_8BIT', 'LCD_FUNCTION_10DOTS', 'LCD_CGRAM', 'LCD_DDRAM', 'LCD_RS_CMD', 'LCD_RS_DATA', 'LCD_RW_WRITE', 'LCD_RW_READ', 'cursor_x', 'cursor_y', 'display_off', 'backlight_on', 'hide_cursor', 'display_on', 'show_cursor', 'blink_cursor_on', 'blink_cursor_off', 'backlight_off', 'move_to', 'putchar', 'putstr', 'custom_char']
它提供了許多方法來顯示字串, 重貼如下 :
I2cLcd 物件的方法 | 說明 |
move_to(x, y) | 移動游標至座標 (x, y) |
putchar(str) | 從游標目前位置開始顯示字串 str, 然後將游標移到字串結束之下一位置 |
putchar(char) | 從游標目前位置開始顯示字元 char, 然後將游標移到下一位置 |
custom_char(location, charmap) | 將字元圖樣 charmap 寫入 CGRAM 記憶體位址 location=0~7 |
clear() | 清除 LCD 螢幕並將游標移至左上角座標 (0, 0) |
show_cursor() | 顯示游標 (底線) |
hide_cursor() | 隱藏游標 |
blink_cursor_on() | 開啟游標閃爍功能 |
blink_cursor_off() | 關閉游標閃爍功能 |
display_on() | 開啟顯示功能 |
display_off() | 關閉顯示功能 (即顯示白屏) |
backlight_on() | 開啟背光 |
backlight_off() | 關閉背光 |
其中最常用的是 putstr() 方法, 它會從目前游標位置開始顯示字串, 例如 :
>>> lcd.putstr("Hello World!\nIt's working!")
注意, 傳入字串中可用 '\n' 表示換列, 結果如下 :
完整程式碼如下 :
# main.py
from machine import I2C, Pin
from esp8266_i2c_lcd import I2cLcd
i2c=I2C(scl=Pin(5), sda=Pin(4), freq=400000)
lcd=I2cLcd(i2c, 0x27, 2, 16)
lcd.putstr("Hello World!\nIt's working!")
由於新版 MicroPython 韌體另外內建了 SoftI2C 類別可模擬任何 GPIO 腳做 I2C 通訊, 所以上面程式碼改為從 machine 匯入 SoftI2C 類別, 並改為呼叫 SoftI2C() 建構式建立 SoftI2C 物件也是可以的 (因 I2C 類別未來將廢棄, 故建議改用 SoftI2C), 例如 :
# main.py
from machine import SoftI2C, Pin
from esp8266_i2c_lcd import I2cLcd
i2c=SoftI2C(scl=Pin(5), sda=Pin(4), freq=400000)
lcd=I2cLcd(i2c, 0x27, 2, 16)
lcd.putstr("Hello World!\nIt's working!")
結果是一樣的.
接下來測試 SoftI2C 是否能將任何 GPIO 腳模擬成 I2C 的 scl 與 sda, 以下選定 D0 (GPIO 16) 當作 scl, D8 (GPIO15) 當作 sda :
# main.py
from machine import SoftI2C, Pin
from esp8266_i2c_lcd import I2cLcd
i2c=SoftI2C(scl=Pin(16), sda=Pin(15), freq=400000)
lcd=I2cLcd(i2c, 0x27, 2, 16)
lcd.putstr("Hello World!\nIt's working!")
更改 scl 與 sda 接線後在 Thonny 輸入
MicroPython v1.19.1 on 2022-06-18; ESP module with ESP8266
Type "help()" for more information.
>>> from machine import SoftI2C, Pin
>>> from esp8266_i2c_lcd import I2cLcd
>>> i2c=SoftI2C(scl=Pin(16), sda=Pin(15), freq=400000)
>>> type(i2c)
<class 'SoftI2C'>
>>> lcd=I2cLcd(i2c, 0x27, 2, 16)
>>> lcd.putstr("Hello World!\nIt's working!")
結果與上面相同.
參考 :
沒有留言:
張貼留言