基于全志H616的智能垃圾桶项目

一、功能需求

  • 靠近时,垃圾桶开启2秒,2秒后关闭
  • 垃圾桶开启带滴滴声
  • 垃圾桶开启超过10秒,滴滴声警报
  • 语音控制垃圾桶开关盖
  • 回顾二阶段的Socket编程,实现Sockect客户端发送指令远程打开/关闭垃圾桶,并显示垃圾桶状态
  • 统计当天垃圾桶开关盖次数及开关盖指令来源并记录在文件中
  • 统计当天垃圾桶开关盖次数及开关盖指令来源并记录在数据库中

二、硬件

超声波测距模块,sg90,蜂鸣器,全志H616,SU-03语音模块。

三、设计模块

简单工厂模式:分模块思想编程,使代码更易于维护;

设备工厂:控制sg90舵机,超声波测距模块和蜂鸣器;

指令工厂:控制语音和Socket客户端收发指令;

记录工厂:控制文件和数据库的读写。

四、代码

contrlDevices.h

#include 
#include 

struct Devices
{
  char deviceName[128];
  int status;
  int pinNum;
  
  char date[32];
  int csbOpen;
  int csbClose;
  int socketOpen;
  int socketClose;
  int voiceOpen;
  int voiceClose;

  int (*open)(int pinNum);
  int (*close)(int pinNum);
  int (*deviceInit)(int pinNum);

  int (*readStatus)(int pinNum);
  int (*changeStatus)(int pinNum);
  struct Devices *next;
  struct timeval start;
  struct timeval stop;
};

struct Devices * addBeepToDeviceLink(struct Devices *phead);
struct Devices * addCsbToDeviceLink(struct Devices *phead);
struct Devices * addDusbinToDeviceLink(struct Devices *phead);

InputCommand.h

#include 
#include 
#include 
#include 
#include 


struct InputCommander
{
  char commandName[128];//socketServer和voice
  char deviceName[128];//打开的设备名称
  char command[32];//获取指令
  char log[1024];
  int baud;//波特率
  int fd;
  int s_fd;
  int c_fd;
  char port[12];//端口号
  char ipAddress[32];//ip地址
  int (*Init)(struct InputCommander *pInputCommand);
  int (*getCommand)(struct InputCommander *pInputCommand);
  int (*sendStatus)(int fd,char *str);
  struct InputCommander *next;
};

struct InputCommander * addSocketContrlToInputCommand(struct InputCommander * phead);
struct InputCommander * addVoiceContrlToInputCommand(struct InputCommander * phead);


record.h

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

struct Records{ 
    char recordName[32];//fileRecords  dataBaseRecords
    char recordPathName[32];//文件名或数据库名 
    sqlite3 *db;
    int fd;
    
    int (*Init)(struct Records *pRecord);
    int (*writeRecords)(struct Records *pRecord);
    struct Records *next;
};

struct Records *addFileToRecordsLink(struct  Records *phead);
struct Records * addDataBaseToRecordsLink(struct Records *phead);

csb.c

#include "contrlDevices.h"
#include 
#include 
#include 

#define Trig 5

int csbInit(int pinNum)
{
    pinMode(Trig,OUTPUT);
    pinMode(pinNum,INPUT);
}

int getDistance(int pinNum)
{
  //测量距离:2-400cm;
        struct timeval tv1;  //timeval是time.h中的预定义结构体 其中包含两个一个是秒,一个是微秒
 
        struct timeval tv2;
        long start, stop;
        float dis;
 
        digitalWrite(Trig, LOW);
        delayMicroseconds(2);
 
        digitalWrite(Trig, HIGH);
        delayMicroseconds(10);      //发出超声波脉冲
        digitalWrite(Trig, LOW);
 
        while(digitalRead(pinNum) != 1);
 
        gettimeofday(&tv1, NULL);           //获取当前时间 开始接收到返回信号的时候
 
        while(digitalRead(pinNum) != 0);
        gettimeofday(&tv2, NULL);           //获取当前时间  最后接收到返回信号的时候
 
        start = tv1.tv_sec * 1000000 + tv1.tv_usec;   //微秒级的时间
        stop  = tv2.tv_sec * 1000000 + tv2.tv_usec;
 
        dis = (float)(stop - start) / 1000000 * 34000 / 2;  //计算时间差求出距离
        if(dis>30){
          return 1;
        }else{
          return 0;
        }

}
struct Devices csb=
{
  .deviceName="csb",
  .pinNum=7,
  .status=1,
  .deviceInit=csbInit,
  .readStatus=getDistance//大于10cm,返回1,小于10cm 返回0;
};

