基于树莓派的智能垃圾桶

基于树莓派的智能垃圾桶项目

预计所需要实现的功能
通过感应能够实现垃圾桶盖子的自动开关。
垃圾桶上装载OLED屏,屏幕上需要显示,温度,时间。
远程控制通过电脑端实现控制垃圾桶的移动。

功能模块:
1树莓派3B开发板一块
2OLED显示屏一块
3超声波模块
4SG90舵机
5直流电机,轮子,电机驱动板
6清洁桶

关于各种树莓派API可以查看

https://www.cnblogs.com/lulipro/p/5992172.html

程序代码:
服务端程序(写在树莓派上的)

include <stdio.h>
#include <netinet/in.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <pthread.h>
#include <wiringPi.h>
#include "oled.h"
#include "log.h"
#include "chao.h"
#include "xiao.h"
#define echo 27
#define trlg 28
float distant;

#define RANGE 200  // 1 means 100 us , 200 means 20 ms
                   // 1等于100微妙,200等于20毫秒
void a_open() {
    softPwmWrite(3, 5);  //将pwm输出复写为使舵机转到0
    delay(100);
}
void b_open() {
    softPwmWrite(3, 15);
    delay(100);
    softPwmWrite(3, 15);
}

void *chaoshenbo() {

    while (1) {
        distant = wiring_distance();
        if (distant < 10) {
             a_open();
             b_open();
        }
         printf("distance=%.2f\n", distant);
    }
    return NULL;
}
int main(int a, char *avg[]) {
    int sock;
    int c_fd;
    pthread_t t1;
    pthread_t t2;
    pthread_t t3;
    softPwmCreate(3, 15, RANGE);

    wiringPiSetup();
    wiring_init();
    che_init();
    struct Msg *rec = (struct Msg *)malloc(sizeof(struct Msg));
    log_creat();
    sock = socket(AF_INET, SOCK_STREAM, 0);
    if (sock == -1) {
        perror("socker failed:\n");
        exit(-1);
    }
    struct sockaddr_in addr1;
    memset(&addr1, 0, sizeof(addr1));
    addr1.sin_family = AF_INET;
    addr1.sin_port = htons(atoi(avg[1]));
    inet_aton("192.168.43.215", &addr1.sin_addr);
    int on = 1;
    setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
    int len = sizeof(struct sockaddr_in);
    bind(sock, (struct sockaddr *)&addr1, sizeof(struct sockaddr_in));
    listen(sock, 10);
    c_fd = accept(sock, (struct sockaddr *)&addr1, &len);
    if (c_fd == -1) {
        printf("accept failed\n");
        exit(-1);
    }
    char *c = (char *)malloc(32);

    printf("connect success/n");
    pthread_create(&t1, NULL, &oled_display, NULL);
    pthread_create(&t2, NULL, chaoshenbo, NULL);

    while (1) {
        int ret = recv(c_fd, c, 1, 0);
        printf("ret=%d\n", ret);
        printf("%c\n", *c);
        xiaochequdon(c);
    }
    pthread_join(t1, NULL);
    pthread_join(t2, NULL);
    return 0;
}

OLED模块程序

#include <time.h>
#include <wiringPi.h>
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include <wiringPiI2C.h>
#include"oled.h"
int fd;
unsigned char yi[4][16] = {
    "                ",  //第一行
    "                ",  //第二行
    "                ",  //第三行
    " made in zcc    "   //第四行
};                       //显示内容
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[1], 16, "%R %p", ptr);     //时:分 am或pm
}
void ipdisplay() {                                           **//用于获得当前设备的ip地址**

    FILE* fp;
    char str[64];
    fp = popen("ifconfig wlan0|grep \"inet\"|awk '{print $2}'", "r");
    if (NULL == fp) {
        printf("-1");
        exit(-1);
    }
    fscanf(fp, "%s", str);
    strcpy(yi[2], str);

    fclose(fp);
}
void wendu() {                                       **这里使用DS18B20温湿度传感器测量温度,具体操作可以 参考   
                                               https://blog.csdn.net/weixuedianzi/article/details/65935296  **
    FILE* fp;
    char str[64];
    char tmp[64];
    fp = fopen("/sys/bus/w1/devices/28-0315977961f4/w1_slave",
               "r");  //以只读方式打开ds18b20设备文件

    if (NULL == fp) {
        printf("wendu fopen failed\n");
        exit(-1);
    }

    while (fscanf(fp, "%s", str) != EOF)
        ;

    strtok(str, "=");
    char* p = strtok(NULL, "\n");

    float temp = (float)atoi(p) / 1000;
    sprintf(tmp, "%f", temp);
    strcpy(yi[0], tmp);
}



