垃圾分类子项目三 - 添加oled显示

本文继承自: 垃圾分类子项目2 - 加入舵机控制-CSDN博客

添加 oled 功能: 

我们要使用oled,就需要添加 i2c 功能 
需要在这个文件中  /boot/orangepiEnv.txt
添加这行,使用  i2c 协议
overlays=uart5 i2c3
 

myoled.c 


#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <stdint.h>
#include "oled.h"
#include "font.h"#define FILENAME "/dev/i2c-3" static struct display_info disp;int myoled_show(void *arg) // oled 显示
{unsigned char *buffer = (unsigned char *)arg; // 传入串口数据 -- bufferoled_putstrto(&disp, 0, 10, "This garbage is:");// 这垃圾是:disp.font = font2; //  指定输出类型switch (buffer[2]){case 0x41:oled_putstrto(&disp, 0, 20, "residual(dry) waste");// 干垃圾break;case 0x42:oled_putstrto(&disp, 0, 20, "wet wastee");// 湿垃圾break;case 0x43:oled_putstrto(&disp, 0, 20, "Recyclable waste");// 可回收垃圾break;case 0x44:oled_putstrto(&disp, 0, 20, "hazardous  waste");// 有害垃圾break;case 0x45:oled_putstrto(&disp, 0, 20, "Recognition failure");// 识别失败break;}disp.font = font2;oled_send_buffer(&disp); return 0;
}int myoled_init(void) //初始化 oled
{int e;disp.address = OLED_I2C_ADDR;disp.font = font2; // 指定显示字样类型e = oled_open(&disp, FILENAME); //打开i2c 设备接口e = oled_init(&disp); // 初始化oledreturn e;
}

myoled.h

#ifndef __MYOLED_H
#define __MYOLED_Hint myoled_show(void *arg);
int myoled_init(void);#endif

main.c

