STM32传感器模块编程实践(十四)DIY语音+满溢检测智能垃圾桶模型

文章目录

一.概要

随着科技的飞速发展和环保意识的日益增强,智能垃圾桶成为了城市生活的新宠,智能垃圾桶人们无需接触垃圾桶的任何部位即可投放垃圾,防止交叉感染,环保卫生,外形雅观。

本文就做一个智能感应垃圾桶套件模型,采用STM32F103C8T6单片机+舵机+超声波模块+红外模块+语音,实现有物体靠近,垃圾桶自动开启,没有物体靠近,一定时间后自动合上,并实现语音播报以及满溢检测。

二.实验模型原理

1.硬件连接原理框图

模型主要分为五部分:主芯片单元,测距感应单元,执行动作单元,语音播报单元,满溢检测单元。

图中主控芯片为STM32F103C8T6单片机,测距传感器为超声波模块,执行传感器为SG90舵机,语音播报单元为MP3语音播放模块,满溢检测单元为红外激光测距检测。

信号线连接:HC-SR04超声波模块信号脚ECHO脚接到单片机的PA0脚,TRIG脚接到单片机的PA1脚。SG90(180度)舵机的信号脚橙色线接到单片机的PA6脚。MP3语音播放模块接单片机的串口PA9,PA10引脚。红外激光测距模块接单片机的模拟IIC通讯引脚PB12,PB13以及PB7引脚。

2.控制原理

超声波模块根据声音的反射原理,对前方的障碍物进行测距。如果没有障碍物,或者障碍物距离>=5CM,单片机驱动舵机转到0度,如果检测到障碍物距离小于5CM,单片机驱动舵机旋转到180度,打开垃圾桶盖子。

超声波测距原理:

以上时序图表明单片机只需要提供一个10uS以上脉冲触发信号给模块的TRIG引脚,超声波模块内部将发出8个40kHz周期电平并检测回波。模块一旦检测到有回波信号则输出回响信号到模块ECHO引脚。回响信号的脉冲宽度与所测的距离成正比。单片机通过采集收到的输出回响信号的宽度时间就可以计算得到距离。

距离公式:距离=回响高电平时间*声速(340M/S)/2

舵机控制原理:

SG90舵机,首先,控制引脚是三根线,分别是GND(棕色)、VCC(红色)、PWM(黄色),控制方式也是一样的PWM时序,具体的方法如下:

(1)采用PWM控制的方式来进行舵机的旋转

(2)舵机的控制需要MCU产生一个20ms周期的脉冲信号,以0.5ms到2.5ms的高电平来控制舵机的角度。

(3)高电平时间跟舵机旋转的角度对应关系:

0.5ms-------------0度;对应函数中占空比为2.5%

1.0ms------------45度;对应函数中占空比为5.0%

1.5ms------------90度;对应函数中占空比为7.5%

2.0ms-----------135度;对应函数中占空比为10.0%

2.5ms-----------180度;对应函数中占空比为12.5%

语音播报原理:

MP3语音播放模块采用MP3主控芯片,支持MP3、WAV格式双解码,模拟U盘下载。模块内置FLASH存储芯片。支持 UART 异步串口控制:支持播放、暂停、上下曲、音量加减、选曲播放、插播等。我们预先通过USB口存储3段MP3语音播报到语音模块,通过STM32单片机控制语音模块进行指定语音播放。

通讯协议采用标准串口,3.3V TTL 电平,波特率9600,播放协议如下:

满溢检测原理:

通过红外激光模块装在垃圾桶顶部区域,单片机通过IIC总线与红外模块进行通讯,读取检测到的距离值,红外激光模块通过光线的反射原理,用来测量障碍物的距离,如果障碍物的距离比较小,说明垃圾桶满了。

三.实验模型控制流程

1.单片机先通过PA0脚驱动超声波模块,模块返回ECHO信号进行测距,超声波模块根据声音的反射原理,对前方的障碍物进行测距。如果没有障碍物,或者障碍物距离>=10CM,单片机不驱动舵机进行动作。

2.单片机一直通过PA0脚驱动超声波模块,模块返回ECHO信号进行测距,如果障碍物距离<10CM,单片机通过PA6引脚输出20ms周期的PWM波。PWM波高电平脉冲时间为2.5ms,这样舵机就会旋转180度,从而带动垃圾桶的盖打开,单片机同时通过串口发送指令给语音模块,发出垃圾桶打开语音,如果障碍物距离一直小于10CM,垃圾桶保持打开状态不变。单片机同时驱动红外激光模块测距,如果距离小于8CM,说明垃圾桶顶部被东西覆盖,垃圾桶已经满了。

