四轮两驱小车(四):STM32驱动5路灰度传感器PID循迹

news2024/11/28 5:29:03

目录

前言:

小车效果展示:

5路数字灰度传感器:

巡线思路:

加入PID调节的代码:


前言:

        之前买了一批5路灰度传感器,想用这传感器进行循迹,无奈网上和官方的资料提供的还是比较少,这里还是做一下当初的学习记录。

小车效果展示:

STM32RCT6主控,5路灰度寻迹,超声波HC_SR04中断式测距,蓝牙模块HC_08通信,AS4950电机驱动芯片,减缓了MPU6050零漂问题,PID丝滑_哔哩哔哩_bilibili

5路数字灰度传感器:

         这是某宝上买的5路灰度传感器,价格稍微有点贵,50多块一个。当然,一分钱一分货,这个模块可以用小螺丝刀来调节传感器上面的旋钮,通过这个旋钮来调节灵敏度,这个灵敏度调节好了的话可以识别黑白循迹、红白循迹。所以还是比较值得的。

        对于这款5路数字灰度传感器来说。识别到黑线,传回来的数字量就是0,识别到白色,传回来的数字量就是1。

巡线思路:

        博主想着用这5路的中间三路来巡线,用最左和最右端的传感器用来识别十字或者丁字路口,巡线时,加入PID算法,遇到十字或者丁字路口就用最左和最右的传感器来识别,识别到了之后,我们就可以搭配MPU6050进行转90°弯了。

加入PID调节的代码:

        其中 sensor_bias 是根据中间三路传感器和黑线的相对位置来估计出的误差(如果你要问我怎么得来的,其实这个数据大差不差就行,它只是为PID服务的一个变量罢了,甚至你可以把62.5改成50,最后只要调好PID三个参数,达到的效果是一样的),这里的decide类似于状态机的信号,我令decide为6的时候,也就是小车跑出了黑线,小车停止。

#include "sensor.h"
#include "stm32f10x.h"
#include "move.h"
#include "motor.h"
#include "FSM.h"

//STEER4 		--> PA11  --> R2  红线
//STEER3 		--> PC9 	--> R1  橘线
//			 		--> PB4   --> M0  黄线
//STEER1 		--> PA6   --> L1  绿线
//ENCODE1_A --> PB5	  --> L2  棕线

float Kp_sensor = 8.134, Ki_sensor = 0.021, Kd_sensor = 2.36;//pid弯道参数参数 
float sensor_bias = 0;
float sensor_bias_last = 0;
float P = 0, I = 0, D = 0, PID_value = 0;  //pid直道参数 
int decide;

unsigned char move_flag;
extern unsigned char FSM_state;
void sensor_Init()
{
	GPIO_InitTypeDef GPIO_InitStructure;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);//开启C时钟   PC9
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
	//GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//这句话其实可以不用,在使用输入功能时,不需要配置频率
	GPIO_Init(GPIOC, &GPIO_InitStructure);
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//开启A时钟  PA11  PA6
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11|GPIO_Pin_6;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	GPIO_PinRemapConfig(GPIO_Remap_SWJ_NoJTRST, ENABLE); 
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);//开启B时钟  PB4  PB5
	
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4|GPIO_Pin_5;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
}

