一、语音模块与Orangepi接线以及环境准备
1、在orange pi 3.0.6上确认已经配置开启了uart5:(overlays=uart5)
跳转到如何开启uart5步骤
https://mp.csdn.net/mp_blog/creation/editor/134051044
2. 同时将USB摄像头接到香橙派上
3. 确认已经运行了mjpg-streamer服务
服务开机自启动脚本编写详见
https://mp.csdn.net/mp_blog/creation/editor/134071144
二、代码实现(在VScode上远程桌面进行代码编写)
garbage.c
#include "Python.h"//包含Python.h头文件,以便使用Python API
#include "garbage.h"
void garbage_init(void){
Py_Initialize();//初始化Python解释器
PyObject *sys=PyImport_ImportModule("sys");
PyObject *path=PyObject_GetAttrString(sys,"path");//获取sys.path对象
PyList_Append(path,PyUnicode_FromString("."));//将当前路径添加到sys.path中,以便加载当前Pythn模块(Python文件)
}
void garbage_final(void){
Py_Finalize();//关闭Python解释器
}
char *garbage_category(char *category){
PyObject *pModule=PyImport_ImportModule("garbage");//导入Python模块,并检查是否有误
if(!pModule){
PyErr_Print();
printf("Error:failed to load garbage.py\n");
goto FAILED_MODULE;
}
PyObject *pFun=PyObject_GetAttrString(pModule,"alibaba_garbage");//获取Python函数对象,并检查是否可调用
if(!pFun){
PyErr_Print();
printf("Error:failed to load alibaba_garbage\n");
goto FAILED_FUN;
}
PyObject *pValue=PyObject_CallObject(pFun,NULL);//调用Python函数,并获取返回值
if(!pValue){
PyErr_Print();
printf("Error:failed to load pFun\n");
goto FAILED_VALUE;
}
char *result=NULL;//用指针来接收返回值
if(!PyArg_Parse(pValue,"s",&result)){
PyErr_Print();
printf("Error:parse failed\n");
goto FAILED_VALUE;
}
printf("result=%s\n",result);
category=(char *)malloc(sizeof(char)*(strlen(result)+1));
memset(category,0,(strlen(result)+1));
strncpy(category,result,(strlen(result)+1));
FAILED_RESULT:
Py_DECREF(pValue);
FAILED_VALUE:
Py_DECREF(pFun);
FAILED_FUN:
Py_DECREF(pModule);
FAILED_MODULE:
return category;
}
garbage.h
#ifndef __GARBAGE__H
#define __GARBAGE__H
void garbage_init(void);
void garbage_final(void);
char *garbage_category(char *category);
//拍照并保存在指定目录
#define WGET_CMD "wget http://127.0.0.1:8080/?action=snapshot -o /tmp/garbage/jpg"
//清除上一次的照片,给下一次拍照留存储空间
#define GARBAGE_FILE "/tmp/garbage.jpg"
#endif
uartTool.c
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdarg.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "wiringSerial.h"
int myserialOpen (const char *device, const int baud)//打开串口
{
struct termios options ;
speed_t myBaud ;
int status, fd ;
switch (baud){
case 9600: myBaud = B9600 ; break ;//常用波特率设置
case 115200: myBaud = B115200 ; break ;
}
if ((fd = open (device, O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK)) == -1)
return -1 ;
fcntl (fd, F_SETFL, O_RDWR) ;
// Get and modify current options:
tcgetattr (fd, &options) ;
cfmakeraw (&options) ;
cfsetispeed (&options, myBaud) ;
cfsetospeed (&options, myBaud) ;
options.c_cflag |= (CLOCAL | CREAD) ;
options.c_cflag &= ~PARENB ;
options.c_cflag &= ~CSTOPB ;
options.c_cflag &= ~CSIZE ;
options.c_cflag |= CS8 ;
options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG) ;
options.c_oflag &= ~OPOST ;
options.c_cc [VMIN] = 0 ;
options.c_cc [VTIME] = 100 ; // Ten seconds (100 deciseconds)
tcsetattr (fd, TCSANOW, &options) ;
ioctl (fd, TIOCMGET, &status);
status |= TIOCM_DTR ;
status |= TIOCM_RTS ;
ioctl (fd, TIOCMSET, &status);
usleep (10000) ; // 10mS
return fd ;
}
void serialSendstring (const int fd, const unsigned char *s,int len)//发送
{
int ret;
ret = write (fd, s, len);
if (ret < 0)
printf("Serial Puts Error\n");
}
int serialGetstring (const int fd,unsigned char *buffer)//接收
{
int n_read;
n_read=read(fd,buffer,32);
return n_read;
}
uartTool.h
#ifndef __UARTTOOL__H
#define __UARTTOOL__H
int myserialOpen (const char *device, const int baud);
void serialSendstring (const int fd, const unsigned char *s,int len);
int serialGetstring (const int fd, unsigned char *buffer);
#define SERIAL_DEV "/dev/ttyS5"
#define BAUD 115200
#endif
main.c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include "uartTool.h"
#include "garbage.h"
static int detect_process(const char *process_name){//判断是否已经自启动了mjp_streamer
int n=-1;
FILE *strm;
char buf[128]={0};
sprintf(buf,"ps -ax | grep %s|greparabage -v grep",process_name);
if((strm=popen(buf,"r"))!=NULL){
if(fgets(buf,sizeof(buf),strm)!=NULL){
n=atoi(buf);
}
}
else{
return -1;
}
pclose(strm);
return n;
}
int main(int argc,char *argv[]){
//初始化阿里云接口
garbage_init();//打开Python解释器
int ret=-1;
ret=detect_process("mjpg_streamer");
if(-1==ret){
goto END;
}
//orangepi串口初始化
int serial_fd =-1;
serial_fd=myserialOpen(SERIAL_DEV,BAUD);
if(serial_fd==-1){//判断是否打开成功
goto END;
}
//orangepi读取语音模块数据
unsigned char buffer[6]={0xAA,0X55,0X00,0X00,0X55,0XAA};//串口发送数据起始位是AA 55,停止位是55 AA
while(1){
int len=0;//用于存放串口接收数据函数的返回值
//int serialGetstring (const int fd, unsigned char *buffer);
len=serialGetstring(serial_fd,buffer);
if(len>0 && buffer[2]==0x46){//判断是否接收到开始识别指令
buffer[2]=0x00;//接收到开始识别指令后清零
system(WGET_CMD);//在终端输出拍照指令使摄像头拍照
if(access(GARBAGE_FILE,F_OK)==0){//判断照片是否存在
char *category=NULL;//用于存储返回值(垃圾类型)
//char *garbage_category(char *category);阿里云接口函数
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;
}
//void serialSendstring (const int fd, const unsigned char *s,int len)
serialSendstring(serial_fd,buffer,6);//将内容回传给语音模块,用于播报垃圾类型
buffer[2]=0x00;
remove(GARBAGE_FILE);//清除本次照片,为下一次拍照留空间
}
}
close(serial_fd);
END:
garbage_final();//关闭(释放)Python解释器
return 0;
}