void* oled_display(void* arg)
{
    init();
    qingping();
    while (1) {
        shijian();
        wendu();
        ipdisplay();
        ascii();
        delay(100);
    }
    return NULL;
}

超声波模块这里使用的是HC-SR04

#include <wiringPi.h>
#include <stdio.h>
#include <sys/time.h>

#define Trig 28
#define Echo 27

void wiring_init(void) {
    wiringPiSetup();                 //初始化树莓派的引脚
    pinMode(Echo, INPUT);             //设置某个引脚的是输入还是输出模式
    pinMode(Trig, OUTPUT);
}

float wiring_distance(void) {
    struct timeval tv1;
    struct timeval tv2;
    long start, stop;
    float dis;

    digitalWrite(Trig, LOW);      //digitalWrite这里是给引脚一个低电平
    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;
}


小车驱动程序,这里由于树莓派没有带直流电机的驱动程序,所以使用了L9110S桥两路直流电机驱动板程序如下

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

//定义接口宏
#define PWM1A 22
#define LUN1 23
#define PWM2A 24
#define LUN2 25

//初始化
void che_init() {
      
    softPwmCreate(LUN1, 0, 100);    //softPwmCreat创建一个pwm波从既定引脚输出
    softPwmCreate(LUN2, 0, 100);
    softPwmCreate(PWM1A, 0, 100);
    softPwmCreate(PWM2A, 0, 100);
    printf("soft pwm create successfully..\n");
}

void go_head() {
    softPwmWrite(PWM1A, 70);
    softPwmWrite(LUN1, 0);
    softPwmWrite(PWM2A, 70);
    softPwmWrite(LUN2, 0);
}
void go_back() {
    softPwmWrite(PWM1A, 0);
    softPwmWrite(LUN1, 70);
    softPwmWrite(PWM2A, 0);
    softPwmWrite(LUN2, 70);
}
void go_left() {
    softPwmWrite(PWM1A, 30);
    softPwmWrite(LUN1, 0);
    softPwmWrite(PWM2A, 70);
    softPwmWrite(LUN2, 0);
}
void go_right() {
    softPwmWrite(PWM1A, 70);
    softPwmWrite(LUN1, 0);
    softPwmWrite(PWM2A, 30);
    softPwmWrite(LUN2, 0);
}
void go_quit()
{
    softPwmWrite(PWM1A, 0);
    softPwmWrite(LUN1, 0);
    softPwmWrite(PWM2A, 0);
    softPwmWrite(LUN2, 0);
}

void xiaochequdon(char* p) {                              //通过键盘输入控制方向

        switch (*p) {
            case 'w':
                go_head();
                break;
            case 's':
                go_back();
                break;
            case 'a':
                go_left();
                break;
            case 'd':
                go_right();
                break;
            case 'q':
                go_quit();
                break;
            default:
                break;
        }
        
}

客户端程序

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

int main(int a, char *avg[]) {
    int s_fd;
    int c_fd;
    log_creat();
    char readbuf[128];
    struct sockaddr_in addr1;

    s_fd = socket(AF_INET, SOCK_STREAM, 0);      //配置套接字
    if (s_fd == -1) {
        perror("socker failed:\n");
        exit(-1);
    }

    memset(&addr1, 0, sizeof(addr1));
    addr1.sin_family = AF_INET;
    addr1.sin_port = htons(atoi(avg[1]));
    //   addr1.sin_addr.s_addr = htonl(INADDR_ANY);
    inet_aton("192.168.43.215", &addr1.sin_addr);
    if(connect(s_fd,(struct sockaddr*)&addr1,sizeof(struct sockaddr_in))==-1)
    {
        printf("failed\n");
        exit(-1);
    }
    printf("connect success\n");
    char* c=(char*)malloc(32);
    while(1){                                             //通过网络控制树莓派
        printf("int put \n");
        scanf("%c",c);
        int ret=send(s_fd,c,1,0);
        printf("ret=%d",ret);
        ffplush(stdin);
    //    while(!getchar()=='\0');
    }
    return 0;
}


おすすめ

転載: blog.csdn.net/qq_42014326/article/details/100549107