樹莓派OLED模組的使用教程大量例程詳解

折騰一哥發表於2021-09-17

簡介

Python有兩個可以用的OLED庫

  • [Adafruit_Python_SSD1306庫]—>只支援SSD1306

  • [Luma.oled庫]—>支援SSD1306 / SSD1309 / SSD1322 / SSD1325 / SSD1327 / SSD1331 / SSD1351 / SSD1362 / SH1106 / WS0010驅動晶片
    通過本篇教程,你可以學習樹莓派環境下I2C介面OLED基礎功能的使用,以及獲取到複雜功能的Demo例程。

    故事背景

    時常有看到網路上有一些OLED做的智慧小時鐘,非常漂亮,OLED作為一款自發光、低功耗、低成本的螢幕,非常受大家的喜愛,因此我也比較好奇,研究了一下OLED的使用,說幹就幹,那我們就開始吧!

    硬體準備

  • 樹莓派主機(3B/3B+ 、 4B等,提前安裝好系統)

  • HDMI螢幕(推薦直接使用VNC或SSH工具遠端登入,則可以少準備一個螢幕)

  • 無線鍵鼠一套(有線也可以,遠端訪問則可以不用)

  • 路由器

  • Windows主機

  • I2C介面的OLED螢幕
    給今天的主角OLED亮個像吧:
    在這裡插入圖片描述

    軟體準備

  1. 啟動樹莓派I2C功能
    樹莓派OLED模組的使用教程大量例程詳解
    樹莓派OLED模組的使用教程大量例程詳解

  2. OLED的驅動庫的選擇
    Python有兩個可以用的OLED庫

  • [Adafruit_Python_SSD1306庫]—>只支援SSD1306
  • [Luma.oled庫]—>支援SSD1306 / SSD1309 / SSD1322 / SSD1325 / SSD1327 / SSD1331 / SSD1351 / SSD1362 / SH1106 / WS0010驅動晶片
    在這裡我們應該怎麼選擇呢?先說結論:我比較推薦Luma.oled這個庫。下面分析對比一下兩個庫的優缺點:
優點 缺點
Adafruit 上手簡單 例程少,功能弱,只支援一種晶片
Luma.oled 例程豐富,功能強大,支援晶片豐富 上手難度稍大

這裡順便貼出Luma和Adafruit庫的連結:
luma庫使用基本官方介紹網頁
luma的例程程式碼git倉庫地址
Luma官方示例程式碼截圖
在這裡插入圖片描述

Adafruit-SSD1306示例程式碼git倉庫地址
示例程式碼目錄如下
在這裡插入圖片描述

從示例程式碼截圖也可以看到Adafruit的例程確實很少

  1. Luma.oled驅動庫的安裝
    Luma.oled是基於 Python 的OLED 庫,所以要用pip來安裝,現在比較流行python3,所以推薦用pip3,輸入指令

    sudo pip3 install luma.oled
    
    • python2 安裝只需要將pip3換成pip即可
    • Adafruit的安裝指令為:sudo pip3 install Adafruit-SSD1306
      [外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片儲存下來直接上傳(img-7p3KdxSL-1631859093083)(index_files/04ecc9f6-9e43-4abc-a966-78822de0a1e4.png)]
      如果安裝失敗,注意檢查pip工具是否需要更新,注意檢查網路是否通暢

    硬體連線

    1. 參考樹莓派引腳圖
      在這裡插入圖片描述

    這個圖比較詳細,也比較複雜了,我們暫時只需要關注表格中間功能名物理引腳功能名這三列,找到1--3.3v,3--SDA.1,5--SCL.1,6--GND這四個引腳

    1. 參考OLED模組的引腳圖

    在這裡插入圖片描述

    引腳編號 功能 功能說明
    1 GND 電源地線,電源負極
    2 VCC 電源正極,大部分OLED模組3.3v即可驅動
    3 SCL I2C時鐘線
    4 SDA I2C資料線
    1. 使用雙母頭杜邦線按照上述引腳圖Pin-to-Pin連線即可,連線好後樹莓派的引腳分佈為L形狀,接線示意圖如下
      在這裡插入圖片描述

    千萬注意電源正負極別接反了,容易燒板子

    知識儲備

    以下知識不在本教程詳細討論範圍,但還是列舉出來,有興趣的可以網上找找資料深入學習

    1. OLED顯示原理,驅動原理(嵌入式內容),推薦這篇部落格進行了解OLED顯示模組(原理講解、STM32例項操作)_玩轉智慧機器人-CSDN部落格
    2. I2C通訊原理,I2C匯流排特點

