使用树莓派 结合Python Adafruit驱动OLED屏幕 显示实时视频

 关于OLED屏幕的驱动,在之前我已经写过很多篇博文:

IIC 协议 和 OLED_oled iic-CSDN博客

香橙派配合IIC驱动OLED & 使用SourceInsight解读源码_香橙派5 驱动屏幕-CSDN博客

这两篇博文都是通过模拟或调用IIC协议来使用C语言驱动OLED屏幕,现在在树莓派中我尝试了和香橙派类似的方法,我发现了一些问题:香橙派中使用了wiringPi库提供的Oled测试代码并进行修改,其中包含了“font.h”和“oled.h”这两个头文件,但是我已经忘记了我当时这两个头文件是从哪里来的= =,如果不使用这两个库,在查阅了一些别人的实现后发现,如果纯用C语言结合wiringPi库来驱动OLED本质还是要模拟IIC协议,比较麻烦。

综上,经过一些比较和考量,我决定使用Python Adafruit驱动OLED屏幕

树莓派的IIC开启和OLED屏幕识别

虽说要使用Python来驱动,但是OLED屏幕底层依然是IIC协议,所以对于树莓派需要先手动开启IIC协议:

IIC开启

  • 运行以下代码进入设置界面:
sudo raspi-config
  • 选择“Interface Options”:

  • 选择“I2c”然后打开:

此时,就可以正常使用IIC了,通过“gpio-readall” 可知:

现在,物理引脚3和5对应的就是SDA.1和SCL.1,其中“.1”代表的就是驱动文件是“/dev/i2c-1

此时,就可以按照引脚连接OLED屏幕了!

OLED屏幕识别

屏幕连接完成后,进行设备的识别:

  • 运行以下命令安装i2c-tools
sudo apt-get install -y i2c-tools    //安装IIC工具
  • 运行以下命令识别OLED屏幕
sudo i2cdetect -y 1
//“1”代表“i2c-1”

 

可见,树莓派已经成功识别到了OLED屏幕!

Adafruit_Python_SSD1306 库的下载和使用

根据淘宝的搜索,可以了解到我的OLED屏幕驱动芯片为SSD1306(这也是市面上绝大部分单片机小OLED屏幕的芯片,不过现在最新的好像换代了)。

驱动芯片为SSD1306对应的python库就是“Adafruit_Python_SSD1306"。

以下是安装的代码:

1. pip install Adafruit-GPIO
2. pip install Adafruit-SSD1306
3. git clone https://github.com/adafruit/Adafruit_Python_SSD1306.git

安装完成后,运行例程查看效果: 

cd Adafruit_Python_SSD1306/examples/
python3 shapes.py

将shapes.py中的“disp = Adafruit_SSD1306_128_32(rst=RST)”修改为“disp = Adafruit_SSD1306_128_64(rst=RST)”,可以显示得更清晰,具体根据不同的OLED屏幕尺寸来修改

成功显示!

修改例程显示图片

 首先,将刚刚测试成功的例程“shapes.py”复制到我的代码路径中:

 cp shapes.py /home/pi/mjm_code/oled_camera.py

由于之后我还是想用C语言来调用这个python文件,所以和我之前博文的思路一样,先将不需要的代码删去,再将python程序定义为函数进行测试:

oled_camera.py: 

由于我的最终目的是显示实时的视频流,所以我先将这个python代码修改,显示一张图片,后续C语言进行while循环不断来显示当前拍照图片就可以有视频的效果。

# Copyright (c) 2014 Adafruit Industries
# Author: Tony DiCola
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
import timeimport Adafruit_GPIO.SPI as SPI
import Adafruit_SSD1306from PIL import Image
from PIL import ImageDraw
from PIL import ImageFontdef init():# Raspberry Pi pin configuration:RST = 24# Note the following are only used with SPI:DC = 23SPI_PORT = 0SPI_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_64(rst=RST)# 128x64 display with hardware I2C:
# disp = Adafruit_SSD1306.SSD1306_128_64(rst=RST)# Note you can change the I2C address by passing an i2c_address parameter like:
# disp = Adafruit_SSD1306.SSD1306_128_64(rst=RST, i2c_address=0x3C)# 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)# Load default font.
#    font = ImageFont.load_default()def display():# Raspberry Pi pin configuration:RST = 24# Note the following are only used with SPI:DC = 23SPI_PORT = 0SPI_DEVICE = 0# 128x32 display with hardware I2C:disp = Adafruit_SSD1306.SSD1306_128_64(rst=RST)# Initialize library.disp.begin()#打开本地的照片#当前路径测试用,需按照实际情况修改img = Image.open('/home/pi/mjm_code/mjm.png')# 调整图片大小到 128x64img_resized = img.resize((128, 64),Image.LANCZOS)image = img_resized.convert('1')# Display image.disp.image(image)disp.display()if __name__ == '__main__': #写一个main调用face_detect函数来测试init()display()

 显示效果

运行“python3 oled_camera.py”:

