iT邦幫忙

2023 iThome 鐵人賽

DAY 20
0
自我挑戰組

ESP32 Micropython 從入門到實用系列 第 20

20.連接外部週邊的匯流排-I2C

  • 分享至 

  • xImage
  •  

還是從點亮 LED 燈談起

變頻電風扇調速,我們總是想要由低至高,分段來表示速度,我們可以利用一個 7-節 顯示器 (7-segment LED display),參考以下影片:How to use a 7-segment LED display with the Raspberry Pi Pico

雖然這個例子使用了 Raspberry Pi Pico 開發板,我相信您應該很容易的改在 ESP32-S3 開發板上執行。從這個例子中,我們發現要使用這樣可以顯示 0-9 數字的 display, 我們必須在開發板中相對的對每一個 LED (代表着一個線段, segment),連接到不同的 GPIO 接腳,這樣,我們需要佔用 7 個 GPIO,若是要顯示兩個位數的 00-99 數字,我們需要 14 接腳,若是要推動 4 個位數,那就要 28 個接腳,那實在是太多了!

另外一種做法是用掃描的方式,利用人們的視覺暫留現象,例如用 4 個 GPIO,來啓動相對應位數的七節顯示器,這樣我們就可以用 4 + 7 ,共 11 個 GPIO 就可以來顯示 4 位數的 7 節顯示器。

但是相對的掃描更新方式,在程式中難免會動用到很多的迴圈來實作,我們也發現,當掃描快的時候,顯示器會亮一些,掃描慢一些,亮度變暗,甚至太慢了,變成了閃爍,看不清數字! 而且還要準備字形,在影片中準備了 0 - 9 數字的字形,字形中的節點(segment)要顯示暗(LED off) 的爲 0 , 要顯示亮 (LED on) 的爲 1.

這樣在軟體或者硬體的設計上其實都很麻煩,這還是 7-segment LED display 而已,若是像 8x8 的點矩陣顯示器,一個位數就需要 8 + 8 個 GPIO, 若是四位數就需要 4 + 8 + 8 個 GPIO,在軟體上的複雜程度可以想像變成很高!

您若是瞭解了這種顯示原理,就會同時理解:從這些低解析度的 7-segment LED display, 到高解析度的 LED 顯示螢幕或是液晶電視,其掃描的原理大致相同。

因爲像這種多位數的七節 LED 顯示器非常常見,用途也很廣,因此有很多廠商已經將這些功能整合到 IC 當中了,這樣大大的降低使用這些元器件的軟硬體複雜度。常見的有 I2C 與 SPI 這類的串口界面,當然,有 內建 IC 的模組,售價相對的比較高一點。我們今天以 I2C 界面來說明。

有關 I2C 的詳細說明可以查閱 wiki I2C ,或是上 google 找資料。同樣地,若您有看不懂的地方,歡迎留言提問。

我們今天以下面這個顯示器模組,來說明如何在 Micropython 中使用 I2C 界面:
https://ithelp.ithome.com.tw/upload/images/20231005/20140037vwA11Vs3gf.png
這個模組使用了 IC TM1367 來驅動一個 4 位數的 7 節顯示器,我們可以從 google 查到 TM1367 的 datasheet

接下來將模組的四個接腳接到開發板上:

GND --> 開發板 GND
VCC --> 開發板 3V3
DIO --> 開發板 GPIO 15 (SDA)
CLK --> 開發板 GPIO 16 (SCL)

依序執行下面的程式

>>> from machine import Pin, SoftI2C
>>> i2c = SoftI2C(scl=Pin(16), sda=Pin(15), freq=100000)
>>> i2c.scan()
[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, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119]
>>>

這代表着 TM1637 顯示模組已經接上了,但是有個問題要特別注意:這種 I2C 週邊 IC 其實並沒有完整實現 I2C 的標準。

正常的情況下,一個 I2C 裝置會有一個 I2C 地址,有 7-bit 與 10-bit 地址,不過目前 Micropython 只支援 7-bit 地址。但我們用 scan() 函數去掃描 I2C BUS 時,被詢問到的裝置會回應 ACK 信號。由於 TM1637 並沒有正式指定到 I2C 地址,但是程式需要收到 ACK 才會認爲裝置有接上 BUS,因此對於每一個 I2C 地址的詢問,TM1637 全都回應了! 這代表著會有什麼後果,您可以思考一下,不過在此並不影響使用!

至於 Micropython 的驅動已經有大神寫好了,您可以參考:https://github.com/mcauser/micropython-tm1637

程式庫模組的安裝可以使用 mpremote:

$ mpremote mip install github:mcauser/micropython-tm1637

基本的使用:

import tm1637
from machine import Pin
tm = tm1637.TM1637(clk=Pin(16), dio=Pin(15))

# all LEDS on "88:88"
tm.write([127, 255, 127, 127])

# all LEDS off
tm.write([0, 0, 0, 0])

# show "0123"
tm.write([63, 6, 91, 79])

# show "COOL"
tm.write([0b00111001, 0b00111111, 0b00111111, 0b00111000])

# show "HELP"
tm.show('help')

# display "dEAd", "bEEF"
tm.hex(0xdead)
tm.hex(0xbeef)

# show "12:59"
tm.numbers(12, 59)

# show "-123"
tm.number(-123)

# show temperature '24*C'
tm.temperature(24)

要注意的是,mcauser 的 TM1637 display 驅動,並不是利用 Micropython I2C 程式庫模組,而是自造出了 I2C 的時序信號出來,程式相當簡潔,值得研究!

接下來,您是否可以挑戰用 I2C 的方式自己寫一個驅動呢?


上一篇
19.紅外線遙控接收
下一篇
21.WebREPL
系列文
ESP32 Micropython 從入門到實用30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言