基于Linux的智能垃圾桶

基于Linux的智能垃圾桶

功能需求

  • 语音接入控制垃圾分类识别,并触发垃圾桶的开关盖
  • 用Sockect发送指令远程控制垃圾分类识别,并触发垃圾桶的开关盖
  • 图像识别垃圾分类功能
  • 语音播报垃圾物品类型
  • OLED显示垃圾物品类型
  • 根据垃圾类型开关不同类型垃圾桶

图像处理使用阿里SDK-只支持Python和Java接口,目的是引入C语言的Python调用

流程图

在这里插入图片描述

完整代码

garbage.c

#if 0
1、包含Python.h头文件,以便使用Python API。
2、使用void Py_Initialize()初始化Python解释器,
3、使用PyObject *PyImport_ImportModule(const char *name)和PyObject
*PyObject_GetAttrString(PyObject *o, const char *attr_name)获取sys.path对象,并利用
int PyList_Append(PyObject *list, PyObject *item)将当前路径.添加到sys.path中,以便加载
当前的Python模块(Python文件即python模块)4、使用PyObject *PyImport_ImportModule(const char *name)函数导入Python模块,并检查是否
有错误。
5、使用PyObject *PyObject_GetAttrString(PyObject *o, const char *attr_name)函数获取
Python函数对象,并检查是否可调用。
6、使用PyObject *Py_BuildValue(const char *format, ...)函数将C类型的数据结构转换成
Python对象,作为Python函数的参数,没有参数不需要调用
7、使用PyObject *PyObject_CallObject(PyObject *callable, PyObject *args)函数调用
Python函数,并获取返回值。
8、使用int PyArg_Parse(PyObject *args, const char *format, ...)函数将返回值转换为C类
型,并检查是否有错误,没有返回值时不需要调用。
9、使用void Py_DECREF(PyObject *o)函数释放所有引用的Python对象。
10、结束时调用void Py_Finalize()函数关闭Python解释器。
相关的函数参数说明参考网站(网站左上角输入函数名即可开始搜索):
https://docs.python.org/zh-cn/3/c-api/import.html
#endif

#include <Python.h>
#include "garbage.h"

void garbage_init()
{
        Py_Initialize();
        // 将当前路径添加到sys.path中
        PyObject *sys = PyImport_ImportModule("sys");
        PyObject *path = PyObject_GetAttrString(sys, "path");
        PyList_Append(path, PyUnicode_FromString("."));
}

void garbage_final()
{
       //释放所有引用的Python对象
        Py_Finalize();
}

//垃圾识别
char* garbage_category(char *category)
{

	// 导入garbage模块
	PyObject *pModule = PyImport_ImportModule("garbage");
	if (!pModule)
	{
		PyErr_Print();
		printf("Error: failed to load garbage.py\n");
		goto FALED_MODULE;
	}
	//获取alibaba_garbage函数对象
	PyObject *pFunc = PyObject_GetAttrString(pModule, "alibaba_garbage");
	if (!pFunc)
	{
		PyErr_Print();
		printf("Error: failed to load alibaba_garbage\n");
		goto FALED_FUNC;
	}
	//调用alibaba_garbage函数并获取返回值
	PyObject *pValue = PyObject_CallObject(pFunc, NULL);
	if (!pValue)
	{
		PyErr_Print();
		printf("Error: function call failed\n");
		goto FALED_PVALUE;
	}
	//将返回值转换为C类型
	char *result = NULL;
	if (!PyArg_Parse(pValue, "s", &result))
	{
		PyErr_Print();
		printf("Error: parse failed\n");
		goto FALED_RESULT;
	}
	//打印返回值
	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);
	//释放所有引用的Python对象
FALED_RESULT:
	Py_DECREF(pValue);
FALED_PVALUE:	
	Py_DECREF(pFunc);
FALED_FUNC:	
	Py_DECREF(pModule);
FALED_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

garbage.py

