11.【Orangepi Zero2】基于Linux的智能垃圾桶项目

基于Linux的垃圾分类项目

功能需求

  • 语音接入控制垃圾分类识别,并触发垃圾桶的开关盖

  • 回顾二阶段的Socket编程,实现Sockect发送指令远程控制垃圾分类识别,并触发垃圾桶的开关盖

  • 图像识别垃圾分类功能

  • 语音播报垃圾物品类型

  • OLED显示垃圾物品类型

  • 根据垃圾类型开关不同类型垃圾桶

图像处理使用阿里SDK支持Python和Java接口,目的是引入C语言的Python调用,感受大厂做的算法bug。

此接口是人工智能接口,阿里云识别模型是通过训练后的模型,精准度取决于训练程度,人工智能范畴 在常规嵌入式设备负责执行居多。

说白的嵌入式设备负责数据采集,然后转发给人工智能识别后,拿到结果进行执行器动作。

阿里云垃圾识别方案

接入阿里云

在垃圾分类的项目中,我们采用阿里云视觉智能开发平台的接口来做垃圾分类的识别方案,通过上传 本地的拍照下的垃圾图片,通过阿里提供的接口来识别出该垃圾是干垃圾、湿垃圾、回收垃圾还是有害 垃圾。

对应官网地址如下:

https://vision.aliyun.com/

然后在上面的输入框输入“垃圾分类”:

在这里插入图片描述

可以跳转到对应的垃圾分类的“免费开通"和”技术文档页面“:

能力展示-阿里云视觉智能开放平台 (aliyun.com)

在这里插入图片描述

可以先选择"技术文档"查看下使用方法:

在这里插入图片描述

根据上面描述的指引,蓝色为可点进去的详细说明,完成注册及运行环境的搭建。

重点:

  1. 开通阿里云账号及图像识别服务,用自己支付宝即可开通。
  2. 创建并获取AccessKey ID和Secret。
  3. 在Linux或开发板上安装所需的SDK。
  4. 根据示例代码进行修改垃圾分类识别。
  5. 选择免费开通,通过自己的支付宝或者账号登录即可。

在这里插入图片描述

在这里插入图片描述

  1. 登录完成后,即可在产品控制台->点击获取Acce Token获取 对应的AccessKey ID和AccessKey Secret

当然,在第一次获取到AccessKey ID和AccessKey Secret,需要点击创建AccessKey, 然后最好把 AccessKey.csv下载下来备份,不然会找不到AccessKey Secret就需要重新创建。

在这里插入图片描述

  1. 在ubuntu 22.04或者众志开发板(orangepi 3.0.6)上安装图像识别(imagerecog)SDK
sudo apt install python3-pip
pip3 install alibabacloud_imagerecog20190930 
  1. 同时配置Linux环境,根据自己实际的ACCESS_KEY_ID和ACCESS_KEY_SECRET,下面的两行写入到家目 录下的.bashrc中:
export ALIBABA_CLOUD_ACCESS_KEY_ID=“你的ID” #根据自己实际的ID填写
export ALIBABA_CLOUD_ACCESS_KEY_SECRET="你的SECRET" #根据自己实际的SECRET填写
vi ~/.bashrc 和 /etc/profile #然后在末尾输入上面两行后保存

在这里插入图片描述

  1. 然后退出终端重新登录下,此时再执行export,能看到这两个Key的存在。

在这里插入图片描述

  1. 抄袭”文件在本地或文件不在同一地域OSS“示例代码,命名为rubbish.py。

在这里插入图片描述

  1. 同时将场景二注释,场景一代码打开,并输入自己测试图片的路径,如下:
rubbish.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 alicloud_classify_Rubbish():
	#场景一:文件在本地
    img = open(r'/home/orangepi/Project/rubbish/test.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)
       return response.body.to_map()['Data']['Elements'][0]['Category']
    except Exception as error:
       # 获取整体报错信息
       print(error)
       # 获取单个字段
       print(error.code)
    
if __name__ == "__main__":
    alicloud_classify_Rubbish()

其中 "/home/orangepi/Project/rubbish/test.jpg" 为本地测试用图片(根据在线文档要求:图像类型:JPEG、JPG、PNG,图像大小:不大于3 MB,图像分辨率:不限制图像分辨率,但图像分辨率太高可能会导致API识别超时,超时时间为5秒) 测试图片如下:

在这里插入图片描述

然后用 python3 rubbish.py 命令测试运行:

orangepi@orangepizero2:~/Project/rubbish$ python3 rubbish.py
{'Data': {'Elements': [{'Category': '干垃圾', 'CategoryScore': 0.9020999999999999, 'Rubbish': '', 'RubbishScore': 0.0}], 'Sensitive': False}, 'RequestId': '75252D93-CF27-59CB-90A9-5F66D5D929BF'}

在这里插入图片描述

如上,测试成功,说明阿里云垃圾分类方案对接成功。

C语言调用阿里云Python接口

rubbish.py

采用上面的代码。

rubbish.c

参照有参python函数的做法, 实封装并现以下代码(rubbish.c):

#include <Python.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void rubbish_Init(void)
{
    Py_Initialize();
    
    PyObject *sys = PyImport_ImportModule("sys");
    PyObject *path = PyObject_GetAttrString(sys, "path");
    PyList_Append(path, PyUnicode_FromString("."));
}

void rubbish_Finalize(void)
{
    Py_Finalize();
}

char *alicloud_rubbish_category(char *category)
{
    PyObject *pModule = PyImport_ImportModule("rubbish");
    if (!pModule)
    {
        PyErr_Print();
        printf("Error: failed to load rubbish.py\n");
        goto FAILED_MODULE;
    }
    
    PyObject *pFunc = PyObject_GetAttrString(pModule, "alicloud_classify_Rubbish");
    if (!pFunc)
    {
        PyErr_Print();
        printf("Error: failed to load classify_Rubbish\n");
        goto FAILED_FUNC;
    }
		
    PyObject *pValue = PyObject_CallObject(pFunc, NULL);
	if (!pValue)
    {
        PyErr_Print();
        printf("Error: function call failed\n");
        goto FAILED_VALUE;
    }
		
	char *result = NULL;
	if(!PyArg_Parse(pValue, "s", &result))
    {
        PyErr_Print();
        printf("Error: parse failed\n");
        goto FAILED_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(pFunc);
FAILED_FUNC:
    Py_DECREF(pModule);
FAILED_MODULE:
    return category;
}

rubbish.h

头文件(rubbish.h)如下:

#ifndef _RUBBISH_H

#define _RUBBISH_H

void rubbish_Init(void);

void rubbish_Finalize(void);

char *alicloud_rubbish_category(char *category);

#endif

main.c

测试代码(main.c)如下:

#include <stdio.h>
#include <stdlib.h>
#include "rubbish.h"

int main()
{
    char *category = NULL;
 
    garbage_init();
 	category  = rubbish_category(category);
 	printf("category=%s\n", category);
 	rubbish_Finalize();
 
    free(category);
 	return 0;
}

然要编译和运行这个程序,可以使用以下命令(假设使用的是gcc编译器和Python 3.10版本):

gcc -o rubbish main.c rubbish.c rubbish.h -I /usr/include/python3.10/ -lpython3.10 ./garbagetest

输出:

category=干垃圾

香橙派使用摄像头

详细可参考《OrangePi_Zero2_H616用户手册v4.0.pdf》 中的3.13.6 USB摄像头测试章节。

语音模块配置

在这里插入图片描述

进入语音模块官网http://www.smartpi.cn/#/,配置词条和识别后的串口输入输出指令,如下:

Pin引脚配置:

在这里插入图片描述

唤醒词定义:

在这里插入图片描述

控制详情:

在这里插入图片描述

语音模块和阿里云结合

环境准备

将语音模块接在UART5的位置。

在这里插入图片描述

在orange pi 3.0.6上确认已经配置开启了uart5:(overlays=uart5)

orangepi@orangepizero2:~/garbage$ cat /boot/orangepiEnv.txt
verbosity=1
bootlogo=false
console=both
disp_mode=1920x1080p60
overlay_prefix=sun50i-h616
rootdev=UUID=15a0010c-94e1-412f-b030-199e90c16cb1
rootfstype=ext4
overlays=uart5 i2c3
usbstoragequirks=0x2537:0x1066:u,0x2537:0x1068:u

同时将USB摄像头接到香橙派上,确认已经运行了mjpg-streamer服务

orangepi@orangepizero2:~/garbage$ ps ax | grep mjpg

rubbish.py

同上

加入mySerial.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>

int my_serialOpen (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 ;

    	default:
      	return -2 ;
  	}

  	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 my_serialPuts(const int fd, const char *s, int len)
{
	int n_write = write(fd, s, len);

	if(n_write == -1)
	{
		perror("write");

		exit(-1);
	}

}

int my_serialGets(const int fd, unsigned char *buffer)
{
	int n_read = read(fd, buffer, 32);
	if(n_read == -1)
	{
		perror("read");

		exit(-1);
	}

	return n_read;
}

char* serialGetchar (const int fd)
{
	char *x;

  	if (read (fd, x, 1) != 1)
    exit(-1);

  	return x;
}

mySerial.h

#ifndef _MYSERIAL_H_
#define _MYSERIAL_H_

#define SERIAL_DEV "/dev/ttyS5"
#define BAUD 115200

int my_serialOpen (const char *device, const int baud);

void my_serialPuts(const int fd, unsigned char *s, int len);

int my_serialGets(const int fd, const char *buffer);

char* serialGetchar(const int fd);

#endif

rubbish.c

#include <Python.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void rubbish_Init(void)
{
    Py_Initialize();
    
    PyObject *sys = PyImport_ImportModule("sys");
    PyObject *path = PyObject_GetAttrString(sys, "path");
    PyList_Append(path, PyUnicode_FromString("."));
}

void rubbish_Finalize(void)
{
    Py_Finalize();
}

char *alicloud_rubbish_category(char *category)
{
    PyObject *pModule = PyImport_ImportModule("rubbish");
    if (!pModule)
    {
        PyErr_Print();
        printf("Error: failed to load rubbish.py\n");
        goto FAILED_MODULE;
    }
    
    PyObject *pFunc = PyObject_GetAttrString(pModule, "alicloud_classify_Rubbish");
    if (!pFunc)
    {
        PyErr_Print();
        printf("Error: failed to load classify_Rubbish\n");
        goto FAILED_FUNC;
    }
		
    PyObject *pValue = PyObject_CallObject(pFunc, NULL);
	if (!pValue)
    {
        PyErr_Print();
        printf("Error: function call failed\n");
        goto FAILED_VALUE;
    }
		
	char *result = NULL;
	if(!PyArg_Parse(pValue, "s", &result))
    {
        PyErr_Print();
        printf("Error: parse failed\n");
        goto FAILED_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(pFunc);
FAILED_FUNC:
    Py_DECREF(pModule);
FAILED_MODULE:
    return category;
}

rubbish.h

#ifndef _RUBBISH_H

#define _RUBBISH_H

#define WGET_CMD "wget http://127.0.0.1:8080/?action=snapshot -O /home/orangepi/Project/rubbish/rubbish.jpg"

#define RUBBISH_FILE "/home/orangepi/Project/rubbish/rubbish.jpg"

void rubbish_Init(void);

void rubbish_Finalize(void);

char *alicloud_rubbish_category(char *category);

#endif

main.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>           /* Definition of AT_* constants */
#include <unistd.h>
#include "rubbish.h"
#include "mySerial.h"

int detect_process(char *process_name)
{
    FILE *file;
    int pid;
    char cmd[64] = {'\0'};
    char buffer[128] = {'\0'};
    
    sprintf(cmd, "ps -ax | grep  %s | grep -v grep", process_name);
    file = popen(cmd, "r");
    if(file != NULL)
    {
        if(fgets(buffer, sizeof(buffer), file) != NULL)
        {
            pid = atoi(buffer);

            return pid;
        }
        else
        {
            return -1;
        }
    }
    else
    {
        return -1;
    }

    pclose(file);
    return pid;
}

int main()
{
    int len = -1;
    int serial_fd = -1;
    int result_detect_process = -1;
    char *category = NULL;
    char *ret_strstr = (char *)malloc(1024);
    unsigned char buffer[6] = {0xAA, 0x55, 0x00, 0x00, 0x55, 0xAA};

    rubbish_Init();
    
    result_detect_process = detect_process("mjpg_streamer");
    if(-1 == result_detect_process)
    {
        perror("detect_process");
        goto END;
    }

    serial_fd = my_serialOpen(SERIAL_DEV, BAUD);
    if(-1 == serial_fd)
    {
        perror("my_serialOpen");

        goto END;
    }

    while(1)
    {
        len = my_serialGets(serial_fd, buffer);

        if(len > 0 && buffer[2] == 0x46)
        {
            buffer[2] = 0x00;
            system(WGET_CMD);

            printf("------------------------------------\n");
            if(access(RUBBISH_FILE, F_OK) == 0)
            {   
                printf("====================================\n");
                category = alicloud_rubbish_category(category);
                printf("category = %s\n", category);

                if(strstr(category, "干垃圾") != NULL)
                {
                    buffer[2] = 0x41;
                    printf("[%d]: 0x%2X\n", __LINE__, buffer[2]);
                    //my_serialPuts(serial_fd, buffer, 6);
                }

                else if(strstr(category, "湿垃圾"))
                {
                    buffer[2] = 0x42;
                    printf("[%d]: 0x%2X\n", __LINE__, buffer[2]);
                    //my_serialPuts(serial_fd, buffer, 6);
                }

                else if(strstr(category, "可回收垃圾"))
                {
                    buffer[2] = 0x43;
                    printf("[%d]: 0x%2X\n", __LINE__, buffer[2]);
                    //my_serialPuts(serial_fd, buffer, 6);
                }

                else if(strstr(category, "有害垃圾"))
                {
                    buffer[2] = 0x44;
                    printf("[%d]: 0x%2X\n", __LINE__, buffer[2]);
                    //my_serialPuts(serial_fd, buffer, 6);
                }

                else
                {
                    buffer[2] = 0x45;
                    printf("[%d]: 0x%2X\n", __LINE__, buffer[2]);
                    //my_serialPuts(serial_fd, buffer, 6);
                }
                //printf("ret_strstr = %s\n", ret_strstr);
            }
            else
            {
                buffer[2] = 0x45;
                printf("[%d]: 0x%2X\n", __LINE__, buffer[2]);
                //my_serialPuts(serial_fd, buffer, 6);
            }

            my_serialPuts(serial_fd, buffer, 6);
            buffer[2] = 0x00;
            remove(RUBBISH_FILE);
        }
    }

END:
    rubbish_Finalize();
    return 0;
}

增加垃圾桶及开关盖功能

实现功能:使用语音模块和摄像头在香橙派上做垃圾智能分类识别, 同时根据识别结果开关不同的垃圾桶的盖子。

环境准备

在这里插入图片描述

流程图

flowchart LR
    B(开始)
    B --> C[阿里云Python接口初始化]
    C --> D[香橙派 串口初始化]
    D --> E{判断是否打开失败}
    E --> F[香橙派读取语音模块数据]
    F --> G{是否读取到语晋模块AA 5546 00 55 AA数据}
    G --> |是| H[香橙派拍照]
    G --> |否| F[香橙派读取语音模块数据]
    H --> I{判断./rubbish.jpg文件是否存在}
    I --> |是| J{执行阿里云垃圾分类接口}
    I --> |否| K[写对应的AA 55 45 00 55 AA 串口数据给语音模块 语音摄报]
    J --> |是| L[写对应的AA 55 4* 00 55 AA 串口数据给语音模块,语音播报]
    J --> |否| F[香橙派读取语音模块数据]
    K --> F[香橙派读取语音模块数据]
    L --> F[香橙派读取语音模块数据]

在这里插入图片描述

pwm.c

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

void pwm_write(int pwm_pin)
{
    pinMode(pwm_pin, OUTPUT);
    softPwmCreate(pwm_pin, 0, 200);
    softPwmWrite(pwm_pin, 25);
    delay(1000);
    softPwmStop(pwm_pin);
}

void pwm_stop(int pwm_pin)
{
    pinMode(pwm_pin, OUTPUT);
    softPwmCreate(pwm_pin, 0, 200);
    softPwmWrite(pwm_pin, 5);
    delay(1000);
    softPwmStop(pwm_pin);
}

pwm.h

#ifndef _PWM_H_
#define _PWM_H_

#define PWM_OTHER_RUBBISH       7
#define PWM_RECOVERABLE_RUBBISH 5

void pwm_write(int pwm_pin);

void pwm_stop(int pwm_pin);

#endif

main.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <wiringPi.h>
#include "rubbish.h"
#include "mySerial.h"
#include "pwm.h"

int detect_process(char *process_name)
{
    FILE *file;
    int pid;
    char cmd[64] = {'\0'};
    char buffer[128] = {'\0'};
    
    sprintf(cmd, "ps -ax | grep  %s | grep -v grep", process_name);
    file = popen(cmd, "r");
    if(file != NULL)
    {
        if(fgets(buffer, sizeof(buffer), file) != NULL)
        {
            pid = atoi(buffer);

            return pid;
        }
        else
        {
            return -1;
        }
    }
    else
    {
        return -1;
    }

    pclose(file);
    return pid;
}

int main()
{
    int len = -1;
    int serial_fd = -1;
    int result_detect_process = -1;
    char *category = NULL;
    char *ret_strstr = (char *)malloc(1024);
    unsigned char buffer[6] = {0xAA, 0x55, 0x00, 0x00, 0x55, 0xAA};

    rubbish_Init();
    if (wiringPiSetup() == -1)
    {
        exit(1);
    }

    result_detect_process = detect_process("mjpg_streamer");
    if(-1 == result_detect_process)
    {
        perror("detect_process");
        goto END;
    }

    serial_fd = my_serialOpen(SERIAL_DEV, BAUD);
    if(-1 == serial_fd)
    {
        perror("my_serialOpen");

        goto END;
    }

    while(1)
    {
        len = my_serialGets(serial_fd, buffer);

        if(len > 0 && buffer[2] == 0x46)
        {
            buffer[2] = 0x00;
            system(WGET_CMD);

            printf("------------------------------------\n");
            if(access(RUBBISH_FILE, F_OK) == 0)
            {   
                printf("====================================\n");
                category = alicloud_rubbish_category(category);
                printf("category = %s\n", category);

                if(strstr(category, "干垃圾") != NULL)
                {
                    buffer[2] = 0x41;
                    printf("[%d]: 0x%2X\n", __LINE__, buffer[2]);
                    //my_serialPuts(serial_fd, buffer, 6);
                }

                else if(strstr(category, "湿垃圾"))
                {
                    buffer[2] = 0x42;
                    printf("[%d]: 0x%2X\n", __LINE__, buffer[2]);
                    //my_serialPuts(serial_fd, buffer, 6);
                }

                else if(strstr(category, "可回收垃圾"))
                {
                    buffer[2] = 0x43;
                    printf("[%d]: 0x%2X\n", __LINE__, buffer[2]);
                    //my_serialPuts(serial_fd, buffer, 6);
                }

                else if(strstr(category, "有害垃圾"))
                {
                    buffer[2] = 0x44;
                    printf("[%d]: 0x%2X\n", __LINE__, buffer[2]);
                    //my_serialPuts(serial_fd, buffer, 6);
                }

                else
                {
                    buffer[2] = 0x45;
                    printf("[%d]: 0x%2X\n", __LINE__, buffer[2]);
                    //my_serialPuts(serial_fd, buffer, 6);
                }
                //printf("ret_strstr = %s\n", ret_strstr);
            }
            else
            {
                buffer[2] = 0x45;
                printf("[%d]: 0x%2X\n", __LINE__, buffer[2]);
                //my_serialPuts(serial_fd, buffer, 6);
            }

            my_serialPuts(serial_fd, buffer, 6);

            if(buffer[2] == 0x43)
            {
                pwm_write(PWM_RECOVERABLE_RUBBISH);
                delay(2300);
                pwm_stop(PWM_RECOVERABLE_RUBBISH);
            }
            else if(buffer[2] != 0x45)
            {
                pwm_write(PWM_OTHER_RUBBISH);
                delay(2300);
                pwm_stop(PWM_OTHER_RUBBISH);
            }

            buffer[2] = 0x00;
            remove(RUBBISH_FILE);
        }
    }

END:
    rubbish_Finalize();
    return 0;
}

项目代码优化

在之前实现的代码中, 主函数是单线程执行的, 导致整个代码的可扩展性非常差,比如想加OLED显示 或者添加网络控制变得非常复杂, 而且执行一次识别开关盖的流程非常长。因此,调整下代码架构,增加并发功能、提升代码的可扩展性 和执行效率。

流程图

开始
阿里云Python接口初始化
串口初始化
香橙派读取语音模块数据线程
阿里云交互线程
网络线程
判断是否读取到语音模块AA 55 46 00 55 AA 数据
发送线程信号给阿里云交互线程
判断是否接收到线程信号
拍照
执行阿里云垃圾识别接口
垃圾桶开盖线程
语音播报垃圾类型线程
OLED显示线程
判断Sever是否接收到来自Client的open字符串

main.c

修改 main.c 代码,调整整体 main 函数的代码架构,利用多线程实现具体的功能(用到了线程里的条件变量控制线程间的数据同步)如下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <pthread.h>
#include <wiringPi.h>
#include "rubbish.h"
#include "mySerial.h"
#include "pwm.h"

int len = -1;
int serial_fd = -1;
pthread_mutex_t mutex;
pthread_cond_t  cond;

int detect_process(char *process_name)
{
    FILE *file;
    int pid;
    char cmd[64] = {'\0'};
    char buffer[128] = {'\0'};
    
    sprintf(cmd, "ps -ax | grep  %s | grep -v grep", process_name);
    file = popen(cmd, "r");
    if(file != NULL)
    {
        if(fgets(buffer, sizeof(buffer), file) != NULL)
        {
            pid = atoi(buffer);

            return pid;
        }
        else
        {
            return -1;
        }
    }
    else
    {
        return -1;
    }

    pclose(file);
    return pid;
}

void* send_voice(void *arg)
{
    printf("%s|%s|%d: \n", __FILE__, __func__, __LINE__);
    pthread_detach(pthread_self());
    unsigned char *buffer = (unsigned char *)arg;

    printf("%s|%s|%d: \n", __FILE__, __func__, __LINE__);

    if(NULL != buffer)
    {
        my_serialPuts(serial_fd, buffer, 6);

        printf("%s|%s|%d: \n", __FILE__, __func__, __LINE__);
    }

    pthread_exit(0);
}

void* trash_can(void *arg)
{
    pthread_detach(pthread_self());
    unsigned char *buffer = (unsigned char *)arg;
    
    printf("%s|%s|%d: \n", __FILE__, __func__, __LINE__);

    if(buffer[2] == 0x43)
    {
        pwm_write(PWM_RECOVERABLE_RUBBISH);
        delay(2300);
        pwm_stop(PWM_RECOVERABLE_RUBBISH);

        printf("%s|%s|%d: \n", __FILE__, __func__, __LINE__);
    }
    else if(buffer[2] != 0x45)
    {
        pwm_write(PWM_OTHER_RUBBISH);
        delay(2300);
        pwm_stop(PWM_OTHER_RUBBISH);

        printf("%s|%s|%d: \n", __FILE__, __func__, __LINE__);
    }

    pthread_exit(0);
}

void* get_voice()
{   

    unsigned char buffer[6] = {0xAA, 0x55, 0x00, 0x00, 0X55, 0xAA};
    while(1)
    {
        len = my_serialGets(serial_fd, buffer);

        if(len > 0 && buffer[2] == 0x46)
        {
//            system(WGET_CMD);
            pthread_mutex_lock(&mutex);
            buffer[2] = 0x00;
            pthread_cond_signal(&cond);
            pthread_mutex_unlock(&mutex);
        }
    }
    pthread_exit(0);
}

void* get_category()
{
    char *category = NULL;
    pthread_t send_voice_tid;
    pthread_t trash_can_tid;
    unsigned char buffer[6] = {0xAA, 0x55, 0x00, 0x00, 0X55, 0xAA};
    
    while(1)
    {
        pthread_mutex_lock(&mutex);
        pthread_cond_wait(&cond, &mutex);
        pthread_mutex_unlock(&mutex);
        
        buffer[2] = 0x00;
        system(WGET_CMD);
        
        if(access(RUBBISH_FILE, F_OK) == 0)
        {   
            category = alicloud_rubbish_category(category);
            printf("category = %s\n", category);
        
            if(strstr(category, "干垃圾") != NULL)
            {
                buffer[2] = 0x41;
                printf("[%d]: 0x%2X\n", __LINE__, buffer[2]);
                //my_serialPuts(serial_fd, buffer, 6);
            }
        
            else if(strstr(category, "湿垃圾"))
            {
                buffer[2] = 0x42;
                printf("[%d]: 0x%2X\n", __LINE__, buffer[2]);
                //my_serialPuts(serial_fd, buffer, 6);
            }
        
            else if(strstr(category, "可回收垃圾"))
            {
                buffer[2] = 0x43;
                printf("[%d]: 0x%2X\n", __LINE__, buffer[2]);
                //my_serialPuts(serial_fd, buffer, 6);
            }
        
            else if(strstr(category, "有害垃圾"))
            {
                buffer[2] = 0x44;
                printf("[%d]: 0x%2X\n", __LINE__, buffer[2]);
                //my_serialPuts(serial_fd, buffer, 6);
            }
        
            else
            {
                buffer[2] = 0x45;
                printf("[%d]: 0x%2X\n", __LINE__, buffer[2]);
                //my_serialPuts(serial_fd, buffer, 6);
            }
            //printf("ret_strstr = %s\n", ret_strstr);
        }
        else
        {
            buffer[2] = 0x45;
            printf("[%d]: 0x%2X\n", __LINE__, buffer[2]);
            //my_serialPuts(serial_fd, buffer, 6);
        }
        printf("%s|%s|%d: \n", __FILE__, __func__, __LINE__);
    
        if(pthread_create(&send_voice_tid, NULL, send_voice, buffer) != 0)
        {
            perror("pthread_create1");
            exit(-1);
        }
        
        if(pthread_create(&trash_can_tid, NULL, trash_can, buffer) != 0)
        {
            perror("pthread_create2");
            exit(-1);
        }
        remove(RUBBISH_FILE);
        
        printf("%s|%s|%d: \n", __FILE__, __func__, __LINE__);

    }
    
    pthread_exit(0);
}

int main()
{
    int result_detect_process = -1;
    char *ret_strstr = (char *)malloc(1024);
    pthread_t get_voice_tid;
    pthread_t get_category_tid;

    rubbish_Init();
    if (wiringPiSetup() == -1)
    {
        exit(1);
    }

    result_detect_process = detect_process("mjpg_streamer");
    if(-1 == result_detect_process)
    {
        perror("detect_process");
        goto END;
    }

    serial_fd = my_serialOpen(SERIAL_DEV, BAUD);
    if(-1 == serial_fd)
    {
        perror("my_serialOpen");

        goto END;
    }

    pthread_create(&get_voice_tid, NULL, get_voice, NULL);
    pthread_create(&get_category_tid, NULL, get_category, NULL);

    pthread_mutex_init(&mutex, NULL);
    pthread_cond_init(&cond, NULL);

    pthread_join(get_voice_tid, NULL);
    pthread_join(get_category_tid, NULL);

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

END:
    rubbish_Finalize();
    return 0;
}

增加OLED显示功能

myOLED.c

直接添在rubbish项目中添加2个OLED实现代码文件 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"

struct display_info disp;

void oled_show(void *arg)
{
    int i;
    unsigned char *buffer = (unsigned char *)arg;

    oled_putstrto(&disp, 1, 9+1, "Rubbish recognition : ");
    disp.font = font2;
    oled_send_buffer(&disp);

    switch(buffer[2])
    {
        case 0x41:
                    oled_putstrto(&disp, 3, 18+2, "dry rubbish");
            break;
        
        case 0x42:
                    oled_putstrto(&disp, 1, 18+2, "wet rubbish");
            break;
        
        case 0x43:
                    oled_putstrto(&disp, 1, 18+2, "recyclable rubbish");
            break;

        case 0x44:
                    oled_putstrto(&disp, 1, 18+2, "hazardous rubbish");
            break;
        
        case 0x45:
                    oled_putstrto(&disp, 1, 18+2, "recognition failure");
            break;

        default:
            break;
    }
    disp.font = font2;
    oled_send_buffer(&disp);

    disp.font = font3;
    for (i = 0; i < 100; i++) {
		oled_putstrto(&disp, 135-i, 36+4, "===");
		oled_send_buffer(&disp);
	}

}

void show_error(int err, int add)
{
	printf("\nERROR: %i, %i\n\n", err, add);
}

void myOled_init(void)
{
    int e;
    disp.address = OLED_I2C_ADDR;
    disp.font = font2;

    e = oled_open(&disp, FILENAME);
    if (e < 0) 
    {
		show_error(1, e);
	}
    else
    {
		e = oled_init(&disp);
    }
}

myOLED.h

#ifndef _MYOLED_H_
#define _MYOLED_H_

#define FILENAME  "/dev/i2c-3"

void oled_show(void *argv);

void myOled_init(void);

#endif

main.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <pthread.h>
#include <wiringPi.h>

#include "rubbish.h"
#include "mySerial.h"
#include "pwm.h"
#include "myOLED.h"

int len = -1;
int serial_fd = -1;
pthread_mutex_t mutex;
pthread_cond_t  cond;

int detect_process(char *process_name)
{
    FILE *file;
    int pid;
    char cmd[64] = {'\0'};
    char buffer[128] = {'\0'};
    
    sprintf(cmd, "ps -ax | grep  %s | grep -v grep", process_name);
    file = popen(cmd, "r");
    if(file != NULL)
    {
        if(fgets(buffer, sizeof(buffer), file) != NULL)
        {
            pid = atoi(buffer);

            return pid;
        }
        else
        {
            return -1;
        }
    }
    else
    {
        return -1;
    }

    pclose(file);
    return pid;
}

void* send_voice(void *arg)
{
    printf("%s|%s|%d: \n", __FILE__, __func__, __LINE__);
    pthread_detach(pthread_self());
    unsigned char *buffer = (unsigned char *)arg;

    printf("%s|%s|%d: \n", __FILE__, __func__, __LINE__);

    if(NULL != buffer)
    {
        my_serialPuts(serial_fd, buffer, 6);

        printf("%s|%s|%d: \n", __FILE__, __func__, __LINE__);
    }

    pthread_exit(0);
}

void* trash_can(void *arg)
{
    pthread_detach(pthread_self());
    unsigned char *buffer = (unsigned char *)arg;
    
    printf("%s|%s|%d: \n", __FILE__, __func__, __LINE__);

    if(buffer[2] == 0x43)
    {
        pwm_write(PWM_RECOVERABLE_RUBBISH);
        delay(2300);
        pwm_stop(PWM_RECOVERABLE_RUBBISH);

        printf("%s|%s|%d: \n", __FILE__, __func__, __LINE__);
    }
    else if(buffer[2] != 0x45)
    {
        pwm_write(PWM_OTHER_RUBBISH);
        delay(2300);
        pwm_stop(PWM_OTHER_RUBBISH);

        printf("%s|%s|%d: \n", __FILE__, __func__, __LINE__);
    }

    pthread_exit(0);
}

void* myOled_show(void *arg)
{
   pthread_detach(pthread_self());
   myOled_init();
   oled_show(arg);
   pthread_exit(0);
}

void* get_voice()
{   

    unsigned char buffer[6] = {0xAA, 0x55, 0x00, 0x00, 0X55, 0xAA};
    while(1)
    {
        len = my_serialGets(serial_fd, buffer);

        if(len > 0 && buffer[2] == 0x46)
        {
//            system(WGET_CMD);
            pthread_mutex_lock(&mutex);
            buffer[2] = 0x00;
            pthread_cond_signal(&cond);
            pthread_mutex_unlock(&mutex);
        }
    }
    pthread_exit(0);
}

void* get_category()
{
    char *category = NULL;
    pthread_t send_voice_tid;
    pthread_t trash_can_tid;
    pthread_t myOled_show_tid;
    unsigned char buffer[6] = {0xAA, 0x55, 0x00, 0x00, 0X55, 0xAA};
    
    while(1)
    {
        pthread_mutex_lock(&mutex);
        pthread_cond_wait(&cond, &mutex);
        pthread_mutex_unlock(&mutex);
        
        buffer[2] = 0x00;
        system(WGET_CMD);
        
        if(access(RUBBISH_FILE, F_OK) == 0)
        {   
            category = alicloud_rubbish_category(category);
            printf("category = %s\n", category);
        
            if(strstr(category, "干垃圾") != NULL)
            {
                buffer[2] = 0x41;
                printf("[%d]: 0x%2X\n", __LINE__, buffer[2]);
                //my_serialPuts(serial_fd, buffer, 6);
            }
        
            else if(strstr(category, "湿垃圾"))
            {
                buffer[2] = 0x42;
                printf("[%d]: 0x%2X\n", __LINE__, buffer[2]);
                //my_serialPuts(serial_fd, buffer, 6);
            }
        
            else if(strstr(category, "可回收垃圾"))
            {
                buffer[2] = 0x43;
                printf("[%d]: 0x%2X\n", __LINE__, buffer[2]);
                //my_serialPuts(serial_fd, buffer, 6);
            }
        
            else if(strstr(category, "有害垃圾"))
            {
                buffer[2] = 0x44;
                printf("[%d]: 0x%2X\n", __LINE__, buffer[2]);
                //my_serialPuts(serial_fd, buffer, 6);
            }
        
            else
            {
                buffer[2] = 0x45;
                printf("[%d]: 0x%2X\n", __LINE__, buffer[2]);
                //my_serialPuts(serial_fd, buffer, 6);
            }
            //printf("ret_strstr = %s\n", ret_strstr);
        }
        else
        {
            buffer[2] = 0x45;
            printf("[%d]: 0x%2X\n", __LINE__, buffer[2]);
            //my_serialPuts(serial_fd, buffer, 6);
        }
        printf("%s|%s|%d: \n", __FILE__, __func__, __LINE__);
    
        if(pthread_create(&send_voice_tid, NULL, send_voice, buffer) != 0)
        {
            perror("pthread_create1");
            exit(-1);
        }
        
        if(pthread_create(&trash_can_tid, NULL, trash_can, buffer) != 0)
        {
            perror("pthread_create2");
            exit(-1);
        }

        if(pthread_create(&myOled_show_tid, NULL, myOled_show, buffer) != 0)
        {
            perror("pthread_create2");
            exit(-1);
        }

        remove(RUBBISH_FILE);
        
        printf("%s|%s|%d: \n", __FILE__, __func__, __LINE__);

    }
    
    pthread_exit(0);
}

int main()
{
    int result_detect_process = -1;
    char *ret_strstr = (char *)malloc(1024);
    pthread_t get_voice_tid;
    pthread_t get_category_tid;

    rubbish_Init();
    if (wiringPiSetup() == -1)
    {
        exit(1);
    }

    result_detect_process = detect_process("mjpg_streamer");
    if(-1 == result_detect_process)
    {
        perror("detect_process");
        goto END;
    }

    serial_fd = my_serialOpen(SERIAL_DEV, BAUD);
    if(-1 == serial_fd)
    {
        perror("my_serialOpen");

        goto END;
    }

    pthread_create(&get_voice_tid, NULL, get_voice, NULL);
    pthread_create(&get_category_tid, NULL, get_category, NULL);

    pthread_mutex_init(&mutex, NULL);
    pthread_cond_init(&cond, NULL);

    pthread_join(get_voice_tid, NULL);
    pthread_join(get_category_tid, NULL);

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

END:
    rubbish_Finalize();
    return 0;
}

增加网络控制功能

TCP 心跳机制解决Soket异常断开问题

socket_Sever.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>

#include "socket_Sever.h"

int socket_init()
{
    int s_fd;
    struct sockaddr_in s_addr;
    memset(&s_addr, 0, sizeof(struct sockaddr_in));

    s_fd = socket(AF_INET,SOCK_STREAM,0);
    if(s_fd == -1)
    {
        perror("socket");
        exit(-1);
    }

    s_addr.sin_family = AF_INET;
    s_addr.sin_port = htons(atoi(MY_PORT));
    inet_aton(MY_IP_ADDRESS, &s_addr.sin_addr);
    //2.bind
    int result_bind = bind(s_fd, (struct sockaddr *)&s_addr, sizeof(struct sockaddr_in));
    if (-1 == result_bind)
    {
        perror("bind");
        return -1;
    }
    //3.listen
    int result_listen = listen(s_fd, 1);
    if (-1 == result_listen)
    {
        perror("listen");
        return -1;
    }

    return s_fd;
}

socket_Sever.h

#ifndef _SOCKET_SEVER_H_
#define _SOCKET_SEVER_H_

#define MY_IP_ADDRESS "192.168.1.82"
#define MY_PORT       "8888"

int socket_init();

#endif

main.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <pthread.h>
#include <wiringPi.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>

#include "rubbish.h"
#include "mySerial.h"
#include "pwm.h"
#include "myOLED.h"
#include "socket_Sever.h"

int len = -1;
int serial_fd = -1;
pthread_mutex_t mutex;
pthread_cond_t  cond;

int detect_process(char *process_name)
{
    FILE *file;
    int pid;
    char cmd[64] = {'\0'};
    char buffer[128] = {'\0'};
    
    sprintf(cmd, "ps -ax | grep  %s | grep -v grep", process_name);
    file = popen(cmd, "r");
    if(file != NULL)
    {
        if(fgets(buffer, sizeof(buffer), file) != NULL)
        {
            pid = atoi(buffer);

            return pid;
        }
        else
        {
            return -1;
        }
    }
    else
    {
        return -1;
    }

    pclose(file);
    return pid;
}

void* send_voice(void *arg)
{
    printf("%s|%s|%d: \n", __FILE__, __func__, __LINE__);
    pthread_detach(pthread_self());
    unsigned char *buffer = (unsigned char *)arg;

    printf("%s|%s|%d: \n", __FILE__, __func__, __LINE__);

    if(NULL != buffer)
    {
        my_serialPuts(serial_fd, buffer, 6);

        printf("%s|%s|%d: \n", __FILE__, __func__, __LINE__);
    }

    pthread_exit(0);
}

void* trash_can(void *arg)
{
    pthread_detach(pthread_self());
    unsigned char *buffer = (unsigned char *)arg;
    
    printf("%s|%s|%d: \n", __FILE__, __func__, __LINE__);

    if(buffer[2] == 0x43)
    {
        pwm_write(PWM_RECOVERABLE_RUBBISH);
        delay(2300);
        pwm_stop(PWM_RECOVERABLE_RUBBISH);

        printf("%s|%s|%d: \n", __FILE__, __func__, __LINE__);
    }
    else if(buffer[2] != 0x45)
    {
        pwm_write(PWM_OTHER_RUBBISH);
        delay(2300);
        pwm_stop(PWM_OTHER_RUBBISH);

        printf("%s|%s|%d: \n", __FILE__, __func__, __LINE__);
    }

    pthread_exit(0);
}

void* myOled_show(void *arg)
{
   pthread_detach(pthread_self());
   myOled_init();
   oled_show(arg);
   pthread_exit(0);
}

void* get_voice()
{   

    unsigned char buffer[6] = {0xAA, 0x55, 0x00, 0x00, 0X55, 0xAA};
    while(1)
    {
        len = my_serialGets(serial_fd, buffer);

        if(len > 0 && buffer[2] == 0x46)
        {
//            system(WGET_CMD);
            pthread_mutex_lock(&mutex);
            buffer[2] = 0x00;
            pthread_cond_signal(&cond);
            pthread_mutex_unlock(&mutex);
        }
    }
    pthread_exit(0);
}

void* get_category()
{
    char *category = NULL;
    pthread_t send_voice_tid;
    pthread_t trash_can_tid;
    pthread_t myOled_show_tid;
    unsigned char buffer[6] = {0xAA, 0x55, 0x00, 0x00, 0X55, 0xAA};
    
    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(access(RUBBISH_FILE, F_OK) == 0)
        {   
            category = alicloud_rubbish_category(category);
            printf("category = %s\n", category);
        
            if(strstr(category, "干垃圾") != NULL)
            {
                buffer[2] = 0x41;
                printf("[%d]: 0x%2X\n", __LINE__, buffer[2]);
                //my_serialPuts(serial_fd, buffer, 6);
            }
        
            else if(strstr(category, "湿垃圾"))
            {
                buffer[2] = 0x42;
                printf("[%d]: 0x%2X\n", __LINE__, buffer[2]);
                //my_serialPuts(serial_fd, buffer, 6);
            }
        
            else if(strstr(category, "可回收垃圾"))
            {
                buffer[2] = 0x43;
                printf("[%d]: 0x%2X\n", __LINE__, buffer[2]);
                //my_serialPuts(serial_fd, buffer, 6);
            }
        
            else if(strstr(category, "有害垃圾"))
            {
                buffer[2] = 0x44;
                printf("[%d]: 0x%2X\n", __LINE__, buffer[2]);
                //my_serialPuts(serial_fd, buffer, 6);
            }
        
            else
            {
                buffer[2] = 0x45;
                printf("[%d]: 0x%2X\n", __LINE__, buffer[2]);
                //my_serialPuts(serial_fd, buffer, 6);
            }
            //printf("ret_strstr = %s\n", ret_strstr);
        }
        else
        {
            buffer[2] = 0x45;
            printf("[%d]: 0x%2X\n", __LINE__, buffer[2]);
            //my_serialPuts(serial_fd, buffer, 6);
        }
        printf("%s|%s|%d: \n", __FILE__, __func__, __LINE__);
    
        if(pthread_create(&send_voice_tid, NULL, send_voice, buffer) != 0)
        {
            perror("pthread_create1");
            exit(-1);
        }
        
        if(pthread_create(&trash_can_tid, NULL, trash_can, buffer) != 0)
        {
            perror("pthread_create2");
            exit(-1);
        }

        if(pthread_create(&myOled_show_tid, NULL, myOled_show, buffer) != 0)
        {
            perror("pthread_create2");
            exit(-1);
        }

        remove(RUBBISH_FILE);
        
        printf("%s|%s|%d: \n", __FILE__, __func__, __LINE__);
        
    }
    
    pthread_exit(0);
}

void* socket_sever()
{
    int s_fd;
    int c_fd;
    ssize_t n_receive;
    struct sockaddr_in c_addr;
    char receive_buf[8] = {'\0'};

    memset(&c_addr, 0, sizeof(struct sockaddr_in));

    s_fd = socket_init();

    printf("%s|%s|%d:s_fd=%d\n", __FILE__, __func__, __LINE__, s_fd); 

    sleep(3);

    int addrlen = sizeof(struct sockaddr_in);

    while(1)
    {   
        memset(receive_buf, '\0', sizeof(receive_buf));

        c_fd = accept(s_fd, (struct sockaddr *)&c_addr, &addrlen);
        if(c_fd == -1)
        {
            perror("accept");
            
            continue;
        }
        
        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));
        
        //5.read
        while(1)
        {   
            memset(receive_buf, '\0', sizeof(receive_buf));
            n_receive = recv(c_fd, receive_buf, sizeof(receive_buf), 0);
            printf("%s|%s|%d : %s\n", __FILE__, __func__, __LINE__, receive_buf);
            
            if(n_receive > 0)
            {
                if(strstr(receive_buf, "open"))
                {   
                    printf("%s|%s|%d\n", __FILE__, __func__, __LINE__);
                    pthread_mutex_lock(&mutex);
                    pthread_cond_signal(&cond);
                    pthread_mutex_unlock(&mutex);
                    
                    printf("%s|%s|%d\n", __FILE__, __func__, __LINE__);
                }
            }
            /*
            if(strstr(receive_buf, "open") && n_receive > 0)
            {
                pthread_mutex_lock(&mutex);
                pthread_cond_(&cond);
                pthread_mutex_unlock(&mutex);
            }
            */
            
            else if(0 == n_receive || -1 == n_receive)
            {
                break;
            }
        }
        close(c_fd);
    }
    pthread_exit(0);
}