struct Devices * addCsbToDeviceLink(struct Devices *phead)
{
  if(phead == NULL){
    return &csb;
  }else{
    csb.next=phead;
    return &csb;
  }
}

beep.c

#include "contrlDevices.h"
#include 

int beepOpen(int pinNum)
{
  digitalWrite(pinNum,HIGH);
}
int beepClose(int pinNum)
{
  digitalWrite(pinNum,LOW);
}
 int beepInit(int pinNum)
 {
    pinMode(pinNum,OUTPUT);
    digitalWrite(pinNum,LOW);//高电平触发;
    
 }

struct Devices beep=
{
  .deviceName="beep",
  .pinNum=8,
  .open = beepOpen,
  .close =beepClose,
  .deviceInit=beepInit,  
};

struct Devices * addBeepToDeviceLink(struct Devices *phead)
{
  if(phead == NULL){
    return &beep;
  }else{
    beep.next=phead;
    return &beep;
  }
}

dusbin.c

#include "contrlDevices.h"
#include "InputCommand.h"
#include "record.h"
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#define SG90Pin 2
char message[200];

extern struct Devices *beepHandler;
extern struct Devices *dusbinHandler;
extern struct InputCommander *socketHandler;
extern struct InputCommander *voiceHandler;
extern struct Devices *csbHandler;
extern struct Records *fileHandler;
struct Records * sqliteHandler;

static int i = 0;
extern int jd_bak;
extern int jd;

void recordCount()
{
    time_t now;
      struct tm* tm_now;
    char datemessage[12]={'\0'};
    time(&now);
    tm_now = localtime(&now);
    strftime(datemessage,12,"%Y/%m/%d",tm_now);//获取当前时间
    if(strcmp(dusbinHandler->date,datemessage)){
        memset(dusbinHandler->date,'\0',32);
        strcpy(dusbinHandler->date,datemessage);
        dusbinHandler->csbOpen=0;
        dusbinHandler->csbClose=0;
        dusbinHandler->voiceOpen=0;
        dusbinHandler->voiceClose=0;
        dusbinHandler->socketOpen=0;
        dusbinHandler->socketClose=0;
    }
        
       
    if(! csbHandler->status){
        dusbinHandler->csbOpen++;
    }else if(!strcmp(voiceHandler->command,"open")){
        dusbinHandler->voiceOpen++;
    }else if(!strcmp(socketHandler->command,"open")){
        dusbinHandler->socketOpen++;
         
    }else if(!strcmp(voiceHandler->command,"close")&& csbHandler->status ){
        dusbinHandler->voiceClose++;
         
    }else if (!strcmp(socketHandler->command,"close")&& csbHandler->status ){
        dusbinHandler->socketClose++;
         
    }else if(csbHandler->status   && strcmp(voiceHandler->command,"open") && strcmp(socketHandler->command,"open" )&& strcmp(voiceHandler->command,"close")&&strcmp(socketHandler->command,"close")){
        dusbinHandler->csbClose++;  
    }   
    memset(voiceHandler->command,'\0',32);
    memset(socketHandler->command,'\0',32);
    
}

int dusbinOpen(int pinNum)
{ 
    
   jd =3;
   gettimeofday(&(beepHandler->stop),NULL);
    if(jd_bak!=jd){   
        recordCount();//记录开关盖次数
        fileHandler->writeRecords(fileHandler);   //写入文件;
        sqliteHandler->writeRecords(sqliteHandler);//写入数据库;
       
        beepHandler->open(beepHandler->pinNum);
        usleep(150000);
        beepHandler->close(beepHandler->pinNum);
        sleep(2);          
    }
   jd_bak=jd; 
 
}