可见,虽然画面很粗糙,但是成功显示图片!而且由于使用了现成的python库,不需要在麻烦的使用IIC协议写命令,初始化,取模了。 

OLED显示实时视频流

现在已经能在OLED上显示一张图片了,再次重复刚刚的思路:

“由于我的最终目的是显示实时的视频流,所以我先将这个python代码修改,显示一张图片,后续C语言进行while循环不断来显示当前拍照图片就可以有视频的效果。”

关于如何拍照并保存本地,和如何使用C语言调用Python,可以看我之前的博文:

树莓派接入USB摄像头并使用fswebcam和mjpg-streamer进行测试_树莓派mjpg-streamer-CSDN博客

基于阿里云平台 通过树莓派实现 1:1人脸识别-CSDN博客 

编写C语言调用oled_camera.py

回顾“C语言调用Python的步骤”:

oled_show.c:
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <Python.h>#include "oled_show.h"void oled_init(void)
{Py_Initialize();PyObject *sys = PyImport_ImportModule("sys");PyObject *path = PyObject_GetAttrString(sys, "path");PyList_Append(path, PyUnicode_FromString("."));
}void oled_final(void)
{Py_Finalize();
}void oled_show_init(void) //由于没有返回参数,所以可以直接定义void型
{PyObject *pModule = PyImport_ImportModule("oled_camera"); //加载python文件if (!pModule){PyErr_Print();printf("Error: failed to load module\n");goto FAILED_MODULE; //goto的意思就是如果运行到这里就直接跳转到FAILED_MODULE}PyObject *pFunc = PyObject_GetAttrString(pModule, "init"); //加载python文件中的对应函数if (!pFunc){PyErr_Print();printf("Error: failed to load function\n");goto FAILED_FUNC;}PyObject *pValue = PyObject_CallObject(pFunc, NULL);if (!pValue){PyErr_Print();printf("Error: function call failed\n");goto FAILED_VALUE;}/* 没有返回值,无需调用int result = 0;if (!PyArg_Parse(pValue, "i", &result)) //ace_detect函数返回的是已经经过提取和取证过的置信度score,是个int型,用‘i’表示{PyErr_Print();printf("Error: parse failed");goto FAILED_RESULT;}*/FAILED_RESULT:Py_DECREF(pValue);
FAILED_VALUE:Py_DECREF(pFunc);
FAILED_FUNC:Py_DECREF(pModule);
FAILED_MODULE://无需return
}void oled_show(void) //由于没有返回参数,所以可以直接定义void型
{PyObject *pModule = PyImport_ImportModule("oled_camera"); //加载python文件if (!pModule){PyErr_Print();printf("Error: failed to load module\n");goto FAILED_MODULE; //goto的意思就是如果运行到这里就直接跳转到FAILED_MODULE}PyObject *pFunc = PyObject_GetAttrString(pModule, "display"); //加载python文件中的对应函数if (!pFunc){PyErr_Print();printf("Error: failed to load function\n");goto FAILED_FUNC;}PyObject *pValue = PyObject_CallObject(pFunc, NULL);if (!pValue){PyErr_Print();printf("Error: function call failed\n");goto FAILED_VALUE;}/* 没有返回值,无需调用int result = 0;if (!PyArg_Parse(pValue, "i", &result)) //ace_detect函数返回的是已经经过提取和取证过的置信度score,是个int型,用‘i’表示{PyErr_Print();printf("Error: parse failed");goto FAILED_RESULT;}*/FAILED_RESULT:Py_DECREF(pValue);
FAILED_VALUE:Py_DECREF(pFunc);
FAILED_FUNC:Py_DECREF(pModule);
FAILED_MODULE://无需return
}
oled_show.h:
#ifndef __oled__H
#define __oled__Hvoid oled_init(void);
void oled_final(void);
void oled_show_init(void);
void oled_show(void);#endif

编写C程序调用刚刚的C函数实现实时视频流显示

test_oled_camera.c:

