循迹小车基本原理和代码实现

news2024/11/19 9:19:32

目录

一、循迹模块使用

二、接线方式

三、循迹小车原理

四、代码实现


一、循迹模块使用

1、TCRT5000传感器的红外发射二极管不断发射红外线,当发出的红外线没有被反射回来或被反射回来但强度不太够时,红外接收管一直处于关断状态,此时模块的输出为高电平指示二极管一直处于熄灭状态,被检测物体出现在检测范围内时,红外线被反射回来且强度足够大,红外接收管饱和,此时模块的输出端为低电平,指示二极管被点亮

总之一句话:没反射回来,D0输出高电平,灭灯

二、接线方式

VCC:接上官一号正极(3-5V)

GND:接上官一号负极

D0:TTL开关信号输出0、1

A0:模拟信号输出(不同距离输出不同的电压,此脚一般可以不接)

三、循迹小车原理

由于黑色具有较强的吸收能力,当循迹模块发射的红外线照射到黑线时,红外线将会被黑线吸收,导致循迹模块上光敏二

0.极管处于关闭状态,此时模块上一个LED熄灭,在没有检测到黑线时,模块上两个LED常亮

总结就是一句话:有感应到黑线,D0输出高电平,灭灯

循迹模块安装在小车车头两侧

下方小车两个模块都能反射回来红外,输出低电平,灯亮,直走

上方小车左循迹模块遇到黑线,红外被吸收,左模块输出高电平,右模块输出低电平,左转,反之右转 

总结:两个小绿灯都亮,那左右两边的车轮就都转动,只亮一个小绿灯的说明这侧遇到了黑线,红外被吸收,红外没有被反射回来,输出高电平,所以就不转动了。

四、代码实现

main.c

#include "motor.h"
#include "delay.h"
#include "uart.h"
#include "time.h"
#include "reg52.h"

extern char speedLeft;   //此变量/函数是在别处定义的,要在此处引用
extern char speedRight;

sbit leftSensor  = P2^7;
sbit rightSensor = P2^6;

void main()
{
	Time0Init();   //定时器0初始化
	Time1Init();   //定时器1初始化
	UartInit();    //串口初始化

	while(1){
		
		if(leftSensor == 0 && rightSensor == 0 ){
			//直走
			speedLeft = 40;   
			speedRight = 40;
		}
		if(leftSensor == 1 && rightSensor == 0 ){
			//左转
			speedLeft = 10;   
			speedRight = 40;
			
		}
		if(leftSensor == 0 && rightSensor == 1 ){
			//右转
			speedLeft = 40;
			speedRight = 10;
			
		}
		if(leftSensor == 1 && rightSensor == 1){
			//停止
			speedLeft = 0;
			speedRight = 0;
		}		
	}
}

motor.c

#include "reg52.h"


sbit RightCon1A = P3^2;
sbit RightCon1B = P3^3;

sbit LeftCon1A = P3^4;
sbit LeftCon1B = P3^5;

void goForWardLeft(){     //小车左前进

	LeftCon1A = 1;
	LeftCon1B = 0;
}

void goForWardRight(){    //小车右前进
	
	
	RightCon1A = 1;
	RightCon1B = 0; 
}

void stopLeft(){          //小车左停止

	LeftCon1A = 0;
	LeftCon1B = 0;
}

void stopRight(){         //小车右停止
	 
	RightCon1A = 0;
	RightCon1B = 0; 
}

void goForWard(){         //小车前转

	LeftCon1A = 1;
	LeftCon1B = 0;
	RightCon1A = 1;
	RightCon1B = 0; 

}

void goBack(){           //小车后转
	
	LeftCon1A = 0;
	LeftCon1B = 1;
	RightCon1A = 0;
	RightCon1B = 1; 
}

void goLeft(){   //小车左转
	
	LeftCon1A = 0;
	LeftCon1B = 0;
	RightCon1A = 1;
	RightCon1B = 0; 
}



void goRight(){   //小车右转
	
	LeftCon1A = 1;
	LeftCon1B = 0;
	RightCon1A = 0;
	RightCon1B = 0; 
}


void stop(){   //小车停止
	
	LeftCon1A = 0;
	LeftCon1B = 0;
	RightCon1A = 0;
	RightCon1B = 0; 
}

motor.h

