树莓派OLED模块的使用教程大量例程详解

2021年9月19日 9点热度 0条评论 来源: 折腾一哥

简介

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功能

  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小车相关文章和知识。

大家对感兴趣的知识点可以在文章下面留言,我可以优先帮大家讲解哦

原创不易,转载请说明出处。

    原文作者:折腾一哥
    原文地址: https://www.cnblogs.com/ChuanYangRiver/p/15305203.html
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系管理员进行删除。