# -*- coding: utf-8 -*-
# 引入依赖包
# pip install alibabacloud_imagerecog20190930

import os
import io
from urllib.request import urlopen
from alibabacloud_imagerecog20190930.client import Client
from alibabacloud_imagerecog20190930.models import ClassifyingRubbishAdvanceRequest
from alibabacloud_tea_openapi.models import Config
from alibabacloud_tea_util.models import RuntimeOptions

config = Config(
  # 创建AccessKey ID和AccessKey Secret,请参考https://help.aliyun.com/document_detail/175144.html。
  # 如果您用的是RAM用户的AccessKey,还需要为RAM用户授予权限AliyunVIAPIFullAccess,请参考https://help.aliyun.com/document_detail/145025.html
  # 从环境变量读取配置的AccessKey ID和AccessKey Secret。运行代码示例前必须先配置环境变量。
  access_key_id=os.environ.get('ALIBABA_CLOUD_ACCESS_KEY_ID'),
  access_key_secret=os.environ.get('ALIBABA_CLOUD_ACCESS_KEY_SECRET'),
  # 访问的域名
  endpoint='imagerecog.cn-shanghai.aliyuncs.com',
  # 访问的域名对应的region
  region_id='cn-shanghai'
)

#获取垃圾的信息
def alibaba_garbage():
    #场景一:文件在本地
    img = open(r'/tmp/garbage.jpg', 'rb')
    #场景二:使用任意可访问的url
    #url = 'https://viapi-test-bj.oss-cn-beijing.aliyuncs.com/viapi-3.0domepic/imagerecog/ClassifyingRubbish/ClassifyingRubbish1.jpg'
    #img = io.BytesIO(urlopen(url).read())
    classifying_rubbish_request = ClassifyingRubbishAdvanceRequest()
    classifying_rubbish_request.image_urlobject = img
    runtime = RuntimeOptions()
    try:
      # 初始化Client
      client = Client(config)
      response = client.classifying_rubbish_advance(classifying_rubbish_request, runtime)
      # 获取整体结果
      print(response.body.to_map()['Data']['Elements'][0]['Category'])
      return response.body.to_map()['Data']['Elements'][0]['Category']
    except Exception as error:
      return '获取失败' 

if __name__ == "__main__":
     alibaba_garbage()

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"
//包含头文件
#include "myoled.h"
#define FILENAME "/dev/i2c-3"
static struct display_info disp;
int oled_show(void *arg)
{
    unsigned char *buffer = (unsigned char *)arg;
    oled_putstrto(&disp, 0, 9+1, "This garbage is:");
    disp.font = font2;
    switch(buffer[2])
    {
        case 0x41:
             oled_putstrto(&disp, 0, 20, "dry waste");
             break;
        case 0x42:
             oled_putstrto(&disp, 0, 20, "wet waste");
             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 failed");
             break;
    }
    disp.font = font2;
    oled_send_buffer(&disp);
    return 0;
}

int myoled_init(void)
{
    int e;
    disp.address = OLED_I2C_ADDR;
    disp.font = font2;
    e = oled_open(&disp, FILENAME);
    e = oled_init(&disp);
    return e;
}

myoled.h

#ifndef __MYOLED__H
#define __MYOLED__H
int myoled_init(void);
int oled_show(void *arg);
#endif

pwm.c

#include<wiringPi.h>
#include<softPwm.h>

/*根据公式:PWMfreq = 1 x 10^6 / (100 x range) ,要得到PWM频率为50Hz,则range为200,即
周期分为200步,控制精度相比硬件PWM较低。*/

void pwm_write(int pwm_pin)
{
    pinMode(pwm_pin,OUTPUT);
    softPwmCreate(pwm_pin,0,200); //range设置周期分为200步,周期20ms
    softPwmWrite(pwm_pin,10); //1ms 45度
    delay(1000);
    softPwmStop(pwm_pin); //在45度位置固定住
}

