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


    目录

    1.项目需求

    2.sg90舵机介绍及实战

    3.声波测距

    4.感应垃圾桶

    4.1GPIO口设置

    4.2代码实现


    1.项目需求

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

    2.sg90舵机介绍及实战

    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函数代码

    1. while (1)
    2. {
    3. /* USER CODE END WHILE */
    4. __HAL_TIM_SetCompare(&htim4, TIM_CHANNEL_3, 5);
    5. HAL_Delay(1000);
    6. __HAL_TIM_SetCompare(&htim4, TIM_CHANNEL_3, 10);
    7. HAL_Delay(1000);
    8. __HAL_TIM_SetCompare(&htim4, TIM_CHANNEL_3, 15);
    9. HAL_Delay(1000);
    10. __HAL_TIM_SetCompare(&htim4, TIM_CHANNEL_3, 20);
    11. HAL_Delay(1000);
    12. __HAL_TIM_SetCompare(&htim4, TIM_CHANNEL_3, 25);
    13. HAL_Delay(1000);
    14. /* USER CODE BEGIN 3 */
    15. }

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

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

    3.声波测距

    • 怎么让它发送波

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

    • 怎么知道它开始发了

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

    • 怎么知道接收了返回波

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

    • 怎么算时间

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

    • 怎么算距离

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

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

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

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

     编写微秒级函数:

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

    编程思路

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

    计算距离的子函数

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

    主函数的代码

    1. float distance;
    2. while (1)
    3. {
    4. /* USER CODE END WHILE */
    5. /* USER CODE BEGIN 3 */
    6. distance=sound_range(); //获得距离
    7. if(distance<5) //根据距离进行不同操作
    8. HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_RESET);
    9. else
    10. HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_SET);
    11. HAL_Delay(500);
    12. }

    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口设置

    4.2代码实现

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

    HAL_NVIC_SetPriority(SysTick_IRQn,0,0);

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

    HAL_TIM_PWM_Start(&htim4,TIM_CHANNEL_4); 

    中断服务函数

    1. void TIM2_Delay_us(uint16_t n_us)
    2. {
    3. /* 使能定时器2计数 */
    4. __HAL_TIM_ENABLE(&htim2);
    5. __HAL_TIM_SetCounter(&htim2, 0);
    6. while(__HAL_TIM_GetCounter(&htim2) < ((1 * n_us)-1) );
    7. /* 关闭定时器2计数 */
    8. __HAL_TIM_DISABLE(&htim2);
    9. }
    10. float sound_range(void) //返回个距离?
    11. {
    12. uint16_t cnt;
    13. //1. Trig ,给Trig端口至少10us的高电平
    14. HAL_GPIO_WritePin(GPIOB,GPIO_PIN_6,GPIO_PIN_SET);
    15. TIM2_Delay_us(15);
    16. HAL_GPIO_WritePin(GPIOB,GPIO_PIN_6,GPIO_PIN_RESET);
    17. //2. echo由低电平跳转到高电平,表示开始发送波
    18. //波发出去的那一下,开始启动定时器
    19. while(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_7) == GPIO_PIN_RESET);
    20. __HAL_TIM_SetCounter(&htim2,0); //定时器计数记得复位 运行了,感觉要不要都可以
    21. HAL_TIM_Base_Start(&htim2); //也可以用启动定时器函数__HAL_TIM_ENABLE(&htim2) 后面用disable
    22. //3. 由高电平跳转回低电平,表示波回来 //波回来的那一下,我们始停止定时器
    23. while(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_7) == GPIO_PIN_SET);
    24. HAL_TIM_Base_Stop(&htim2);
    25. //4. 计算出中间经过多少时
    26. cnt=__HAL_TIM_GetCounter(&htim2);
    27. //5. 距离 = 速度 340m/s* 时间/2(计1次表1us
    28. return (340*cnt*0.000001/2*100); //返回的是cm
    29. }
    30. //重写外部中断服务函数
    31. void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
    32. {
    33. switch(GPIO_Pin){
    34. case (GPIO_PIN_4):
    35. HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_RESET);
    36. HAL_Delay(500);
    37. HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_SET);
    38. HAL_GPIO_WritePin(GPIOB,GPIO_PIN_4,GPIO_PIN_RESET); //蜂鸣器响一声
    39. HAL_Delay(500);
    40. HAL_GPIO_WritePin(GPIOB,GPIO_PIN_4,GPIO_PIN_SET); //蜂鸣器关
    41. __HAL_TIM_SetCompare(&htim4, TIM_CHANNEL_4, 25); //打开舵机90度
    42. HAL_Delay(2000);
    43. __HAL_TIM_SetCompare(&htim4, TIM_CHANNEL_4, 5); //关闭舵机0度
    44. break;
    45. case (GPIO_PIN_1):
    46. HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_RESET);
    47. HAL_Delay(500);
    48. HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_SET);
    49. HAL_GPIO_WritePin(GPIOB,GPIO_PIN_4,GPIO_PIN_RESET); //蜂鸣器响一声
    50. HAL_Delay(500);
    51. HAL_GPIO_WritePin(GPIOB,GPIO_PIN_4,GPIO_PIN_SET); //蜂鸣器关
    52. __HAL_TIM_SetCompare(&htim4, TIM_CHANNEL_4, 25); //打开舵机90度
    53. HAL_Delay(2000);
    54. __HAL_TIM_SetCompare(&htim4, TIM_CHANNEL_4, 5); //关闭舵机0度
    55. break;
    56. case (GPIO_PIN_5):
    57. HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_RESET);
    58. HAL_Delay(500);
    59. HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_SET);
    60. HAL_GPIO_WritePin(GPIOB,GPIO_PIN_4,GPIO_PIN_RESET); //蜂鸣器响一声
    61. HAL_Delay(500);
    62. HAL_GPIO_WritePin(GPIOB,GPIO_PIN_4,GPIO_PIN_SET); //蜂鸣器关
    63. __HAL_TIM_SetCompare(&htim4, TIM_CHANNEL_4, 25); //打开舵机90度
    64. HAL_Delay(2000);
    65. __HAL_TIM_SetCompare(&htim4, TIM_CHANNEL_4, 5); //关闭舵机0度
    66. break;
    67. }
    68. }

    main函数

    1. float distance;
    2. HAL_NVIC_SetPriority(SysTick_IRQn,0,0);
    3. HAL_TIM_PWM_Start(&htim4,TIM_CHANNEL_4);
    4. while (1)
    5. {
    6. /* USER CODE END WHILE */
    7. /* USER CODE BEGIN 3 */
    8. //1.距离小于5cm进入中断
    9. distance=sound_range(); //获得距离
    10. if(distance<5){ //如果距离小于5cm,拉低PA4进入中断
    11. HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4,GPIO_PIN_SET);
    12. HAL_Delay(5);
    13. HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4,GPIO_PIN_RESET);
    14. }
    15. //2.无限遥控按键(433M):D0(A按键)-(PA1变为高电平)//- 进入中断
    16. //3.震动传感器:(发出低电平)---PB5变为低电平----进入中断
    17. //__HAL_TIM_SetCompare(&htim4, TIM_CHANNEL_4, 25); //关闭舵机0度
    18. HAL_Delay(500);
    19. }

  • 相关阅读:
    基础篇-基本架构
    lammps数据后处理:python绘制应力应变曲线 附程序代码
    【华为机试真题 JAVA】火星文计算-100
    JVM_JVM启动参数及堆内存分布及GC触发条件
    uboot 启动流程详细分析参考
    目标检测——day 53 Concealed Object Detection
    515. 在每个树行中找最大值
    网络标准之:IANA定义的传输编码
    input 输入框限制只能输入两位小数正数
    跑步时戴什么耳机好、分享五款最适合跑步的运动耳机排名清单
  • 原文地址:https://blog.csdn.net/m0_67794575/article/details/131101026