今日得以继续我的MSP432学习之路,今日学习八路寻迹模块的编程与测试:
本章需要掌握的知识只有俩个:串口通信发送数据、GPIO基础初始化与获取电平状态
这俩个在我专栏里都可寻到,大家可以自行查找~~
八路灰度寻迹模块的原理与应用:
下图就是八路灰度传感寻迹模块了,它长这样:
为何称之为灰度传感器,而不是颜色传感器呢,因为它实质上是没有颜色传感的:
灰度传感器利用不同颜色的检测面对光的反射程度不 同的原理进行颜色深浅检测。在有效的检测距离内 (理论上距离可以无限远,实际受外界光 源的影响,最佳距离为 15mm 至 50mm, 如果距离过高的话,需要进行遮光) ,发光二极管发 出的光,照射在检测面上,检测面反射部分光线,光敏二极管检测此光线的强度并将其转换 为单片机可以识别的电信号。这个电信号是一个模拟值,单片机可以根据不同处理手段对其处理后反馈给主机
况且 :
颜色传感器容易受外界光线影响,需要在黑暗环境下使用,而且颜色传感器获得的信号是反应 RGB 三色的复杂数据信号,因此,颜色传感器的通信过程非常复杂,更重要的是价格昂贵。
这里我画了它的原理框图,帮助大家理解:
主要还是推荐直接用那八根线,IIC是接OLED调试用的,UART用处不明,商家自己说用到PID算法,但MSP432串口资源有限,因此不建议占用串口~~
直接使用OUT1~8这八根高低电平输出线即可,因为通用输入输出口资源足够的。
编程思路:
基本是使用商家给的八路寻迹代码,但商家没有注释,此处我贴出注释就好理解了:
我们可以看到,它是根据车辆与线在横向的左右偏移量来决定车辆轮胎运转差速的:
而这个左右便宜的量的大小是根据八路寻迹探测情况八个输出口的高低电平情况判断的:
检测到线,就会返回低电平,反之为高:
void XunXian() //巡线检测
{
//刚好在线上,车轮均匀速
if((D4 == 0)&&(D5 == 0))
{
// motor(40,40);
}
//车辆右偏0~1cm,左慢右快
else if((D4 == 0)&&(D5 != 0))
{
// motor(38,40);
}
//车辆左偏0~1cm,右慢左快
else if((D4 != 0)&&(D5 == 0))
{
// motor(40,38);
}
//车辆右偏1.5cm,
else if((D3 == 0)&&(D4 == 0))
{
// motor(32,40);
}
//车辆左偏1.5cm,
else if((D5 == 0)&&(D6 == 0))
{
// motor(40,32);
}
//车辆右偏2.5cm,
else if((D3 == 0)&&(D4 != 0))
{
// motor(25,40);
}
//车辆左偏2.5cm,
else if((D5 != 0)&&(D6 == 0))
{
// motor(40,25);
}
//车辆右偏3.5cm,
else if((D2 == 0)&&(D3 == 0))
{
// motor(20,40);
}
//车辆左偏3.5cm,
else if((D6 == 0)&&(D7 == 0))
{
// motor(40,20);
}
//车辆右偏4.5cm,
else if((D2 == 0)&&(D3 != 0))
{
// motor(15,40);
}
//车辆左偏4.5cm,
else if((D6 != 0)&&(D7 == 0))
{
// motor(40,15);
}
//车辆右偏5.5cm,
else if((D1 == 0)&&(D2 == 0))
{
// motor(10,40);
}
//车辆左偏5.5cm,
else if((D7 == 0)&&(D8 == 0))
{
// motor(40,10);
}
//车辆右偏6.5cm,
else if((D1 == 0)&&(D2 != 0))
{
// motor(0,40);
}
//车辆左偏6.5cm,
else if((D7 !=0)&&(D8 == 0))
{
// motor(40,0);
}
//其余检测不到的情况先停止
else
{
// motor(20,20);
}
模块调试:
模块需要我们调试给定什么是背景,什么是线,因为背景与线的颜色可能不一致,这个需要我们给模块调试上去,不喜欢看字的可以看一遍调试视频:
我们发现模块上有三个按键:K1、RST、K2
RST是复位用的,一般不用~
进入调试模式:
长按K1俩秒左右进入调试模式,此时红色指示灯会亮起:
1、采集背景色模式:
第一个灯会亮,此时进入采集背景色的环节,将传感头一排都放在背景色上,按一下K2,红灯会闪烁一下,表示采集有效,不闪就是无效
2.采集巡线颜色模式:
背景采集结束后,按一下K1,第二个灯会亮,此时采集的是巡线的颜色,将传感头一排都放在背景色上,按一下K2,红灯会闪烁一下,表示采集有效,不闪就是无效
3.设置高低电平输出模式:
巡线颜色采集结束后,按一下K1,第三个灯会亮,此时可以按K2切换输出电平,要结合D6灯观看,D6亮起,表示巡线输出低电平,反之,则高电平
4.切换数据输出类型:
高低电平输出模式设置结束后,按一下K1,第四个灯会亮,此时按K2切换数据输出的类型,要结合D7观看,D7亮,表示输出误差值,D7灭,表示输出高低电平情况
5.采集线中位置数据:
数据类型输出切换结束后,按一下K1,第五个灯会亮起,此时需要将模块正放在线上,使其中间的D4,D5在线上,其余在背景上,表示正确的巡线位置,按一下K2进行采集,红灯会闪烁一下,表示采集有效,不闪就是无效
完成调试后长按我们的K1退出调试模式,红灯灭就是退出了~
调试视频:
寻迹模块的调试
编程实践:
首先确定我们需要使用的引脚,P4^0~P4^7,分别接上OUT1~8,其次初始化以上的GPIO口为输入模式:
void inint_Xunxian(void)//巡线引脚初始化
{
//设置为输入脚:
GPIO_setAsInputPin (GPIO_PORT_P4,GPIO_PIN0);
GPIO_setAsInputPin (GPIO_PORT_P4,GPIO_PIN1);
GPIO_setAsInputPin (GPIO_PORT_P4,GPIO_PIN2);
GPIO_setAsInputPin (GPIO_PORT_P4,GPIO_PIN3);
GPIO_setAsInputPin (GPIO_PORT_P4,GPIO_PIN4);
GPIO_setAsInputPin (GPIO_PORT_P4,GPIO_PIN5);
GPIO_setAsInputPin (GPIO_PORT_P4,GPIO_PIN6);
GPIO_setAsInputPin (GPIO_PORT_P4,GPIO_PIN7);
}
此处位带操作没有实际意义用途,纯属为了接线提示:
// 位带操作
//定义八路寻迹引脚名称
#define OUT1 BITBAND_PERI(P4OUT,0)
#define OUT2 BITBAND_PERI(P4OUT,1)
#define OUT3 BITBAND_PERI(P4OUT,2)
#define OUT4 BITBAND_PERI(P4OUT,3)
#define OUT5 BITBAND_PERI(P4OUT,4)
#define OUT6 BITBAND_PERI(P4OUT,5)
#define OUT7 BITBAND_PERI(P4OUT,6)
#define OUT8 BITBAND_PERI(P4OUT,7)
我们在需要获得引脚状态的时候使用函数: 来获取引脚高低电平状态:
uint8_t GPIO_getInputPinValue (uint8_t selectedPort,uint16_t selectedPins )
代码部分十分简单,这个自己编写就行,实在不会参考以下:
#include "main.h"
int main(void)
{
SysInit();
uart_init(115200);
delay_init();
TimA0_Int_Init(CCR0_COMMON,CLK_DIV_COMMON);//用宏定义初始化通用定时器,周期1ms
// Interrupt_CAP_inint(); //外部中断初始化
// inint_TB6612(); //初始化电机
inint_Xunxian(); //巡线引脚初始化
printf("Hello,MSP432!\r\n");
MAP_Interrupt_enableMaster(); // 开启总中断
while (1)
{
if(FTT_flag==1)
{
FTT_flag=0;
XunXian(); //巡线检测,获取电平情况,再分析
printf("D1=%d,D2=%d,D3=%d,D4=%d,D5=%d,D6=%d,D7=%d,D8=%d\r\n",D1,D2,D3,D4,D5,D6,D7,D8);//打印结果
}
}
}
//通用定时器中断中断服务函数,周期2ms
void TA0_0_IRQHandler(void)
{
MAP_Timer_A_clearCaptureCompareInterrupt(TIMER_A0_BASE, TIMER_A_CAPTURECOMPARE_REGISTER_0);
if(++FTT_cnt==1000) //每1反馈一次寻迹结果
{ FTT_cnt=0;FTT_flag=1;}
}
#ifndef _main_h_
#define _main_h_
#include "sysinit.h"
#include "usart.h"
#include "delay.h"
#include "led.h"
#include "tim32.h"
#include "TB6612.h"
#include "string.h"
#include "timA.h"
#include <ti/devices/msp432p4xx/driverlib/driverlib.h>
#include "FTT.h"
//宏定义 通用定时器需要的参数
#define CCR0_COMMON 999
#define CLK_DIV_COMMON 48
uint16_t FTT_flag=0; //寻迹检测标志
uint32_t FTT_cnt; //寻迹计时标志
#endif
#include "FTT.h"
uint8_t D1,D2,D3,D4,D5,D6,D7,D8;
void inint_Xunxian(void)//巡线引脚初始化
{
//设置为输入脚:
GPIO_setAsInputPin (GPIO_PORT_P4,GPIO_PIN0);
GPIO_setAsInputPin (GPIO_PORT_P4,GPIO_PIN1);
GPIO_setAsInputPin (GPIO_PORT_P4,GPIO_PIN2);
GPIO_setAsInputPin (GPIO_PORT_P4,GPIO_PIN3);
GPIO_setAsInputPin (GPIO_PORT_P4,GPIO_PIN4);
GPIO_setAsInputPin (GPIO_PORT_P4,GPIO_PIN5);
GPIO_setAsInputPin (GPIO_PORT_P4,GPIO_PIN6);
GPIO_setAsInputPin (GPIO_PORT_P4,GPIO_PIN7);
}
void XunXian(void) //巡线检测,获取电平情况,再分析
{
//获取电平状态
D1=GPIO_getInputPinValue (GPIO_PORT_P4,GPIO_PIN0);
D2=GPIO_getInputPinValue (GPIO_PORT_P4,GPIO_PIN1);
D3=GPIO_getInputPinValue (GPIO_PORT_P4,GPIO_PIN2);
D4=GPIO_getInputPinValue (GPIO_PORT_P4,GPIO_PIN3);
D5=GPIO_getInputPinValue (GPIO_PORT_P4,GPIO_PIN4);
D6=GPIO_getInputPinValue (GPIO_PORT_P4,GPIO_PIN5);
D7=GPIO_getInputPinValue (GPIO_PORT_P4,GPIO_PIN6);
D8=GPIO_getInputPinValue (GPIO_PORT_P4,GPIO_PIN7);
}
#ifndef _FTT_h_
#define _FTT_h_
#include <ti/devices/msp432p4xx/driverlib/driverlib.h>
// 位带操作
//定义八路寻迹引脚名称
#define OUT1 BITBAND_PERI(P4OUT,0)
#define OUT3 BITBAND_PERI(P4OUT,2)
#define OUT5 BITBAND_PERI(P4OUT,4)
#define OUT7 BITBAND_PERI(P4OUT,6)
#define OUT2 BITBAND_PERI(P4OUT,1)
#define OUT4 BITBAND_PERI(P4OUT,3)
#define OUT6 BITBAND_PERI(P4OUT,5)
#define OUT8 BITBAND_PERI(P4OUT,7)
extern uint8_t D1,D2,D3,D4,D5,D6,D7,D8;
void inint_Xunxian(void);//巡线引脚初始化
void XunXian(void); //巡线检测,获取电平情况,再分析
#endif
测试效果视频:
巡线下载测试