NanoPC-T4(RK3399) game1 oled(I2C)显示时间天气温度

本文介绍了如何在NanoPC-T4(RK3399)上利用I2C连接0.96寸OLED显示器,展示时间、天气和CPU温度。通过Python的luma库配置GPIO,使用i2c-tools验证硬件连接,并展示了一个使用SSD1306驱动的示例代码,实现滚动文字显示。
摘要由CSDN通过智能技术生成


下面如果遇到一些问题, 请见这篇介绍 令人惊艳的NanoPC-T4(RK3399)作为工作站的初始配置和相关应用

很久以前在本科阶段做单片机玩的时候, 余下的0.96 oled还有一个, 正好最近看稚晖君的小电视, 灵机一动, 就想利用这个oled做一个能够显示当前时间, 天气和cpu温度的显示屏; 同时需要注意的是, NanoPC-T4(RK3399) 这个板子已经打开了I2C的硬件驱动, 也就是说只要根据引脚图接上I2C, 这个板子就能在总线上识别到对应的设备, 就跟USB一个原理; 所以硬件方面就这样解决了!!!

这里缺个展示图
在这里插入图片描述

说实话, Linux开发下, 一切都那么简单, 尤其是python, 一切你能想到的任务, 都已经有人在GitHub做好了包等你clone和使用了, 今天这个玩意就是这样子的, 直接去GitHub搜一波python oled驱动 就搜出来一个, 然后在深入了解一下, luma包就是调用oled各种型号驱动的python包, 所以软件方面也解决了!!!

在这里插入图片描述

1. 查看GPIO定义 wiringpi库

wiringpi库就是一个操作硬件GPIO驱动库, 安装完之后就可以对外设引脚高低电平, 以及不同的通信协议进行配置, 比如I2C, SPI等

mkdir -p /home/02_hardware && cd /home/02_hardware

# 移除旧版本
wget http://112.124.9.243:8888/wiringpi/friendlyelec-rk3399/remove_oldversion_wiringPi.sh
chmod 755 remove_oldversion_wiringPi.sh
sudo ./remove_oldversion_wiringPi.sh

# 安装新版本
wget http://112.124.9.243:8888/wiringpi/friendlyelec-rk3399/wiringpi-v2.44-friendlyelec-rk3399.deb
sudo dpkg -i  wiringpi-v2.44-friendlyelec-rk3399.deb
(base) pi@NanoPC-T4:~$ gpio readall
 +------+-----+----------+------+ Model  NanoPC-T4 +------+----------+-----+------+
 | GPIO | wPi |   Name   | Mode | V | Physical | V | Mode |   Name   | wPi | GPIO |
 +------+-----+----------+------+---+----++----+---+------+----------+-----+------+
 |      |     |     3.3V |      |   |  1 || 2  |   |      | 5V       |     |      |
 |      |     | I2C2_SDA |      |   |  3 || 4  |   |      | 5V       |     |      |
 |      |     | I2C2_SCL |      |   |  5 || 6  |   |      | GND(0V)  |     |      |
 |   32 |   7 | GPIO1_A0 |   IN | 0 |  7 || 8  |   |      | I2C3_SCL |     |      |
 |      |     |  GND(0V) |      |   |  9 || 10 |   |      | I2C3_SDA |     |      |
 |   33 |   0 | GPIO1_A1 |   IN | 0 | 11 || 12 | 1 | IN   | GPIO1_C2 | 1   |  50  |
 |   35 |   2 | GPIO1_A3 |   IN | 0 | 13 || 14 |   |      | GND(0V)  |     |      |
 |   36 |   3 | GPIO1_A4 |   IN | 0 | 15 || 16 | 0 | IN   | GPIO1_C6 | 4   |  54  |
 |      |     |     3.3V |      |   | 17 || 18 | 0 | IN   | GPIO1_C7 | 5   |  55  |
 |   40 |  12 | GPIO1_B0 |  ALT |   | 19 || 20 |   |      | GND(0V)  |     |      |
 |   39 |  13 | GPIO1_A7 |  ALT |   | 21 || 22 | 0 | IN   | GPIO1_D0 | 6   |  56  |
 |   41 |  14 | GPIO1_B1 |  ALT |   | 23 || 24 |   | ALT  | GPIO1_B2 | 10  |  42  |
 |      |     |  GND(0V) |      |   | 25 || 26 |   | ALT  | GPIO4_C5 | 11  |  140 |
 |      |     | I2C2_SDA |      |   | 27 || 28 |   |      | I2C2_SCL |     |      |
 |  132 |  21 | GPIO4_A4 |   IN | 0 | 29 || 30 |   |      | GND(0V)  |     |      |
 |  133 |  22 | GPIO4_A5 |   IN | 0 | 31 || 32 |   |      | I2S_CLK  |     |      |
 |  131 |  23 | GPIO4_A3 |   IN | 0 | 33 || 34 |   |      | GND(0V)  |     |      |
 |  134 |  24 | GPIO4_A6 |   IN | 0 | 35 || 36 | 0 | IN   | GPIO4_A7 | 27  |  135 |
 |  124 |  25 | GPIO3_D4 |  ALT |   | 37 || 38 |   | ALT  | GPIO3_D5 | 28  |  125 |
 |      |     |  GND(0V) |      |   | 39 || 40 |   | ALT  | GPIO3_D6 | 29  |  126 |
 +------+-----+----------+------+---+----++----+---+------+----------+-----+------+