void goForWard();
void goBack();
void goLeft();
void goRight();
void stop();
void goForWardLeft();
void goForWardRight();
void stopLeft();
void stopRight();

delay.c


#include "intrins.h"

void Delay1000ms()		//@11.0592MHz
{
	unsigned char i, j, k;

	_nop_();
	i = 8;
	j = 1;
	k = 243;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}

void Delay10ms()		//@11.0592MHz
{
	unsigned char i, j;

	i = 18;
	j = 235;
	do
	{
		while (--j);
	} while (--i);
}

delay.h

void Delay1000ms();
void Delay10ms();

uart.c------串口初始化文件

#include "reg52.h"
#include "motor.h"
#include "string.h"
#include "delay.h"
#define SIZE 12

sfr AUXR = 0x8E;
char cmd;
char buffer[SIZE];

void UartInit(void)		//9600bps@11.0592MHz
{
	AUXR = 0x01;   //降低时钟对外界的辐射
	SCON = 0x50;   //串行口寄存器工作模式选择方式1,RNE=1,为串行允许接收状态
	
	TMOD &= 0x0F;  //定时器1工作方式位8位自动重装
	TMOD |= 0x20;
	
	TH1 = 0xFD; 
	TL1 = 0xFD;   //9600波特率的初值
	TR1 = 1;      //启动定时器
	
	EA = 1;       //总中断寄存器,开启总中断
	ES = 1;       //开启串口中断
	
}



void	Uart_Handler()	interrupt 4
{
	
	char tmp;
	static int i = 0;   //静态变量,被初始化一次
	if(RI == 1){        //中断处理函数中,对于接收中断的响应  
		RI = 0;           //清除接收中断标志位
		tmp = SBUF;
		if(tmp == 'M'){
			i = 0;
		}
		buffer[i++] = tmp;
	
		if(buffer[0] == 'M'){
			switch(buffer[1]){
				
				case '1':
					goForWard();
					Delay10ms();
					break;
				case '2':
					goBack();
					Delay10ms();
					break;
				case '3':
					goLeft();
					Delay10ms();
					break;
				case '4':
					goRight();
					Delay10ms();
					break;
				default:
					stop();
					break;
			}
			
		}
		if(i == 12) {
			i = 0;
			memset(buffer,'\0',SIZE);
		}
	}
}

uart.h

void UartInit(void);

time.c------初始化定时器及定时器开启中断文件


#include "motor.h"
#include "reg52.h"

char speedLeft;
char cntLeft = 0;


char speedRight;
char cntRight = 0;

void Time1Init(){

	//1、配置定时器0工作模式位16位计时
	TMOD &= 0x0F;
	TMOD |= 0x1 << 4;
	//2、给定时器一个初值,每个周期都等于0.5ms
	TL1 = 0x33;
	TH1 = 0xFE;
	//3、定时器开始计时
	TR1 = 1;
	TF1 = 0;
	
	//4、打开中断定时器1
	ET1 = 1;
	//5、设置总中断定时器
	EA = 1;
	
}

void Time0Init(){

	//1、配置定时器0工作模式位16位计时
	TMOD = 0x01;
	//2、给定时器一个初值,每个周期都等于0.5ms
	TL0 = 0x33;
	TH0 = 0xFE;
	//3、定时器开始计时
	TR0 = 1;
	TF0 = 0;
	
	//4、打开中断定时器
	ET0 = 1;
	//5、设置总中断定时器
	EA = 1;
	
}

void Time1Handler() interrupt 3   //定时器0的中断号为 interrupt 1
{
	
	cntRight ++;           //统计爆表的次数
	//给定时器重新定义初值,每个周期都等于0.5ms
	TL1 = 0x33;      
	TH1 = 0xFE;
	//控制PWM波形
	if(cntRight < speedRight){
		//右前进
		goForWardRight();
		
	}else{
		//右停止
		stopRight();
		
	}
	
	if(cntRight == 40){   //要爆表40次,经过了20ms
			cntRight = 0;      //当100次表示1s,重新让cnt从0开始,计算下一次的1s
			
	}
}


