在自动驾驶和机器人技术领域,循迹模块是至关重要的组成部分。它能够使车辆或机器人沿着预定的路径精确行驶,从而实现各种复杂任务。
本次要介绍的是 TCRT5000 红外循迹模块,将深入探讨它的工作原理、技术实现和应用场景,无论您是学生、爱好者还是从业者,阅读本文将帮助您全面了解循迹模块,并为您提供更多关于该设备的深入见解。
1. 源码下载及前置阅读
本文首发 良许嵌入式网 :https://www.lxlinux.net/e/ ,欢迎关注!
本文所涉及的源码及安装包如下(由于平台限制,请点击以下链接阅读原文下载):
如果你是嵌入式开发小白,那么建议你先读读下面几篇文章。
- 从零开始轻松掌握STM32开发的必备指南:零基础快速上手STM32开发(手把手保姆级教程)
- 如果你想搭一个属于自己的工程模板:手把手带你创建HAL版本MDK工程模板
- 计算机概念理清,生动形象,通俗易懂:图解固件、驱动、软件的区别
往期教程,有兴趣的小伙伴可以看看。
- 深入浅出,帮助您理解和应用MQTT协议:万字猛文:MQTT原理及案例
- 简单好用,为你的智能语音项目提供核心支持:SU-03T语音控制模块详解
- 继电器模块的原理、功能和应用:继电器模块详解
作者简介 |
---|
大家好,我是良许,博客里所有的文章皆为我的原创。 下面是我的一些个人介绍,欢迎交个朋友: · 211工科硕士,国家奖学金获得者; · 深耕嵌入式11年,前世界500强外企高级嵌入式工程师; · 书籍《速学Linux作者》,机械工业出版社专家委员会成员; · 全网60W粉丝,博客分享大量原创成体系文章,全网阅读量累计超4000万; · 靠自媒体连续年入百万,靠自己买房买车。 |
我本科及硕士都是学机械,通过自学成功进入世界500强外企。我已经将自己的学习经验写成了一本电子书,超千人通过此书学习并转行成功。现在将这本电子书免费分享给大家,希望对你们有帮助:
2. 模块介绍
2.1 型号介绍
TCRT5000 不断发射红外信号,当红外信号:
- 有反射回来,DO 输出低电平,开关指示灯(绿灯)亮。
- 没反射回来,DO 输出高电平,开关指示灯(绿灯)灭。
TCRT5000 常见用途:
- 电度表脉冲数据采样
- 传真机碎纸机纸张检测
- 障碍检测
- 黑白线检测(包含循迹小车)
2.2 工作参数及引脚介绍
TCRT5000 红外循迹模块工作参数:
- 工作电压:DC 3.3 ~ 5V
- 检测反射距离:1mm ~ 25mm 适用(不同厂家会略有差异)
模块中蓝色的电位器用于调节灵敏度,顺时针旋转,灵敏度变高;逆时针越小,灵敏度变低。
上电后电源指示灯(红灯)亮。
当红外反射回来,DO 输出低电平,开关指示灯(绿灯)亮。
接线如下:
TCRT5000 | STM32 | 备注 |
---|---|---|
VCC | 3.3/5V | 电源正极 |
GND | GND | 电源负极 |
D0 | 任意 GPIO 口 | 数字输出 |
A0 | 有 ADC 功能的引脚 | 模拟输出(一般不用) |
3. TCRT5000工作原理
TCRT5000 传感器的红外发射二极管不断发射红外线,当发射出的红外线没有被反射回来或被反射回来但强度不够大时,红外接收管一直处于关断状态,此时模块的输出端为高电平,指示二极管一直处于熄灭状态;被检测物体出现在检测范围内时,红外线被反射回来且强度足够大,红外接收管饱和,此时模块的输出端为低电平,指示二极管被点亮。
模拟输出 AO:当发射管的红外信号经反射被接收管接收后,接收管的电阻会发生变化,在电路上一般以电压的变化形式体现出来,经过 ADC 转换或 LM324 等电路整形后得到处理后的输出结果。电阻的变化取决于接收管所接收的红外信号强度,常表现在反射面的颜色(反射率)、形状和反射面接收管的距离等方面。
4. 通信示意图
实现目标:我们有一个三色 LED 灯,当模块面前出现障碍物时,红灯亮,绿灯灭;没有障碍物时,红灯灭,绿灯亮。
这个小案例的应用场景可以应用在工业自动化,当物体或人在禁止区域或危险区域时,红灯亮起以提醒离开此区域。
5. 编程实战
5.1 硬件接线
本教程使用的硬件如下:
- 单片机:STM32F103C8T6
- 循迹模块:TCRT5000
- 小灯:三色 LED 灯模块
- 烧录器:ST-LINK V2
接线如下:
TCRT5000 | STM32 |
---|---|
VCC | 5V |
GND | G |
DO | A4 |
AO | 悬空 |
烧录的时候接线如下表,如果不会烧录的话可以看我之前的文章【STM32下载程序的五种方法】。
ST-Link V2 | STM32 |
---|---|
SWCLK | SWCLK |
SWDIO | SWDIO |
GND | GND |
3.3V | 3V3 |
接好如下图:
开发板使用的是我们自绘的板子。大家也可以用自己的板子,只要是 STM32F103C8T6 主控芯片就行。
5.2 LED初始化
LED 灯,我们的老朋友了,不多介绍了。
void led_init(void)
{
GPIO_InitTypeDef gpio_init_struct;
LED1_GPIO_CLK_ENABLE(); /* LED1时钟使能 */
LED3_GPIO_CLK_ENABLE(); /* LED3时钟使能 */
gpio_init_struct.Pin = LED1_GPIO_PIN; /* LED1引脚 */
gpio_init_struct.Mode = GPIO_MODE_OUTPUT_PP; /* 推挽输出 */
gpio_init_struct.Pull = GPIO_PULLUP; /* 上拉 */
gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH; /* 高速 */
HAL_GPIO_Init(LED1_GPIO_PORT, &gpio_init_struct); /* 初始化LED1引脚 */
gpio_init_struct.Pin = LED3_GPIO_PIN; /* LED3引脚 */
HAL_GPIO_Init(LED3_GPIO_PORT, &gpio_init_struct); /* 初始化LED3引脚 */
LED1(0); /* 关闭 LED1 */
LED3(0); /* 关闭 LED3 */
}
LED 的 .h文件:
#ifndef _LED_H
#define _LED_H
#include "sys.h"
/******************************************************************************************/
/* 引脚 定义 */
#define LED1_GPIO_PORT GPIOA
#define LED1_GPIO_PIN GPIO_PIN_5
#define LED1_GPIO_CLK_ENABLE() do{ __HAL_RCC_GPIOA_CLK_ENABLE(); }while(0) /* PA口时钟使能 */
#define LED3_GPIO_PORT GPIOA
#define LED3_GPIO_PIN GPIO_PIN_7
#define LED3_GPIO_CLK_ENABLE() do{ __HAL_RCC_GPIOA_CLK_ENABLE(); }while(0) /* PA口时钟使能 */
/******************************************************************************************/
/* LED端口定义 */
#define LED1(x) do{ x ? \
HAL_GPIO_WritePin(LED1_GPIO_PORT, LED1_GPIO_PIN, GPIO_PIN_SET) : \
HAL_GPIO_WritePin(LED1_GPIO_PORT, LED1_GPIO_PIN, GPIO_PIN_RESET); \
}while(0)
#define LED3(x) do{ x ? \
HAL_GPIO_WritePin(LED3_GPIO_PORT, LED3_GPIO_PIN, GPIO_PIN_SET) : \
HAL_GPIO_WritePin(LED3_GPIO_PORT, LED3_GPIO_PIN, GPIO_PIN_RESET); \
}while(0)
/* LED取反定义 */
#define LED1_TOGGLE() do{ HAL_GPIO_TogglePin(LED1_GPIO_PORT, LED1_GPIO_PIN); }while(0) /* 翻转LED1 */
#define LED3_TOGGLE() do{ HAL_GPIO_TogglePin(LED3_GPIO_PORT, LED3_GPIO_PIN); }while(0) /* 翻转LED3 */
/******************************************************************************************/
/* 外部接口函数*/
void led_init(void); /* LED初始化 */
#endif
5.3 循迹模块初始化
初始化一下循迹模块的 DO 引脚。
我们采用中断的方式亮灯,需要初始化和使能一下 EXTI。
void tc_init(void)
{
GPIO_InitTypeDef gpio_initstruct;
TC_CLK(); /* IO口时钟使能 */
gpio_initstruct.Pin = TC_PIN; /* DO引脚 */
gpio_initstruct.Mode = GPIO_MODE_IT_RISING_FALLING; /* 中断沿触发 */
gpio_initstruct.Pull = GPIO_NOPULL; /* 无电阻 */
HAL_GPIO_Init(TC_GPIO, &gpio_initstruct); /* 初始化DO引脚 */
HAL_NVIC_SetPriority(EXTI4_IRQn,2,0); /* 抢占优先级2,响应优先级0 */
HAL_NVIC_EnableIRQ(EXTI4_IRQn); /* 使能EXTI4 */
}
5.4 循迹模块控制灯
复写「HAL_GPIO_EXTI_Callback」函数,检测中断沿,下降沿表示循迹模块感受到有障碍,「tcflag」置1;上降沿表示循迹模块感受到无障碍,「tcflag」置0。
uint16_t tcflag;
uint16_t get_tcflag(void)
{
return tcflag;
}
void set_tcflag(uint16_t value)
{
tcflag = value;
}
void EXTI4_IRQHandler(void)
{
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_4); /* 调用中断处理公用函数 清除中断线 的中断标志位 */
__HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_4); /* HAL库默认先清中断再处理回调,退出时再清一次中断,避免按键抖动误触发 */
}
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if(GPIO_Pin == TC_PIN){
if(HAL_GPIO_ReadPin(TC_GPIO, TC_PIN) == GPIO_PIN_SET) //如果无障碍
{
set_tcflag(0);
}
if(HAL_GPIO_ReadPin(TC_GPIO, TC_PIN) == GPIO_PIN_RESET) //如果有障碍
{
set_tcflag(1);
}
}
}
5.5 主函数
主函数如下:
依据「tcflag」,为1时表示有障碍,红灯亮,绿灯灭;为0时表示无障碍,绿灯亮,红灯灭。
int main(void)
{
HAL_Init(); /* 初始化HAL库 */
sys_stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟, 72Mhz */
led_init(); /* LED初始化 */
tc_init(); /* 循迹红外模块初始化 */
while(1)
{
if (get_tcflag()) //有障碍时,红灯亮,绿灯灭
{
HAL_GPIO_WritePin(LED1_GPIO_PORT, LED1_GPIO_PIN, GPIO_PIN_SET);
HAL_GPIO_WritePin(LED3_GPIO_PORT, LED3_GPIO_PIN, GPIO_PIN_RESET);
}else{ //无障碍时,绿灯亮,红灯灭
HAL_GPIO_WritePin(LED3_GPIO_PORT, LED3_GPIO_PIN, GPIO_PIN_SET);
HAL_GPIO_WritePin(LED1_GPIO_PORT, LED1_GPIO_PIN, GPIO_PIN_RESET);
}
}
}
5.6 运行效果
当模块面前没有障碍物时,红灯灭,绿灯亮。
出现障碍物时,红灯亮,绿灯灭;
6. 小结
循迹模块在智能车、机器人和自动导航系统等领域发挥着重要的作用,通过使用红外传感器,循迹模块能够准确地检测和跟踪路径标记,实现自动导航和路径控制功能。
随着科技的进步,循迹模块将继续发展和创新,为自动化、嵌入式等领域带来更多的可能性。希望本文对您对循迹模块有所启发,并激发您进一步探索和应用这一技术。感谢各位看官,peace and love!
另外,想进大厂的同学,一定要好好学算法,这是面试必备的。这里准备了一份 BAT 大佬总结的 LeetCode 刷题宝典,很多人靠它们进了大厂。
有收获?希望老铁们来个三连击,给更多的人看到这篇文章
推荐阅读:
欢迎关注我的博客:良许嵌入式教程网,满满都是干货!