基于Linux全志H3开发板的智能垃圾桶

一、功能要求

功能需求:
靠近时,垃圾桶开启2秒,2秒后关闭
垃圾桶开启带滴滴声
垃圾桶开启超过10秒,滴滴声警报
垃圾桶长期开启不能让舵机有顿挫感 (尚未解决)
语音控制垃圾桶开关盖
拓展需求:回顾二阶段的Socket编程,实现Sockect客户端发送指令远程打开/关闭垃圾桶,并打印出垃圾桶状态

二、开发环境

1、准备电子器件:

Orangepi Zero2 全志H616开发板,超声波模块,蜂鸣器,舵机sg90,语音模块SU-03T

2,使用软件:

MobaXterm_Personal_20.3(命令控制终端控制开发板)

3、配置

语音模块的配置如下图,按照官网步骤检测配置通过即可语音模块唤醒词

控制命令
语音控制命令通过串口发送数据,O对应ASCII码数据79,C对应67,A对应65

4、引脚分配

通过输入gpio readall可以查看开发板上的所有引脚图
开发板所有引脚分配图
全部模块vcc接5v,gnd接gnd,!!!除了蜂鸣器vcc接3.3v
语音模块:b7接开发板的RXD.5 wPi 4口
蜂鸣器:I/O接开发板的 wPi 7口
舵机:PWM接开发板的wPi 5口
超声波:Trig 接开发板的wPi 0口,Echo 接开发板的wPi 1口

5、环境变量

添加环境变量命令 export PATH=$PATH:(你想要添加的环境变量路径),
我添加的环境变量路径因为里面有自用需包含头文件的 uartTool.h,如果下列操作编译不通过可能没有这个头文件,或者有其他库没安装。

6、编译运行

(1)服务运行端rubbinTest.c
先编译,编译rubbinTest.c 和 uartTool.h通过,没通过,看编译报警
gcc rubbinTest.c uartTool.c -lwiringPi -lwiringPiDev -lpthread -lm -lcrypt -lrt

运行(sudo是用户超级权限,./a.out是运行程序,/dev/ttyS5是串口,127.0.0.1 是本地可用ip,8989是端口号)
sudo ./a.out /dev/ttyS5 127.0.0.1 8989

(2)socket控制端clientTest.c
先编译,gcc clientTest.c -o client
编程出运行程序名字叫client

运行
./client 127.0.0.1 8989

三、代码

rubbinTest.c文件的代码

#include <stdio.h>
#include <string.h>
#include <wiringPi.h>
#include <sys/time.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <pthread.h>			//线程
#include <sys/types.h>			//socket
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include "uartTool.h"

#define BEEP 7   //设置7针脚为蜂鸣器控制引脚
#define Trig 0
#define Echo 1
#define SG90Pin 5

int fd;
int jd = 0;
double distance;
int jd_bak;
char get_cmd;

/******socket所需变量**************/
char readBuf[128];
static int c_fd;
int n_read;

int fdPipe[2];
//int pid;
char buf[128];

/********************/
static int i 			= 0;
static int openCnt 		= 0;
static int openUart 	= 0;
static int openSocket 	= 0;
static int j 			= 0;

/***********服务器指令控制****************/
char get_cmd_type(char *get_cmd)
{
	if(strstr(get_cmd,"open")  !=NULL) 	        return 'O';
	if(strstr(get_cmd,"close") !=NULL)       	return 'C';
	if(strstr(get_cmd,"alarm") !=NULL)          return 'A';

	return 'E';//error
}

void* mysocket_cmd()
{

	while(1){
    //  memset(buffer,'\0',sizeof(buffer));
    //  serialGetstring(fd, buffer);
      memset(readBuf,0,sizeof(readBuf));
      n_read = read(c_fd,readBuf,128);
      if(n_read == -1){
              perror("read");
	  }else{
           printf("\n read get:%s\n",readBuf);
           get_cmd = get_cmd_type(readBuf);
	  }

        printf("socket GET->0x%c\n",get_cmd);
        switch(get_cmd){
            case 'O':
                printf("open\n");
                openSocket = 1;
				close(fdPipe[0]);//无名管道,用于进程间通信
    			write(fdPipe[1],&openSocket,sizeof(int));
    		//	wait();
                break;
            case 'C':
                printf("close\n");
                if(distance < 10.00){
                    openSocket = 1;
                }else{
                    openSocket = 0;
                }
				close(fdPipe[0]);//无名管道,用于进程间通信
               	write(fdPipe[1],&openSocket,sizeof(int));
              //  wait();
                break;
            case 'A':
                printf("alarm\n");
                break;
            default :
                printf("input cmd error!\n");
        }
    }
	
}

