来自好奇吖斌的投稿,感谢~
最近在学习树莓派,驱动OLED屏时出现了一个问题,就是花屏,折腾了两天后发现原来这个OLED的驱动芯片不是SSD1306而是SH1106,所以用Adafruit_Python_SSD1306这个库是花屏的。
OLED的驱动芯片有好几种,但是有的库只支持SSD1306芯片,所以当你的OLED屏出现花屏时就应该是芯片和库没对应上,购买OLED屏时最好购买i2c的SSD1306芯片的,库多且接线比较简单。
Python有两个可以用的OLED库:
- Adafruit_Python_SSD1306库—>只支持SSD1306
- Luma.oled库—>支持SSD1306 / SSD1322 / SSD1325 / SSD1331 / SH1106
Adafruit_Python_SSD1306库与Luma.oled库的安装说明(看不懂英文没关系,看下面我会说)。
- SSD1306 OLED Displays with Raspberry Pi and BeagleBone Black
- Luma.OLED: Display drivers for SSD1306 / SSD1322 / SSD1325 / SSD1331 / SH1106
本文的Luma.oled库参考了I2C接口的OLED在树莓派3上的应用 ,但这是旧版本的,新版本库不是这样安装,请看下文。
i2c接线
OLED引脚 | 树莓派物理BOARD引脚 |
---|---|
VCC | 1号 |
GND | 6号 |
SCL | 5号 |
SDA | 3号 |
接好线后就是像一个L型的。
开启i2c功能
sudo apt-get install -y python-smbus sudo apt-get install -y i2c-tools sudo raspi-config
打开树莓派配置选择5 Interfacing Options。
选择P5 I2C回车激活I2C。
按回车启动就得了。
查看i2c地址
sudo i2cdetect -y 1
然后你能看到下面的地址,3c就是oled屏的i2c地址了,说明已经成功开启i2c啦
– 安装Adafruit_Python_SSD1306库
终端输入下面命令。
sudo apt-get update sudo apt-get install build-essential python-dev python-pip sudo pip install RPi.GPIO sudo apt-get install python-imaging python-smbus sudo apt-get install git git clone https://github.com/adafruit/Adafruit_Python_SSD1306.git cd Adafruit_Python_SSD1306 sudo python setup.py install
安装好Adafruit_Python_SSD1306库后,cd examples进入例程目录,ls查看文件,以shapes.py例程说明。
import time import Adafruit_GPIO.SPI as SPI import Adafruit_SSD1306 import Image import ImageDraw import ImageFont # Raspberry Pi pin configuration: RST = 24 # Note the following are only used with SPI: DC = 23 SPI_PORT = 0 SPI_DEVICE = 0 # Beaglebone Black pin configuration: # RST = 'P9_12' # Note the following are only used with SPI: # DC = 'P9_15' # SPI_PORT = 1 # SPI_DEVICE = 0 # 128x32 display with hardware I2C: disp = Adafruit_SSD1306.SSD1306_128_32(rst=RST) # 128x64 display with hardware I2C: # disp = Adafruit_SSD1306.SSD1306_128_64(rst=RST) # Alternatively you can specify an explicit I2C bus number, for example # with the 128x32 display you would use: # disp = Adafruit_SSD1306.SSD1306_128_32(rst=RST, i2c_bus=2) # 128x32 display with hardware SPI: # disp = Adafruit_SSD1306.SSD1306_128_32(rst=RST, dc=DC, spi=SPI.SpiDev(SPI_PORT, SPI_DEVICE, max_speed_hz=8000000)) # 128x64 display with hardware SPI: # disp = Adafruit_SSD1306.SSD1306_128_64(rst=RST, dc=DC, spi=SPI.SpiDev(SPI_PORT, SPI_DEVICE, max_speed_hz=8000000)) # Alternatively you can specify a software SPI implementation by providing # digital GPIO pin numbers for all the required display pins. For example # on a Raspberry Pi with the 128x32 display you might use: # disp = Adafruit_SSD1306.SSD1306_128_32(rst=RST, dc=DC, sclk=18, din=25, cs=22) # Initialize library. disp.begin() # Clear display. disp.clear() disp.display() # Create blank image for drawing. # Make sure to create image with mode '1' for 1-bit color. width = disp.width height = disp.height image = Image.new('1', (width, height)) # Get drawing object to draw on image. draw = ImageDraw.Draw(image) # Draw a black filled box to clear the image. draw.rectangle((0,0,width,height), outline=0, fill=0) # Draw some shapes. # First define some constants to allow easy resizing of shapes. padding = 2 shape_width = 20 top = padding bottom = height-padding # Move left to right keeping track of the current x position for drawing shapes. x = padding # Draw an ellipse. draw.ellipse((x, top , x+shape_width, bottom), outline=255, fill=0) x += shape_width+padding # Draw a rectangle. draw.rectangle((x, top, x+shape_width, bottom), outline=255, fill=0) x += shape_width+padding # Draw a triangle. draw.polygon([(x, bottom), (x+shape_width/2, top), (x+shape_width, bottom)], outline=255, fill=0) x += shape_width+padding # Draw an X. draw.line((x, bottom, x+shape_width, top), fill=255) draw.line((x, top, x+shape_width, bottom), fill=255) x += shape_width+padding # Load default font. font = ImageFont.load_default() # Alternatively load a TTF font. # Some other nice fonts to try: http://www.dafont.com/bitmap.php #font = ImageFont.truetype('Minecraftia.ttf', 8) # Write two lines of text. draw.text((x, top), 'Hello', font=font, fill=255) draw.text((x, top+20), 'World!', font=font, fill=255) # Display image. disp.image(image) disp.display()
按照你的oled屏修改代码,程序默认是12832的,你的oled屏是这个就不用改直接运行就OK。
如果是12864的I2C就像下面那样修改,把12832加#注释,12864#注释去掉保存。
# 128x32 display with hardware I2C: #disp = Adafruit_SSD1306.SSD1306_128_32(rst=RST) # 128x64 display with hardware I2C: disp = Adafruit_SSD1306.SSD1306_128_64(rst=RST)
终端输入sudo python shapes.py或用Python打开文件运行就能看到OLED屏有显示了。
– 安装Luma.oled库
终端输入下面命令。
sudo apt-get install python-dev python-pip libfreetype6-dev libjpeg-dev sudo -H pip install --upgrade pip sudo apt-get purge python-pip sudo -H pip install --upgrade luma.oled
注:如果你需要安装Python3的Luma.oled库的则按下面对应的Python3版本修改上面的命令进行安装。
pip ⇒ pip3
python ⇒ python3
python-dev ⇒ python3-dev
python-pip ⇒ python3-pip
如果安装Luma.oled库时出现红字错误,请继续执行命令重试,那是因为网络问题下载一个叫Pillow的库不成功。
安装好Luma.oled库后新建文件命名为oled.py,复制粘贴下面代码。参考这里使用说明
from luma.core.interface.serial import i2c, spi from luma.core.render import canvas from luma.oled.device import ssd1306, ssd1325, ssd1331, sh1106 # rev.1 users set port=0 # substitute spi(device=0, port=0) below if using that interface serial = i2c(port=1, address=0x3C) # substitute ssd1331(...) or sh1106(...) below if using that device device = sh1106(serial)#这里改ssd1306, ssd1325, ssd1331, sh1106 with canvas(device) as draw: draw.rectangle(device.bounding_box, outline="white", fill="black") draw.text((30, 40), "Hello World", fill="white")
如果你的oled驱动芯片是其它型号找到device = sh1106(serial),把sh1106改成库支持的其它型号。
树莓派上用Python2打开oled.py运行就能看到下图的Hello World。
能驱动成功后我们去下载Luma.oled的examples代码。
然后是examples里面的例子怎么用呢?如果是非ssd1306芯片直接运行还是花屏的,因为那个examples的代码需要修改。
下面以pi_logo.py为例参考上面那个Hello World的例子修改成自己OLED芯片型号的(文件放在在examples内)。
#!/usr/bin/env python # -*- coding: utf-8 -*- # Copyright (c) 2014-17 Richard Hull and contributors # See LICENSE.rst for details. # PYTHON_ARGCOMPLETE_OK """ Display the Raspberry Pi logo (loads image as .png). """ import os.path from PIL import Image from luma.core.interface.serial import i2c, spi from luma.oled.device import ssd1306, ssd1325, ssd1331, sh1106 def main(): img_path = os.path.abspath(os.path.join(os.path.dirname(__file__), 'images', 'pi_logo.png')) logo = Image.open(img_path).convert("RGBA") fff = Image.new(logo.mode, logo.size, (255,) * 4) background = Image.new("RGBA", device.size, "white") posn = ((device.width - logo.width) // 2, 0) while True: for angle in range(0, 360, 2): rot = logo.rotate(angle, resample=Image.BILINEAR) img = Image.composite(rot, fff, rot) background.paste(img, posn) device.display(background.convert(device.mode)) if __name__ == "__main__": try: serial = i2c(port=1, address=0x3C) device = sh1106(serial) main() except KeyboardInterrupt: pass
Python运行上面的程序oled屏会出现一个能旋转的树莓派LOGO。
全文完。
来源:解决树莓派驱动OLED(非SSD1306)花屏问题
作者:好奇吖斌
按照这个流程装了下去,我是用SH1106来显示,出现了以下提示:
File “hello.py”, line 10, in
device = sh1106(serial)#ssd1306, ssd1325, ssd1331, sh1106
File “/usr/local/lib/python2.7/dist-packages/luma/oled/device.py”, line 80, in __init__
self.clear()
File “/usr/local/lib/python2.7/dist-packages/luma/core/mixin.py”, line 44, in clear
self.display(Image.new(self.mode, self.size))
File “/usr/local/lib/python2.7/dist-packages/luma/oled/device.py”, line 114, in display
self.data(list(buf))
File “/usr/local/lib/python2.7/dist-packages/luma/core/device.py”, line 46, in data
self._serial_interface.data(data)
File “/usr/local/lib/python2.7/dist-packages/luma/core/interface/serial.py”, line 112, in data
write(self._addr, self._data_mode, list(data[i:i + 32]))
File “/usr/local/lib/python2.7/dist-packages/smbus2/smbus2.py”, line 411, in write_i2c_block_data
ioctl(self.fd, I2C_SMBUS, msg)
IOError: [Errno 121] Remote I/O error
不知为何。。
树莓派的 I2C 未配置为启用?
之前的问题解决了,我想问下在使用luma这个库怎么用三线SPI来驱动呢?
为什么屏幕只是闪了一下就关了?
我写了个while True循环就一直在显示了
代码运行没有出现错误 但是屏幕就是不亮 真不知道是什么问题,难道屏幕是坏的
安装Adafruit_Python_SSD1306库的第一步最后一条命令sudo python setup.py install花了很长时间没弄好是什么情况呀,目前就luma库能使用
Adafruit的库不能用了,只能查看
sudo i2cdetect -y 1
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: — — — — — — — — — — — — —
10: — — — — — — — — — — — — — — — —
20: — — — — — — — — — — — — — — — —
30: — — — — — — — — — — — — — — — —
40: — — — — — — — — — — — — — — — —
50: — — — — — — — — — — — — — — — —
60: — — — — — — — — — — — — — — — —
70: — — — — — — — —
前面的都没问题 怎么这里就老是这样啊?
接好设备才会显示地址
为啥闪一下就暗了,改写while True循环之后一直闪……救命