到这里我们知道 引脚3,5是对应的I2C2_SDA/SCL
所以将oled的四个引脚 vcc/gnd,sda,scl 插上就行了

2. 确保硬件无问题 (i2c-tools)

在使用下面命令之前需要注意的点有两个:

  1. i2c设备在进行命令(0x00)和数据(0x04)读写时是有区分的
  2. 这个板子第一个I2C接口是使用的I2C-2号总线
  3. 这个板子的I2C 硬件芯片是 rk3x-i2c, 而不是常见的xxx
# 安装识别i2c的工具
sudo apt-get install i2c-tools
(base) pi@NanoPC-T4:~$ apt-cache policy i2c-tools
i2c-tools:
  Installed: 4.0-2
  Candidate: 4.0-2
  Version table:
 *** 4.0-2 500
        500 http://mirrors.ustc.edu.cn/ubuntu-ports bionic/universe arm64 Packages
        100 /var/lib/dpkg/status

# 打印所有i2c总线, 发现这里用的芯片是rk3x-i2c, 而不是树莓派的bcm2835
(base) pi@NanoPC-T4:~$ sudo i2cdetect -l
i2c-0	i2c       	rk3x-i2c                        	I2C adapter
i2c-1	i2c       	rk3x-i2c                        	I2C adapter
i2c-2	i2c       	rk3x-i2c                        	I2C adapter
i2c-4	i2c       	rk3x-i2c                        	I2C adapter
i2c-7	i2c       	rk3x-i2c                        	I2C adapter
i2c-9	i2c       	DP-AUX                          	I2C adapter
i2c-10	i2c       	DP-AUX                          	I2C adapter

# 检测I2C总线 
(py3.7) pi@NanoPC-T4:zjq$ sudo i2cdetect -F 2
Functionalities implemented by /dev/i2c-2:
I2C                              yes
SMBus Quick Command              yes
SMBus Send Byte                  yes
SMBus Receive Byte               yes
SMBus Write Byte                 yes
SMBus Read Byte                  yes
SMBus Write Word                 yes
SMBus Read Word                  yes
SMBus Process Call               yes
SMBus Block Write                yes
SMBus Block Read                 no
SMBus Block Process Call         no
SMBus PEC                        yes
I2C Block Write                  yes
I2C Block Read                   yes


# 将oled插入到1356引脚, 查询占用的iic地址, 注意通过上图可知, 1345引脚对应的是i2c-2总线
# 所以这里查询i2c-2总线
pi@NanoPC-T4:~$ sudo i2cdetect -y -r -a 2
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
30: -- -- -- -- -- -- -- -- -- -- -- -- 3c -- -- -- 
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
70: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
# 这里就一个I2C地址 0xUU

