STM32循迹小车系列教程(三)—— 使用灰度传感器循迹

本章节主要讲解如何获取灰度传感器值以及如何使用灰度传感器循迹

灰度传感器简介

灰度传感器如图 1 所示

灰度传感器 使用一对抗干扰较强的光电传感器,其中发射管的光源采用高亮白色聚光 LED,发射管端发出的光线通过不同环境背景的反射之后,最终由光敏接收管来接收,光敏接收管的阻抗随反射光线的强弱变化而变化(反射光线越强,阻值越小),最后通过分压和运放比较电路实现数字/模拟信号的双输出。

灰度传感器模块对白光反射强弱不同背景环境有非常好的识别效果,背景差异越大,分辨效果越好。灰度传感器相比普通红外传感器有着更高的抗干扰能力。

灰度传感器检测原理

灰度传感器是一组模拟传感器,由一只发光二极管和一只光敏接收管组成,二者安装在同一面上。 灰度传感器利用不同颜色的检测背景对光的反射程度不同,同时光敏接收管接收到不同检测面返回的光线,其阻值也不同的原理进行颜色深浅检测。

当光敏接收管接收到的光线越强, 它的阻值就越小, 即地面背景灰度越深或者离地距离越远, 光敏二极管的阻值越大。

在有效的检测距离内,发光二极管发出白光,照射在检测面上,检测面反射部分光线, 光敏接收管检测此光线的强度并通过分压电路和运放比较电路将其转换模拟/数字信号,最后通过机器人主板上的模拟/数字口输入到微控制器进行处理。

电路分析

在上图所示灰度传感器检测电路中,LED1~3为发射补光管, LEDP1为光敏接收管,U1为比较运放芯片LM393A。用户可根据是否使用比较运放芯片决定使用模拟量或数字量。

使用模拟量时,ADC端的电压通过光电二极管分压得到,由光电二极管的特性曲线可得,当光电二极管接收光线弱时,光电二极管阻值趋向于无穷,此时ADC端电压接近于0。反之,当光电二极管接收光线强时,光电二极管阻值趋向于0,此时ADC端电压接近5V,由于不用颜色对于光的吸收程度不同,ADC端反映的值也不同,由此可根据光电二极管的值判断小车处于线的位置。

使用数字量时,当地面背景为深色或者高灰度值时, 经地面反射后进入光敏接收管端的光线较少, 2端输出的电压较高,经比较器比较后1端输出低电平控制三极管导通,GPIO输出高电平。同理当地面背景为浅色或者低灰度值时, 经地面反射后进入光敏接收管端的光线较多, 2端输出的电压较低,经比较器比较后1端输出低电平控制三极管截止,GPIO输出低电平。

数字量可满足大部分MCU,用户通过调节电位器RPOT1即可设定循迹阈值,而模拟量需要MCU具备ADC转化功能,将转化的数字量比较赛道路线的阈值即可获得和数字量一样的效果。相比之下,使用模拟量相对简单,但是需要消耗的MCU资源较多,而数字量不方便调节,但目前大多数MCU的IO口均有检测电平输入功能,用户无需二次配置。

循迹原理

巡线原理

1.先在平整的路面上调小车走直线。通过调整小车左右电机的速度,尽可能的让小车走直线,这样可以减少在巡线过程中调整的次数,可以让小车跑的更快。

2.巡线过程中,小车偏离线,如图1左,小车向左偏,应该增加左侧电机的速度,减小右侧的速度,减小或增加的量,根据小车实际情况修改测试。如图1右,小车向右偏,则相反。

3.靠近中心的探头照到线,调整的量要小些,越是离中心探头远的管子照到线,调整的量要越大。

4.调整的时候,切记不要将其中一个轮子停下来或者倒转。要用差速来调整方向这样车行走比较稳,而且速度要快。

路口判断

路口判断,如图2所示,以7路巡线传感器为例,1号探头用来判断左侧T型路口。7号探头用来判断右侧T型路口。1和7同时照到线,用来判断十字路口。

转弯判断