void pwm_stop(int pwm_pin)
{
   pinMode(pwm_pin,OUTPUT);
   softPwmCreate(pwm_pin,0,200); //range设置周期分为200步,周期20ms
   softPwmWrite(pwm_pin,5); //1ms,45度
   delay(1000);
   softPwmStop(pwm_pin);
}

pwm.h

#ifndef _PWM_H
#define _PWM_H

#define PWM_GARBAGE 7             //干垃圾
#define PWM_WET_GARBAGE 8         //湿垃圾
#define PWM_RECOVERALE_GARBAGE 5  //可回收垃圾
#define PWM_HARMFUL_GARBAGE 11    //有害垃圾

void pwm_write(int pwm_pin);
void pwm_stop(int pwm_pin);

#endif

socket.c

#include "socket.h"

int socket_init(const char *ipaddr,const char *ipport)
{
    int s_fd=-1;
    int ret=-1;
    struct sockaddr_in s_addr;
    memset(&s_addr,0,sizeof(struct sockaddr_in));
    //1. socket
	s_fd = socket(AF_INET, SOCK_STREAM, 0);
	if(-1==s_fd)
    {
		perror("socket");
		return -1;
	}
	s_addr.sin_family = AF_INET;
	s_addr.sin_port = htons(atoi(ipport));
	inet_aton(ipaddr,&s_addr.sin_addr);
	//2. bind
	ret=bind(s_fd,(struct sockaddr *)&s_addr,sizeof(struct sockaddr_in));
    if(-1==ret)
    {
        perror("bind");
        return -1;
    }
	//3. listen
	ret=listen(s_fd,1); //允许一个监听,只能允许一个时刻一个垃圾桶打开
    if(-1==ret)
    {
       perror("listen");
       return -1;
    }

    return s_fd;
}

socket.h

#ifndef _SOCKET_H_
#define _SOCKET_H_
#include <stdio.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <string.h>

#define IPADDR "192.168.1.103"
#define IPPORT "8192" //不要用8080,摄像头已经用了8080#define IPADDR "192.168.1.103"

int socket_init(const char* ipaddr,const char* ipport);


#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<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<errno.h>
#include<wiringPi.h>
#include<pthread.h>
#include "pwm.h"
#include "uartTool.h"
#include "garbage.h"
#include "myoled.h"
#include "socket.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) //读取数据
     {
          if(fgets(buf, sizeof(buf), strm) != NULL) //获取pid
          {
               n = atoi(buf);  //转换为数字
          }
     }
     else
     {
          return -1;
     }
     pclose(strm);
     return n;
}

#if  0
int main(int argc,char* argv[])
{
    int serial_fd=-1;
    int len=0;
    int ret=-1;
    char* category=NULL;
    unsigned char buffer[6]={0xAA,0x55,0x00,0x00,0x55,0xAA};

    wiringPiSetup(); //初始化wiringPi库
    garbage_init(); //初始化阿里云接口

    ret=detect_process("mjpg_streamer"); //简称mjpg_streamer是否打开
    if(-1==ret)
    {
         printf("detect process failed\n");
         goto END;
    }

    serial_fd=myserialOpen(SERIAL_DEV,BAUD); //初始化串口
    if(-1==serial_fd) //串口打开失败
    {
         printf("open serial failed\n");
         goto END;
    }

    //进行垃圾分类识别
    while(1)
    {
       len=serialGetstring(serial_fd,buffer); //获取串口的数据
       if(len>0&&buffer[2]==0x46) //识别垃圾类型
       {
           buffer[2]=0x00; //对buffer[2]进行清空
           system(WGET_CMD); //进行拍照
           if(0==access(GARBAGE_FILE,F_OK)) //文件存在
           {
               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;
           }

           serialSendstring(serial_fd,buffer,6); //将识别的垃圾类型回传给语音模块
           if(buffer[2]==0x43)
           {
               pwm_write(PWM_RECOVERALE_GARBAGE); //开盖
               delay(5000);//开盖5s
               pwm_stop(PWM_RECOVERALE_GARBAGE);//关盖
           }
           else if(buffer[2]==0x41)
           {
               pwm_write(PWM_GARBAGE); //开盖
               delay(5000);//开盖5s
               pwm_stop(PWM_GARBAGE);//关盖
           }
           else if(buffer[2]==0x42)
           {
               pwm_write(PWM_WET_GARBAGE); //开盖
               delay(5000);//开盖5s
               pwm_stop(PWM_WET_GARBAGE);//关盖
           }
           else if(buffer[2]==0x44)
           {
               pwm_write(PWM_HARMFUL_GARBAGE); //开盖
               delay(5000);//开盖5s
               pwm_stop(PWM_HARMFUL_GARBAGE);//关盖
           }
           buffer[2]=0x00;//清空是为了下一次识别
           remove(GARBAGE_FILE); //清理缓存
       }
    }

    close(serial_fd);
END:
    garbage_final(); //释放python解析器   
    return 0;
}
#endif