例程一:使用OLED顯示“Hello,World”

編程式碼先從Hello,World開始,有了一,就有了無限可能,步驟如下:

  1. 根據前文的步驟連線好OLED模組,查詢oled的I2C地址,每個OLED模組的I2C地址不一定都相同,需要先查詢獲取地址,同時也檢查一下OLED模組是否連線正常。
    輸入指令:
sudo i2cdetect -y 1

在這裡插入圖片描述

如圖所示3c就是OLED模組的I2C地址

  1. 執行如下程式碼即可
#!/usr/bin/python3
# -*- coding: utf-8 -*-
from luma.core.interface.serial import i2c, spi
from luma.core.render import canvas
from luma.oled.device import ssd1306, ssd1325, ssd1331, sh1106
from time import sleep
"""
OLED luma 驅動庫測試程式
功能:顯示 hello world 和矩形外框持續10秒
"""
__version__ = 1.0
# 初始化埠
serial = i2c(port=1, address=0x3C)
# 初始化裝置,這裡改ssd1306, ssd1325, ssd1331, sh1106
device = ssd1306(serial)
print("當前版本:", __version__)
# 呼叫顯示函式
with canvas(device) as draw:
 draw.rectangle(device.bounding_box, outline="white", fill="black")
 draw.text((30, 20), "Hello World", fill="white")
# 延時顯示10s
sleep(10)

此程式碼會在Oled螢幕上畫出一個矩形邊框,並在內部顯示Hello,World,10s後關閉,效果如下圖:
在這裡插入圖片描述

  1. 程式碼解析

    # 初始化裝置,這裡改ssd1306, ssd1325, ssd1331, sh1106
    device = ssd1306(serial)
    

    這段程式碼主要作用是初始化裝置

    • 如果OLED的驅動晶片不是ssd1306,這裡需要更換對應的函式名
    • 如果OLED尺寸不同,則需要傳不同引數,例如如果是0.91寸的128*32的OLED則程式碼應修改為:device = ssd1306(serial, width=128, height=32)
    # 呼叫顯示函式
    with canvas(device) as draw:
        draw.rectangle(device.bounding_box, outline="white", fill="black")
        draw.text((30, 20), "Hello World", fill="white")
    
    • canvas 英文單詞含義為畫布,意思就是可以在這裡輸入各種需要顯示的內容
    • 這段程式碼使用了with...as...:語法,關於with的詳細用法可以暫且不論,這裡可以簡單理解為先執行canvas函式,然後將返回物件賦值給draw變數,用此語法建立的物件,會在使用結束後自動釋放資源,常用於開啟某個檔案,之後自動關閉檔案,舉例如下:
    # 開啟1.txt檔案,並列印輸出檔案內容
    with open('1.txt', 'r') as f:
        print(f.read())
    
    • draw.rectangle() 為畫矩形的函式,類似的還有畫圓,畫三角形

例程二:顯示漢字

  1. 程式碼如下:
#!/usr/bin/python3
# -*- coding: utf-8 -*-
from luma.core.interface.serial import i2c, spi
from luma.core.render import canvas
from luma.oled.device import ssd1306, ssd1325, ssd1331, sh1106
from time import sleep
from PIL import ImageFont
"""
OLED luma 驅動庫測試程式
功能:顯示 漢字古詩持續10秒
"""
__version__ = 1.0
# 初始化埠
serial = i2c(port=1, address=0x3C)
# 初始化裝置,這裡改ssd1306, ssd1325, ssd1331, sh1106
device = ssd1306(serial)
print("當前版本:", __version__)
font = ImageFont.truetype('./msyh.ttc', 12)
# 呼叫顯示函式
with canvas(device) as draw:
 draw.rectangle(device.bounding_box, outline="white", fill="black")
 draw.text((5, 10), "古詩一首", fill="white", font=font)
 draw.text((5, 24), "白日依山盡,", fill="white", font=font)
 draw.text((5, 38), "黃河入海流。", fill="white", font=font)