思路: 在主函数中,增加一条线程用于将垃圾类型 显示 到oled

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h> // access()
#include <error.h>  // remove()
#include <wiringPi.h>
#include <softPwm.h>
#include <pthread.h>#include "uartTool.h"
#include "garbage.h"
#include "pwm.h"
#include "myoled.h"static int detect_process(const char *process_name) // 判断进程是否在运行
{int n = -1;FILE *strm;char buf[128] = {0};sprintf(buf, "ps -ax | grep %s|grep -v grep", process_name); // 组合进程名字,为完整命令if ((strm = popen(buf, "r")) != NULL)                        // 通过 popen 的 方式去执行{if (fgets(buf, sizeof(buf), strm) != NULL) // 执行完后 判断是否能拿到正确的进程号,空格分开,第一个字符串就是进程号{n = atoi(buf); // 拿到就放回 进程号,不然  返回 -1}}else{return -1; // 执行失败}pclose(strm);return n;
}int serial_fd = -1;    // 线程调用 -- 定义为全局
pthread_cond_t cond;   // 设置条件变量
pthread_mutex_t mutex; //  设置线程锁void *pget_voice(void *arg) // 语言播放线程函数
{int len = 0;unsigned char buffer[6] = {0xAA, 0x55, 0x00, 0x00, 0x55, 0xAA}; // 初始化 buffer[2] --  关联垃圾类型if (-1 == serial_fd){printf("%s | %s | %d:open serial failed\n", __FILE__, __func__, __LINE__); // 三个宏的含义: 文件名 - main.c,函数名 - pget_voice ,行号 -  138pthread_exit(0);                                                           // 串口打开失败 -->退出}while (1){len = serialGetstring(serial_fd, buffer); // 通过串口获得语言输入if (len > 0 && buffer[2] == 0x46)         // 判断是否 接到识别指令{pthread_mutex_lock(&mutex);   //  先上锁,保证后面执行这块不会被打断buffer[2] = 0x00;             // 判断完后的复位pthread_cond_signal(&cond);   // 发送信号,告诉阿里云线程开始识别了pthread_mutex_unlock(&mutex); // 解锁,与上锁包含的代码块执行的时候不会被打断}}pthread_exit(0);
}void *popen_trash_can(void *arg) // 开盖
{ pthread_detach(pthread_self());unsigned char *buffer = (unsigned char *)arg;if(buffer[2] == 0x43){pwm_write(PWM_GARBAGE1);delay (2000); //开盖5spwm_stop(PWM_GARBAGE1); //停止写入波形}else if(buffer[2] != 0x45){pwm_write(PWM_GARBAGE2);delay (2000); //开盖5spwm_stop(PWM_GARBAGE2); //停止写入波形}pthread_exit(0); 
}void *psend_voice(void *arg) // 发送语言播报
{pthread_detach(pthread_self()); // pthread_self -- 拿到自己的线程id --> 与父进程分离,不然开盖等待时间太长影响下一次识别unsigned char *buffer = (unsigned char *)arg;if (-1 == serial_fd) //判断串口是否打开{printf("%s | %s | %d:open serial failed\n", __FILE__, __func__, __LINE__); // 三个宏的含义: 文件名 - main.c,函数名 - pget_voice ,行号 -  138pthread_exit(0);                                                           // 串口打开失败 -->退出}printf("buffer[2] = 0x%x\n",buffer[2]);  if(NULL!=buffer) //有数据serialSendstring(serial_fd, buffer, 6); // 将识别到的数据发送到串口,回传给语音模块,语言模块收到数据后进行相应输出 -- 实现语言播报pthread_exit(0); 
}void *poled_show(void *arg)  // 显示oled 的线程函数
{pthread_detach(pthread_self()); myoled_init();myoled_show(arg); // 将buffer 传进来,用于oled的显示pthread_exit(0); 
}void *pcategory(void *arg) // 阿里云 -- 垃圾类型识别线程函数
{unsigned char buffer[6] = {0xAA, 0x55, 0x00, 0x00, 0x55, 0xAA}; // 初始化 buffer[2] --  关联垃圾类型char *category = NULL;pthread_t send_voice_tid,trash_tid,oled_tid;while (1){pthread_mutex_lock(&mutex);       // 拿锁pthread_cond_wait(&cond, &mutex); // 等待 接受到信号 -- 才能开始识别pthread_mutex_unlock(&mutex);// 开始识别  buffer[2] = 0x00;  // 拍照前复位         system(WGET_CMD); // 拍照if (access(GARBAGE_FILE, F_OK) == 0) // 判断 文件存在{category = garbage_category(category); // 通过通过阿里云接口图像识别 获取垃圾类型if (strstr(category, "干垃圾")){buffer[2] = 0x41;}else if (strstr(category, "湿垃圾")){buffer[2] = 0x42;}else if (strstr(category, "可回收垃圾")){buffer[2] = 0x43;}else if (strstr(category, "有害垃圾")){buffer[2] = 0x44;}else{buffer[2] = 0x45;}}else{ // 没有获取到图片buffer[2] = 0x45;//}}// 创建打开垃圾桶线程  pthread_create(&trash_tid, NULL, popen_trash_can, (void*)buffer);// 创建语音播报线程pthread_create(&send_voice_tid, NULL,  psend_voice, (void*)buffer);// 创建oled显示线程pthread_create(&oled_tid, NULL, poled_show, (void*)buffer);// buffer[2] = 0x00;                       // 发送完后,一堆有效数据位清零,方便下一次调用remove(GARBAGE_FILE);                   // 清理缓存 删除刚刚拍摄的图片,避免对下一次拍摄造成干扰}pthread_exit(0);
}int main(int argc, char **argv)
{int len = 0;int ret = -1;char *category = NULL;pthread_t get_voice_tid, category_tid; // 创建线程idunsigned char buffer[6] = {0xAA, 0x55, 0x00, 0x00, 0x55, 0xAA}; // 初始化 buffer[2] --  关联垃圾类型wiringPiSetup(); // 初始化wiringPi库garbage_init();  // 初始化 阿里云接口ret = detect_process("mjpg_streamer"); // 用于判断mjpg_streamer服务是否已经启动if (-1 == ret){puts("detect process failed");goto END;}serial_fd = myserialOpen(SERIAL_DEV, BAUD); // 初始化串口,打开串口设备(语言模块)if (serial_fd == -1){ // 初始化串口失败goto END;}// 创建语音线程  -- 注意第一个参数类型是指针变量 pthread_t *pthread_create(&get_voice_tid, NULL, pcategory, NULL);// 创建阿里云交互线程pthread_create(&category_tid, NULL, pget_voice, NULL);// 第二个参数表示接收到的返回值 -- 没有就NULLpthread_join(get_voice_tid, NULL); // 等待线程退出pthread_join(category_tid, NULL);pthread_mutex_destroy(&mutex); // 释放锁pthread_cond_destroy(&cond);  // 释放条件变量close(serial_fd); // 关闭串口文件描述符  fd
END:garbage_final();return 0;
}

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

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

相关文章

第十五届蓝桥杯C/C++B组题解

第十五届蓝桥杯大赛软件类省赛C/C大学B组 赛题链接A握手问题B小球反弹C好数DR格式E宝石组合F数字接龙G爬山H拔河

[笔试训练](七)

目录 019&#xff1a;字符串中找出连续最长的数字串 020&#xff1a;岛屿数量 021&#xff1a;拼三角 019&#xff1a;字符串中找出连续最长的数字串 字符串中找出连续最长的数字串_牛客题霸_牛客网 (nowcoder.com) 题目&#xff1a; 题解&#xff1a; 边遍历边记下遇到的…

ionic 中对Input输入框、searchbar进行solr检索

一、概述 Ionic 是一个用于开发跨平台应用程序的开源工具&#xff0c;可以使用 Angular、React 或 Vue 等前端框架。要在 Ionic 应用程序中实现实时与 Solr 通信&#xff0c;可以使用 HTTP 客户端&#xff08;如 Angular 的 HttpClient 或 Ionic 的 Native HTTP&#xff09;…

鸿蒙入门11-DataPanel组件

数据面板组件 用于将多个数据的占比情况使用 占比图 进行展示 参数 参数形式 &#xff1a; DataPanel( options:{ values: number[], max?: number, type?: DataPanelType } ) 参数名 参数类型 是否必填 默认值 参数描述 values number[] 是 - 数据值列表 最大支持…

Feign功能详解、使用步骤、代码案例

简介&#xff1a;Feign是Netflix开发的声明式&#xff0c;模板化的HTTP客户端&#xff0c;简化了HTTP的远程服务的开发。Feign是在RestTemplate和Ribbon的基础上进一步封装&#xff0c;使用RestTemplate实现Http调用&#xff0c;使用Ribbon实现负载均衡。我们可以看成 Feign R…

IDEA快速入门

目录 1. 概述 2. 安装 3. 激活 4. 关闭自动更新 5. 创建Java项目 5.1 配置JRE 5.2 创建项目 6. 配置设置 6.1 主题 6.2 设置字体默认大小 6.3 鼠标滚轮改变字体大小 6.4 设置自动导入 6.5 项目选择 7. lombok插件 7.1 安装插件 7.2 启用注解 8. 安装包及插件…

linux-进程(2)

1.通过系统调用获取进程标示符 进程id&#xff08;PID&#xff09; 父进程id&#xff08;PPID&#xff09; 每一个可执行程序运行起来之后都会成为一个进程&#xff0c;每个进程都有一个自己的id&#xff0c;以及一个父进程id&#xff0c;父进程就是创建自己进程的进程&#xf…

一条龙-T检验+绘制boxplot

1.输入文件&#xff1a; 2.代码 #title:boxplot-5utr-cds-3tr-ATCG的百分比分布和T检验_封装函数版 rm(listls(allTRUE)) setwd("E:/R/Rscripts/5UTR_ABD_TE") library(tidyverse) library(ggplot2) # library(RColorBrewer) library(patchwork) library(dplyr) l…

windows文件夹共享设置

目录 操作如何在同个局域网下的两个主机间分享文件?(尤其是在虚拟机与物理机中) 待续、更新中 操作 如何在同个局域网下的两个主机间分享文件?(尤其是在虚拟机与物理机中) 主机A(被访问) 两个主机在一个局域网中/被访问主机位本地账户 —— 桌面新建文件夹 —— 右键设置共享…

【k8s】(七) kubernetes1.29.4离线部署之-部署网络插件

&#xff08;一&#xff09;kubernetes1.29.4离线部署之-安装文件准备 &#xff08;二&#xff09;kubernetes1.29.4离线部署之-镜像文件准备 &#xff08;三&#xff09;kubernetes1.29.4离线部署之-环境初始化 &#xff08;四&#xff09;kubernetes1.29.4离线部署之-组件安装…

Python-100-Days: Day01

Day01 Python简介 1.1989年Guido von Rossum在圣诞节之夜开始着手python语言编译器的编写。 2.1991年2月 Python v1 编译器诞生&#xff0c;使用C实现的&#xff0c;此时可以调用C的库函数。 3.1994年1月&#xff0c;Python v1.0 正式版发布。 4.2000年10月16日&#xff0…

【Docker】Docker 中不能使用 nvidia-smi

目录 1. 问题 2. 解决方法 1. 问题 在 docker 中执行 nvidia-smi 后报错&#xff1a; Failed to initialize NVML: Unknown Error这个错误表示不能成功初始化NVML(Nvidia Management Library)库来管理和监测Nvidia GPU。可能的原因和解决方法如下: 检查是否正确安装并加载了…

mediasoupWork中引入本地so库

文章目录 1. gyp官方一般修改2. 尝试修改1本篇是一个bug的记录,原自一次需求对mediasoup worker层的修改需要引入一个自己的库,但是只有so库,找不到源码无法使用静态库的方式通过修改.gyp连接到worker中; 对于.gyp中so库的引入网上很难找到对应的文档,所以按照ld连接库的方…

新药品注册分类5大类的注册标准

在医药行业的浩瀚海洋中&#xff0c;药品注册分类就如同一座明亮的航标灯&#xff0c;指引着每一款新药从实验室走向市场&#xff0c;从理论概念变成患者手中的生命希望。本文将深入探讨化学药、中药、生物药的药品注册分类标准&#xff0c;药品分类常见问题、以及如何高效查询…

linux系统-深入学习文件系统与日志分析

目录 一、inode于block inode于block概括inode的内容inode包含文件的元信息用stat命令可以查看某个文件的inode信息Linux系统文件三个主要的时间属性目录文件架构 用户通过文件名打开文件时&#xff0c;系统内部的过程查看inode号码的实操硬盘分区后的结构 &#x1f447;用户访…

走向大规模应用之前,DePIN 如何突破技术、数据与市场之网

近期&#xff0c;随着分布式物理基础设施网络&#xff08;DePIN&#xff09;的快速演变&#xff0c;一个旨在利用区块链技术彻底改造传统基础设施模型的新兴生态系统正在逐渐浮现。2024 年 4 月&#xff0c;以 peaq 为代表的 DePIN 项目成功筹集了 1500 万美元用于生态系统的扩…

mac配置maven

在 macOS 上配置 Maven 也相对简单。以下是一种常用的方法&#xff1a; 1. 安装maven **下载 Maven&#xff1a;**首先&#xff0c;你需要从 Maven 官网&#xff08;https://maven.apache.org/download.cgi&#xff09;下载最新版本的 Maven。你可以选择二进制压缩包&#xf…

02.Scala简单演示

Scala创建对象的方法与Java有所不同 class可以直接传入形参&#xff1b; 形式为 变量名称&#xff1a;变量类型 逗号隔开 ** ** 方法定义也比较特殊 ** ** def方法名&#xff08;&#xff09;:返回值 { } 其中返回值Unit 等价于Java中的void

系统服务(22年国赛)—— 磁盘管理(压缩去重)

前言&#xff1a;原文在我的博客网站中&#xff0c;持续更新数通、系统方面的知识&#xff0c;欢迎来访&#xff01; 系统服务&#xff08;22年国赛&#xff09;—— 磁盘管理(压缩&&去重)https://myweb.myskillstree.cn/90.html 目录 StorageSrv 安装并创建vdo 将…

多输入多输出 | Matlab实现WOA-LSSVM鲸鱼算法优化最小二乘支持向量机多输入多输出预测

多输入多输出 | Matlab实现WOA-LSSVM鲸鱼算法优化最小二乘支持向量机多输入多输出预测 目录 多输入多输出 | Matlab实现WOA-LSSVM鲸鱼算法优化最小二乘支持向量机多输入多输出预测预测效果基本介绍程序设计往期精彩参考资料 预测效果 基本介绍 Matlab实现WOA-LSSVM鲸鱼算法优化…