STM32开发——感应垃圾桶(舵机、超声波测距、振动检测)

目录

1.项目需求

2.sg90舵机介绍及实战

3.声波测距

4.感应垃圾桶

4.1GPIO口设置

4.2代码实现


1.项目需求

  • 检测靠近时,垃圾桶自动开盖并伴随滴一声,2秒后关盖
  • 发生震动时,垃圾桶自动开盖并伴随滴一声,2秒后关盖
  • 按下按键时,垃圾桶自动开盖并伴随滴一声,2秒后关盖

STM32开发——感应垃圾桶(舵机、超声波测距、振动检测)_第1张图片

2.sg90舵机介绍及实战

STM32开发——感应垃圾桶(舵机、超声波测距、振动检测)_第2张图片

PWM波的频率不能太高,大约50HZ,即周期=1/频率=1/50=0.02s,20ms左右。

确定  定时时间=1/频率


其中:
Tclk:定时器的输入时钟频率(单位MHZ)
Tout:定时器溢出时间(单位为us)
.TIM_Period = arr; eg;4999
.TIM_Prescaler = psc; eg:7199
Tout = ((4999+1)×(7199+1))/72000000 = 0.5s = 500ms

如果周期为20ms,则 PSC=7199,ARR=199

角度控制

  • 0.5ms-------------0度; 2.5% 对应函数中CCRx为5
  • 1.0ms------------45度; 5.0% 对应函数中CCRx为10
  • 1.5ms------------90度; 7.5% 对应函数中CCRx为15
  • 2.0ms-----------135度; 10.0% 对应函数中CCRx为20
  • 2.5ms-----------180度; 12.5% 对应函数中CCRx为25

需求:
每隔1s,转动一个角度:0度 --> 45度 --> 90度 --> 135度 --> 180度 --> 0度

main函数代码

  while (1)
  {
    /* USER CODE END WHILE */
		__HAL_TIM_SetCompare(&htim4, TIM_CHANNEL_3, 5);
		HAL_Delay(1000);
		__HAL_TIM_SetCompare(&htim4, TIM_CHANNEL_3, 10);
		HAL_Delay(1000);
		__HAL_TIM_SetCompare(&htim4, TIM_CHANNEL_3, 15);
		HAL_Delay(1000);
		__HAL_TIM_SetCompare(&htim4, TIM_CHANNEL_3, 20);
		HAL_Delay(1000);
		__HAL_TIM_SetCompare(&htim4, TIM_CHANNEL_3, 25);
		HAL_Delay(1000);
    /* USER CODE BEGIN 3 */
  }

记得在定时器初始化后产生PWM波

HAL_TIM_PWM_Start(&htim4,TIM_CHANNEL_3);  //放在在定时器初始化后

3.声波测距

STM32开发——感应垃圾桶(舵机、超声波测距、振动检测)_第3张图片

  • 怎么让它发送波

Trig ,给Trig端口至少10us的高电平

  • 怎么知道它开始发了

Echo信号,由低电平跳转到高电平,表示开始发送波

  • 怎么知道接收了返回波

Echo,由高电平跳转回低电平,表示波回来了

  • 怎么算时间

Echo引脚维持高电平的时间!
波发出去的那一下,开始启动定时器
波回来的拿一下,我们开始停止定时器,计算出中间经过多少时间

  • 怎么算距离

距离 = 速度 (340m/s)* 时间/2

STM32开发——感应垃圾桶(舵机、超声波测距、振动检测)_第4张图片

 需求:
使用超声波测距,当手离传感器距离小于5cm时,LED1点亮,否则保持不亮状态。

STM32开发——感应垃圾桶(舵机、超声波测距、振动检测)_第5张图片

STM32中HAL库没有定时10us的函数,用定时器封装一个us的延时函数。

定时器配置:
使用 TIM2 ,只用作计数功能,不用作定时。
将 PSC 配置为71,则计数 1 次代表 1us 。

STM32开发——感应垃圾桶(舵机、超声波测距、振动检测)_第6张图片

 编写微秒级函数:

//使用TIM2来做us级延时函数
void TIM2_Delay_us(uint16_t n_us)
{
/* 使能定时器2计数 */
__HAL_TIM_ENABLE(&htim2);
__HAL_TIM_SetCounter(&htim2, 0);
while(__HAL_TIM_GetCounter(&htim2) < ((1 * n_us)-1) );
/* 关闭定时器2计数 */
__HAL_TIM_DISABLE(&htim2);
}