/*********串口部分语音控制部分************/
void* readSerial()
{
    char cmd;
    while(1){
    //  memset(buffer,'\0',sizeof(buffer));
    //  serialGetstring(fd, buffer);
        cmd = myserialGetchar (fd);
        printf("uart GET->0x%c\n",cmd);
        switch(cmd){
            case 'y'://测试过程有问题,暂时把'O'改成'y'
                printf("open\n");
				openUart = 1;
                break;
            case 'g'://测试过程有问题,暂时把'C'改成'y'
                printf("close\n");
				if(distance < 10.00){
					openUart = 1;
				}else{
					openUart = 0;
				}
                break;
           /* case 'A':
                printf("alarm\n");
                break;*///测试过程有问题先注释掉
			default :
				printf("input cmd error!\n");
        }
    }
}

/********蜂鸣器部分***********/
int beepInit(void)
{
    pinMode (BEEP, OUTPUT) ;//设置io口输入输出,输出
    return 0;
}

void beepOn(void)
{
    digitalWrite (BEEP, LOW) ;  // low输出低电平,蜂鸣器响
}

void beepOff(void)
{
    digitalWrite (BEEP, HIGH) ;  // high输出高电平,蜂鸣器不响
}

/********超声波部分*************/
void csbInit()
{
    pinMode(Trig, OUTPUT);
    pinMode(Echo, INPUT);
}

double getDistance()
{
    double dis;
    struct timeval start;
    struct timeval stop;
//  pinMode(Trig, OUTPUT);
//  pinMode(Echo, INPUT);

    digitalWrite(Trig ,LOW);
    usleep(5);
    digitalWrite(Trig ,HIGH);
    usleep(10);
    digitalWrite(Trig ,LOW);

    /*above init CSB*/
//    printf("%d\n",j++);
    while(!digitalRead(Echo));
//    printf("%d\n",j++);
    gettimeofday(&start,NULL);
    while(digitalRead(Echo));
//    printf("%d\n",j++);
    gettimeofday(&stop,NULL);
    long diffTime = 1000000*(stop.tv_sec-start.tv_sec)+(stop.tv_usec -
            start.tv_usec);
    printf("diffTime = %ld us\n",diffTime);
    dis = (double)diffTime/1000000 * 34000 / 2;

    return dis;
}

void *csb()
{
	 while(1){
        usleep(500000);
        distance = getDistance();
        printf("distance = %lf cm\n",distance);
 	}	
}

/************舵机部分************/
void signal_handler(int signum)
{
    if(i <= jd){
        digitalWrite(SG90Pin, HIGH);
    }else{
        digitalWrite(SG90Pin, LOW);
    }
    if(i == 40){
        i = 0;
    }
    i++;
}

int sg90Init(void)
{
    struct itimerval itv;
    jd = 1;
//  wiringPiSetup();
    pinMode(SG90Pin, OUTPUT);

    //设定定时时间
    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)){
        perror("error");
        exit(-1);
    }
    //信号处理
    signal(SIGALRM,signal_handler);
}

void openRubbin()
{
	jd = 3;
	if(jd_bak != jd){
		i = 0;
		beepOn();usleep(200000);
		beepOff();usleep(100000);
		beepOn();usleep(200000);
		beepOff();
	}
	jd_bak = jd;
	usleep(50000);
}	

void closeRubbin()
{
	jd = 1;
	if(jd_bak != jd){
		beepOn();usleep(200000);
		beepOff();
	}
	jd_bak = jd;
	usleep(50000);
}

void *sg90()
{
	while(1){
		usleep(20000);
		
//		memset(buf,0,sizeof(buf));

 		if(distance < 10.00 | openUart == 1 | openSocket == 1){
            printf("jd: 3-90 开盖 \n");
            openRubbin();//转动90度,开盖
            sleep(2);
			openUart = 0;  openSocket = 0;
			openCnt++;
			if(openCnt == 5){
				while(1){
					beepOn();usleep(200000);
		        	beepOff();usleep(100000);
					if(distance > 10.00) break;
				}
			}
        }else{
			//printf("jd: 1-0 关盖 \n");
            closeRubbin();//转动0度,关盖
			openCnt = 0;
        }
	}
	
}

void * type_change()
{
	while(1){
		usleep(500000);
		memset(buf,0,sizeof(buf));
		close(fdPipe[1]);
        read(fdPipe[0],buf,128);
        openSocket = (int) buf[0];
	}
}