int  dusbinClose(int pinNum)
{
    jd = 1;
    
    if(jd_bak!=jd){   
        recordCount();
        fileHandler->writeRecords(fileHandler);
        sqliteHandler->writeRecords(sqliteHandler);

        usleep(150000);
    }
    jd_bak=jd;
    gettimeofday(&(beepHandler->start),NULL);   
     
}


void signal_handler(int signum)
{
    if(i <= jd){
        digitalWrite(SG90Pin, HIGH);
    }else{
     digitalWrite(SG90Pin, LOW);
    }
    if(i == 40){//20ms
     i = 0;
    } 
    i++;
}

 int dusbinInit(int pinNum)
 {
    struct itimerval itv;
    jd = 1;
    jd_bak=1;
    i=0;
    
    pinMode(pinNum,OUTPUT);
    digitalWrite(pinNum,LOW);
   
    //设定定时时间:500微秒,
    itv.it_interval.tv_sec = 0;
    itv.it_interval.tv_usec = 500;
    //设定开始生效,启动定时器的时间
    itv.it_value.tv_sec = 1;
    itv.it_value.tv_usec = 0;
    //设定定时方式
    if( -1 == setitimer(ITIMER_REAL, &itv, NULL)){
        printf("setitimer error\n");
        exit(-1);
    }
    //信号处理
    signal(SIGALRM,signal_handler);

 }



struct Devices dusbin=
{
  .deviceName="dusbin",
  .pinNum=2,
  .deviceInit=dusbinInit,
  .open=dusbinOpen,
  .close=dusbinClose,
  .date={'\0'},
   .csbOpen=0,
    .csbClose=0,
    .socketOpen=0,
    .socketClose=0,
    .voiceOpen=0,
    .voiceClose=0,
    
  
};

struct Devices * addDusbinToDeviceLink(struct Devices *phead)
{
  if(phead == NULL){
    return &dusbin;
  }else{
    dusbin.next=phead;
    return &dusbin;
  }
}

file.c

#include "record.h"
#include 
#include 
#include 
#include "contrlDevices.h"


extern struct Devices *dusbinHandler;


int fileInit(struct Records *pRecord)
{
    int fd;
    if((fd=open(pRecord->recordPathName,O_RDWR|O_CREAT,0600))==-1){
        perror("file open error");
        exit(-1);
    }
    close(fd);
    pRecord->fd=fd;
    return fd;
}

