基于合泰HT32F52352的智慧垃圾桶总结



文章目录

  • 基于合泰HT32F52352的智慧垃圾桶总结
  • 前言
  • 一、HT32智慧垃圾桶介绍
  • 1.1 功能介绍
  • 1.2 简单流程图和原理图
  • 二、硬件模块
  • 2.1 外设硬件
  • 2.2 所遇问题
  • 三、工程部分代码
  • 四、总结



实物图

ESP32 开机按键设计_ESP32 开机按键设计

前言

历经几个月的合泰杯比赛已经落下了帷幕,今天官方网站也发布了相关的获奖名单,很幸运得了一个三等奖,虽然不是很好的成绩,对于初次参加的我来说已经很满足了。
本篇内容分享一下我做的智慧垃圾桶的过程,以及自己在整个过程遇到的一些问题,希望可以帮助到准备合泰杯比赛的小伙伴。


相关的资料链接我都放这里了需要的小伙伴可以自行下载

链接:https://pan.baidu.com/s/1T5hdpYP5vEHSN5gdbjV0Ng?pwd=lkqt 
提取码:lkqt 
--来自百度网盘超级会员V4的分享
gitHub链接
https://github.com/FDForerver/HT32F52352

ESP32 开机按键设计_数据_02

ESP32 开机按键设计_数据_03

一、HT32智慧垃圾桶介绍

1.1 功能介绍

1.通过Esp8266wifi模块将实时检测到的温湿度数据、下雨情况、火灾情况等数据上传到Onenet云平台
2.通过onenet云平台远程控制不同垃圾桶的状态以及灯光控制
3.通过简易按键控制不同垃圾桶的状态
4.通过红外模块实时检测当前环境下是否发生火灾,发生火灾发出相应的警报
5.通过雨滴传感器实时检测当前环境的天气状态,是否下雨在下雨情况下自动关闭所有未关闭的垃圾桶
6.红外检测是否有人进行垃圾处理,感应到则打开相应的垃圾桶
7.通过语音控制不同垃圾桶的状态以及灯光控制
8.通过温度传感器实时检测当前环境下温度和湿度的值

1.2 简单流程图和原理图

ESP32 开机按键设计_初始化_04

ESP32 开机按键设计_数据_05

二、硬件模块

2.1 外设硬件

1.简易塑制垃圾桶

ESP32 开机按键设计_数据_06

2.esp8266模块

ESP32 开机按键设计_数据_07

3.LD322语音模块

ESP32 开机按键设计_数据_08

4.火焰传感器

ESP32 开机按键设计_数据_09

5.雨滴检测传感器

ESP32 开机按键设计_数据_10

6.红外检测模块

ESP32 开机按键设计_数据_11

2.2 所遇问题

