使用树莓派 结合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.rhkb.cn/news/278760.html

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

相关文章

【Linux】进程---概念---进程---优先级

主页&#xff1a;醋溜马桶圈-CSDN博客 专栏&#xff1a;Linux_醋溜马桶圈的博客-CSDN博客 gitee&#xff1a;mnxcc (mnxcc) - Gitee.com 目录 1.操作系统(Operator System) 1.1 概念 1.2 设计OS的目的 1.3 定位 1.4 如何理解 "管理" 1.5 总结 1.6 系统调用和…

数据可视化-ECharts Html项目实战(3)

在之前的文章中&#xff0c;我们学习了如何创建堆积折线图&#xff0c;饼图以及较难的瀑布图并更改图标标题。想了解的朋友可以查看这篇文章。同时&#xff0c;希望我的文章能帮助到你&#xff0c;如果觉得我的文章写的不错&#xff0c;请留下你宝贵的点赞&#xff0c;谢谢。 …

主存中存储单元地址的分配

主存中存储单元地址的分配 为什么写这篇文章? 因为我看书中这部分时&#xff0c;看到下面的计算一下子没反应过来&#xff1a; 知识回顾&#xff08;第1章&#xff09; 计算机系统中&#xff0c;字节是最小的可寻址的存储单位&#xff0c;通常由8个比特&#xff08;bit&…

OpenCV 单目相机标定

文章目录 一、简介二、实现代码三、实现效果参考资料一、简介 单目相机的标定过程与双目相机的标定过程很类似,具体过程如下所述: 1、首先我们需要获取一个已知图形的图像(这里我们使用MATLAB所提供的数据)。 2、找到同名像点(匹配点),这里主要是探测黑白格子之间的角点…

鸿蒙Harmony应用开发—ArkTS声明式开发(画布组件:Canvas)

提供画布组件&#xff0c;用于自定义绘制图形。 说明&#xff1a; 该组件从API Version 8开始支持。后续版本如有新增内容&#xff0c;则采用上角标单独标记该内容的起始版本。 子组件 不支持。 接口 Canvas(context?: CanvasRenderingContext2D) 从API version 9开始&…

huawei services HK华为云服务

huaweiserviceshk是一种云计算服务&#xff0c;为华为云服务用户提供了多种服务&#xff0c;包括云服务器、数据库、存储、网络等&#xff0c;用户可以根据自己的需求选择不同的服务并支付相应的费用 如何付费呢&#xff0c;这里可以使用441112&#xff0c;点击获取 卡片信息在…

机器人可反向驱动能力与力控架构

反向驱动性是电机传动系统的机械特性&#xff0c;它描述了运动是否可以轻松反转 。特别是&#xff0c;反向驱动能力取决于两个因素&#xff1a;传动运动效率和整体执行器机械阻抗。反向运动中传动装置的低运动效率意味着所施加的外力的大部分被运动反作用力抵消。然而&#xff…

24 OpenCV直方图反向投影

文章目录 参考反向投影作用calceackProject 反向投影mixchannels 通道图像分割示例 参考 直方图反向投影 反向投影 反向投影是反映直方图模型在目标图像中的分布情况简单点说就是用直方图模型去目标图像中寻找是否有相似的对象。通常用HSV色彩空间的HS两个通道直方图模型 作用…

Unity PS5开发 天坑篇 之 DEVKit环境部署与系统升级02

上一篇各位大神们已经收到了SONY官方免费寄送的PS5开发机与测试机&#xff0c;恭喜大家成为SONY的开发者, 本篇继续PS5开发机的部署与开发套件使用。 一, PC安装PS5 SDK与系统升级 1. PC/PS5 SDK Manager下载安装包 登录开发者账号后&#xff0c;Development->Resources&a…

Android 开发环境搭建(Android Studio 安装图文详细教程)

Android Studio 下载 https://developer.android.google.cn/studio?hlzh-cn Android Studio 安装 检查电脑是否启用虚拟化 如果没有开启虚拟化&#xff0c;则需要进入电脑的 BIOS 中开启 直接 next选择安装的组件&#xff0c;Android Studio 和 Android 虚拟设备&#xff…

【MLLM+轻量多模态模型】24.02.Bunny-v1.0-2B-zh: 轻量级多模态语言模型 (效果一般)