int writeToFile(struct Records *pRecord)
{
    int nwrite;
    char *readBuf;
    char message[100]={'\0'};
    char info[200]={'\0'};
    int j;
    
    sprintf(message,"date=%s;",dusbinHandler->date);
    sprintf(info,"date=%s;csbOpen=%d;csbClose=%d;voiceOpen=%d;voiceClose=%d;socketOpen=%d;socketClose=%d;\r\n",dusbinHandler->date,dusbinHandler->csbOpen,dusbinHandler->csbClose,dusbinHandler->voiceOpen,dusbinHandler->voiceClose,dusbinHandler->socketOpen,dusbinHandler->socketClose);
    


    pRecord->fd = open(pRecord->recordPathName,O_RDWR,0600);
    int fileSize=lseek(pRecord->fd,0,SEEK_END);

    readBuf= (char *)malloc(sizeof(char )*(fileSize+strlen(info)+12));
    lseek(pRecord->fd,0,SEEK_SET);
    memset(readBuf,'\0',sizeof(readBuf));
    read(pRecord->fd,readBuf,fileSize);
    lseek(pRecord->fd,0,SEEK_SET);

    char *p = strstr(readBuf,message);
    if(p==NULL&& strlen(dusbinHandler->date)!=0){
            strncat(readBuf,info,strlen(info));//在尾部追加;
	}else{
       for(j=0;jfd,readBuf,strlen(readBuf));
    printf("write file success:%s\n",readBuf);
    close(pRecord->fd);
    return nwrite;

}

struct Records file={
    .recordName="fileRecords",
    .recordPathName="file1", 
    .Init=fileInit,
    .writeRecords=writeToFile,
    
};


struct Records *addFileToRecordsLink(struct  Records *phead)
{
  if(phead == NULL){
    return &file;

  }else{
    file.next=phead;
    return &file;
  }
}

lite.c

#include "record.h"
#include "contrlDevices.h"
#include 
#include 
#include 


extern struct Devices *dusbinHandler;
int callback1(void *arg, int column_size, char *column_value[], char
*column_name[])
{
    int i;
    printf("records of dusbin.db:\n");
    for(i=0;idate,dusbinHandler->csbOpen,dusbinHandler->csbClose,dusbinHandler->voiceOpen,dusbinHandler->voiceClose,dusbinHandler->socketOpen,dusbinHandler->socketClose);
      rc=sqlite3_exec(arg, sql, NULL, 0, &zErrMsg);
         if( rc != SQLITE_OK ){
            fprintf(stderr, "insert error: %s\n", zErrMsg);
            sqlite3_free(zErrMsg);
          }else{
            fprintf(stdout, "insert  successfully\n");
        } 
  }
  memset(sql,'\0',strlen(sql));
  sprintf(sql,"select * from dusbin where date = '%s';",dusbinHandler->date);
   rc=sqlite3_exec(arg, sql,callback1, arg, &zErrMsg);
         if( rc != SQLITE_OK ){
            fprintf(stderr, "SQL error: %s\n", zErrMsg);
            sqlite3_free(zErrMsg);
          }else{
            fprintf(stdout, " select successfully\n");
        } 
        sqlite3_close(arg);

    return 0;     
}
    
int writeToDB(struct Records *pRecord)
{
    int rc;
   char *zErrMsg = NULL;
  char sql[256]={'\0'};
    sprintf(sql,"update dusbin set csbOpen = %d, csbClose=%d ,voiceOpen=%d,voiceClose=%d,socketOpen=%d,socketClose=%d where date ='%s' ;select count(*) from dusbin where date='%s';",dusbinHandler->csbOpen,dusbinHandler->csbClose,dusbinHandler->voiceOpen,dusbinHandler->voiceClose,dusbinHandler->socketOpen,dusbinHandler->socketClose ,dusbinHandler->date,dusbinHandler->date);    
   rc = sqlite3_open(pRecord->recordPathName, &(pRecord->db));
    if( rc!=SQLITE_OK ){

        fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(pRecord->db));
        exit(0);
    }else{
         fprintf(stderr, "Opened database successfully\n");
    }
    rc=sqlite3_exec(pRecord->db, sql, callback, pRecord->db, &zErrMsg);
    if( rc != SQLITE_OK ){
        fprintf(stderr, "update database error: %s\n", zErrMsg);
        sqlite3_free(zErrMsg);
    }else{
        fprintf(stdout, "update  successfully\n");
    }

 sqlite3_close(pRecord->db);
}

int DBInit(struct Records *pRecord)
{
   int rc;
   char *zErrMsg = NULL;
    char *sql = "create table dusbin(date char,csbOpen interger, csbClose interger ,voiceOpen interger ,voiceClose interger, socketOpen interger, socketClose interger );";


    rc = sqlite3_open(pRecord->recordPathName, &(pRecord->db));
    if( rc ){
        fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(pRecord->db));
        exit(0);
    }else{
        fprintf(stderr, "Opened database successfully\n");
    }

    rc = sqlite3_exec(pRecord->db, sql, NULL, 0, &zErrMsg);
    if( rc != SQLITE_OK ){
     fprintf(stderr, "table existed: %s\n", zErrMsg);
        sqlite3_free(zErrMsg);
    }else{
        fprintf(stdout, "created Table successfully\n");
    }

    sqlite3_close(pRecord->db);
    return 0;
}



struct Records dbOfRecords={
    .recordName="dataBaseRecords",
    .recordPathName="dusbin.db", 
    .Init=DBInit,
    .writeRecords=writeToDB,
    
};