unsigned char times;
extern unsigned char FSM_hc08;
unsigned char back_flag;
unsigned char one_time;
unsigned char one_flag;
unsigned char channel_num;//channel的存在导致发送2号通道的时候只会进入一次
void sensor_read()
{
	if((L2 == 1)&&(L1 == 1)&&(M0 == 1)&&(R1 == 0))// 1 1 1 0 
	{
		if(one_time == 0)
		{
			if(FSM_hc08 == Channel_1)
			{
				FSM_state = Turn_lift_state;//跳出循环,将PID分别清零。
				one_time++;
				P = 0;I = 0; D = 0;
			}
			else if(FSM_hc08 == Channel_2)
			{
				if(one_flag == 0)
				{
					channel_num++;
					one_flag = 1;
				}
				if(channel_num == 2)
				{	
					FSM_state = stay2_state;//跳出循环,将PID分别清零。
					one_time++;
					P = 0;I = 0; D = 0;
				}
			}
		}
	}
	else if((L1 == 0)&&(M0 == 1)&&(R1 == 0))// 0 1 0 
	{
		sensor_bias = 0;decide = 3;one_flag = 0;//积分项清零
	}
	else if((L1 == 1)&&(M0 == 1)&&(R1 == 0))// 1 1 0 
	{
		sensor_bias = -62.5;decide = 2;
	}
	else if((L1 == 0)&&(M0 == 1)&&(R1 == 1))// 0 1 1 
	{
		sensor_bias = 62.5;decide = 2;
	}
	else if((L1 == 1)&&(M0 == 0)&&(R1 == 0))// 1 0 0 
	{
		sensor_bias = -125;decide = 4;
	}
	else if((L1 == 0)&&(M0 == 0)&&(R1 == 1))// 0 0 1 
	{
		sensor_bias = 62.5;decide = 4;
	}
	else if((L1 == 0)&&(M0 == 0)&&(R1 == 0))// 0 0 0 
	{
		decide = 6;
	}
	else if((L1 == 1)&&(M0 == 1)&&(R1 == 1))// 1 1 1 
	{
		decide = 6;FSM_state = Judge_state;		//如果读取到了整条黑线,那么就进入下一状态
		if(back_flag == 1)
		{
			FSM_state = Back_state;
			back_flag = 0;
		}			//第一次识别到全黑线为小车停止线。第二次识别到,代表小车即将回归循迹
	}

}
void Sensor_pid()
{
	if(decide<=5)
	{
		P = sensor_bias;
		I = I + sensor_bias;
		D = sensor_bias-sensor_bias_last;
		PID_value = Kp_sensor*P + Ki_sensor*I + Kd_sensor*D;
		sensor_bias_last = sensor_bias;
		//对积分值设置一个限制,防止积分值超标
		
		if(I >=3500)I = 3500;
		if(I <= -3500)I = -3500;
		PWM_value_R = 2099 - (int)PID_value;
		PWM_value_L = 2099 + (int)PID_value;//当线在左,左轮要慢,右轮要快,左轮要加,右轮要减,但这里的偏差是负值
		Motor3_forward(PWM_value_R);
		Motor4_forward(PWM_value_L);
		//4 --> 右电机
		//3 --> 左电机	
	}
	else{
		Move_stop();
	}
}

        对应的头文件部分

#ifndef __SENSOR_H
#define __SENSOR_H

//STEER4 --> PA11 --> R2  绿线
//STEER3 --> PC9 	--> R1  黄线
//		B  --> PB6  --> M0  橘线
//STEER1 --> PA6  --> L1  红线
// 		A  --> PB7	--> L2  白线
// 灰度传感器,当传感器识别到黑线的时候,输出为1,其余时刻输出为0
// 所以在这里我们要使用下拉输入
#define L2 GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_5)
#define L1 GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_6)
#define M0 GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_4)
#define R1 GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_9)
#define R2 GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_11)

void sensor_Init(void);
void sensor_read(void);
void Sensor_pid(void);

#endif

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ARM X210 官方 uboot 配置编译实践

一、X210官方uboot配置编译实践1 1. 找到官方移植好的 uboot&#xff08;BSP 概念&#xff09; (1) 源头的源代码是 uboot 官网下载的。这个下载的源代码可能没有你当前使用的开发板的移植&#xff0c;甚至找不到当前开发板使用的 SoC 对应的移植版本。 (2) SoC 厂商在推出一…

分享145个ASP源码,总有一款适合您

