目录:
文章:OrangePi Zero2 全志H616 开发初探 🔗点此打开 智能垃圾分类识别垃圾桶代码示例
main.c 主函数
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <wiringPi.h>
#include <pthread.h>
#include "serial.h"
#include "garbage.h"
#include "pwm.h"
#include "myoled.h"
#include "socket.h"
int serial_fd = -1;
pthread_cond_t cond;
pthread_mutex_t mutex;
/* 检查 process_name 进程是否存在、运行 */
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);
// 构造 ps -ax | grep process_name|grep -v grep 终端命令
if((strm = popen(buf, "r")) != NULL) // 使用 popen 执行 buf 命令
{
// 返回值不为 -1 表明存在该进程
if(fgets(buf, sizeof(buf), strm) != NULL) // 取出输出的信息存放到 buf
{
printf("buf=%s\n",buf); // 将信息打印出来
n = atoi(buf); // 取出进程 ID 号,因为输出的信息最前方就是进程 ID 号
printf("n=%d\n",n); // 打印进程 ID 号
}
}
else // 进程不存在
{
return -1;
}
pclose(strm); // 关闭文件流
return n; // 返回进程 ID 号,不为 -1
}
/* 语音指令接收线程 */
void *pget_voice(void *arg)
{
unsigned char buffer[6] = {
0xAA, 0x55, 0x00, 0x00, 0X55, 0xAA}; // 初始化接收串口信息的内存空间
int len = 0;
printf("%s|%s|%d\n", __FILE__, __func__, __LINE__); // 调试信息
if (-1 == serial_fd) // 串口打开失败
{
printf("%s|%s|%d: open serial failed\n", __FILE__, __func__, __LINE__);
pthread_exit(0);
}
printf("%s|%s|%d\n", __FILE__, __func__, __LINE__); // 调试信息
while(1)
{
len = serialGetstring(serial_fd, buffer); // 获取串口信息,语音模块发送的信息
printf("%s|%s|%d, len=%d\n", __FILE__, __func__, __LINE__,len); // 调试信息
/* 语音模块识别到 “开始识别垃圾”,会向串口发送 0xAA 0x55 0x46 0x00 0x55 0xAA 的数据 */
if (len > 0 && buffer[2] == 0x46)
{
printf("%s|%s|%d\n", __FILE__, __func__, __LINE__); // 调试信息
/*
与阿里云线程、网络指令接收线程的互斥条件
一次只能通过一种方式(语音或网络)命令垃圾桶开启一次识别
与网络指令接收线程互斥、与阿里云线程互为条件变量
*/
pthread_mutex_lock(&mutex);
buffer[2] = 0x00; // 初始化接收串口信息的内存空间
pthread_cond_signal(&cond); // 触发条件,唤醒 “阿里云垃圾分类识别” 线程
pthread_mutex_unlock(&mutex);
}
}
pthread_exit(0); // 语音线程退出
}
/* 语音播报线程 */
void *psend_voice(void *arg)
{
// 线程脱离,如果阿里云线程等待该线程退出,那么将失去创建该线程的意义
pthread_detach(pthread_self());
unsigned char *buffer = (unsigned char *)arg;
if (-1 == serial_fd) // 串口打开失败
{
printf("%s|%s|%d: open serial failed\n", __FILE__, __func__, __LINE__);
pthread_exit(0);
}
if (NULL != buffer) // 传递过来的参数不为空
{
serialSendstring(serial_fd, buffer, 6);
// 向串口发送 buffer 数据,语音模块根据数据进行播报
}
pthread_exit(0); // 线程退出
}
/* 垃圾桶开关控制线程 */
void *popen_trash_can(void *arg)
{
// 线程脱离,如果阿里云线程等待该线程退出,那么将失去创建该线程的意义
pthread_detach(pthread_self());
unsigned char *buffer = (unsigned char *)arg;
if (buffer[2] == 0x41 || buffer[2] == 0x42 || buffer[2] == 0x43)
{
// 识别为干垃圾、湿垃圾、可回收垃圾,由于硬件模块数量有限,此处打开同一个垃圾桶盖
printf("%s|%s|%d: buffer[2]=0x%x\n", __FILE__, __func__, __LINE__, buffer[2]);
pwm_write(PWM_RECOVERABLE_GARBAGE); // 打开垃圾桶
delay(2000); // 延时两秒
pwm_stop(PWM_RECOVERABLE_GARBAGE); // 关闭垃圾桶
}
else if (buffer[2] != 0x44) // 识别为有害垃圾
{
printf("%s|%s|%d: buffer[2]=0x%x\n", __FILE__, __func__, __LINE__, buffer[2]);
pwm_write(PWM_GARBAGE); // 打开垃圾桶
delay(2000); // 延时两秒