1.巡线走到需要转弯的路口,如图3。

2.车继续向前走一小段,让小车的旋转中心点靠近线的交叉点。小车有编码器可以用编码器精确控制,或没有编码器可以用延时,让车继续向前走一段时间,这些都需要实际写代码测试。

3.小车原地转弯,直到中间的探头(4号),照到线。这是转到第一个路口,若这条线是设定的路线,则巡线向前走,若不是这条线,继续旋转,等待中间的探头照到线,则转到了下一个路口。

循迹小车功能实现

灰度部分

uint8_t stop_way = 0;//停止线检测
uint8_t sensor_val[5];//灰度返回值
uint16_t gray_state = 0x0;//当前灰度状态
uint16_t gray_status[2]={0},gray_status_backup[2][20]={0};//灰度传感器状态与历史值
uint32_t gray_status_worse=0;	//灰度管异常状态计数器

/****************************
函数名称:
函数作用:5路循迹获取状态
函数参数:无
函数返回值:当前巡线状态 16进制
****************************/
uint16_t Sensor_GetState(void)
{
	uint16_t State = 0X0000;
	
//	sensor_val[0] = HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0);
//	sensor_val[1] = HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_1);
//	sensor_val[2] = HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_2);
//	sensor_val[3] = HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_3);
//	sensor_val[4] = HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_4);
//	
//	State |= (sensor_val[4] << 4);
//	State |= (sensor_val[3] << 3);
//	State |= (sensor_val[2] << 2);
//	State |= (sensor_val[1] << 1);
//	State |= (sensor_val[0] << 0);
	
	for(int8_t i=4;i>=0;i--)
	{
		sensor_val[i] = HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0<<i);
		State |= (sensor_val[i]<<i);
	}
	
	return State;
}

void gray_check(void)
{
	gray_state = Sensor_GetState();
	
	//记录上一次传感器量
	for(uint16_t i=19;i>0;i--)
	{
	    gray_status_backup[0][i]=gray_status_backup[0][i-1];
	}
	
	gray_status_backup[0][0]=gray_status[0];
	
	//灰度检测
	switch(gray_state)
	{
		case 0x01:gray_status[0] = 4; gray_status_worse/=2;break;	  //00001b
		case 0x03:gray_status[0] = 3; gray_status_worse/=2;break;	  //00011b
	    case 0x02:gray_status[0] = 2;	gray_status_worse/=2;break;   //00010b
		case 0x06:gray_status[0] = 1;	gray_status_worse/=2;break;	  //00110b
		case 0x04:gray_status[0] = 0;	gray_status_worse/=2;break;   //00100b
		case 0x0C:gray_status[0] = -1;gray_status_worse/=2;break;		//01100b
		case 0x08:gray_status[0] = -2;gray_status_worse/=2;break;		//01000b
		case 0x18:gray_status[0] = -3;gray_status_worse/=2;break;		//11000b
		case 0x10:gray_status[0] = -4;gray_status_worse/=2;break;		//10000b
		case 0x00:gray_status[0] = gray_status_backup[0][0];gray_status_worse++;break; //00000b
		
		default://其它特殊情况单独判断
		{
			gray_status[0]=gray_status_backup[0][0];
			gray_status_worse++;
		}
	}	
	
		switch(gray_state)//停止线检测
		{
			case 0x0F://01111b
			case 0x1E://11110b
			case 0x1F://11111b
			{
				stop_way++;
			}
			break;
		}		
}

主函数部分

/**
  * @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();
  MX_TIM4_Init();
  /* USER CODE BEGIN 2 */
		HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_1);
		HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_2);
		
		HAL_TIM_Encoder_Start(&htim2, TIM_CHANNEL_ALL);
		HAL_TIM_Encoder_Start(&htim4, TIM_CHANNEL_ALL);

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
		motor_ctrl(500+gray_status[0]*100,-(500-gray_status[0]*100));
		Get_Encoder();
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

可以观察到小车延黑线行驶 

循迹效果

需要代码的朋友可以点击以下链接下载,有问题请私信我。 