3.单片机一直通过PA0脚驱动超声波模块,模块返回ECHO信号进行测距,如果障碍物距离>=10CM,单片机通过PA6引脚输出20ms周期。PWM波高电平脉冲时间为0.5ms,这样舵机就回到0度,从而带动垃圾桶的盖闭合,单片机同时通过串口发送指令给语音模块,发出闭合语音。

四.智能感应垃圾桶模型程序

复制代码
板子与超声波模块用杜邦线连接:
板子G-----模块GND
板子3.3---模块VCC
板子A0----模块Trig
板子A1----模块Echo

板子与SG90舵机(180度舵机)用杜邦线连接:
板子5V----红色线
板子A6----橙色线
板子G-----棕色线



板子与红外激光测距模块用杜邦线连接:
板子3.3V----VIN
板子B12----SCL
板子B13----SDA
板子B7------XSHUT
板子G-------GND

USB线需要接小系统板,给STM32板子供5V, 板子与语音模块直接相连。

打开STM32CubeMX软件,新建工程

Part Number处输入STM32F103C8,再双击就创建新的工程

配置下载口引脚

配置外部晶振引脚

配置系统主频

配置PA0为输出,PA1为输入,PA1管脚选择下拉

配置定时器2,10us产生中断一次,用来统计后续采集超声波返回的脉冲宽度时间

配置PWM输出,定时器3通道1,周期20ms

配置串口1,9600波特率,PA9为发送,PA10为接收

配置工程文件名,保存路径,KEIL5工程输出方式

生成工程

用Keil5打开工程

添加代码

添加红外激光代码:

添加舵机控制与超声波检测以及语音播报代码:

添加满溢检测代码:

主要程序:

c 复制代码
//超声波测距,通过检测脉冲时间测试距离
uint32_t Distance_Calculate(uint32_t count)//传入时间单位10us
{
    uint32_t Distance = 0;
    Distance = (uint32_t)(((float)count *17)/100);//距离单位cm,声速340M/S,时间*速度/2=距离
    return Distance;
}
//等待us级别
void Delay_us(unsigned long i)
{
	unsigned long j;
	for(;i>0;i--)
	{
			for(j=8;j>0;j--);
	}
}
//发送播放指令语音指令
void MY1690_Appoint_ID_SendCMD(uint16_t	ID)
{	
	uint8_t H_ID;
	uint8_t	L_ID;
	
	uint8_t MY1690_Appoint_ID[7]; //播放 //根据协议不使用这条。
	uint8_t i = 0;
	
	H_ID = (ID >>8)&0xff;
	L_ID = ID&0xff;
	MY1690_Appoint_ID[i++] = 0x7E;
	MY1690_Appoint_ID[i++] = 0x05;
	MY1690_Appoint_ID[i++] = 0x41;
	MY1690_Appoint_ID[i++] = H_ID;
	MY1690_Appoint_ID[i++] = L_ID;
	MY1690_Appoint_ID[i++] = Xor_Valid(&MY1690_Appoint_ID[1],MY1690_Appoint_ID[1]-1);
	MY1690_Appoint_ID[i++] = 0xEF;
	MY1690_SendCMD(MY1690_Appoint_ID);
}
int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_TIM3_Init();
  MX_TIM2_Init();
  MX_USART1_UART_Init();
  /* USER CODE BEGIN 2 */
	
		 while(vl53l0x_init(&vl53l0x_dev))//vl53l0x初始化
	 {	 
		HAL_Delay(500);
	 }
	if (HAL_TIM_Base_Start_IT(&htim2) != HAL_OK)//启动定时器2,10us进入中断一次
 {
	 while(1);
 }
   if (HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1) != HAL_OK)//PA6脚PWM输出
  {
    /* PWM generation Error */
    while(1);
  }
	HAL_Delay(200);//等待200ms
	//以180度角度伺服为例,那么对应的控制关系是这样的(t为高电平时间):
	//t=0.5ms(占空比2.5%)---------0°;
	//t=1.0ms(占空比5%)-----------45°;
	//t=1.5ms(占空比7.5%)---------90°;
	//t=2.0ms(占空比10%)---------135°;
	//t=2.5ms(占空比12.5%)-------180°;
	Pluse_Time=500;//0.5ms高电平脉冲,用于控制舵机转到0度
	HAL_TIM_PWM_Stop(&htim3, TIM_CHANNEL_1);//PWM停止输出
	HAL_Delay(100);//等待100ms
	MX_TIM3_Init();//重新初始化配置PWM波
	if (HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1) != HAL_OK)//PA6脚PWM输出
	{
	/* PWM generation Error */
	while(1);
	}
	HAL_Delay(200);//等待200ms
	HAL_TIM_PWM_Stop(&htim3, TIM_CHANNEL_1);//PWM停止输出	
	OpenFlag=0;//关闭
	vl53l0x_general_Init(&vl53l0x_dev,Default_Mode);//默认模式测试

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */

		HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0,GPIO_PIN_RESET);//预先拉低Trig引脚
		HAL_Delay(5);
		HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0,GPIO_PIN_SET);//拉高Trig引脚
		Delay_us(40);
		HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0,GPIO_PIN_RESET);//拉低Trig引脚
		Delay_us(20);
		while(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_1) == 0);//如果是低电平,一直等
		HalTime1= TimeCounter;
		while(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_1) == 1);//如果是高电平,一直等
		if(TimeCounter>HalTime1)
		{
			HalTime2 = TimeCounter-HalTime1;
			if(HalTime2<0x300)
			{
					 Distance = Distance_Calculate(HalTime2);//计算距离
			}else
			{
				   Distance=100;
			}
		}
		HAL_Delay(100);
		DistanceTimeCounter++;
		if(DistanceTimeCounter>2)//连续监测2次
		{
			DistanceTimeCounter=0;
			
		}else
		{
			if(Distance<=10 && Distance>0)
			{
				DistanceCounter++;
			}
			
			continue;//没到3次,不动作,防止超声波抖动
		}
		
		
		if(DistanceCounter>=2 && OpenFlag==0)//距离小于10CM,说明有手挡住
		{
			MY1690_Appoint_ID_SendCMD(0001); //指定曲目播放//打开垃圾桶语音
			DistanceCounter=0;
  		Pluse_Time=2500;
			HAL_TIM_PWM_Stop(&htim3, TIM_CHANNEL_1);//PWM停止输出
			MX_TIM3_Init();//重新初始化配置PWM波
			if (HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1) != HAL_OK)//PA6脚PWM输出
			{
			while(1);
			}
			HAL_Delay(1000);
			OpenFlag=1;
					
		}else if((Distance>=10 || Distance==0) && OpenFlag==1)
		{
			
			DistanceCounter=0;
			  Pluse_Time=500;//0.5ms高电平脉冲,用于控制舵机转到0度
				if(Old_Pluse_Time!=Pluse_Time)
				{
						MY1690_Appoint_ID_SendCMD(0002); //关闭垃圾桶语音
						HAL_TIM_PWM_Stop(&htim3, TIM_CHANNEL_1);//PWM停止输出
						MX_TIM3_Init();//重新初始化配置PWM波
						HAL_Delay(100);//等待100ms
						if (HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1) != HAL_OK)//PA6脚PWM输出
						{
						/* PWM generation Error */
						while(1);
						}
						HAL_Delay(1000);//等待1000ms
						OpenFlag=0;	
				}			

		}
		
		if(OpenFlag==1)//打开的时候做满检测
		{
			vl53l0x_general_Test(&vl53l0x_dev);
			if(Vl53l0_OK_Flag==1&& vl53l0x_data.RangeMilliMeter<=50)//检测到有效距离,且距离小于5cm,说明满了
			{
				
				Vl53l0_FullFlag++;
				if(Vl53l0_FullFlag>=3)
				{
					MY1690_Appoint_ID_SendCMD(0003); //指定曲目播放//满了满了
				  HAL_Delay(1000);//等待1000ms
				}
			}else
			{
				Vl53l0_FullFlag=0;
			}
		}
		
		Old_Pluse_Time=Pluse_Time;


  }
  /* USER CODE END 3 */
}

五.实验效果视频

基于STM32单片机带语音播报和满溢检测智能垃圾桶模型

六.小结

融合了舵机,超声波模块,语音播报模块,红外激光测距的控制,对STM32的单片机的定时器PWM功能,定时器功能,IIC通讯,串口通讯有更深的了解。