struct Records * addDataBaseToRecordsLink(struct Records *phead)
{
  if(phead == NULL){
    return &dbOfRecords;
  }else{
    dbOfRecords.next=phead;
    return &dbOfRecords;
  }
}

mainPro.c

#include 
#include 
#include 
#include 
#include 
#include         
#include 
#include 
#include "contrlDevices.h"
#include "InputCommand.h"
#include 
#include 
#include "record.h"


struct Devices *pdeviceHead = NULL;
struct InputCommander *pCommandHead=NULL;
struct Records *pRecordsHead=NULL;

struct InputCommander *socketHandler;
struct InputCommander *voiceHandler;

struct Devices *dusbinHandler;
struct Devices *beepHandler;
struct Devices *csbHandler;
struct Records *fileHandler;
struct Records * sqliteHandler;

long diffTime;
 int jd_bak=0;
 int jd=0;




struct Devices * findDevicesByName(char *str,struct Devices * phead)
{
  struct Devices *tmp = phead;
  if(tmp == NULL){
    printf("find devices error\n");
    return NULL;
  }else{
    while(tmp!=NULL){
      if(!strcmp(tmp->deviceName,str)){
        return tmp;
      }
      tmp=tmp->next;
    }
  }
}
struct InputCommander * findInputCommanderByName(char *str,struct InputCommander * phead)
{
  struct InputCommander *tmp = phead;
  if(tmp == NULL){
    printf("find InputCommander error\n");
    return NULL;
  }else{
    while(tmp!=NULL){
      if(!strcmp(tmp->commandName,str)){
        return tmp;
      }
      tmp=tmp->next;
    }
  }
}

struct Records * findRecordsByName(char *str,struct Records * phead)
{
  struct Records *tmp = phead;
  if(tmp == NULL){
    printf("find records error\n");
    return NULL;
  }else{
    while(tmp!=NULL){
      if(!strcmp(tmp->recordName,str)){
        return tmp;
      }
      tmp=tmp->next;
    }
  }
}



void *read_thread(void *datas)
{
  int n_read;
  char buffer[32]={'\0'};
  
  while(1){
        memset(buffer,'\0',sizeof(buffer));
        n_read = read(socketHandler->c_fd,buffer, sizeof(buffer));
         if(n_read == -1){
            perror("read");
        }else if(n_read>0){ 
            memset(socketHandler->command,'\0',sizeof(socketHandler->command));
            strcpy(socketHandler->command,buffer);
            printf("socket get cmd:%s\n",socketHandler->command);
            
        }else{
            printf("client quit\n");
            break;
        }
    
  } 
}


void *socket_thread(void *datas)
{
  pthread_t readThread;
 

  struct sockaddr_in c_addr;

  int n_read = 0;
  int clen = sizeof(struct sockaddr_in);
  memset(&c_addr,0,clen);
  socketHandler=findInputCommanderByName("socketServer",pCommandHead);

  if(socketHandler==NULL){
    printf("find socketHandler error\n");
    pthread_exit(NULL);
  }else{
    socketHandler->Init(socketHandler);
    printf("%s init success\n",socketHandler->commandName);
    while(1){
      //不断接收新的客户端的接入,接入新的客户端后创建新的读线程;
      socketHandler->c_fd = accept(socketHandler->s_fd,(struct sockaddr *)&c_addr,&clen);
      if(socketHandler->c_fd == -1){
			perror("accept");
		}
        printf("c_fd:%d\n",socketHandler->c_fd);
      pthread_create(&readThread,NULL,read_thread,NULL);
    }
  }
    
}

void *voice_thread(void *datas)
{
  
  int nread;
  pthread_t cmdThread;
  voiceHandler=findInputCommanderByName("voice",pCommandHead);
  if(voiceHandler==NULL){
    printf("find voiceHandler error\n");
    pthread_exit(NULL);
  }else{
    if(voiceHandler->Init(voiceHandler)<0){
      printf("voice init error\n");
      pthread_exit(NULL);
    }else{
      printf("%s init success\n",voiceHandler->commandName);
    }
    while(1){
         nread=voiceHandler->getCommand(voiceHandler);
      if(nread==0){
         continue;
      }else{
        printf("voice get cmd: %s\n",voiceHandler->command);   
      }
    }
    
    }
} 

