树莓派3B与0.96 oled屏幕的局部刷新实践探讨 IIC实现

网上对于SSD1306的中文技术文章应用并不多,甚至都没有有关 局部刷新的文章。我在这里说下我的实现方案

本人技术有限。如果有更好的代码实现能告诉我那就再感激不过了。

树莓派3B与0.96 oled屏幕的局部刷新实践探讨 IIC实现_第1张图片
效果

关于接线,很简单,套用一张网上的图:


树莓派3B与0.96 oled屏幕的局部刷新实践探讨 IIC实现_第2张图片
接线

关于底层实现,我研究了Adafruit_Python_SSD1306的源码,麻烦的是不同硬件设备的适配问题。感谢开源的伟大。

git clone https://github.com/adafruit/Adafruit_Python_SSD1306.git   # 下载源码
cd Adafruit_Python_SSD1306 # 移动到源码文件夹
sudo python3 ez_setup.py install # 先安装这个 顺序不要搞错了
sudo python3 setup.py install

首先导入我们需要的库:

import Adafruit_SSD1306
import time
import threading

from PIL import Image
from PIL import ImageDraw
from PIL import ImageFont

PIL库会在上面安装Adafruit_Python_SSD1306时自动给你安装。这里会用到多线程,关于这个屏幕刷新,如果你想实现的东西多了,自然会用到的吧。

虽然我这个例子不会用到。还是写出来学习一下。

我还打算添加其他功能,代码规范化还是很有必要的。

如果你还不会多线程,可以参考 python 多线程就这么简单 我也是现学现用。这文章确实写的非常好,通俗易懂。

你可以在Adafruit_Python_SSD1306中找到例子,打开看会有一堆初始化代码。那主要是为了适配硬件设备的。我自己用的时只有四个管脚,I2C通信的0.96oled屏幕,所以我就直接吧适配的代码节减掉一部分。如果你使用的时spi通信。稍稍修改就可以实现。我会在以后更新更优的内容。

先把这段整个代码贴出来,再分段解释:

class SSD1306_IIC:
    def __init__(self): # 初始化
        self.disp = Adafruit_SSD1306.SSD1306_128_64(rst=24)
        self.disp.begin()
        self.disp.clear()
        self.disp.display()
        self.width = self.disp.width
        self.height = self.disp.height
        self.image = Image.new('1', (self.width, self.height))
        self.draw = ImageDraw.Draw(self.image)

    def Drawnow(self): # 屏幕刷新
        self.disp.image(self.image)
        self.disp.display()

    def Cleanup(self, size=None): # 局部覆盖矩形or整体覆盖矩形
        if size is None:
            size = (0, 0, self.width, self.height)
        self.draw.rectangle(size, outline=0, fill=0)

    def Text(self, size, content, font, fontsize, visible=True):
        # Some other nice fonts to try: http://www.dafont.com/bitmap.php
        if visible == True:
            self.draw.text(size, content, font=ImageFont.truetype(font, fontsize), fill=255)
        elif visible == False:
            self.draw.text(size, content, font=ImageFont.truetype(font, fontsize), fill=0)def

init 内的代码就是初始化。 你会发现,如果单独使用Cleanup函数屏幕是没有任何变化的。因为还需要调用Drawnow刷新一下屏幕。

全局刷新是设一个充满屏幕的矩形覆盖, 局部刷新就是指定区域设置一个矩形覆盖,不只是矩形,甚至连字体都可以这样做。

重点说下Text中最后一个参数visible,这个就相当于文章刷新了,仔细看不难发现其实只有 fill 参数改变了。

你可以这样理解,0就相当于 假,225就相当于 真。控制区域像素点的亮灭。这里的区域就是文字。

具体代码实现在后面。

我们要将用到的字体ttf文件就跟代码文件放在同一文件夹。字体最好是bitmap(位图)。

屏幕是可以显示中文的。可是我一直没找到较好的中文字体。so放弃,如果你有好的中文字体能发给我那就太好了。我找了接近一天,实践了20多个ttf字体。远点看还好,稍微近了,歪歪扭扭。

具体的局部刷新实现在这里,我们以时间为例:

class displayTime(SSD1306_IIC):
    def nowTime(self):
        # time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
        font = 'dos.ttf'
        size = (0, 0)
        #先初始化显示时间
        #因为当初我是没有秒的,所有是设置的10秒刷新一次。
        self.Text(size, time.strftime("%H:%M:%S", time.localtime()), font, 16) 
        while 1:
            oldTime = time.strftime("%H:%M:%S", time.localtime())
            time.sleep(0.2)
            newTime = time.strftime("%H:%M:%S", time.localtime())
            if oldTime != newTime:
                self.Text(size, oldTime, font, 16, False)
                self.Text(size, newTime, font, 16)

    def threadDrawnow(self): # 帧的概念
        while 1:
            self.Drawnow()
            time.sleep(0.1)


    def main(self):
        GUI = []
        time__ = threading.Thread(target=self.nowTime)
        GUI.append(time__)
        Drawnow__ = threading.Thread(target=self.threadDrawnow)
        GUI.append(Drawnow__)
        for i in GUI:
            i.setDaemon(True)
            i.start()

        i.join()

这里用到了两个线程,一个是nowtime另一个就是 threadDrawnow了。这就相当与 帧 的概念。你还可以添加更多的东西到线程。这就是我写线程的原因。打算在以后添加更有用的东西,而不仅仅只是显示时间。

关于时间你可以在linux终端输入 date 查看当前时间。如果你没有设置,一般会相差8小时。

这就是时区问题了。

sudo raspi-config

  • 打开第四个 Localisation Options 本地化设置
  • 打开第二个Change Timezone 改变时区
  • 选择Asia 亚洲
  • 最后选择Chongqing 重庆

python中调用当前时间要导入time模块,我们在代码开头已经导入了。
>>>time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
>>>'2017-06-06 11:31:29' # 返回的是字符串

这篇文章我是写在自己的博客上的,但是搜索引擎根本搜索不到这篇文章。所以转载到。希望大家多多评价。

完。

你可能感兴趣的:(树莓派3B与0.96 oled屏幕的局部刷新实践探讨 IIC实现)