C语言基于树莓派开发的智能清洁桶

今天是老师催稿的最后一天,由于上课时间冲突,没有把博文写完,今天在这补个博文,这个博文会持续更新,因为目前的项目我还没有改完整,所以后续会补上。
首先,我们用到的器件有如下几个:
树莓派Pi3、DS18B20温湿度传感器、L9110S桥两路直流电机驱动板、两个马达、两个轮子、HC-SR04超声波模块、SG90舵机、0.91‘Oled。
以下为服务端代码代码:

#include "oled.h"				//oled.h文件包含了所有的需要用到的器件的驱动代码
#include <time.h>
#include <wiringPi.h>
#include <wiringPiI2C.h>
#include <unistd.h>
#include <stdio.h>
#include "log.h"
#include <sys/socket.h>
//#include <linux/in.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <string.h>
#include "msg.h"
#include <pthread.h>
#include "char.h"

int g_running;
    
void handle_cmd(struct Msg *in_cmd,struct Msg *out_cmd){
    out_cmd->cmd = in_cmd->cmd;

    switch(in_cmd->cmd){
        case FTP_CMD_QUIT:
            g_running = 0;
            Write("recv command: quit\n");
            //exit(0);
            break;
        case FTP_CMD_GO:					
        
            digitalWrite(21,0);
            digitalWrite(22,1);
            digitalWrite(23,0);
            digitalWrite(24,1);

            Write("recv command: go\n");
            break;
        case FTP_CMD_BACK:
            digitalWrite(21,1);
            digitalWrite(22,0);
            digitalWrite(23,1);
            digitalWrite(24,0);

            Write("recv command: back\n");
            break;
        //case FTP_CMD_TEMPTURE:           
        //    pthread_create(&poled,NULL,(void *)oled,NULL);
            //oled();
        //    Write("recv command: tempture\n");
        //    break;
        case FTP_CMD_STOP:
            digitalWrite(21,1);
            digitalWrite(22,1);
            digitalWrite(23,1);
            digitalWrite(24,1);

            Write("recv command: stop\n");
            break;
         case FTP_CMD_LEFT:
            digitalWrite(21,0);
            digitalWrite(22,1);
            digitalWrite(23,1);
            digitalWrite(24,1);

            Write("recv command: left\n");
            break;
         case FTP_CMD_RIGHT:
            digitalWrite(21,1);
            digitalWrite(22,1);
            digitalWrite(23,0);
            digitalWrite(24,1);

            Write("recv command: right\n");
            break;
        default:
            Write("command is not right\n");
            break;
    }
}