void Time0Handler() interrupt 1   //定时器0的中断号为 interrupt 1
{
	
	cntLeft ++;           //统计爆表的次数
	//给定时器重新定义初值,每个周期都等于0.5ms
	TL0 = 0x33;      
	TH0 = 0xFE;
	//控制PWM波形
	if(cntLeft < speedLeft){
		//左前进
		goForWardLeft();
		
	}else{
		//左停止
		stopLeft();
		
	}
	
	if(cntLeft == 40){   //要爆表40次,经过了20ms
			cntLeft = 0;      //当100次表示1s,重新让cnt从0开始,计算下一次的1s
			
	}
}

time.h

void Time0Init();
void Time1Init();

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

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

相关文章

将本地SpringBoot微服务制作成Docker Image镜像包然后运行

将本地SpringBoot微服务制作成Docker Image镜像包然后运行 文章目录将本地SpringBoot微服务制作成Docker Image镜像包然后运行1&#xff09;环境准备2&#xff09;验证jar包3&#xff09;制作images镜像包4&#xff09;注意1&#xff09;环境准备 准备一个SpringBoot项目&…

音视频笔记

音视频笔记 基础理论知识 雷神的博客 [总结]视音频编解码技术零基础学习方法 视频压缩 H264码流结构 码流结构&#xff1a;原来你是这样的H264 H265码流结构 音视频基础&#xff1a;H265/HEVC&码流结构 FFMPEG 雷神的博客 [总结]FFMPEG视音频编解码零基础学习方法…

1583_AURIX_TC275_SMU的控制以及FSP

全部学习汇总&#xff1a; GreyZhang/g_TC275: happy hacking for TC275! (github.com) SMU的软件控制接口主要是实现了一些控制命令&#xff0c;用于控制SMU的状态机以及FSP。具体的内容在上面的一部分表格以及接下来的一页中的表格中有介绍。 涉及到ed命令&#xff0c;用几个…

NC6 Error to init aggVOStyle,Please check the back log

由于近期调整及抵消模板的公式字段长度不够&#xff0c;就修改了元数据的字符长度&#xff0c;结果导致修改保存后保存&#xff0c;报错如下&#xff08;如果大家有什么好的解决方案&#xff0c;欢迎评论留言一起探讨学习&#xff09;&#xff1a; 错误日志&#xff1a; 11:1…

Slurm中集群配置文件slum.conf

1.slurm.conf简介slurm.conf是一个ASCII文件&#xff0c;它描述了一般的Slurm 配置信息、要管理的节点、有关如何将这些节点分组到分区中&#xff0c;以及各种调度与这些分区关联的参数。此文件应为在群集中的所有节点上保持一致。可以通过设置SLURM_CONF在执行时修改文件位置 …

初识网络:IP、端口、网络协议、TCP-IP五层模型

目录 一、了解IP地址&#xff1a; 二、了解端口号: 三、网络协议 网络协议的三要素: ①语法 ②语义 ③时序 四、协议的分层(TCP/IP五层模型&#xff09; ①应用层 ②传输层&#xff08;也称为运输层&#xff09; ③网络层 ④数据链路层 ⑤物理层 五、A用户通过QQ给B发送一…

【Java基础知识 2】Java中常用的48个关键字和2个保留字 || Java命名规范(从此告别起名难)

本文已收录专栏 &#x1f332;《Java进阶之路》&#x1f332; 目录 本文已收录专栏 &#x1f332;《Java进阶之路》&#x1f332; Java中常用的48个关键字和2个保留字 关键字 保留字 Java命名规范&#xff08;从此告别起名难&#xff09; 01、包&#xff08;package&#…

Spring MVC 整合 Shiro 权限控制

Apache Shiro 是一个功能强大且灵活的开放源代码安全框架&#xff0c;可以细粒度地处理认证 (Authentication)&#xff0c;授权 (Authorization)&#xff0c;会话 (Session) 管理和加密 (cryptography) 等企业级应用中常见的安全控制流程。 Apache Shiro 的首要目标是易于使用和…

python实现excel和csv中的vlookup函数

本篇博客会介绍如何使用python在excel和csv里实现vlookup函数的功能&#xff0c;首先需要简单了解一下python如何操作excel 1. python处理excel 1.1 删除excel中指定行 在文件夹里创建了一个excel文件&#xff0c;可以看到里面放的是三国人物的数据 会发现在【蜀】里&#…

ESP-IDF:在C++环境下实现动态数组例程,包括初始化,添加数值,查找,删除,打印等功能