编程思路

//1. Trig ,给Trig端口至少10us的高电平
//2. echo由低电平跳转到高电平,表示开始发送波
//波发出去的那一下,开始启动定时器
//3. 由高电平跳转回低电平,表示波回来了 //波回来的那一下,我们开始停止定时器
//4. 计算出中间经过多少时间
//5. 距离 = 速度 (340m/s)* 时间/2(计数1次表示1us)
//每500毫秒测试一次距离

计算距离的子函数

float sound_range(void)   //返回个距离?
{
	uint16_t cnt;
	//1. Trig ,给Trig端口至少10us的高电平
	HAL_GPIO_WritePin(GPIOB,GPIO_PIN_6,GPIO_PIN_SET);
	delay_us(15);
	HAL_GPIO_WritePin(GPIOB,GPIO_PIN_6,GPIO_PIN_RESET);
	//2. echo由低电平跳转到高电平,表示开始发送波
	//波发出去的那一下,开始启动定时器
	while(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_7) == GPIO_PIN_RESET);	
	__HAL_TIM_SetCounter(&htim2,0);  //定时器计数记得复位  运行了,感觉要不要都可以
	HAL_TIM_Base_Start(&htim2);    //也可以用启动定时器函数__HAL_TIM_ENABLE(&htim2) 后面用disable
	
	//3. 由高电平跳转回低电平,表示波回来 //波回来的那一下,我们始停止定时器
	while(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_7) == GPIO_PIN_SET);
	HAL_TIM_Base_Stop(&htim2);
	//4. 计算出中间经过多少时
	cnt=__HAL_TIM_GetCounter(&htim2);
	//5. 距离 = 速度 340m/s* 时间/2(计1次表1us
	return (340*cnt*0.000001/2*100);  //返回的是cm
	
}	

主函数的代码

float distance;

while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
		distance=sound_range();      //获得距离
		if(distance<5)               //根据距离进行不同操作
			HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_RESET);
		else
			HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_SET);
		
		HAL_Delay(500);
  }

4.感应垃圾桶

项目需求:

  • 超声波感应到物体靠近,打开垃圾桶(蜂鸣器响一下)(舵机到一定角度)物体移开1s后关闭(蜂鸣器响一下)
  • 按键后打开垃圾桶(蜂鸣器响一下)(舵机到一定角度)2s后关闭(蜂鸣器响一下)
  • 震动后打开垃圾桶(蜂鸣器响一下)(舵机到一定角度)2s后关闭(蜂鸣器响一下)

超声波模块:  用定时器2
Trig      --    PB6    (发出10us低)
Echo    -- PB7    (低到高到低)
PA4用于超声波模块中断(低电平触发中断)
无限遥控按键(433M):(变为高电平)
D0(A按键)-- PA1(中断)
震动传感器:(发出低电平)
D0 -- PB5(中断)
VCC -- 5V


sg90舵机:  用定时器4
PWM -- PB9     (有效电平为高)
LED灯:(需要低电平)
LED1 -- PB8
蜂鸣器:(低电平响)
IO -- PB4
VCC -- 3V3

4.1GPIO口设置

STM32开发——感应垃圾桶(舵机、超声波测距、振动检测)_第7张图片

4.2代码实现

 中断中使用延时函数(放在定时器初始化后)

HAL_NVIC_SetPriority(SysTick_IRQn,0,0);

定时器4初始化后产生PWM波(放在定时器初始化后)

HAL_TIM_PWM_Start(&htim4,TIM_CHANNEL_4); 

中断服务函数

void TIM2_Delay_us(uint16_t n_us)
{
/* 使能定时器2计数 */
__HAL_TIM_ENABLE(&htim2);
__HAL_TIM_SetCounter(&htim2, 0);
while(__HAL_TIM_GetCounter(&htim2) < ((1 * n_us)-1) );
/* 关闭定时器2计数 */
__HAL_TIM_DISABLE(&htim2);
}