int serial_fd=-1;

pthread_cond_t cond;//条件变量
pthread_mutex_t mutex; //互斥锁

//获取语音数据线程
void* get_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);
          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* 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); //将识别的垃圾类型回传给语音模块
    }
    pthread_exit(0);
}

//垃圾桶开盖线程
void* popen_trash_can(void *arg)
{
    pthread_detach(pthread_self()); //父子线程分离,防止等待太久
    unsigned char *buffer=(unsigned char*)arg; 
    if(buffer[2]==0x43)
    {
        printf("%s|%s|%d,buffer[2]=0x%x\n",__FILE__,__func__,__LINE__,buffer[2]);
        pwm_write(PWM_RECOVERALE_GARBAGE); //开盖
        delay(2000);//开盖5s
        pwm_stop(PWM_RECOVERALE_GARBAGE);//关盖
    }
    else if(buffer[2]!=0x45)
    {
        printf("%s|%s|%d,buffer[2]=0x%x\n",__FILE__,__func__,__LINE__,buffer[2]);
        pwm_write(PWM_GARBAGE); //开盖
        delay(2000);//开盖5s
        pwm_stop(PWM_GARBAGE);//关盖
    }

    pthread_exit(0);
}

//oled显示线程
void* poled_show(void* arg)
{
     pthread_detach(pthread_self());
     
     myoled_init();
     oled_show(arg);

     pthread_exit(0);
}

//垃圾分类识别线程
void* pcategory(void *arg)
{
      unsigned char buffer[6]={0xAA,0x55,0x00,0x00,0x55,0xAA};
      char* category=NULL;
      pthread_t send_voice_tid;
      pthread_t trash_tid;
      pthread_t oled_tid;
      
      printf("%s|%s|%d\n",__FILE__,__func__,__LINE__);
      while(1)
      {   
          printf("%s|%s|%d\n",__FILE__,__func__,__LINE__);
          pthread_mutex_lock(&mutex);
          pthread_cond_wait(&cond,&mutex);
          pthread_mutex_unlock(&mutex);
          printf("%s|%s|%d\n",__FILE__,__func__,__LINE__);
          buffer[2]=0x00;//清空是为了下一次识别
          system(WGET_CMD); //进行拍照
          if(0==access(GARBAGE_FILE,F_OK)) //文件存在
          {
               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);


          remove(GARBAGE_FILE); //清理缓存
      }

      pthread_exit(0);
}