int deviceInit(char deviceName[32])
{
	int ret;
//    char deviceName[32] = {'\0'};//串口名称

    pthread_t readt;
    pthread_t csb1;
    pthread_t sg90_2;
	pthread_t type_change_t;

/*     if(argc <2){
        printf("uage:%s /dev/ttyS?\n",argv[0]);
        return -1;
    }

    strcpy(deviceName, argv[1]);*/

    if( (fd = myserialOpen(deviceName,115200)) == -1){
        printf("open %s error\n",deviceName);
        return -1;
    }

    wiringPiSetup () ;//初始化wiringpi库

    beepInit();
    csbInit();
    sg90Init();
//  csbInit();
    sleep(1);

    ret = pthread_create(&readt,NULL ,readSerial, (void *)0);
    ret = pthread_create(&csb1,NULL,csb,(void *)0);
    ret = pthread_create(&sg90_2,NULL,sg90,(void *)0);	
	ret = pthread_create(&type_change_t,NULL,type_change,(void *)0);
}

/************socket服务器在mian函数运行**********/
/*****运行格式sudo ./a.out /dev/ttyS5 可用IP地址 可用端口号*******/
int main (int argc,char **argv)
{
	int s_fd;
//    int c_fd;
//    int n_read;
//    char readBuf[128];//已放置全局变量

//  char *msg = "I get your connect";
    int mark = 0;
    char msg[128] = {0};
    struct sockaddr_in s_addr;
    struct sockaddr_in c_addr;
	char deviceName[32] = {'\0'};//串口名称

	if(argc <4){//对应上述运行条件四个参
        printf("uage:%s /dev/ttyS? Or Ip and Port is not well\n",argv[0]);
        return -1;
    }

	strcpy(deviceName, argv[1]);
	deviceInit(deviceName);

	memset(&s_addr,0,sizeof(struct sockaddr_in));
    memset(&c_addr,0,sizeof(struct sockaddr_in));

	//1.socket
    s_fd = socket(AF_INET,SOCK_STREAM,0);
    if(s_fd == -1){
        perror("socket");
        exit(-1);
    }

    s_addr.sin_family = AF_INET;
    s_addr.sin_port = htons( atoi(argv[3]) );//duan kou hao ,fan wei 5000-9999
    inet_aton(argv[2],&s_addr.sin_addr);

    //2.bind
    bind(s_fd,(struct sockaddr *)&s_addr,sizeof(struct sockaddr_in));

    //3.listen
    listen(s_fd,10);

    //4.accept
    int clen = sizeof(struct sockaddr_in);
    while(1){

        c_fd = accept(s_fd,(struct sockaddr *)&c_addr,&clen);
        if(c_fd == -1){
            perror("accept");
        }

        mark++;

        printf("connnect\n");
        printf("get connect: %s\n",inet_ntoa(c_addr.sin_addr));

		pipe(fdPipe);

        if(fork() == 0){
			pthread_t socket_cmd;
			 pthread_create(&socket_cmd,NULL ,mysocket_cmd, (void *)0);

            if(fork() == 0){
                while(1){
                sprintf(msg,"welcom No.%d client",mark);
                write(c_fd,msg,strlen(msg));
                sleep(10);
                }
            }


			 //5.read
           /* while(1){
                memset(readBuf,0,sizeof(readBuf));
                n_read = read(c_fd,readBuf,128);
                if(n_read == -1){
                    perror("read");
                }else{
                    printf("\nget:%s\n",readBuf);
					get_cmd = get_cmd_type(readBuf);
                }
            }*/
            //6.write

         //   break;
        }

    }

    return 0;
}

uartTool.c的代码,创建uartTool.h文件里需对.c文件进行函数声明,并且按照上述添加环境变量(最好添加在工程文件目录下)

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdarg.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>

#include "wiringSerial.h"

char myserialGetchar (const int fd)//获取一个字符
{
  char x ;

  if (read (fd, &x, 1) != 1)
    return -1 ;

  return x ;
}


int myserialOpen(const char *device, const int baud)//串口打开,第一个参哪个串口,第二个参波特率
{
	struct termios options ;
  	speed_t myBaud ;
  	int     status, fd ;

	switch (baud){
		 case    9600:	myBaud =    B9600 ; break ;
		 case  115200:	myBaud =  B115200 ; break ;
	}

	if ((fd = open (device, O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK)) == -1)
    return -1 ;

	fcntl (fd, F_SETFL, O_RDWR) ;

// Get and modify current options:

  	tcgetattr (fd, &options) ;

    cfmakeraw   (&options) ;
    cfsetispeed (&options, myBaud) ;
    cfsetospeed (&options, myBaud) ;

    options.c_cflag |= (CLOCAL | CREAD) ;
    options.c_cflag &= ~PARENB ;
    options.c_cflag &= ~CSTOPB ;
    options.c_cflag &= ~CSIZE ;
    options.c_cflag |= CS8 ;
    options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG) ;
    options.c_oflag &= ~OPOST ;

    options.c_cc [VMIN]  =   0 ;
    options.c_cc [VTIME] = 100 ;	// Ten seconds (100 deciseconds)

 	tcsetattr (fd, TCSANOW, &options) ;

  	ioctl (fd, TIOCMGET, &status);

  	status |= TIOCM_DTR ;
  	status |= TIOCM_RTS ;

  	ioctl (fd, TIOCMSET, &status);

  	usleep (10000) ;	// 10mS

  	return fd ;
	
}