float sound_range(void)   //返回个距离?
{
	uint16_t cnt;
	//1. Trig ,给Trig端口至少10us的高电平
	HAL_GPIO_WritePin(GPIOB,GPIO_PIN_6,GPIO_PIN_SET);
	TIM2_Delay_us(15);
	HAL_GPIO_WritePin(GPIOB,GPIO_PIN_6,GPIO_PIN_RESET);
	//2. echo由低电平跳转到高电平,表示开始发送波
	//波发出去的那一下,开始启动定时器
	while(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_7) == GPIO_PIN_RESET);	
	__HAL_TIM_SetCounter(&htim2,0);  //定时器计数记得复位  运行了,感觉要不要都可以
	HAL_TIM_Base_Start(&htim2);    //也可以用启动定时器函数__HAL_TIM_ENABLE(&htim2) 后面用disable
	
	//3. 由高电平跳转回低电平,表示波回来 //波回来的那一下,我们始停止定时器
	while(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_7) == GPIO_PIN_SET);
	HAL_TIM_Base_Stop(&htim2);
	//4. 计算出中间经过多少时
	cnt=__HAL_TIM_GetCounter(&htim2);
	//5. 距离 = 速度 340m/s* 时间/2(计1次表1us
	return (340*cnt*0.000001/2*100);  //返回的是cm
	
}	

//重写外部中断服务函数
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
	switch(GPIO_Pin){
			
		case (GPIO_PIN_4): 
			HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_RESET);
			HAL_Delay(500);
			HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_SET);

			HAL_GPIO_WritePin(GPIOB,GPIO_PIN_4,GPIO_PIN_RESET); //蜂鸣器响一声
			HAL_Delay(500);
			HAL_GPIO_WritePin(GPIOB,GPIO_PIN_4,GPIO_PIN_SET); //蜂鸣器关
			__HAL_TIM_SetCompare(&htim4, TIM_CHANNEL_4, 25);   //打开舵机90度
			HAL_Delay(2000);
			__HAL_TIM_SetCompare(&htim4, TIM_CHANNEL_4, 5);   //关闭舵机0度
			break;
		case (GPIO_PIN_1): 
			HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_RESET);
			HAL_Delay(500);
			HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_SET);
			HAL_GPIO_WritePin(GPIOB,GPIO_PIN_4,GPIO_PIN_RESET); //蜂鸣器响一声
			HAL_Delay(500);
			HAL_GPIO_WritePin(GPIOB,GPIO_PIN_4,GPIO_PIN_SET); //蜂鸣器关
			__HAL_TIM_SetCompare(&htim4, TIM_CHANNEL_4, 25);   //打开舵机90度
			HAL_Delay(2000);
			__HAL_TIM_SetCompare(&htim4, TIM_CHANNEL_4, 5);   //关闭舵机0度
			break;	
		case (GPIO_PIN_5):   
			HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_RESET);
			HAL_Delay(500);
			HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_SET);
			HAL_GPIO_WritePin(GPIOB,GPIO_PIN_4,GPIO_PIN_RESET); //蜂鸣器响一声
			HAL_Delay(500);
			HAL_GPIO_WritePin(GPIOB,GPIO_PIN_4,GPIO_PIN_SET); //蜂鸣器关
			__HAL_TIM_SetCompare(&htim4, TIM_CHANNEL_4, 25);   //打开舵机90度
			HAL_Delay(2000);
			__HAL_TIM_SetCompare(&htim4, TIM_CHANNEL_4, 5);   //关闭舵机0度
			break;	
	}
}

main函数

float distance;

HAL_NVIC_SetPriority(SysTick_IRQn,0,0);

HAL_TIM_PWM_Start(&htim4,TIM_CHANNEL_4); 

while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
		//1.距离小于5cm进入中断
		distance=sound_range();      //获得距离
		if(distance<5){               //如果距离小于5cm,拉低PA4进入中断
			HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4,GPIO_PIN_SET);
			HAL_Delay(5);
			HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4,GPIO_PIN_RESET);	
		}
		//2.无限遥控按键(433M):D0(A按键)-(PA1变为高电平)//- 进入中断
		//3.震动传感器:(发出低电平)---PB5变为低电平----进入中断

		//__HAL_TIM_SetCompare(&htim4, TIM_CHANNEL_4, 25);   //关闭舵机0度
		HAL_Delay(500);
  }

你可能感兴趣的:(#,STM32开发,嵌入式开发,stm32,单片机,嵌入式硬件)