void *dusbin_thread(void *datas)
{
  

    dusbinHandler=findDevicesByName("dusbin",pdeviceHead );
    dusbinHandler->deviceInit(dusbinHandler->pinNum);
    fileHandler= findRecordsByName("fileRecords",pRecordsHead);
    fileHandler->Init(fileHandler);
    sqliteHandler = findRecordsByName("dataBaseRecords",pRecordsHead);
    sqliteHandler->Init(sqliteHandler);
 
    while(1){    
         //距离大于30cm,返回1;
        if(! csbHandler->status||!strcmp(voiceHandler->command,"open")||!strcmp(socketHandler->command,"open")){  
          //靠近时,垃圾桶开启2秒,2秒后关闭 
          dusbinHandler->open(dusbinHandler->pinNum);
        }else if( (!strcmp(voiceHandler->command,"close")||!strcmp(socketHandler->command,"close")) && csbHandler->status ){   
            dusbinHandler->close(dusbinHandler->pinNum);
        }else if(csbHandler->status && strcmp(voiceHandler->command,"open") && strcmp(socketHandler->command,"open")&& strcmp(voiceHandler->command,"close")&&strcmp(socketHandler->command,"close")){
             dusbinHandler->close(dusbinHandler->pinNum); 
        } 
    }
}




void *csb_thread(void *datas)
{
    csbHandler=findDevicesByName("csb",pdeviceHead); 
    beepHandler=findDevicesByName("beep",pdeviceHead);
    beepHandler->deviceInit(beepHandler->pinNum);
    csbHandler->deviceInit(csbHandler->pinNum);
    gettimeofday(&(beepHandler->start),NULL);
    while(1){
       csbHandler->status=csbHandler->readStatus(csbHandler->pinNum);
        diffTime=beepHandler->stop.tv_sec-beepHandler->start.tv_sec;
       if(diffTime>10){  
        beepHandler->open(beepHandler->pinNum);
       }else{
        beepHandler->close(beepHandler->pinNum);
       }
       usleep(500000);
    }
}


int main()
{
  
  pthread_t voiceThread;
  pthread_t socketThread;
  pthread_t csbThread;
  pthread_t dusbinThread;
 
  
  if(wiringPiSetup()==-1){
    printf("wiringPi init error\n");
    exit(-1);
  }
  //1.指令工厂初始化
  pCommandHead= addSocketContrlToInputCommand(pCommandHead);
  pCommandHead=addVoiceContrlToInputCommand(pCommandHead);
  
   //2.设备控制工厂初始化
  pdeviceHead=addBeepToDeviceLink(pdeviceHead);
  pdeviceHead=addCsbToDeviceLink(pdeviceHead);
  pdeviceHead=addDusbinToDeviceLink(pdeviceHead);

    //文件工厂初始化
  pRecordsHead = addFileToRecordsLink(pRecordsHead);
  pRecordsHead=addDataBaseToRecordsLink(pRecordsHead);

  //3.线程池建立
  //超声波测距线程
  pthread_create(&csbThread,NULL,csb_thread,NULL);
  //3.2语音线程
  pthread_create(&voiceThread,NULL, voice_thread,NULL);
  //3.3socket 线程
  pthread_create(&socketThread,NULL, socket_thread,NULL);
  //dusbin线程
  pthread_create(&dusbinThread,NULL, dusbin_thread,NULL);


  //等待线程退出:
  pthread_join(csbThread,NULL);
  pthread_join(voiceThread,NULL);
  pthread_join(socketThread,NULL);
  pthread_join(dusbinThread,NULL);
  
  return 0;
}

编译:

gcc  file.c lite.c beep.c dusbin.c mainPro.c socketContrl.c csb.c voiceContrl.c -lwiringPi -lwiringPiDev -lpthread -lm -lcrypt -lrt -lsqlite3

执行:

sudo ./a.out

五、功能展示

智能垃圾桶

你可能感兴趣的:(全志H616,linux,tcp/ip,http)