void serialSendstring (const int fd, const char *s)//发送字符串
{
	int ret;
	ret = write (fd, s, strlen (s));
	if (ret < 0)
		printf("Serial Puts Error\n");
}

int serialGetstring (const int fd,char *buffer)//获取字符串
{
	int n_read;

	n_read = read(fd,buffer,32);
	
	return n_read;
}

控制端clientTest.c,运行时对应ip和端口号

#include <stdio.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
//#include <linux/in.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

int main(int argc,char **argv)
{
	int c_fd;
	int n_read;
	char readBuf[128];

//	char *msg = "msg from client";
	char msg[128] = {0};
	struct sockaddr_in c_addr;

	 if(argc != 3){
                printf("param is not good\n");
                exit(-1);
        }
	
	memset(&c_addr,0,sizeof(struct sockaddr_in));

	//1.socket
	c_fd = socket(AF_INET,SOCK_STREAM,0);
	if(c_fd == -1){
		perror("socket");
		exit(-1);
	}

	c_addr.sin_family = AF_INET;
	c_addr.sin_port = htons( atoi(argv[2]) );//duan kou hao ,fan wei 5000-9999
	inet_aton(argv[1],&c_addr.sin_addr);

	//2.connect
        if( connect(c_fd,(struct sockaddr *)&c_addr,sizeof(struct sockaddr)) == -1){
		perror("connect");
		exit(-1);
	}

	while(1){
		if(fork() == 0){
			while(1){
			memset(msg,0,sizeof(msg));
			printf("input:");
			fgets(msg, 128, stdin);
			write(c_fd,msg,strlen(msg));
			}
		}
		while(1){
		memset(readBuf,0,sizeof(readBuf));
		 n_read = read(c_fd,readBuf,128);
       		 if(n_read == -1){
          	      perror("read");
       		 }else{
        	        printf("get message from sever:%d,%s\n",n_read,readBuf);
	        }
		}
	}

	//3.send
//	write(c_fd,msg,strlen(msg));
	

	//4.read

	
	return 0;
}

四、视频展示

Linux智能垃圾桶小项目

五、作品心得

历时5天的小项目一步一步终于在调试过程做了出来,作品是在学习过程中做出来的,难免有些bug还没有解决,作品也仅供大家参考学习。有兴趣的可以一起学习和讨论如何继续修改开发,喜欢的点个赞吧!
阅读终点,创作起航,您可以撰写心得或摘录文章要点写篇博文。去创作
  • 5
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
全志H3开发板底板设计是指针对全志H3芯片进行的底层电路设计和布局。底板设计是开发板的核心部分,它决定了开发板的功能拓展性、稳定性和可靠性。 在全志H3开发板底板设计中,需要考虑以下几个主要方面: 1. 电源供电:针对H3芯片及外围器件的供电需求,设计合适的电源电路,保证电源的稳定性和可靠性。同时,还需考虑电源滤波和短路保护等问题。 2. 视频输出:对于H3支持的视频输出接口(如HDMI、VGA等),需要进行信号转换和驱动电路设计,保证视频信号的稳定输出。 3. 存储器接口:根据H3芯片支持的存储器接口类型(如NAND Flash、eMMC等),设计相应的接口电路,使开发板能够支持外部存储器的读写。 4. 扩展接口:为了满足开发板的功能拓展需求,需要设计合适的扩展接口(如GPIO、SPI、I2C等),用于与其他模块进行通信和连接。 5. 网络接口:根据H3芯片支持的网络接口类型(如以太网、WiFi等),设计相应的接口电路,以实现开发板的网络通信功能。 6. 时钟电路:设计合理的时钟电路,为H3芯片及外围器件提供稳定的时钟信号。 总之,全志H3开发板底板设计旨在充分发挥H3芯片的性能和功能,并满足开发板的各项要求。通过合理的电路设计和布局,能够保证开发板的稳定性和可靠性,为开发者提供一个可靠的硬件平台,方便进行软件开发和调试。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

听雨眠、

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值