int main()
{
    int result_detect_process = -1;
    char *ret_strstr = (char *)malloc(1024);
    pthread_t get_voice_tid;
    pthread_t get_category_tid;
    pthread_t socket_sever_tid;

    rubbish_Init();
    if (wiringPiSetup() == -1)
    {
        exit(1);
    }

    result_detect_process = detect_process("mjpg_streamer");
    if(-1 == result_detect_process)
    {
        perror("detect_process");
        
        goto END;
    }

    serial_fd = my_serialOpen(SERIAL_DEV, BAUD);
    if(-1 == serial_fd)
    {
        perror("my_serialOpen");

        goto END;
    }

    pthread_create(&get_voice_tid, NULL, get_voice, NULL);
    pthread_create(&get_category_tid, NULL, get_category, NULL);
    pthread_create(&socket_sever_tid, NULL, socket_sever, NULL);

    pthread_mutex_init(&mutex, NULL);
    pthread_cond_init(&cond, NULL);

    pthread_join(get_voice_tid, NULL);
    pthread_join(get_category_tid, NULL);
    pthread_join(socket_sever_tid, NULL);

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

END:
    rubbish_Finalize();
    return 0;
}
  • 33
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
编译 Linux 内核需要以下步骤: 1. 获取 Linux 内核源代码。你可以从官方网站或 GitHub 上下载最新的内核源代码。 2. 安装交叉编译工具链。如果你的开发环境是 x86 架构的,你需要安装交叉编译工具链来编译适用于 ARM 架构的内核。你可以使用 apt-get 命令或其他包管理器来安装工具链。例如,在 Ubuntu 或 Debian 上,你可以使用以下命令来安装: ``` sudo apt-get install gcc-arm-linux-gnueabihf ``` 3. 配置内核。进入内核源代码目录,使用以下命令来配置内核: ``` make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- orangepi_zero2_defconfig ``` 这将使用默认配置文件来配置内核。 4. 编译内核。使用以下命令来编译内核: ``` make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- zImage dtbs modules ``` 这将编译内核镜像、设备树和内核模块。 5. 安装内核。将编译好的内核镜像和设备树文件复制到 SD 卡的 boot 分区中。例如,在 Ubuntu 或 Debian 上,你可以使用以下命令来安装: ``` sudo cp arch/arm/boot/zImage /media/boot/ sudo cp arch/arm/boot/dts/sun8i-h2-plus-orangepi-zero2.dtb /media/boot/ ``` 6. 配置引导加载程序。编辑 SD 卡的 boot 分区中的 boot.cmd 文件,并添加以下内容: ``` setenv bootargs console=ttyS0,115200 root=/dev/mmcblk0p2 rootwait panic=10 fatload mmc 0:1 ${kernel_addr_r} zImage fatload mmc 0:1 ${fdt_addr_r} sun8i-h2-plus-orangepi-zero2.dtb bootz ${kernel_addr_r} - ${fdt_addr_r} ``` 这将配置引导加载程序以加载内核镜像和设备树,并指定内核参数。 7. 生成引导加载程序镜像。使用以下命令来生成引导加载程序镜像: ``` mkimage -C none -A arm -T script -d boot.cmd boot.scr ``` 这将生成一个名为 boot.scr 的文件,它是引导加载程序镜像。 8. 将引导加载程序镜像复制到 SD 卡的 boot 分区中: ``` sudo cp boot.scr /media/boot/ ``` 9. 将 SD 卡插入 Orange Pi Zero 2 开发板,并启动板子。如果一切正常,你应该看到内核启动信息在串口终端中输出。 注意:这只是一个简单的指南,实际的操作可能会因环境和设备而有所不同。请确保你熟悉 Linux 内核编译和 Orange Pi Zero 2 开发板的使用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值