1.打开官方的例程看不懂代码,网上查找资料,几乎找不到自己所需型号的开发代码(只有很少例程代码)
2.所给例程并不想之前所接触32的库函数分模块编写,而是都在主函数中实现,代码太多,太乱。最先想到就是自己整 理一个库函数分模块编写的模板,在此基础之上在进行模块代码的编写
3.在网上下载了一个类似的模版,然后在这个上面先将每一个功能都创建一个文件夹并在文件夹中放入.c .h文件方便移值以及自己查看代码
进行感应开盖控制更换了三种方案
1.超声波实现感应开盖:在进行超声波功能代码编写的时候,是将之前在stm32上面使用的代码进行了简单移值,将所需配置全部改成了HT32所需的格式,在代码执行过程一直卡到了对Echo电平读取哪里(个人肯定的是除了定时配置外其他都没问题,可能对时钟配置不精确),最后感觉代码也没变不过可以接着向下执行了所测的结果很不准(最大显示的是16cm多,并且这才一个超声波,对多个超声波同时测距,相互间的处理也没搞好,放弃了这种方式。
2.使用HC-SR501人体红外感应就行感应垃圾桶的实现:在使用这个模块的过程中所遇问题还是比较少,单个HC-SR501进行感应开盖也是很快就实现了,但我加入多个的时候发现相互间的冲突也挺大的,首先这个模块不像超声波那样是垂直测距这个模块有很大的角度范围都可以进行人体感应,而且距离还挺远的,最终因为相互间的冲突没有完美解决,也放弃了这种方法的实现。
3.红外避障模块:红外避障模块在小车比赛中是经常用到的模块,而且使用的非常简单,就对引脚高低电平的读取,遇到障碍引脚输出低电平(这时可以在这个条件中实现我们想要的功能),而且每个避障模块间的使用相互间没有影响,进行感应开开盖也是那种比较短距离的测试,所遇在实现感应处理功能使用这个模块是相对比较好的一个方案,最后也是使用了4个红外避障模块,功能也是很好的实现了,只是相互间的先后处理同时进行感应有点问题。(毕竟所用的开发板是没有跑操做系统的在多并发这方面功能很不理想,不过对于该功能的单个效果还是很不错的。
pwm调节占空比所遇问题
1.在进行PWM实现的时候我使用的是GPTM定时器,配置了4路PWM的输出,具体pwm引脚的输出可以查看相关的数据手册,都有相应的通道所对应的引脚是哪个。
2.掌握舵机进行PWM调节使用的原理 将每个角度所对应的PWM数据列出来 通过Switch进行参数的选择,进行控制不同的转动角度。
3.遇到的主要问题是:舵机所转动的角度和我们想要实现的功能不相符合,需要进行一个一个的进行调试,找到那个最佳的转动角度。有时候之前调节好了的角度在次烧入的时候转动角度又是乱的了。
4.按键处理问题
在该项目中我使用了三个外部中断进行按键的控制,最开始是想使用轮询的方式进行按键控制,但是在程序运行之后因为不只按键一个功能,其他功能在运行的时候,按键这时候就会出现不灵的现象,最后将其改为了外部中断处理这个问题。

三、工程部分代码

主函数

#include "usart.h"
#include "led.h"
#include "delay.h"
#include "time.h"
#include "dht11.h"
#include "key.h"
#include "fire.h"
#include "buzzer.h"
#include "oled.h"
#include "rain.h"
#include "infrared.h"

//网络
#include "esp8266.h"
//协议设备
#include "onenet.h"

//C包
#include "string.h"


extern uint8_t servo_status;
extern uint8_t light_status ,rain_status ; //灯光 下雨标志
uint8_t trash_flag = 0,trash2_flag = 0,trash3_flag = 0,trash4_flag = 0;; //每个垃圾桶如果是打开的都有个标志数据  默认0关闭
float dis = 0;

/*=============================================oled界面显示===================================*/

//主页面 只刷新一次
void main_interface(void)
{
//		OLED_Clear(0);
//		delay_ms(10);

	
	
//		OLED_ShowCHinese_trash(6,0,0); //智
//		OLED_ShowCHinese_trash(26,0,1);//慧
//		OLED_ShowCHinese_trash(46,0,2);//垃
//		OLED_ShowCHinese_trash(66,0,3);//圾
//		OLED_ShowCHinese_trash(82,0,4);//桶	  
	
	
		OLED_ShowNum(6,3,2022,4,16);
		OLED_ShowCHinese_TWO(40,3,0);//年 
		OLED_ShowNum(50,3,6,2,16);
		OLED_ShowCHinese_TWO(74,3,1);//月 
		OLED_ShowNum(92,3,1,2,16);
		OLED_ShowCHinese_TWO(108,3,2);//日 
}


//温湿度显示
void Temp_humi_display(void)
{
	OLED_Clear(0);
	//以字符串的形式显示
	OLED_ShowString(35,1,(unsigned char *)"C_T:",3); // Current_Temperature 当前温度
	OLED_ShowCHinese_Three(85,0,11); //C
	
	OLED_ShowString(35,3,(unsigned char *)"C_H:",3); // Current_Humidity 当前湿度
	OLED_ShowCHinese_Three(85,2,13); //.
	
	OLED_ShowNum(68,1,T_H/10,3,3);
	OLED_ShowNum(76,1,T_H%10,3,3);
	OLED_ShowNum(68,3,H_H/10,3,3);
	OLED_ShowNum(76,3,T_L%10,3,3);
}


//参数刷新显示
void  oled_data_display(void)
{
	
	OLED_Clear(0);
	//火灾状态
	OLED_ShowString(25,0,(unsigned char *)"fire:",6);
	OLED_ShowNum(65,0,fire_status1,1,8);
	
	OLED_ShowString(25,2,(unsigned char *)"fire:",6);
	OLED_ShowNum(65,2,fire_status2,1,8);
	
	OLED_ShowString(25,4,(unsigned char *)"fire:",6);
	OLED_ShowNum(65,4,fire_status3,1,8);
	
	OLED_ShowString(25,6,(unsigned char *)"fire:",6);
	OLED_ShowNum(65,6,fire_status4,1,8);
	//照明状态
  delay_ms(2000);
	OLED_Clear(0);
	
	OLED_ShowString(25,0,(unsigned char *)"Light:",6);
	OLED_ShowNum(65,0,light_status,1,8);
	//是否下雨
	OLED_ShowString(25,2,(unsigned char *)"rain:",6);
	OLED_ShowNum(65,2,rain_status,1,8);
	//警报状态
	OLED_ShowString(25,4,(unsigned char *)"buzzer:",8);
	OLED_ShowNum(80,4,buzzer_status,1,1);	
	delay_ms(1000);
	
}



void Hardware_Init(void)
{
	
	USART1_Configuration();//打印信息用				//串口1,打印信息用
	
	USART0_Configuration();						//串口2,驱动ESP8266用
	
	Led_Init();        //LED初始化
	dou_dht11_init();   //温度初始化
	GPTM_PWM_init();  //舵机相关初始化
	Key_Init(); //按键初始化
	Init_Fire(); //火焰初始化
	Buzzer_Init(); //蜂鸣器初始化
	Init_Rain(); //雨滴传感器初始化
	Infrared_Init();
	OLED_Init(); //Oled初始化
	
	
	Servo_Run(45);
//	delay_ms(2000);  //调试转动 蓝色
//	Servo_Run(90);
	Servo_Run2(135);
	//	delay_ms(2000); //棕色
//	Servo_Run2(90);
	Servo_Run3(45);
	delay_ms(2000); //黑色
	Servo_Run3(0);
	Servo_Run4(135);
//	delay_ms(2000);  //红色
//	Servo_Run4(180);
	OLED_Clear(0);
	main_interface();
	
	
	//UsartPrintf(USART_DEBUG, " Hardware init OK\r\n");
	
}



int main(void)
 {	

	unsigned char *dataPtr = NULL;
	 
	unsigned short timeCount = 0;	//发送间隔变量
	 
	Hardware_Init();//硬件初始化
	
	 
	ESP8266_Init();					//初始化ESP8266
	 
	//printf("8266_INIT_END\n");
	 
	while(OneNet_DevLink())			//接入OneNET
	delay_ms(500);
	//printf("接入onenet成功");

	while(1) 
	{		
		
  dou_dht11_get_data();
	//	infrared_test();	
	Fire_Test();	
	infrared_test();			
			rain_test();
				
	
		if(++timeCount >= 100)		//时间间隔1s
		{
				
				Temp_humi_display();
				delay_ms(1000);
				oled_data_display();
				delay_ms(1000);
	
		//	printf("hum temp=%d .%d %d .%d\r\n",H_H,H_L,T_H,T_L);
		//	printf("fire1:%d ,fire2:%d ,fire3:%d ,fire4:%d ,buzzer:%d\r\n",fire_status1,fire_status2,fire_status3,fire_status4,buzzer_status);

			
		//	 printf( "OneNet_SendData\r\n");//通过串口1发送提示信息(要开始发送数据了)
					
				OneNet_SendData();//发送数据给onenet
				
			//	printf("send_data_end\n");
				timeCount = 0;
				
				ESP8266_Clear();
		}
		
		dataPtr = ESP8266_GetIPD(0);//获取平台返回的数据
		if(dataPtr != NULL)//如果返回数据不为空
		OneNet_RevPro(dataPtr);//平台返回数据检测		
		delay_ms(10); 	
	}
	
}


/*============================================下雨处理=======================================*/

//先判断是否下雨 ,下雨了再判断垃圾桶是否是打开的 如果打开的则关闭
void rain_test(void)
{
	if(GPIO_Read_rain() == RESET)  //下雨
	{
		rain_status = 1;
		if(trash_flag | trash2_flag | trash3_flag | trash4_flag) //判断垃圾桶是否处于打开状态
		{
			//关闭打开的垃圾桶
			delay_ms(2000);// 延时2s后关闭
			Servo_Run(45);
			Servo_Run2(135);
			Servo_Run3(45);
			Servo_Run4(135);
		}
		
		LED2_ON();
	}
	else{
		LED2_OFF();
		rain_status = 0;
		
	}
}


/*==========================================蓝牙/语音接收处理=================================*/

//使用串口1 进行数据的接收
void COM1_IRQHandler(void)
{
	uint8_t data;
	if( USART_GetFlagStatus(COM1_PORT, USART_FLAG_RXDR) )
	{
		USART_ClearFlag(COM1_PORT, USART_FLAG_RSADD);
		data = USART_ReceiveData(COM1_PORT);
		switch(data)
		{
			case '0':break; //唤醒命令
			//其他垃圾桶控制
			case '1':
			case 'e':
			case 'f':
			case 'g':Servo_Run2(90);delay_ms(3000);Servo_Run2(135);//打开其他垃圾桶	 
			break;
			
			//有害垃圾桶控制
			case '2':
			case '3':
			case '4':Servo_Run4(180);delay_ms(3000);Servo_Run4(135);
			break;
		 
			//可回收垃圾桶控制
			case '5':
			case '7':
			case '8':
			case '9':Servo_Run(90);delay_ms(3000);Servo_Run(45);
			break;
			
			
			//厨余垃圾控制
			case 'a':
			case 'b':
			case 'c':
			case 'd':Servo_Run3(0);delay_ms(3000);Servo_Run3(45);
			break;
			
			
			//灯光控制
			case 'j':LED1_ON();break;
			case 'k':LED1_OFF();break;
			
			//垃圾桶独立控制
			case 'l': Servo_Run(90); break;//打开可回收垃圾
			case 'm':Servo_Run(45);break; //关闭可回收垃圾桶
			
			case 'n': Servo_Run4(180); break;//打开有害收垃圾
			case 'o':Servo_Run4(135);break; //关闭有害收垃圾桶
			
			case 'p':Servo_Run3(0); break;//打开厨余收垃圾
			case 'q':Servo_Run3(45);break; //关闭厨余收垃圾桶break;
			
			case 'r':Servo_Run2(90);break;   //打开其他垃圾桶
			case 's':Servo_Run2(135);break;  //关闭其他垃圾桶
			
			case 'h':Servo_Run(90);Servo_Run2(90);Servo_Run3(0);Servo_Run4(180);break;//打开所有垃圾桶
			case 'i':Servo_Run(45);Servo_Run2(135);Servo_Run3(45);Servo_Run4(135);break;//关闭所有垃圾桶
			// 可以加上其他控制功能 
			default:break;
		}	
	}
}


/*=============================================外部中断控制处理=======================================*/
//细节函数局部里面key_stat 定义为static修饰要不然按键第二次无反应

void EXTI4_15_IRQHandler(void)
{
 		static uint8_t key_stat = 0; //按键状态切换
    if(key_stat == 0)
		{
			key_stat = 1;  
			trash_flag = 1; //垃圾桶打开标志
			trash4_flag = 1;
			//LED1_ON();
			Servo_Run(90);
				Servo_Run4(180);
		}
		else if(key_stat == 1)
		{
			key_stat = 0;
			trash_flag = 0; //垃圾桶1关闭
				trash4_flag = 0; //垃圾桶4关闭
			//LED1_OFF();
			Servo_Run(45);
				Servo_Run4(135);
		}
		EXTI_ClearEdgeFlag(EXTI_CHANNEL_4);
}

void EXTI2_3_IRQHandler(void)
{
	static uint8_t key_stat = 0; //按键状态 
	if(key_stat == 0)
		{
			key_stat = 1;
			trash2_flag = 2; //垃圾桶2打开
			//LED2_ON();
			Servo_Run2(90);
		}
		else if(key_stat == 1)
		{
			key_stat = 0;
			trash2_flag = 0; //垃圾桶2关闭
			//LED2_OFF();
			Servo_Run2(135);
		}
		EXTI_ClearEdgeFlag(EXTI_CHANNEL_2);
}



void EXTI0_1_IRQHandler(void)
{
		static uint8_t key_stat = 0;
		if(key_stat == 0)
		{
			key_stat = 1;
			trash3_flag = 1;  //垃圾桶3打开
			
			LED2_ON();
			Servo_Run3(0); //45
		
		}
		else if(key_stat == 1)
		{
			key_stat = 0;
			trash3_flag = 0; //垃圾桶3关闭
		
			//LED2_OFF();
			Servo_Run3(45);
		
		}
		EXTI_ClearEdgeFlag(EXTI_CHANNEL_0);
}

注意

因为子整个工程中使用了多个串口HT32上我只用了两个1个接的esp8266进行数据云端上传,另一个串口接的STM32,语音模块和播报模块接在STM32上面的,STM32收到语音指令后通过串口发送给HT32然后进行功能控制。

四、总结

总的来说,在整个制作过程中学会了很多虽然功能比较简单但通过自己完整做出来还是有成就感的。
遇到问题慢慢来,多尝试、多总结。主函数中各个功能模块的实现大家可以看我HT32专栏的讲解,都有详细记录各个功能的实现。ヾ(◍°∇°◍)ノ゙