int main(int argc, char const *argv[])
{
    wiringPiSetup();						//程序一运行,先初始化

    pinMode(21,OUTPUT);				//设置引脚
    pinMode(22,OUTPUT);
    pinMode(23,OUTPUT);
    pinMode(24,OUTPUT);
    
    pinMode(1,PWM_OUTPUT);			//设置引脚1为脉冲输出信号
    pwmSetMode(PWM_MODE_MS);
    pwmSetRange(2500);              //设置脉冲周期
    pwmSetClock(192);					//默认为192,可不写

    struct Msg *send_msg = NULL;
    struct Msg *recv_msg = NULL;

    send_msg = (struct Msg *)malloc(sizeof(struct Msg));
    recv_msg = (struct Msg *)malloc(sizeof(struct Msg));
   
    int s_fd;
    int c_fd;
    int ret;
    struct sockaddr_in s_addr;
    struct sockaddr_in c_addr;
    pthread_t ac;
    pthread_t poled;
    pthread_create(&poled,NULL,(void *)oled,NULL);			//运行线程,此时所有的功能都在这个线程里运行,其实这样根本没有用到客户端,但是因为时间比较短,暂时先写成这样,后续修改。

    Create("./server.txt");
    
    //1 socket
    s_fd = socket(AF_INET,SOCK_STREAM,0);
    if(s_fd == -1){
        Write("socket failed\n");
        exit(-1);
    }

    //2 bind
    memset(&c_addr,0,sizeof(struct sockaddr_in));
    s_addr.sin_family = AF_INET;
    s_addr.sin_port = htons(8990);
    s_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    ret = bind(s_fd,(struct sockaddr *)&s_addr,sizeof(struct sockaddr));
    if(ret < 0){
        Write("bind error %d\n",ret);
        return -1;
    }

    //3 listen
    if(listen(s_fd,10)== -1){
        Write("listen failed\n");
        exit(-1);
    }

    //4 accept
    socklen_t clen = sizeof(struct sockaddr);
    c_fd =accept(s_fd,(struct sockaddr *)&c_addr,&clen);
        if(c_fd == -1){
            Write("accept error\n");
            exit(-1);
        }
        Write("Get connect:%s\n", inet_ntoa(c_addr.sin_addr));
   
    struct Auth auth;
    ret = recv_handle(c_fd,(char *)&auth,sizeof(struct Auth));
    Write("recd ret %d %s %s\n",ret,auth.username,auth.password);

    struct Auth server;
    FILE *fp = fopen("psw","r");
    if(fp != NULL ){
        fscanf(fp,"%s %s",server.username,server.password);
        Write("server %s %s\n",server.username,server.password);
        fclose(fp);
    }

    if(0 != memcmp(auth.username,server.username,strlen(server.username)) ||
        0 != memcmp(auth.password,server.password,strlen(server.password))){
        auth.cmd = FTP_CMD_ERROR;
        Write("auth falied\n");
    }

    ret =send_handle(c_fd,(char *)&auth,sizeof(struct Auth));
    Write("send ret %d\n",ret);

    memset(auth.username,0,sizeof(auth.username));
    memset(auth.password,0,sizeof(auth.password));
    memset(server.username,0,sizeof(server.username));
    memset(server.password,0,sizeof(server.password));

    if(FTP_CMD_ERROR == auth.cmd){
        return -1;
    }

    //5 recv
    //memset(readBuf,0,sizeof(readBuf));
    g_running = 1;
    while(1){
    memset(send_msg,0,sizeof(struct Msg));
    memset(recv_msg,0,sizeof(struct Msg));
        //ret = recv(c_fd,recv_msg,sizeof(struct Msg),0);
        ret = recv_handle(c_fd,(char *)recv_msg,sizeof(struct Msg));
        if(ret == -1){
            Write("recv error\n");
            exit(-1);
        }
        if(FTP_CMD_QUIT == recv_msg->cmd){
            printf("server quit\n");
            exit(-1);
        }

        handle_cmd(recv_msg,send_msg);

        //6 send
        //send_handle(c_fd,send_msg->data,send_msg->data_length);
        //ret = send(c_fd,send_msg,sizeof(struct Msg),0);
        ret = send_handle(c_fd,(char *)send_msg,sizeof(struct Msg));
        Write("send ret %d\n",ret);

    }
    Destroy();

   return 0;
}

oled.c部分代码:

#include "temperature.h"
#include <time.h>
#include <wiringPi.h>
#include <wiringPiI2C.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>

#define Echo 29
#define Trig 28

int fd;

void  UltrasonicInit(){				//初始化超声波引脚和设置引脚1的脉冲信号
        pinMode(Trig,OUTPUT);				
        pinMode(Echo,INPUT);

        pinMode(1,PWM_OUTPUT);
        pwmSetMode(PWM_MODE_MS);
        pwmSetRange(2500);
        pwmSetClock(192);
}

