基于树莓派上实现的智能垃圾桶
整体功能
垃圾桶分为移动模式和清洁桶模式,移动模式垃圾桶通过电机操作马达轮子进行移动,清洁桶模式则LED屏幕亮起,检测温度,自动拉起桶盖,整体通过远程利用客户端进行控制。
LED屏的实现
oled.c
#include <wiringPi.h>
#include <wiringPiI2C.h>
#include <time.h>
#include <stdio.h>
#include <string.h>
#include <dirent.h>
#include <stdlib.h>
#include "wd.h"
int fd;
unsigned char yi[4][16]={
" ",//第一行
" ",//第二行
" ",//第三行
" " //第四行
}; //显示内容
const unsigned char zi[];
void initoled(void)//初始化
{
wiringPiSetup();
fd=wiringPiI2CSetup(0x3c);//i2c初始化 0x3c是oled的从机地址
wiringPiI2CWriteReg8(fd,0x00,0xa1);//图像反了修改成0xa0
wiringPiI2CWriteReg8(fd,0x00,0xc8);//行输出反了修改成0xc0
wiringPiI2CWriteReg8(fd,0x00,0x8d);//允许电荷泵
wiringPiI2CWriteReg8(fd,0x00,0x14);
wiringPiI2CWriteReg8(fd,0x00,0xa6);//想反相显示改成0xa7
wiringPiI2CWriteReg8(fd,0x00,0x21);//重置列地址
wiringPiI2CWriteReg8(fd,0x00,0x00);
wiringPiI2CWriteReg8(fd,0x00,0x7f);
wiringPiI2CWriteReg8(fd,0x00,0xaf);//开显示
system("sudo modprobe w1-gpio");
system("sudo modprobe w1-therm");
}
void qingping(void)//清屏
{
char zt1,zt2;
for(zt1=0;zt1<8;zt1++)
{
wiringPiI2CWriteReg8(fd,0x00,0xb0+zt1);
for(zt2=0;zt2<128;zt2++) wiringPiI2CWriteReg8(fd,0x40,0x00);
}
}
void ascii(void)//显示ASCII码8*16
{
int zt;
char zt3,zt4;
for(zt3=0;zt3<4;zt3++)
{
wiringPiI2CWriteReg8(fd,0x00,0xb0+(zt3*2));
for(zt4=0;zt4<16;zt4++)
for(zt=0;zt<8;zt++)
wiringPiI2CWriteReg8(fd,0x40,zi[yi[zt3][zt4]*16+zt]);
wiringPiI2CWriteReg8(fd,0x00,0xb0+(zt3*2)+1);
for(zt4=0;zt4<16;zt4++)
for(zt=0;zt<8;zt++)
wiringPiI2CWriteReg8(fd,0x40,zi[yi[zt3][zt4]*16+zt+8]);
}
}
void wendu(void)//调用温度函数
{
float value;
char buf[100];
value=wd();
gcvt(value, 5, buf);
strcpy(yi[0],buf);
}
void shijian(void)//当前时间
{
struct tm *ptr;
time_t lt;
FILE *f;
char data[255];
lt=time(<);
ptr=localtime(<);
strftime(yi[1],16,"%m/%d %a",ptr); //月/日 周几
strftime(yi[2],16,"%R %p",ptr);//时:分 am或pm
}
void oled(void)
{
while(1)
{
shijian();
wendu();
ascii();
delay(100);
}
}
这是利用SSD1306的0.91OLED模块通过以上代码实现显示在LED屏幕,温度函数这是利用DS18B20通过以下代码显示在LED屏
wd.c
#include <wiringPi.h>
#include <wiringPiI2C.h>
#include <time.h>
#include <stdio.h>
#include <string.h>
#include <dirent.h>
#include <stdlib.h>
float wd(void)
{
char path[50] = "/sys/bus/w1/devices/";
FILE *f;
char rom[20];
char buf[100];
char cat[100];
DIR *dirp;
struct dirent *direntp;
float value;
char *get;
get=malloc(sizeof(char));
memset(cat,0,100);
memset(buf,0,100);
stpcpy(cat,"cat ");
if((dirp = opendir(path)) == NULL)
{
printf("opendir error\n");
exit(-1);
}
while((direntp = readdir(dirp)) != NULL)
{
if(strstr(direntp->d_name,"28-0"))
{
strcpy(rom,direntp->d_name);
}
}
closedir(dirp);
strcat(path,rom);
strcat(path,"/w1_slave");
strcat(cat,path);
if((f = popen(cat,"r")) < 0)
{
printf("open error\n");
exit(-1);
}
fread(buf,1,100,f);
get=strstr(buf,"t=");
fclose(f);
get++;
get++;
value = atof(get)/1000;
return value;
}
电机
dj.c
#include <wiringPi.h>
#include <stdio.h>
int i;
void initdj()
{
pinMode(22,OUTPUT);
pinMode(23,OUTPUT);
pinMode(24,OUTPUT);
pinMode(25,OUTPUT);
digitalWrite(22,LOW);
digitalWrite(23,LOW);
digitalWrite(24,LOW);
digitalWrite(25,LOW);
}
void qian()
{
digitalWrite(22,HIGH);
digitalWrite(23,LOW);
digitalWrite(24,HIGH);
digitalWrite(25,LOW);
while(1)
{
if(i==1)
{
digitalWrite(22,LOW);
digitalWrite(23,LOW);
digitalWrite(24,LOW);
digitalWrite(25,LOW);
break;
}
}
}
void hou()
{
digitalWrite(22,LOW);
digitalWrite(23,HIGH);
digitalWrite(24,LOW);
digitalWrite(25,HIGH);
delay(10000);
digitalWrite(22,LOW);
digitalWrite(23,LOW);
digitalWrite(24,LOW);
digitalWrite(25,LOW);
}
void zhou
{
digitalWrite(22,LOW);
digitalWrite(23,HIGH);
delay(10000);
digitalWrite(22,LOW);
digitalWrite(23,LOW);
}
void you
{
digitalWrite(24,LOW);
digitalWrite(25,HIGH);
delay(10000);
digitalWrite(24,LOW);
digitalWrite(25,LOW);
}
舵机
sg.c
#include <stdio.h>
#include <string.h>
#include <wiringPi.h>
#include <pthread.h>
extern int i;
extern int o;
void initsg()
{
pinMode(1,PWM_OUTPUT);
pwmSetMode(PWM_MODE_MS);
pwmSetRange(2000);
pwmSetClock(192);
}
void sg()
{
while(1)
{
if(i==1)
pwmWrite(1,100);
else if(i==0)
pwmWrite(1,200);
if(o==0)
pthread_exit((void*)0);
}
}
客户端
#include <stdio.h>
#include "log.h"
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <string.h>
#include "msg.h"
#include "util.h"
int get_cmd(char *buf)
{
if (memcmp(buf,"yd",2)==0)
{
return 0;
}
else if (memcmp(buf,"qjt",3)==0)
{
return 1;
}
else if (memcmp(buf,"qian",4)==0)
{
return 2;
}
else if (memcmp(buf,"quit",4)==0)
{
return 4;
}
else if (memcmp(buf,"hou",3)==0)
{
return 3;
}
else
{
return 5;
}
}
int main()
{
int c_fd;
enum FTP_CMD cmd;
int ret;
struct sockaddr_in c_addr;
int con;
logcreate("./client.txt");
struct Msg *msg_send;
struct Msg *msg_recv;
msg_send = (struct Msg *)malloc(sizeof(struct Msg));
msg_recv = (struct Msg *)malloc(sizeof(struct Msg));
c_fd=socket(AF_INET,SOCK_STREAM,0);
if (c_fd==-1)
{
logwrite("perror connect: %s",c_fd);
exit(-1);
}
c_addr.sin_family=AF_INET;
c_addr.sin_port=htons(8989);
inet_aton("192.168.43.60", &c_addr.sin_addr);
con=connect(c_fd,(struct sockaddr*)&c_addr,sizeof(struct sockaddr));
if (con==-1)
{
logwrite("perror connect: %d",con);
exit(-1);
}
struct password dl;
printf("name:");
scanf("%s",dl.name);
printf("pass:");
scanf("%s",dl.pass);
logwrite("nmae:%s pass%s\n",dl.name,dl.pass);
ret=send2(c_fd,(char *)&dl,sizeof(struct password));
logwrite("perror send: %d\n",ret);
ret=recv(c_fd,&dl,sizeof(struct password),0);
logwrite("perror recv: %d\n",ret);
if (FTP_CMD_ERROR==dl.cmd)
{
printf("name or pass error\n");
return -1;
}
while(1)
{
char buf[256];
memset(msg_send,0,sizeof(struct Msg));
memset(msg_recv,0,sizeof(struct Msg));
// 等待用户输入
fgets(buf,sizeof(buf),stdin);
logwrite("get:%s",buf);
// buf转为FTP_CMD
cmd = get_cmd(buf);
logwrite("cmd %d\n", cmd);
msg_send->cmd=cmd;
send2(c_fd,(char *)msg_send,sizeof(struct Msg));
recv2(c_fd,(char *)msg_recv,sizeof(struct Msg));
printf("%s\n",msg_recv->data);
if (cmd==FTP_CMD_QUIT)
{
break;
}
}
logout();
close(c_fd);
return 0;
}
服务端
#include <stdio.h>
#include "a.h"
#include "dj.h"
#include "oled.h"
#include "log.h"
#include "msg.h"
#include "util.h"
#include "sg.h"
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <string.h>
#include <pthread.h>
int i=0;
int o=1;
void yd(int c_fd)//移动模式
{
struct Msg *msg_send;
struct Msg *msg_recv;
msg_send = (struct Msg *)malloc(sizeof(struct Msg));
msg_recv = (struct Msg *)malloc(sizeof(struct Msg));
memset(msg_send,0,sizeof(struct Msg));
memset(msg_recv,0,sizeof(struct Msg));
strcpy(msg_send->data,"please output qian or hou or quit");
send2(c_fd,(char *)msg_send,sizeof(struct Msg));
while(1)
{
memset(msg_send,0,sizeof(struct Msg));
memset(msg_recv,0,sizeof(struct Msg));
recv2(c_fd,(char *)msg_recv,sizeof(struct Msg));
if (msg_recv->cmd==2)
{
qian();
send2(c_fd,(char *)msg_send,sizeof(struct Msg));
}
else if (msg_recv->cmd==3)
{
hou();
send2(c_fd,(char *)msg_send,sizeof(struct Msg));
}
else if (msg_recv->cmd==4)
{
msg_recv->cmd=9;
break;
}
else
{
strcpy(msg_send->data,"please output qian or hou or quit");
send2(c_fd,(char *)msg_send,sizeof(struct Msg));
}
}
}
void qjt(int c_fd)//清洁桶模式
{
pthread_t thread1;
pthread_t thread2;
struct Msg *msg_send;
struct Msg *msg_recv;
msg_send = (struct Msg *)malloc(sizeof(struct Msg));
msg_recv = (struct Msg *)malloc(sizeof(struct Msg));
memset(msg_send,0,sizeof(struct Msg));
memset(msg_recv,0,sizeof(struct Msg));
strcpy(msg_send->data,"please output qian or hou or quit");
send2(c_fd,(char *)msg_send,sizeof(struct Msg));
pthread_create(&thread1,NULL,(void *)oled,NULL);
pthread_create(&thread2,NULL,(void *)sg,NULL);
while(1)
{
memset(msg_send,0,sizeof(struct Msg));
memset(msg_recv,0,sizeof(struct Msg));
printf("1111\n");
recv2(c_fd,(char *)msg_recv,sizeof(struct Msg));
printf("1111\n");
if (msg_recv->cmd==FTP_CMD_QUIT)
{
msg_recv->cmd=9;
o=0;
break;
}
}
}
void chuli(struct Msg * get_cmd,int c_fd)
{
switch(get_cmd->cmd)
{
case FTP_CMD_YD:
yd(c_fd);
break;
case FTP_CMD_QJT:
qjt(c_fd);
break;
default:
break;
}
}
int main()
{
int s_fd;
int c_fd;
int ret;
int ret2;
struct sockaddr_in s_addr;
struct sockaddr_in c_addr;
struct Msg *msg_send;
struct Msg *msg_recv;
msg_send = (struct Msg *)malloc(sizeof(struct Msg));
msg_recv = (struct Msg *)malloc(sizeof(struct Msg));
memset(msg_send,0,sizeof(struct Msg));
memset(msg_recv,0,sizeof(struct Msg));
pthread_t thread;
logcreate("./server.txt");
//1.socket
s_fd=socket(AF_INET,SOCK_STREAM,0);
if(s_fd==-1)
{
logwrite("perror bind: %s",s_fd);
exit(-1);
}
int on=1;
if((setsockopt(s_fd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on)))<0)
{
perror("setsockopt failed");
exit(EXIT_FAILURE);
}
//2.bind
s_addr.sin_family=AF_INET;
s_addr.sin_port=htons(8989);
s_addr.sin_addr.s_addr=htonl(INADDR_ANY);
ret=bind(s_fd,(struct sockaddr*)&s_addr,sizeof(struct sockaddr_in));
if (ret==-1)
{
logwrite("perror bind: %s",ret);
exit(-1);
}
//3.listen
ret2=listen(s_fd,10);
if (ret2==-1)
{
logwrite("perror listen: %s",ret2);
exit(-1);
}
//4.accpet
int len=sizeof(struct sockaddr);
c_fd=accept(s_fd,(struct sockaddr*)&c_addr, (socklen_t *)&len);
if (c_fd==-1)
{
logwrite("perror accpet: %s",c_fd);
exit(-1);
}
struct password *dl;
dl=malloc(sizeof(struct password ));
char name[64];
char passw[64];
recv2(c_fd,(char *)dl,sizeof(struct password));
printf("%s %s\n",dl->name,dl->pass);
dl->cmd=FTP_CMD_YD;
logwrite("nmae:%s pass%s\n",dl->name,dl->pass);
FILE *fd=fopen("passw.txt","r");
if (NULL!=fd)
{
fscanf(fd,"%s %s",name,passw);
fclose(fd);
}
if (strcmp(name,dl->name)!=0||strcmp(passw,dl->pass)!=0)
{
dl->cmd=FTP_CMD_ERROR;
}
send2(c_fd,(char *)dl,sizeof(struct password));
if (dl->cmd==FTP_CMD_ERROR)
{
exit(-1);
}
initoled();//初始化
qingping();
initcsb();
initdj();
initsg();
pthread_create(&thread,NULL,(void *)csb,NULL);
while(1)
{
memset(msg_send,0,sizeof(struct Msg));
memset(msg_recv,0,sizeof(struct Msg));
recv2(c_fd,(char *)msg_recv,sizeof(struct Msg));
chuli(msg_recv,c_fd);
strcpy(msg_send->data,"please output yd or qjt ");
send2(c_fd,(char *)msg_send,sizeof(struct Msg));
if (msg_recv->cmd==FTP_CMD_QUIT)
{
printf("client quit\n");
logwrite("client quit\n");
break;
}
}
close(s_fd);
logout();
return 0;
}
整套程序通过用户登录服务端,服务端接收指令来对垃圾桶进行操作。
感想
这个项目做了三天,三天来最大的问题在与一开始对于每个模块的不熟悉,以及网上对这些模块资料的不多,大多数都是用python写的C的资料较少,必须通过更多的实验来了解这些模块,还有就是对于线程的一些不熟悉导致有些问题会不能迅速解决,但幸好有日志,可以通过日志迅速的了解问题出在哪,在改程序的时候省下了不少时间。