# 延時顯示10s
sleep(10)
  1. 顯示效果如下
    圖片名稱

  2. 程式碼解析

  • from PIL import ImageFont 這個是強大的PIL庫中的字型類,顯示漢字,預設字型就不行了,所以需要新增字型檔案
  • font = ImageFont.truetype('./msyh.ttc', 12) 這段程式碼含義是呼叫當前目錄下的字型檔案 "msyh.ttc"建立一個字型類,"msyh.ttc"是微軟雅黑字型,可以百度一下自行下載,我也是在盜版網站上扒到的,此處就不貼連結了。
  • draw.text((5, 10), "古詩一首", fill="white", font=font) 這段程式碼跟上一個示例相比,就是多了一個字型賦值,含義是在(5,10)的位置顯示漢字。

例程三:畫幾何圖形

1.程式碼如下:

  #!/usr/bin/python3
  # -*- coding: utf-8 -*-
  from luma.core.interface.serial import i2c, spi
  from luma.core.render import canvas
  from luma.oled.device import ssd1306, ssd1325, ssd1331, sh1106
  from time import sleep
  from PIL import ImageFont
  """
  OLED luma 驅動庫測試程式
  功能:顯示 幾何圖形 持續10秒
  """
  __version__ = 1.0
  # 初始化埠
  serial = i2c(port=1, address=0x3C)
  # 初始化裝置,這裡改ssd1306, ssd1325, ssd1331, sh1106
  device = ssd1306(serial)
  print("當前版本:", __version__)
  font = ImageFont.truetype('./msyh.ttc', 12)
  # 呼叫顯示函式
  with canvas(device) as draw:
  draw.rectangle(device.bounding_box, outline="white", fill="black")
  # Draw an ellipse.
  draw.ellipse((2, 2, 20, 60), outline="white", fill="black")
  # Draw a rectangle.
  draw.rectangle((24, 2, 42, 60), outline="blue", fill="black")
  # Draw a triangle.
  draw.polygon([(44, 60), (54, 2), (64, 60)], outline="green", fill="black")
  # Draw an X.
  draw.line((66, 60, 86, 2), fill="yellow")
  draw.line((66, 2, 86, 60), fill="yellow")
  # 延時顯示10s
  sleep(10)

2.顯示效果如下:
圖片名稱

  1. 程式碼解析

    # Draw an ellipse.
        draw.ellipse((2, 2, 20, 60), outline="white", fill="black")
    

    繪製橢圓,傳入第一個引數為橢圓外接矩形的對角座標,outline引數為幾何圖形邊線的顏色,fill 為幾何圖形內部填充的顏色

    # Draw a rectangle.
        draw.rectangle((24, 2, 42, 60), outline="blue", fill="black")
    

    繪製矩形,傳入第一個引數為矩形的對角座標,outline引數為幾何圖形邊線的顏色,fill 為幾何圖形內部填充的顏色

    # Draw a triangle.
        draw.polygon([(44, 60), (54, 2), (64, 60)], outline="green", fill="black")
    

    繪製三角形,此處呼叫了繪製多半形的函式,傳入第一個引數為三角形三個頂點的座標,outline引數為幾何圖形邊線的顏色,fill 為幾何圖形內部填充的顏色

    # Draw an X.
        draw.line((66, 60, 86, 2), fill="yellow")
        draw.line((66, 2, 86, 60), fill="yellow")
    

    繪製一個"X"形狀的交叉線

    此處呼叫了劃線函式,傳入第一個引數為線的兩個端點座標,fill 為線的顏色