# 检查i2c是否有驱动
cat /sys/bus/i2c/devices/i2c-1/name


# 寄存器数据导出。总线上i2c设备的数据是要存储在寄存器上。
(base) pi@NanoPC-T4:~$ sudo i2cdump -y 2 0x3c
No size specified (using byte-data access)
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f    0123456789abcdef
00: 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43    CCCCCCCCCCCCCCCC
10: 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43    CCCCCCCCCCCCCCCC
20: 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43    CCCCCCCCCCCCCCCC
30: 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43    CCCCCCCCCCCCCCCC
40: 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43    CCCCCCCCCCCCCCCC
50: 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43    CCCCCCCCCCCCCCCC
60: 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43    CCCCCCCCCCCCCCCC
70: 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43    CCCCCCCCCCCCCCCC
80: 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43    CCCCCCCCCCCCCCCC
90: 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43    CCCCCCCCCCCCCCCC
a0: 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43    CCCCCCCCCCCCCCCC
b0: 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43    CCCCCCCCCCCCCCCC
c0: 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43    CCCCCCCCCCCCCCCC
d0: 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43    CCCCCCCCCCCCCCCC
e0: 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43    CCCCCCCCCCCCCCCC
f0: 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43 43    CCCCCCCCCCCCCCCC


# 寄存器数据写入,即向寄存器中某一位地址上插入数据:
sudo i2cset -y 2 0x3c 0x20 0x55

# 读取I2C总线上设备0x3c的0x80寄存器地址的数据
sudo i2cget -y 2 0x3c 0x20

3. 安装oled驱动python包

git clone  https://github.com.cnpmjs.org/rm-hull/luma.examples
cd luma.examples && pip install -e .

3.1 用例测试

cd /home/02_hardware/luma.examples/examples
python 3d_box.py --help

I2C:
  --i2c-port I2C_PORT   I2C bus number (default: 1)
  --i2c-address I2C_ADDRESS
                        I2C display address (default: 0x3C)
# 因此可以使用下面的命令直接运行demo
python 3d_box.py --i2c-port=2 --i2c-address=0x3c

3.2 测试用例2

# https://blog.csdn.net/ki1381/article/details/79291138/
# https://blog.csdn.net/u011198687/article/details/120347965

#!/usr/bin/python3
# -*- coding: utf-8 -*-
from luma.core.interface.serial import i2c
from luma.core.render import canvas
# SSD1306, SSD1309, SSD1322, SSD1325, SSD1327, SSD1331,SSD1351, SSD1362 and SH1106 devices.
from luma.oled.device import ssd1306, ssd1309, ssd1322, ssd1325, ssd1327, ssd1331, ssd1351, ssd1362, sh1106
from time import sleep

from PIL import ImageDraw, ImageFont

"""
OLED luma 驱动库测试程序
功能:显示 hello world 和矩形外框持续10秒
"""
__version__ = 1.0
# 初始化端口
serial = i2c(port=2, address=0x3C)
# # 初始化设备,这里改ssd1306, ssd1325, ssd1331, sh1106
device = ssd1306(serial)
# 调用显示函数
with canvas(device) as draw:
    font = ImageFont.load_default()
    # 这里的font2字体可以修改成中文字体, 比如从win10的路径windows/fonts/的楷体, 放到这里后, 就可以啦
    font2 = ImageFont.truetype('/usr/share/fonts/truetype/freefont/FreeSans.ttf', 20)
    draw.rectangle(device.bounding_box, outline="white", fill="black")
    draw.text((10, 25), "hello world", font=font2, fill=255)
# 延时显示10s
while True:
    pass
注意: 这里用到的字体可以去`c:/windows/fonts/楷书等.ttf` 上传到板子上, 然后根据绝对路径进行使用即可

4. oled显示时间, 天气, 温度

注意: oled如果显示中文字体需要从win里面拷贝一个中文字体的ttf文件放到板子里面