x(85条消息) 【免费】STM32循迹小车(灰度+OpenMV权重判断)资源-CSDN文库 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/599397.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

软件系统安全设计规范(word原件)

1.1安全建设原则 1.2 安全管理体系 1.3 安全管理规范 1.4 数据安全保障措施 1.4.1 数据库安全保障 1.4.2 操作系统安全保障 1.4.3 病毒防治 1.5安全保障措施 1.5.1实名认证保障 1.5.2 接口安全保障 1.5.3 加密传输保障 1.5.4终端安全保障 软件资料清单列表部分文档…

嵌入式全栈开发学习笔记---C语言笔试复习大全13(编程题9~16)

目录 9.查找字符数组中字符位置&#xff08;输入hello e 输出2&#xff09;&#xff1b; 10、查找字符数组中字符串的位置&#xff08;输入hello ll 输出3&#xff09;&#xff1b; 11、字符数组中在指定位置插入字符&#xff1b;&#xff08;输入hello 3 a 输出heallo…

编程算法赛

1偶数累加 2、统计字符的数量 3、计算表达式的值 4、哥德巴赫猜想 5、进制的转换

英语学习笔记5——Nice to meet you.

Nice to meet you. 很高兴见到你。 词汇 Vocabulary Mr. 先生 用法&#xff1a;自己全名 / 姓 例如&#xff1a;Mr. Zhang Mingdong 或 Mr. Zhang&#xff0c;绝对不能是 Mr. Mingdong&#xff01; Miss 女士&#xff0c;小姐 未婚 用法&#xff1a;自己全名 / 姓 例如&#…

【论文阅读】Fuzz4All: Universal Fuzzing with Large Language Models

文章目录 摘要一、介绍二、Fuzz4All的方法2.1、自动提示2.1.1、自动提示算法2.1.2、自动提示的例子2.1.3、与现有自动提示技术的比较 2.2、fuzzing循环2.2.1、模糊循环算法2.2.2、Oracle 三、实验设计3.1、实现3.2、被测系统和baseline3.3、实验设置以及评估指标 四、结果分析4…

P8801 [蓝桥杯 2022 国 B] 最大数字

P8801 [蓝桥杯 2022 国 B] 最大数字 分析 dfs 思路&#xff1a;题目的意思&#xff0c;要让一个数最大&#xff0c;用贪心去考虑&#xff0c;从高位开始&#xff0c;对其进行a / b操作&#xff0c;使其变为9&#xff0c;可让该数最大 1.a 操作&#xff1a;1&#xff1b;b 操…

嵌入式学习<1>:建立工程、GPIO

嵌入式学习_part1 本部分笔记用于学习记录&#xff0c;笔记源头 >>b站江科大_STM32入门教程 建立工程、GPIO 开发环境&#xff1a;keil MDK、STM32F103C8T6 1 &#xff09;建立工程 &#xff08;1&#xff09;基于寄存器开发、基于标准库 或者 基于HAL库开发; &…

【代码随想录——哈希表】

1.哈希表理论基础 首先什么是 哈希表&#xff0c;哈希表&#xff08;英文名字为Hash table&#xff0c;国内也有一些算法书籍翻译为散列表&#xff0c;大家看到这两个名称知道都是指hash table就可以了&#xff09;。 那么哈希表能解决什么问题呢&#xff0c;一般哈希表都是用…

高素质高学历婚恋相亲交友平台有哪些?分享我的网上找对象成功脱单经历!

尽管觉得在社交软件上找到真爱的可能性很小&#xff0c;但我却时常看到别人成功的案例&#xff0c;这也让我跃跃欲试了。没想到&#xff0c;我真的成功了&#xff01;以下是我亲身使用过的一些方法&#xff0c;在此与大家分享&#xff0c;仅供参考哦&#xff01; &#x1f449;…

c++ cpp 在类中执行线程 进行恒定计算