24.02 北京人工智能研究院&#xff08;BAAI&#xff09;提出以数据为中心的轻量级多模态模型 arxiv论文&#xff1a;2402.Efficient Multimodal Learning from Data-centric Perspective 代码&#xff1a;https://github.com/BAAI-DCAI/Bunny 在线运行&#xff1a;https://wis…

【GDB Debugger】新手快速入门学习笔记

文章目录 前言第一讲 什么是GDB第二讲 搭建实验环境第三讲 快速开始第四讲 举例说明如何查看变量信息——print、step第五讲 使用GDB的技巧&#xff08;只在此展开观察点&#xff09;第六讲 调试core文件&#xff08;针对UNIX&#xff0c;程序崩溃时&#xff09;第七讲 调试一个…

如何搭建“Docker Registry私有仓库,在CentOS7”?

1、下载镜像Docker Registry docker pull registry:2.7.1 2、运行私有库Registry docker run -d -p 5000:5000 -v ${PWD}/registry:/var/lib/registry --restartalways --name registry registry:2.7.1 3、拉取镜像 docker pull busybox 4、打标签&#xff0c;修改IP&#x…

uniapp可视范围高度 - 用户屏幕可操作的屏幕高度 - 适用于APP、H5@公众号、纯H5@Chrome

可视范围高度 let heightPx uni.getWindowInfo().windowHeight uni.getWindowInfo().windowTop 官方手册 uni.getWindowInfo() | uni-app官网uni-app,uniCloud,serverless,uni.getWindowInfo()https://uniapp.dcloud.net.cn/api/system/getWindowInfo.html 实测数据 uni.ge…

BI让数据分析不在困难,分解企业数据分析流程

一、数据培养 数据分析最关键的是什么&#xff1f;其实从名字上就可以看出来&#xff0c;数据是一切的关键&#xff0c;没有数据的话数据分析从何谈起呢。但数据的积累不是一天两天就能成功的&#xff0c;企业的一定要有培养数据的意识&#xff0c;在业务活动中沉淀数据&#…

开源堡垒机Jumpserver

开源堡垒机Jumpserver 文章目录 开源堡垒机Jumpserver1 Jumpserver介绍2 Jumpserver部署用户管理资产创建账号管理模板添加 用户组管理权限管理远程连接免密连接 1 Jumpserver介绍 Jumpserver 是全球首款完全开源的堡垒机&#xff0c;使用 GNU GPL v2.0 开源协议&#xff0c;是…

《论文阅读》EmpDG:多分辨率交互式移情对话生成 COLING 2020

《论文阅读》EmpDG:多分辨率交互式移情对话生成 COLING 2020 前言简介模型架构共情生成器交互鉴别器损失函数前言 亲身阅读感受分享,细节画图解释,再也不用担心看不懂论文啦~ 无抄袭,无复制,纯手工敲击键盘~ 今天为大家带来的是《EmpDG: Multi-resolution Interactive E…

文心一言赋能问卷生成,打造高效问卷调研工具

当前&#xff0c;各种大语言模型&#xff08;LLM&#xff0c;Large Language Model&#xff09;井喷式发展&#xff0c;基于LLM的应用也不断涌现。但是&#xff0c;当开发者基于LLM开发下游应用时&#xff0c;LLM直接生成的结果在格式、内容等方面都存在许多不确定因素&#xf…

Cesium:绘制一个 3DTiles 对象的外包盒顶点

作者:CSDN @ _乐多_ 本文将介绍如何使用 Cesium 引擎根据模型的中心坐标,半轴信息,绘制一个 3DTiles 对象的外包盒顶点。 外包盒是一个定向包围盒(Oriented Bounding Box),它由一个中心点(center)和一个包含半轴(halfAxes)组成。半轴由一个3x3的矩阵表示,这个矩阵…

Python Web开发记录 Day13:Django part7 Ajax入门与案例(任务管理)

名人说&#xff1a;莫道桑榆晚&#xff0c;为霞尚满天。——刘禹锡&#xff08;刘梦得&#xff0c;诗豪&#xff09; 创作者&#xff1a;Code_流苏(CSDN)&#xff08;一个喜欢古诗词和编程的Coder&#x1f60a;&#xff09; 目录 1、Ajax入门①简介②工作原理③优点④缺点⑤使用…