其实很简单, 直接使用系统时间, 通过天气API查询天气, 在通过读取CPU温度文件获取温度, 最后显示在oled上面

# 设置oled显示
# 城市: 祝福
# 日期 时间 星期
# 今天天气
# 明天天气
# 每十秒更新一次
from luma.core.interface.serial import i2c
from luma.core.render import canvas
# SSD1306, SSD1309, SSD1322, SSD1325, SSD1327, SSD1331,SSD1351, SSD1362 and SH1106 devices.
from luma.oled.device import ssd1306, ssd1309, ssd1322, ssd1325, ssd1327, ssd1331, ssd1351, ssd1362, sh1106
from PIL import ImageDraw, ImageFont
import urllib.request
import gzip
import json
import datetime
import time


__version__ = 1.0
# 初始化端口
serial = i2c(port=2, address=0x3C)
# # 初始化设备,这里改ssd1306, ssd1325, ssd1331, sh1106
device = ssd1306(serial)

def get_weather_data() :
    url1 = 'http://wthrcdn.etouch.cn/weather_mini?city='+urllib.parse.quote("西安")
    url2 = 'http://wthrcdn.etouch.cn/weather_mini?citykey=101010100'
    weather_data = urllib.request.urlopen(url1).read()
    weather_data = gzip.decompress(weather_data).decode('utf-8')
    weather_dict = json.loads(weather_data) # 将json数据转成字典格式
    forecast = weather_dict.get('data').get('forecast')
    today_weather = "今: " + forecast[0].get('type') + " " + weather_dict.get('data').get('wendu')+'℃ ' + \
        "(" +forecast[0].get('low')[3:-1] + "~" + forecast[0].get('high')[3:-1] +")"
    # print(today_weather)
    tomorrow_weather = "明: " + forecast[1].get('type') + " " +\
        forecast[1].get('low')[3:] + "~" + forecast[1].get('high')[3:]
    # print(tomorrow_weather)
    
    return today_weather, tomorrow_weather

font1 = ImageFont.load_default() # 默认字体
font2 = ImageFont.truetype('/home/pi/zjq/04_hardware/oled/ttf_font/STKAITI.TTF', 16) # 中文字体


def display():
    today_weather, tomorrow_weather = get_weather_data()
    now_time = datetime.datetime.now().strftime("%m-%d %A %H:%M ")# now.strftime("%Y-%m-%d %H:%M:%S")
    # print(now_time)
    with open("/sys/devices/virtual/thermal/thermal_zone0/temp", "r") as f:
        temperature = str(int(int(f.read())/1000))
    with canvas(device) as draw:
        draw.rectangle(device.bounding_box, outline="white", fill="black")
        draw.text((0, 0), today_weather, font=font2, fill=255)
        draw.text((0, 16), tomorrow_weather, font=font2, fill=255)
        draw.text((5, 38), "CPU:" + temperature+"°", font=font1, fill=255)
        draw.text((5, 50), now_time, font=font1, fill=255)
    time.sleep(10)
    
while True:
    display()
# display()

5. 应用1 oled滚动显示文字

text = "将进酒 李白 君不见黄河之水天上来,奔流到海不复回。\
君不见高堂明镜悲白发,朝如青丝暮成雪。 人生得意须尽欢,\
莫使金樽空对月。天生我材必有用,千金散尽还复来。"


from time import sleep
from luma.core.virtual import viewport
from PIL import ImageDraw, ImageFont
virtual = viewport(device, width=2048, height=720)
font2 = ImageFont.truetype('/home/pi/zjq/04_hardware/oled/STKAITI.TTF', 16) # 中文字体


# 水平滚动
def horizontal_scroll():
    with canvas(virtual) as draw:
        draw.text((0,0), text=text, fill="white", font=font2)
    sleep(1)
    y = 0
    for x in range(len(text)*16):
        virtual.set_position((x, y))
        sleep(0.05)
        
def main():
    print("当前版本:", __version__)
    horizontal_scroll()
#     vertical_scroll()
 
main() 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

落子无悔!

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值