传感器模块编程实践(三)舵机+超声波模块融合DIY智能垃圾桶模型

文章目录

一.概要

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

本文就做了一个简单的智能感应垃圾桶套件模型,采用STM32F103C8T6单片机+舵机+超声波模块,实现有物体靠近,垃圾桶自动开启,没有物体靠近,一定时间后自动合上。

二.实验模型原理

1.硬件连接原理框图

模型主要分为三部分:主芯片单元,测距感应单元,执行动作单元。

图中主控芯片为STM32F103C8T6单片机,测距传感器为超声波模块,执行传感器为SG90舵机。

信号线连接:HC-SR04超声波模块信号脚ECHO脚接到单片机的PA0脚,TRIG脚接到单片机的PA1脚。SG90(180度)舵机的信号脚橙色线接到单片机的PA6脚。

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%

三.实验模型控制流程

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

2.单片机一直通过PA0脚驱动超声波模块ECHO信号进行测距,如果障碍物距离<10CM,单片机通过PA6引脚输出20ms周期的PWM波。PWM波高电平脉冲时间为2.5ms,这样舵机就会旋转180度,从而带动垃圾桶的盖打开,如果障碍物距离一直小于10CM,垃圾桶保持打开状态不变。

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

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

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

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

USB线需要接小系统板,给板子供5V。

打开STM32CubeMX软件,新建工程

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

配置下载口引脚

配置外部晶振引脚

配置系统主频

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

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

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

配置工程文件名,保存路径,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--);
	}
}
uint32_t Distance;//距离
uint32_t HalTime1,HalTime2;//时间临时变量
extern volatile uint32_t TimeCounter;//时间计数,单位10us

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
uint16_t Pluse_Time=500,Old_Pluse_Time,DistanceTimeCounter,DistanceCounter;//1毫秒脉冲,单位是us
/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
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();
  /* USER CODE BEGIN 2 */
	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停止输出	
  /* 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)//距离小于10CM,说明有手挡住
		{
			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(50);
			HAL_TIM_PWM_Stop(&htim3, TIM_CHANNEL_1);//PWM停止输出
					
		}else
		{
			DistanceCounter=0;
			  Pluse_Time=500;//0.5ms高电平脉冲,用于控制舵机转到0度
				if(Old_Pluse_Time!=Pluse_Time)
				{
					for(int i=0;i<2;i++)
					{
						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输出
						{
						/* PWM generation Error */
						while(1);
						}
						HAL_Delay(300);//等待300ms
						HAL_TIM_PWM_Stop(&htim3, TIM_CHANNEL_1);//PWM停止输出
					}		
				}			

		}
		
		Old_Pluse_Time=Pluse_Time;


  }
  /* USER CODE END 3 */
}
/* TIM3 init function */
void MX_TIM3_Init(void)
{
  TIM_MasterConfigTypeDef sMasterConfig = {0};
  TIM_OC_InitTypeDef sConfigOC = {0};

  htim3.Instance = TIM3;
  htim3.Init.Prescaler = 71;
  htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim3.Init.Period = 19999;
  htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  if (HAL_TIM_PWM_Init(&htim3) != HAL_OK)
  {
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }
  sConfigOC.OCMode = TIM_OCMODE_PWM1;
  sConfigOC.Pulse = Pluse_Time;//通过引入变量,方便调整占空比,高电平时间,单位us
  sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
  sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
  if (HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
  {
    Error_Handler();
  }
  HAL_TIM_MspPostInit(&htim3);

}

五.实验效果视频

STM32F103单片机+舵机+超声波模块智能垃圾桶模型效果

六.小结

融合了舵机,超声波模块的控制,对STM32的单片机的定时器PWM功能,定时器功能有更深的了解。

相关推荐
MARIN_shen44 分钟前
Marin说PCB之POC电路layout设计仿真案例---06
网络·单片机·嵌入式硬件·硬件工程·pcb工艺
Asa3191 小时前
STM32-按键扫描配置
stm32·单片机·嵌入式硬件
南城花随雪。1 小时前
单片机:实现驱动超声波(附带源码)
单片机·嵌入式硬件
嵌入式科普1 小时前
十三、从0开始卷出一个新项目之瑞萨RZN2L串口DMA接收不定长
c语言·stm32·瑞萨·e2studio·rzn2l
yutian060610 小时前
Keil MDK下载程序后MCU自动重启设置
单片机·嵌入式硬件·keil
析木不会编程13 小时前
【小白51单片机专用教程】protues仿真独立按键控制LED
单片机·嵌入式硬件·51单片机
枯无穷肉17 小时前
stm32制作CAN适配器4--WinUsb的使用
stm32·单片机·嵌入式硬件
不过四级不改名67717 小时前
基于HAL库的stm32的can收发实验
stm32·单片机·嵌入式硬件
嵌入式科普17 小时前
十一、从0开始卷出一个新项目之瑞萨RA6M5串口DTC接收不定长
c语言·stm32·cubeide·e2studio·ra6m5·dma接收不定长
嵌入式大圣17 小时前
单片机UDP数据透传
单片机·嵌入式硬件·udp