ASP源码 分享145个ASP源码&#xff0c;总有一款适合您 下面是文件的名字&#xff0c;我放了一些图片&#xff0c;文章里不是所有的图主要是放不下...&#xff0c; 145个ASP源码下载链接&#xff1a;https://pan.baidu.com/s/1gxm3rFFLu8pUhVncQga6-g?pwd7n85 提取码&#x…

HJ56、HJ58、JZ4、JZ6、JZ15、JZ17几道题

文章目录HJ56 完全数计算题目描述&#xff1a;具体实现&#xff1a;HJ58 输入n个整数&#xff0c;输出其中最小的k个题目描述&#xff1a;具体实现&#xff1a;JZ4 二维数组中的查找题目描述&#xff1a;具体实现&#xff1a;JZ6 从尾到头打印链表题目描述&#xff1a;具体实现…

springboot文件上传,单文件上传和多文件上传,以及数据遍历和回显

springboot文件上传&#xff0c;单文件上传和多文件上传项目结构及pom.xml创建文件表单页面编写javabean编写controller映射MultipartFile类RequestPart注解controller代码application.properties中的文件上传配置遍历数据显示页面运行显示项目结构及pom.xml pom.xml: <dep…

SQL用法详解补充

本文是对上次“SQL用法详解”的一些补充&#xff0c;一些基本操作可以点击链接查看 目录 一.对表结构的常用操作 查看表结构格式 修改表结构格式 1.修改列名和类型 2.修改添加列 3.修改表删除列 4.修改表名 5.数据删除 二.总结 三.实例 解决 完整代码 一.对表结构的常用操…

TIA博途中启用或禁用DP从站或PROFINET IO设备的具体方法

TIA博途中启用或禁用DP从站或PROFINET IO设备的具体方法 在实际项目中我们会遇到这样的问题, 例如:硬件组态中配置了一个控制器和3个 PN IO设备,但是最后只用到了2个PN IO设备,这样控制器一侧无法连接到第3个PN IO设备时,CPU会产生报警,PLC的Error指示灯会一直闪烁。 那么…

蓝桥杯2021省赛Python

蓝桥杯2021省赛Python 不得不说2021的比2020的难 1.卡片 很明显&#xff0c;最先没的肯定是1或者0&#xff0c;我们只要统计到谁会消耗2022个1或者0就好了 if __name__ __main__:res1 0res0 0for i in range(1,100000):i str(i)res1 i.count(1)res0 i.count(0)if res1…

[Rust笔记] 规则宏的“卫生保健”

规则宏代码的“卫生保健”规则宏mbe即是由macro_rules!宏所定义的宏。它的英文全称是Macro By Example。相比近乎“徒手攀岩”的Cpp模板元编程&#xff0c;rustc提供了有限的编译时宏代码检查功能&#xff08;名曰&#xff1a;Mixed Hygiene宏的混合保健&#xff09;。因为rust…

pointcovn 阅读笔记

各种点云采样算法 https://blog.csdn.net/weixin_41485242/article/details/107150963 Inverse Density 1.2 Inverse Density Importance Sampling (IDIS): 这个也比较好理解&#xff0c;简而言之就是根据每个点的密度来对其重新进行排序&#xff0c;尽可能地保留密度比较低的地…

python第九章 异常笔记

和Java类似程序运行有异常的时候&#xff0c;服务器会采用系统默认的异常处理机制&#xff1a;返回信息&#xff0c;终止程序。异常的类型&#xff1a;常见异常类型&#xff1a;1.NameError&#xff1a;访问了未定义的变量2.IndexError&#xff1a;越界访问3.AttributeError&am…

网络原理-网络发展史和通信基础

目录 1.网络发展史 面向终端的计算机网络 计算机网络阶段(局域网LAN) 组网方式 计算机网络互联阶段(广域网WAN) 2.通信基础 IP地址 端口号 网络协议 协议的作用 知名协议的默认端口 协议分层 分层的作用 OSI七层模型 TCP/IP五层模型 网络设备所在分层 网络分层…