例程四:滾動顯示

  1. 程式碼如下:

    #!/usr/bin/python3
    # -*- coding: utf-8 -*-
    
    from luma.core.interface.serial import i2c, spi
    from luma.core.render import canvas
    from luma.oled.device import ssd1306, ssd1325, ssd1331, sh1106
    from luma.core.virtual import viewport
    from time import sleep
    from PIL import ImageFont
    
    """
    OLED luma 驅動庫測試程式
    功能:顯示 漢字古詩持續10秒
    """
    
    __version__ = 1.0
    
    # 初始化埠
    serial = i2c(port=1, address=0x3C)
    
    # 初始化裝置,這裡改ssd1306, ssd1325, ssd1331, sh1106
    device = ssd1306(serial)
    
    
    font = ImageFont.truetype('./msyh.ttc', 12)
    
    txt = """
    將進酒
    李白
    君不見黃河之水天上來,
    奔流到海不復回。
    君不見高堂明鏡悲白髮,
    朝如青絲暮成雪。
    人生得意須盡歡,
    莫使金樽空對月。
    天生我材必有用,
    千金散盡還復來。
    
    """
    
    txt2 = """將進酒
    李白
    君不見黃河之水天上來,奔流到海不復回。君不見高堂明鏡悲白髮,朝如青絲暮成雪。
    人生得意須盡歡,莫使金樽空對月。天生我材必有用,千金散盡還復來。
    """ 
    
    
    virtual = viewport(device, width=500, height=768)
    
    def horizontal_scroll():
        with canvas(virtual) as draw:
            for i, line in enumerate(txt2.split("\n")):
                draw.text((0, (i * 16)), text=line, fill="white", font=font)
    
        sleep(2)
    
        # update the viewport one position below, causing a refresh,
        # giving a rolling up scroll effect when done repeatedly
        y = 0
        for x in range(240):
            virtual.set_position((x, y))
            sleep(0.01)
    
    def vertical_scroll():
        with canvas(virtual) as draw:
            for i, line in enumerate(txt.split("\n")):
                draw.text((0, 20 + (i * 16)), text=line, fill="white", font=font)
    
        sleep(2)
    
        # update the viewport one position below, causing a refresh,
        # giving a rolling up scroll effect when done repeatedly
        x = 0
        for y in range(240):
            virtual.set_position((x, y))
            sleep(0.01)
    
    
    def main():
        print("當前版本:", __version__)
        horizontal_scroll()
        vertical_scroll()
    
    
    if __name__ == "__main__":
        try:
            main()
        except KeyboardInterrupt:
            pass
    
    
    
  2. 顯示效果如下(動圖):
    水平滾動:
    在這裡插入圖片描述
    垂直滾動:
    在這裡插入圖片描述

  3. 程式碼解析

    • virtual = viewport(device, width=500, height=768) 這段程式碼建立了一個虛擬畫布,viewport 類支援建立一個可以改變定位的虛擬畫布,而且可以建立比實際解析度更大的畫布,再通過重新定位的方式來進行一個滾動顯示,理解這一點對後面的程式碼理解很有幫助。
    • def horizontal_scroll():
          with canvas(virtual) as draw:
              for i, line in enumerate(txt2.split("\n")):
                  draw.text((0, (i * 16)), text=line, fill="white", font=font)
          sleep(2)
          # update the viewport one position below, causing a refresh,
          # giving a rolling up scroll effect when done repeatedly
          y = 0
          for x in range(240):
              virtual.set_position((x, y))
              sleep(0.01)
      
    • 這段程式碼,是水平滾動程式碼,首先用with...as...語法建立並更新顯示畫布,超出解析度的內容沒有被顯示,然後for x in range(240):這個迴圈不斷改變畫布的原點x座標的位置,以實現水平滾動。
    • 垂直滾動原理類似,先顯示,後改變原點y軸的座標,以此實現垂直滾動

更多示例

  1. 介紹到這裡,OLED的基本使用就已經入門了,想研究其他更多的示例,可以直接參考官方的例程

傳送陣在這裡: luma的例程程式碼git倉庫地址

  1. 恭喜你! 又get一個外設模組!

歡迎各位老鐵一鍵三連,本號後續會不斷更新樹莓派、人工智慧、STM32、ROS小車相關文章和知識。

大家對感興趣的知識點可以在文章下面留言,我可以優先幫大家講解哦

原創不易,轉載請說明出處。

相關文章