STM32__红外避障模块的使用
目录
一、红外避障模块 概述
二、直接读取OUT引脚电平
三、使用中断方式触发
一、红外避障模块 概述
引脚解释:
VCC | 接3.3V 或 5.0V |
GND | 接开发板的GND |
OUT | 数字量输出(0或1); 低电平时表示前方有障碍 ; 通过可调电阻调整检测距离 |
产品特点:
工作电压 | 推荐3.3V, 也可以5V |
模块功耗 | 23mA~40mA |
检测距离 | <=30cm ; 通过可调电阻调整检测距离 |
指示灯 | 电压灯 + 障碍指示灯 |
模块描述:
1、可以广泛应用于机器人避障、避障小车、流水线计数、黑白线循迹 等众多场合。
2、采用3.3V 或 5V 直流电源对模块进行供电。当电源接通时,红色电源指示灯点亮;
3、该传感器模块对环境光线适应能力强,其具有一对红外线发射与接收管,发射管发射出一定频率的红外线,当检测方向遇到障碍物(反射面)时,红外线反射回来被接收管接收,经过比较器电路处理之后,绿色指示灯会亮起,同时OUT端口持续输出低电平信号(0);
4、检测距离2~30cm,检测角度35°; 检测距离可以通过电位器进行调节,顺时针调电位器,检测距离增加;逆时针调电位器,检测距离减少。
5、传感器是主动红外线反射探测, 因此目标的反射率和形状是探测距离的关键。其中黑色探测距离最小, 白色最大; 小面积物体距离小,大面积距离大。
6、输出端口OUT可直接与单片机IO口连接,使用代码读取OUT电平,或使用中断触发的方式; 另外, OUT引脚也可以直接驱动一个5V继电器;
7、使用前,建议先用螺丝刀调节好需要的触发距离 (绿灯亮),再接入单片机进行开发调试。
8、具有3mm的螺丝孔,便于固定、安装;
二、程序直接读取OUT引脚电平
OUT接口在闲时(没有发现障碍物),是持续的输出高电平状态;
当发现障碍物时,OUT接口将持续地输出低电平,直到障碍物消失时再输出高电平;
因此,我们可以在STM32工程中,直接用代码读取OUT接口的电平,即可知道是否遇到障碍物。
- 这里以OUT接口,连接PC12引脚为示例;(哪个引脚都可以,只要是空闲的引脚即可)
- PC12引脚工作模式,无需初始化、设置。因为读电平,不管哪种模式状态下都可以直接读。
在main的while中,编写以下代码即可:
HAL_Delay(500); // 延时间隔uint8_t state = HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_12); // 读取OUT引脚电平; 只是读引脚电平,用哪个引脚都可以,无需提前初始化
if (state == 0) // 判断 OUT 引脚是否是低电平(闲时高电平,遇到障碍物时持续输出低电平)
{HAL_GPIO_WritePin(GPIOB, GPIO_PIN_2, GPIO_PIN_RESET); // 点亮蓝色LED; 引脚PB2, 低电平通路点亮;printf("发现障碍物!\r\n"); // 打印提示信息; printf需要预先使能UART1,并重定向到UART1输出
}
else
{HAL_GPIO_WritePin(GPIOB, GPIO_PIN_2, GPIO_PIN_SET); // 熄灭蓝色LED; 引脚PB2, 高电平断路熄灭;
}
完成后,位置如下图:
上面的代码,当PC12为低电平时(遇到障碍物):亮灯、printf输出提示信息;
三、使用中断方式触发
上面的读取方式,操作简单、容易理解。
但这种方式有一个潜在隐患:处理可能不及时。
如,当小车高速开跑中,遇到了障碍物,但程序却正在运行其它功能的代码, ......。
小车翻车没啥事,但如果用在工业现场,如电机、导轨等, 那就严重了!
我们可以使用中断触发的方式,发现障碍物,立即进入执行处理!
下面,还是以OUT接口连接PC12作示例,示范CubeMX的中断触发配置、编写回调函数代码。
1、配置引脚的工作模式
- 点击需要使用的引脚,选择:GPIO_EXTI,即 外部中断模式
2、配置触发方式
- 根据OUT接口的工作特点,配置为: Interrupt Falling ,即下降沿触发中断;
- 设置为上拉,即 闲时引脚电平保持在高电平状态;
3、使能中断线
- 在 NVIC 中断控制器页面中,打勾对应的中断线,令中断控制器能够响应该中断线,从而使芯片能够接收并处理引脚的电平跳变事件。
引脚编号与中断线对应的关系是:
GPIO_PIN_0 | EXTI_Line0 |
GPIO_PIN_1 | EXTI_Line |
GPIO_PIN_2 | EXTI_Line |
GPIO_PIN_3 | EXTI_Line |
GPIO_PIN_4 | EXTI_Line |
GPIO_PIN_5 至 GPIO_PIN_9 共用一个中断线 | EXTI_Line[9:5] |
GPIO_PIN_10 至 GPIO_PIN_15 共用一个中断线 | EXTI_LineEXTI_Line[15:10] |
至此,引脚的中断触发,配置完成,重新生成。
4、编写中断回调函数
CubeMX配置上述中断后,将自动生成底层的初始化、中断服务函数等代码。
当引脚发生了配置中的电平跳变时,将触发硬件自动调用程序里的中断服务函数,继而调用程序里的EXTI中断回调函数:HAL_GPIO_EXTI_Callback ( );
这个回调函数在CubeMX生成时,在stm32xx_hal_gpio.c中已生成了弱定义;
我们在适合的、喜欢的位置,自行重新编写HAL_GPIO_EXTI_Callback函数,即能被中断函数调用到。
我们在main.c的下方,/* USER CODE BEGIN 4 */之下,编写此回调函数:
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{if (GPIO_Pin == GPIO_PIN_12) // 由PC12触发{HAL_GPIO_WritePin(GPIOB, GPIO_PIN_2, GPIO_PIN_RESET); // 点亮蓝色LED; 引脚PB2, 低电平通路点亮;printf("发现障碍物!\r\n"); // 打印提示信息; printf需要预先使能UART1,并重定向到UART1输出}}
完成后,位置如下图:
如上,即可实现遇到障碍物时,实时地执行处理。
这里的亮灯、printf,只是示范,你可以替换成需要的执行,如刹车、关闭设备电源等。
5、多次触发的解决思路
当使用中断触发,可能会有一个使用上明显的bug:连续多次触发!
这个bug的产生,是OUT接口输出低电平信号过程中的振铃现象所导致的。
测试了三个不同店家的红外避障模块,有两家模块存在多次触发现象。
物理解决方案:
在 OUT接口与GND间,并联一个1uF左右的小电容(1uF只是建议,具体得根据现场而定);
代码解决方案:
在中断回调函数里,增加5ms延时,即HAL_Delay(10ms),让程序刻意“错过”振铃导致的多次触发。这种方式有点像按键的消抖处理。但是,不建议使用这种方式,因为在中断里延时死等,有可能导致其它通信的中断无法及时执行,数据丢包! 如果确定要使用这种方式(在中断里使用HAL_Delay), 注意会产生中断嵌套冲突。需要在CubeMX里修改NVIC的Time base响应优先级,默认是15 (最低),把它修改为0 (最高),然后,把引脚中断线的优先级,默认是0 (最高),修改为大于0的值,如1、6等。这样处理后,在EXTI的中断回调函数里才能使用HAL_Delay函数。
操作如下图:
如有错漏,望指正,将及时更新修改~~~