//网络线程
void* pget_socket(void *arg)
{
    int s_fd=-1;
    int c_fd=-1;
    int n_read=-1;
    char buffer[6];
    struct sockaddr_in c_addr;
    memset(&c_addr,0,sizeof(struct sockaddr_in));

    s_fd=socket_init(IPADDR,IPPORT);
    if(-1==s_fd)
    {
         printf("%s|%s|%d:s_fd=%d\n",__FILE__,__func__,__LINE__,s_fd);
         pthread_exit(0);
    }
    int clen = sizeof(struct sockaddr_in);
     
    while(1)
    {
        c_fd = accept(s_fd,(struct sockaddr *)&c_addr,&clen);
        int keepalive = 1; // 开启TCP KeepAlive功能
        int keepidle = 5; // tcp_keepalive_time 3s内没收到数据开始发送心跳包
        int keepcnt = 3; // tcp_keepalive_probes 每次发送心跳包的时间间隔,单位秒
        int keepintvl = 3; // tcp_keepalive_intvl 每3s发送一次心跳包
        setsockopt(c_fd, SOL_SOCKET, SO_KEEPALIVE, (void *)&keepalive,
          sizeof(keepalive));
        setsockopt(c_fd, SOL_TCP, TCP_KEEPIDLE, (void *) &keepidle, sizeof
          (keepidle));
        setsockopt(c_fd, SOL_TCP, TCP_KEEPCNT, (void *)&keepcnt, sizeof
          (keepcnt));
        setsockopt(c_fd, SOL_TCP, TCP_KEEPINTVL, (void *)&keepintvl, sizeof
          (keepintvl));
        printf("%s|%s|%d:Accept a connection from %s:%d\n",__FILE__,__func__,__LINE__, inet_ntoa(c_addr.sin_addr), ntohs(c_addr.sin_port));
        if(-1==c_fd)
        {
           perror("accept");
           continue;
        }
        while(1)
        {
               memset(buffer,0,sizeof(buffer));
               n_read=recv(c_fd,buffer,sizeof(buffer),0);
               printf("%s|%s|%d:n_read=%d,buffer=%s\n",__FILE__,__func__,__LINE__,n_read,buffer);
               if(n_read>0)
               {
                    if(strstr(buffer,"open")) //给阿里云交互线程发信号
                    {
                         pthread_mutex_lock(&mutex);
                         pthread_cond_signal(&cond);
                         pthread_mutex_unlock(&mutex);
                    }
               }
               else if(0==n_read||-1==n_read)
               {
                    break;
               } 
        }
        close(c_fd);
    }

    pthread_exit(0);
}

int main(int argc,char* argv[])
{
    int len=0;
    int ret=-1;
    char* category=NULL;
    pthread_t get_voice_tid;
    pthread_t category_tid;
    pthread_t get_socket_tid;

    wiringPiSetup(); //初始化wiringPi库
    garbage_init(); //初始化阿里云接口

    ret=detect_process("mjpg_streamer"); //简称mjpg_streamer是否打开
    if(-1==ret)
    {
         printf("detect process failed\n");
         goto END;
    }

    serial_fd=myserialOpen(SERIAL_DEV,BAUD); //初始化串口
    if(-1==serial_fd) //串口打开失败
    {
         printf("open serial failed\n");
         goto END;
    }

    //开语音线程
    printf("%s|%s|%d\n",__FILE__,__func__,__LINE__);
    pthread_create(&get_voice_tid,NULL,get_voice,NULL);
    //开阿里云交互线程
    printf("%s|%s|%d\n",__FILE__,__func__,__LINE__);
    pthread_create(&category_tid,NULL,pcategory,NULL);
    //开网络线程
    printf("%s|%s|%d\n",__FILE__,__func__,__LINE__);
    pthread_create(&get_socket_tid,NULL,pget_socket,NULL);

    pthread_join(get_voice_tid,NULL); //阻塞语音线程
    pthread_join(category_tid,NULL); //阻塞阿里云交互线程
    pthread_join(get_socket_tid,NULL); //阻塞网络线程

    pthread_mutex_destroy(&mutex);
    pthread_cond_destroy(&cond);

    close(serial_fd);
END:
    garbage_final(); //释放python解析器   

    return  0;
}
  • 6
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值