在编程中&#xff0c;顺序执行是常见的模式&#xff0c;但是对cpu的利用率不是很高&#xff0c;采用线程池&#xff0c;又太麻烦了&#xff0c;原因是还得不断地把任务拆分&#xff0c;扫描返回值。 如果 初始化n个类的时候&#xff0c;传递数据自身即可异步计算&#xff0c;那…

六、文件查找

一、文件查找 1.查找文件内容 ​ 命令&#xff1a;grep keywords /dir_path/filename 2.查找系统命令 ​ 命令&#xff1a;which command 3.查找命令及配置文件位置 ​ 命令&#xff1a;whereis command 4.find查找 ​ find $find_path -name|-type|-perm|-size|-atime…

【前端】HTML基础(3)

文章目录 前言一、HTML基础1、表格标签1.1 基本使用1.2 合并单元格 2、列表标签2.1 无序列表2.2 有序列表2.3 自定义列表 3、 表单标签2.1 form标签2.2 input标签2.3 label标签2.4 select标签2.5 textarea标签 4、无语义标签5、HTML特殊字符 前言 这篇博客仅仅是对HTML的基本结…

RVM(相关向量机)、CNN_RVM(卷积神经网络结合相关向量机)、RVM-Adaboost(相关向量机结合Adaboost)

当我们谈到RVM&#xff08;Relevance Vector Machine&#xff0c;相关向量机&#xff09;、CNN_RVM&#xff08;卷积神经网络结合相关向量机&#xff09;以及RVM-Adaboost&#xff08;相关向量机结合AdaBoost算法&#xff09;时&#xff0c;每种模型都有其独特的原理和结构。以…

streamlit通过子目录访问

运行命令&#xff1a; streamlit hello 系统默认使用8501端口启动服务&#xff1a; 如果想通过子目录访问服务&#xff0c;可以这么启动服务 streamlit hello --server.baseUrlPath "app" 也可以通过以下命令换端口 streamlit hello --server.port 9999 参考&…

2024最新CTF入门的正确路线

目录 前言 一、什么是CTF比赛&#xff1f; 二、CTF比赛的流程 三、需要具备的知识 四、总结 前言 随着网络安全意识的增强&#xff0c;越来越多的人开始涉足网络安全领域&#xff0c;其中CTF比赛成为了重要的学习和竞赛平台。本人从事网络安全工作多年&#xff0c;也参加过…

甲小姐对话柳钢:CEO对股东最大的责任,是对成功的概率负责|甲子光年

只有看见最微小的事物&#xff0c;才能洞悉伟大的定律。 来源&#xff5c;甲子光年 作者&#xff5c;甲小姐 刘杨楠 编辑&#xff5c;栗子 商业史上&#xff0c;职业经理人成为“空降CEO”的故事往往胜少败多。 “究其原因有三条——容易自嗨、喊口号&#xff1b;不顾公司历…

笔试强训Day19 数学知识 动态规划 模拟

[编程题]小易的升级之路 题目链接&#xff1a;小易的升级之路__牛客网 思路&#xff1a; 按题目写即可 注意辗转相除法。 AC code&#xff1a; #include<iostream> using namespace std; int gcd(int a, int b) {return b ? gcd(b, a % b) : a; } int main() {int n…

三步学会苹果手机怎么关震动的方法!

苹果手机的震动功能在某些情况下可能会被认为是不必要的&#xff0c;比如在会议、课堂或者晚间睡眠时。因此&#xff0c;学会如何关闭苹果手机的震动功能是非常实用的。苹果手机怎么关震动&#xff1f;在本文中&#xff0c;我们将介绍三个步骤&#xff0c;帮助你关闭苹果手机的…

openEuler 22.03 GPT分区表模式下磁盘分区管理

目录 GPT分区表模式下磁盘分区管理parted交互式创建分区步骤 1 执行如下步骤对/dev/sdc磁盘分区 非交互式创建分区步骤 1 输入如下命令直接创建分区。 删除分区步骤 1 执行如下命令删除/dev/sdc1分区。 GPT分区表模式下磁盘分区管理 parted交互式创建分区 步骤 1 执行如下步骤…