美文网首页物联网IOT创意开发树莓派raspberry pi
树莓派3B与0.96 oled屏幕的局部刷新实践探讨 IIC实现

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

作者: u5510 | 来源:发表于2017-06-07 20:53 被阅读508次

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

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

    效果

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


    接线

    关于底层实现,我研究了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实现

        本文链接:https://www.haomeiwen.com/subject/bbvafxtx.html