注意,由于此处涉及了拍照,拍照保存的路径和照片的名字需要和oled_camera.py中保持一样,所以此处需要按照需求修改python代码

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <wiringPi.h>#include "oled_show.h"int main()
{oled_init();oled_show_init();while(1){system("wget http://192.168.2.56:8080/?action=snapshot -O /home/pi/mjm_code/oled_pic.png"); //拍照delay(10);//给一点时间让照片拍出来if(0 == access("/home/pi/mjm_code/oled_pic.png", F_OK)){ //如果照片成功拍到了oled_show();}else{printf("pic not exist!\n");}remove("/home/pi/mjm_code/oled_pic.png");delay(50); //此处决定帧率,delay时间越短帧率越高}oled_final();return 0;
}

编译运行

  • 输入以下指令编译:
gcc test_oled_camera.c oled_show.c -I /usr/include/python3.11/ -l python3.11 -lwiringPi
  • 输入以下指令运行程序: 
./a.out
  • 输入以下指令结束运行:
ps -ef|grep 程序名称
kill 进程编号

最终效果

视频中我出现在画框中并朝着屏幕挥手:

可见,虽然帧率和分辨率低的可怕,但是的确实现了使用OLED实时显示视频流的功能!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/549557.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Tomcat:Session ID保持会话

目录 前言 ​一、部署环境 二、部署nginx反向代理服务器 三、部署tomcat服务器1 四、部署tomcat服务器2 五、客户端测试&#xff08;Session ID不断变动&#xff09; 六、配置Session ID会话保持 七、客户端测试&#xff08;Session ID保持&#xff09; 前言 此次实验…

研究人员发现 OpenAI ChatGPT、Google Gemini 的漏洞

自 OpenAI 推出 ChatGPT 以来&#xff0c;生成式 AI 聊天机器人的数量及其在企业中的采用率在一年多时间里呈爆炸式增长&#xff0c;但网络安全专业人士的担忧也随之增加&#xff0c;他们不仅担心威胁组织对新兴技术的使用&#xff0c;还担心大型网络的安全性及模型&#xff08…

分类预测 | Matlab实现BiTCN双向时间卷积神经网络数据分类预测/故障识别

分类预测 | Matlab实现BiTCN双向时间卷积神经网络数据分类预测/故障识别 目录 分类预测 | Matlab实现BiTCN双向时间卷积神经网络数据分类预测/故障识别分类效果基本描述程序设计参考资料 分类效果 基本描述 1.Matlab实现BiTCN双向时间卷积神经网络数据分类预测/故障识别。 2.自…

计算机生物科技在基因编辑中的应用及其前景

一、引言 基因编辑&#xff0c;作为一种能够精准修改生物体基因组的技术&#xff0c;近年来受到了广泛的关注。 而计算机生物科技作为连接计算机科学与生物学的桥梁&#xff0c;为基因编辑技术的快速发展提供了强大的支持。通过利用计算机算法和数据分析方法&#xff0c;研究人…

windows取证

Windows事件日志分析 使用Windows事件日志查看器&#xff0c;打开实验文档“security01.evtx”。按“日期和时间”对日志进行分组统计&#xff1b;按“事件ID”对日志进行分组统计&#xff1a; 问题&#xff1a;日志中是否有用户登录失败的记录。如果有&#xff0c;请按“登录…

信息系统项目管理师019:存储和数据库(2信息技术发展—2.1信息技术及其发展—2.1.3存储和数据库)

文章目录 2.1.3 存储和数据库1.存储技术2.数据结构模型3.常用数据库类型4.数据仓库 记忆要点总结 2.1.3 存储和数据库 1.存储技术 存储分类根据服务器类型分为&#xff1a;封闭系统的存储和开放系统的存储。封闭系统主要指大型机等服务器。开放系统指基于包括麒麟、欧拉、UNIX…

java 类和对象

1、什么是对象&#xff1f; 万物皆对象&#xff0c;客观存在的事物皆为对象。大到名胜古迹&#xff08;万里长城、秦始皇兵马俑等&#xff09;&#xff0c;小到生活中的小物品&#xff08;水杯、钢笔、手机等&#xff09;&#xff0c;只要是客观存在的事物都可以称之为对象。 …

【随笔】汇编(寄存器、内存模型、常用指令、语法)

文章目录 一、简介二、寄存器三、内存模型3.1 Heap3.2 Stack 四、指令4.1 示例4.2 语法4.3常用指令 一、简介 汇编语言&#xff08;英语&#xff1a;assembly language&#xff09;是任何一种用于电子计算机、微处理器、微控制器&#xff0c;或其他可编程器件的低级语言。在不…

11 html 学习/作业

<!DOCTYPE html> <html><head><meta charset"utf-8"><title></title></head><body><a href"./index.html">首页</a><a href"https://www.baidu.com/">百度</a><a h…

数字化社会的新纪元:揭秘 Web3 的社交网络

随着区块链技术的不断发展和普及&#xff0c;Web3作为其重要组成部分&#xff0c;正逐渐改变着社交网络的面貌。Web3的出现不仅为社交网络带来了新的技术和理念&#xff0c;还为用户提供了更加开放、透明和安全的社交体验。本文将深入探讨Web3的社交网络&#xff0c;揭示其在数…

ev多域名ssl证书2000元一年送一月

多域名SSL证书是一种特殊的数字证书产品。多域名SSL证书可以同时保护多个独立的域名站点&#xff0c;这些域名站点可以是多个主域名、子域名&#xff0c;多域名SSL证书可以为它们提供传输数据加密服务以及身份认证服务。EV多域名SSL证书具有更高的安全性&#xff0c;所以一些金…

怎么做好独立站的SEO优化

随着全球贸易的蓬勃发展&#xff0c;越来越多的企业开始关注外贸市场&#xff0c;并将目光投向了外贸网站。然而&#xff0c;在竞争激烈的外贸市场中&#xff0c;如何写出吸引人的文章&#xff0c;以及如何优化网站以在搜索引擎中脱颖而出&#xff0c;成为了外贸独立网站必须面…