《数据结构》八大排序和拓展的排序(详细教学并提供多种版本、动态图分析)

今天&#xff0c;我将带来数据结构的排序算法&#xff0c;排序算法作为校招中常考知识点之一&#xff0c;我们必须要熟练的掌握它,对自己提出高要求&#xff0c;才能有高回报。 目录排序的概念和应用内部排序和外部排序排序算法需要掌握的知识插入排序1.直接插入排序2.希尔排序…

【教程】Python实时检测CPU和GPU的功耗

目录 前言 GPU功耗检测方法 CPU功耗检测方法 sudo的困扰与解决 完整功耗分析示例代码 转载请注明出处&#xff1a;小锋学长生活大爆炸[xfxuezhang.cn] 前言 相关一些检测工具挺多的&#xff0c;比如powertop、powerstat、s-tui等。但如何通过代码的方式来实时检测&#xf…

Unsafe Fileupload-基础篇(文件上传绕过技巧与upload-labs靶场)

数据来源 本文仅用于信息安全的学习&#xff0c;请遵守相关法律法规&#xff0c;严禁用于非法途径。若观众因此作出任何危害网络安全的行为&#xff0c;后果自负&#xff0c;与本人无关。 文件上传基础 01 什么是文件上传 02 文件上传产生漏洞的原因 03 文件上传漏洞危害 0…

济人药业更新招股书:计划在A股上市,中成药业务收入持续下滑

近日&#xff0c;安徽济人药业股份有限公司&#xff08;下称“济人药业”&#xff09;递交预披露更新招股书&#xff0c;准备在上海证券交易所主板上市。据贝多财经了解&#xff0c;济人药业于2022年7月1日递交上市申请&#xff0c;此次更新了截至2022年6月30日的财务数据等信息…

Android深入系统完全讲解(42)

红色部分 pc 000007cc 代表当前 pc 指向的位置。libnative-lib.so 代表在哪个库里面。于是我 们就需要知道&#xff0c;libnative-lib.so 库的 pc 000007cc 偏移位置&#xff0c;是个什么代码。 我们从 NDK 开发包中找到 D:\android-ndk-r19c\toolchains\arm-linux-androideabi…

远程控制软件

远程控制软件1. 概述2. TeamViewer3. Todesk4. 向日葵5. AnyDesk6. Splashtop结束语1. 概述 出门在外或者工作时突然需要访问家中的电脑拿取文件或者资料时&#xff0c;是直接跑回家拿去、还是委托家里人员帮忙呢&#xff1f; 这时候你就需要一类软件来完成这个任务了&#xf…

前端图片压缩方案及代码实现

1. 为什么要进行图片压缩? 随着互联网的发展&#xff0c;图片在各种网站和应用中铺天盖地&#xff0c;运营人员在后台管理系统中上传图片时常常忽略的图片的体积大小&#xff0c;随之产生的带宽和服务器容量也大大增加&#xff0c;图片压缩的需求随之产生。 常见的压缩图片的…

【笔记】SemGCN

一. 论文总结 1.1 核心贡献 提出了一种改进的图卷积操作&#xff0c;称为语义图卷积(SemGConv)&#xff0c;它源自cnn。其关键思想是学习图中暗示的边的信道权值&#xff0c;然后将它们与核矩阵结合起来。这大大提高了图卷积的能力。其次&#xff0c;我们引入了SemGCN&#x…

GPU服务器上跑深度学习模型

1 问题来源 近期在本地 Windows 系统上跑深度学习人群计数模型时&#xff0c;由于笔记本 NVIDIA 显卡 NVIDIA GeForce GTX 1650 的专用 GPU 内存只有 4 GB&#xff0c;无法设置较大的 batchsize 进行训练&#xff0c;导致模型训练时间过长&#xff0c;且易发生内存溢出&#xf…