float Distance(){					//超声波测距的代码
        struct timeval tv1;
        struct timeval tv2;
        long start;
        long stop;
        float dis;

        digitalWrite(Trig,LOW);
        delayMicroseconds(2);

        digitalWrite(Trig,HIGH);
        delayMicroseconds(10);
        digitalWrite(Trig,LOW);

        while(!(digitalRead(Echo) == 1));
        gettimeofday(&tv1,NULL);

        while(!(digitalRead(Echo) == 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;

        return dis; 
}

unsigned char yi[4][16] = {"     C       Ray",  //第一行
                           "                ",  //第二行
                           "                ",  //第三行
                           "IP:192.168.43.86"   //第四行
};                                              //显示内容

const unsigned char zi[];

void init(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);  //开显示
}

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 shijian(void)  //当前时间
{
    struct tm *ptr;
    time_t lt;
    lt = time(&lt);
    ptr = localtime(&lt);
    strftime(yi[1], 16, "%m/%d %a", ptr);  //月/日 周几
    strftime(yi[2], 16, "%R %p", ptr);     //时:分 am或pm
}

void oled(){
    float c;
    float dis;
    char pstr[20];
    
    init();
    UltrasonicInit();
    qingping();

    digitalWrite(21,0);			//程序一调用,先让轮子跑起来
    digitalWrite(22,1);
    digitalWrite(23,0);
    digitalWrite(24,1);

    while (1) {

        dis = Distance();		//然后调用Distance函数测距
        printf("Distance:%0.2f cm\n",dis);

        if(dis < 10){							//如果距离小于10cm,给四个引脚置高电平,轮子停止运转,
                digitalWrite(21,1);
                digitalWrite(22,1);
                digitalWrite(23,1);
                digitalWrite(24,1);
        
                pwmWrite(1,50);					//向舵机发送脉冲信号,角度调到0度,然后延迟一段时间再把角度转到180
                delay(1000);
                pwmWrite(1,250);

                c = Temperature();				//调用检测温度函数,获取温度数据
                gcvt(c,3,pstr);					//把单精度转成字符型
                strcpy(yi[0],pstr);				//把温度数据拷入yi字符数组,输出到屏幕上
                shijian();
                ascii();
                printf("Temperature: %s C\n",pstr);		
        }else{			//如果不是上面的情况,就让轮子一直转
                digitalWrite(21,0);
                digitalWrite(22,1);
                digitalWrite(23,0);
                digitalWrite(24,1);
        }
    }
}

temperature代码:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <dirent.h>
#include <string.h>
#include <time.h>
float value;

float Temperature() {
    char path[50] = "/sys/bus/w1/devices/";
    char rom[20];
    char buf[100];
    DIR *dirp;
    struct dirent *direntp;
    int fd = -1;
    char *temp;

    system("sudo modprobe w1-gpio");
    system("sudo modprobe w1-therm");

    if ((dirp = opendir(path)) == NULL) {
        printf("opendir error\n");
        return -1;
    }

    while ((direntp = readdir(dirp)) != NULL) {
        if (strstr(direntp->d_name, "28-03169779636a")) {
            strcpy(rom, direntp->d_name);
            osedir(dirp);
            strcat(path, rom);
            strcat(path, "/w1_slave");

                if ((fd = open(path, O_RDONLY)) < 0) {
                    printf("open error\n");
                    return -1;
                    if (read(fd, buf, sizeof(buf)) < 0) {
                        printf("read error\n");
                        return -1;
                    }
                    temp = strchr(buf, 't');
                    sscanf(temp, "t=%s", temp);
                    value = atof(temp) / 1000;
                    // printf("Temperature: %0.1f\n",value);
                    // sleep(3);
                    return value;
                }
        }
    }
}

代码实现的大概效果:程序一运行,轮子就会不停地砖,直到检测到有障碍物靠近10厘米内,轮子会停止转动,舵机会打开一段时间然后关闭。
今天比较仓促,代码就先改到这里,中间有遇到一个问题是加入多个线程之后运行客户端时服务端会出现段错误,找了半天不知道在哪,个人估计是两个线程在运行时争夺某个共同的资源时产生了冲突,因为这个问题我去掉了多线程,所以我改成了所有的功能都写在了一个.c文件下,后面持续调改。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值