代码&#xff1a; /* 动态数组 */ struct DYNAMICARRAY { int *pAddress; int size; int capacity; }; DYNAMICARRAY *initialDynamicArray() { DYNAMICARRAY *p (DYNAMICARRAY *)malloc(sizeof(DYNAMICARRAY)); p->size 0; p->capacity 5; p->pAddress (int *)…

数据结构与算法--python版-01

文章目录基本概念数据存储方式算法案例基本概念 程序 数据结构 算法 数据结构&#xff0c;数据的存储&#xff08;物理结构&#xff09;及相互间的关联关系(逻辑结构)&#xff1b; 线性表&#xff08;顺序表、链表、队列、栈&#xff09;&#xff0c;一个前驱&#xff0c;一…

口语语言理解最新进展及前沿

口语语言理解 作为任务型对话系统的核心组件&#xff0c;目的是为了获取用户询问语句的框架语义表示信息&#xff0c;进而将这些信息为对话状态的追踪模块DSTDSTDST, 以及自然语言生成模块NLGNLGNLG所使用 SLUSLUSLU任务通常包含以下两个任务: 意图识别任务: intent detectio…

企企购商城 | 破解降本难题,非生采购“利器”来了

近年来&#xff0c;疫情反复无常&#xff0c;全球市场环境动荡不安&#xff0c;在瞬息万变的环境下&#xff0c;很多企业都处于降本处境&#xff0c;采购降本成了其中的重要一环。其中&#xff0c;非生采购作为贯穿企业各个职能板块的采购活动&#xff0c;众多国际先进的企业已…

应用PID算法对ABS系统的仿真和分析

1、内容简介略635-论文V2 可以交流、咨询、答疑2、内容说明摘要&#xff1a;本文旨在设计一种利用模糊控制理论优化的pid控制器&#xff0c;控制abs系统&#xff0c;达到对滑移率最佳控制范围的要求 &#xff0c;所提出的方案采用级联控制架构&#xff1a;设计用于外环中的车轮…

零基础开始QT绘图(6)

前面我们开始提到了GraphicView的使用&#xff0c;也提到GraphicsItem的使用&#xff0c;并且开始了自定义GraphicsItem的编写&#xff0c;而且上次我们的GraphicsItem也是可以拖动了&#xff0c;但这离我们需要的效果还有一定的距离。 所以&#xff0c;这次&#xff0c;我们进…

工程电磁设备在2018年杭州电磁大会的报告

1 方法原理 本篇是对多频电磁方法,应用的解读。 本汇报讲述了EMI传感器的基本情况,以及用手持多频电磁仪进行实际探测应用的例子。 什么是电磁感应?用发射装置(TX)激发谐波,产生一次场(Primary field),地下导体目标会相应产生涡流电磁场,产生二次场,被接收装置(RX…

「网络安全渗透」如果你还不懂CSRF?这一篇让你彻底掌握

1 什么是 CSRF 面试的时候的著名问题&#xff1a;"谈一谈你对 CSRF 与 SSRF 区别的看法" 这个问题&#xff0c;如果我们用非常通俗的语言讲的话&#xff0c;CSRF 更像是钓鱼的举动&#xff0c;是用户攻击用户的&#xff1b;而对于 SSRF 来说&#xff0c;是由服务器…

14.0、Linux-yum方式安装 docker

14.0、Linux-yum方式安装 docker 第一步&#xff1a; 检测 CentOS7 -> cat /etc/redhat-release 第二步&#xff1a; 用以下命令安装准备环境 -> yum -y install gcc yum -y install gcc-c 第三步&#xff1a; 如果之前安装过 docker 的&#xff0c;先用以下命令删…

【每日一题】【LeetCode】【第十三天】移动零

解决之路 题目描述 测试案例&#xff08;部分&#xff09; 第一次 看到这题目&#xff0c;第一时间还真想到了双指针法&#xff08;暴力解法是个会写代码的都能第一时间想到&#xff0c;所以自己学会了尽量不第一时间用暴力解法&#xff09; right的初始位置元素若为0&…

Jenkins-Slave分布式架构搭建

♥ Jenkins的分布式构建&#xff0c;在Jenkins的配置中叫做节点&#xff0c;分布式构建能够让同一套代码或项目在不同的环境(如&#xff1a;Windows和Linux系统)中编译、部署等。 ♥ 将jenkins项目发布在不同服务器上&#xff08;分布jenkins工作空间&#xff0c;部署项目到不同…