垃圾分类子项目三 - 添加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; // 传入串口数据 -- buffer
  oled_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); // 初始化oled
    return e;
}

myoled.h

#ifndef __MYOLED_H
#define __MYOLED_H

int 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 ,行号 -  138
        pthread_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); //开盖5s
      pwm_stop(PWM_GARBAGE1); //停止写入波形
      }
      else if(buffer[2] != 0x45){
      pwm_write(PWM_GARBAGE2);
      delay (2000); //开盖5s
      pwm_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 ,行号 -  138
        pthread_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; // 创建线程id

    unsigned 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);

    // 第二个参数表示接收到的返回值 -- 没有就NULL
    pthread_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;
}

相关推荐

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

    2024-04-27 06:44:02       14 阅读
  2. 垃圾分类子项目2 - 加入舵机控制

    2024-04-27 06:44:02       11 阅读
  3. STM32-OLED显示屏

    2024-04-27 06:44:02       34 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-04-27 06:44:02       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-04-27 06:44:02       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-04-27 06:44:02       18 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-04-27 06:44:02       20 阅读

热门阅读

  1. Python:一切皆对象!

    2024-04-27 06:44:02       12 阅读
  2. web server apache tomcat11-22-logging 日志

    2024-04-27 06:44:02       11 阅读
  3. web server apache tomcat11-23-APR

    2024-04-27 06:44:02       16 阅读
  4. 【electron 4】electron配置打包环境

    2024-04-27 06:44:02       12 阅读
  5. React Router v5 版本中,路由传参主要方式

    2024-04-27 06:44:02       10 阅读
  6. 搭建vue3组件库(一):Monorepo架构搭建

    2024-04-27 06:44:02       12 阅读
  7. day03--react中setState的使用

    2024-04-27 06:44:02       14 阅读
  8. linux安装opencv

    2024-04-27 06:44:02       15 阅读
  9. Kafka

    Kafka

    2024-04-27 06:44:02      14 阅读