项目需求
检测靠近时,垃圾桶自动开盖并伴随滴一声,2秒后关盖 发生震动时,垃圾桶自动开盖并伴随滴一声,2秒后关盖 按下按键时,垃圾桶自动开盖并伴随滴一声,2秒后关盖
项目框图
硬件清单
SG90舵机,超声波模块,震动传感器,蜂鸣器
a. sg90舵机介绍及实战
sg90舵机介绍
PWM波的频率不能太高,大约50HZ,即周期=1/频率=1/50=0.02s,20ms左右。
确定周期/频率
如果周期为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度
接线
代码:
HAL_TIM_PWM_Start(&htim4,TIM_CHANNEL_3);
while (1)
{
HAL_Delay(1000);
__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);
}
b. 超声波传感器介绍及实战
超声波传感器介绍
怎么让它发送波Trig ,给Trig端口至少10us的高电平( 根据我的实测,有的超声波模块要20us,甚至10ms)
怎么知道它开始发了Echo信号,由低电平跳转到高电平,表示开始发送波
怎么知道接收了返回波Echo,由高电平跳转回低电平,表示波回来了
怎么算时间Echo引脚维持高电平的时间!波发出去的那一下,开始启动定时器波回来的拿一下,我们开始停止定时器,计算出中间经过多少时间
怎么算距离距离 = 速度 (340m/s)* 时间/2
时序图
编程实战
需求:
使用超声波测距,当手离传感器距离小于5cm时,LED1点亮,否则保持不亮状态。
接线:
Trig --- PB6 Echo --- PB7 LED1 --- PB8
定时器配置:
使用 TIM2 ,只用作计数功能,不用作定时。
将 PSC 配置为71,则计数 1 次代表 1us 。
编写微秒级函数:
//使用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);
}
主函数:
int cnt;
float distance;
while (1) {
//1. Trig ,给Trig端口至少10us的高电平
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_SET); //拉高
TIM2_Delay_us(20);
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_Base_Start( & htim2);
__HAL_TIM_SetCounter( & htim2, 0);
//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)
distance = cnt * 340 / 2 * 0.000001 * 100; //单位:cm
if (distance < 5) HAL_GPIO_WritePin(GPIOB, GPIO_PIN_8, GPIO_PIN_RESET);
else HAL_GPIO_WritePin(GPIOB, GPIO_PIN_8, GPIO_PIN_SET);
//每500毫秒测试一次距离
HAL_Delay(500);
}
项目设计及实现
项目设计 超声波模块: Trig -- PB6 Echo -- PB7
sg90舵机: PWM -- PB9
按键: KEY1 -- PA0 LED灯: LED1 -- PB8
震动传感器: D0 -- PB5 VCC -- 5V
蜂鸣器: IO -- PB4 VCC -- 3V3
代码-项目实现
void sg90_init()
{
HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_3);
__HAL_TIM_SetCompare(&htim3,TIM_CHANNEL_3,5);//设置最开始为0度
}
void openDustbin()
{
if(flag == close){
flag = open;
__HAL_TIM_SetCompare(&htim3,TIM_CHANNEL_3,20);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_3,GPIO_PIN_RESET);
HAL_Delay(100);
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_3,GPIO_PIN_SET);
}
HAL_Delay(2000);
}
void closeDutbin()
{
flag = close;
__HAL_TIM_SetCompare(&htim3,TIM_CHANNEL_3,5);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_SET);
HAL_Delay(150);
}
void Tim2_Delay_us(uint32_t n_us)
{
__HAL_TIM_ENABLE(&htim2);//使能定时器2计数
__HAL_TIM_SetCounter(&htim2,0);
while(__HAL_TIM_GetCounter(&htim2) <(n_us-1));
__HAL_TIM_DISABLE(&htim2);
}
double getDistance()
{
int cnt = 0;
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_6,GPIO_PIN_SET);
Tim2_Delay_us(20);
// HAL_Delay(10);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_6,GPIO_PIN_RESET);
while(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_7) == GPIO_PIN_RESET);
__HAL_TIM_SetCounter(&htim2,0);
HAL_TIM_Base_Start(&htim2);
while(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_7) == GPIO_PIN_SET);
HAL_TIM_Base_Stop(&htim2);
cnt = __HAL_TIM_GetCounter(&htim2);
return (cnt*340/2*0.000001*100);
}
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if(GPIO_Pin == GPIO_PIN_0 || GPIO_Pin == GPIO_PIN_4){
if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0) == GPIO_PIN_RESET || HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_4) == RESET){
openDustbin();
}
}
}
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
double dis;
/* 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_TIM2_Init();
MX_TIM3_Init();
/* USER CODE BEGIN 2 */
sg90_init();
HAL_NVIC_SetPriority(SysTick_IRQn,0,0);//修改滴答定时器优先级
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
dis = getDistance();
if(dis < 10){
openDustbin();
}else{
closeDutbin();
}
}
/* USER CODE END 3 */
}