6.2小车循迹,跟随,摇头测距功能实现

1.循迹小车

  1. 1循迹模块的使用

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

  • 接线方式 VCC:接电源正极(3-5V) GND:接电源负极 DO:TTL开关信号输出0、1 AO:模拟信号输出(不同距离输出不同的电压,此脚一般可以不接),ADC在后面学习stm32中学到

1.2 循迹小车原理

由于黑色具有较强的吸收能力,当循迹模块发射的红外线照射到黑线时,红外线将会被黑线吸收,导致 循迹模块上光敏三极管处于关闭状态,此时模块上一个LED熄灭。在没有检测到黑线时,模块上两个LED 常亮

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

循迹模块安装在小车车头两侧 下方小车两个模块都能反射回来红外,输出低电平,灯亮,直走 上方小车左模块遇到黑线,红外被吸收,左模块输出高电平,右模块输出低电平,左转,反之右转

1.3代码-循迹小车不调速

main.c

void main()
{
//    没反射回来,D0输出高电平,灭灯      都反射回来亮灯
//    Timer0Init();
//    Timer1Init();
//    UartInit();

    while(1){
        if(LeftTarce == 0 && RightTarce == 0){
           goForward();
    
         }
        if(LeftTarce == 0 && RightTarce == 1){
            goRight();
        }
        if(LeftFollow == 1 && RightTarce == 0){
             goLeft();
        }
        if(LeftTarce == 1 && RightTarce == 1){
          stop();
        }
    }    

}

1.4代码-循迹小车调速

main.c

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

extern int speedLeft;
extern int speedRight;

void main()
{
//    没反射回来,D0输出高电平,灭灯
    Timer0Init();
    Timer1Init();
//    UartInit();

    while(1){
        if(LeftTarce == 0 && RightTarce == 0){
           //都反射回来,没遇到黑色,直走
           speedLeft   = 70;
           speedRight = 70;
         }
        if(LeftTarce == 0 && RightTarce == 1){
           //右侧遇到黑色,需要右转
           speedLeft   = 80;
           speedRight  = 10;
        }
        if(LeftTarce == 1 && RightTarce == 0){
          //左侧遇到黑色,需要右转
          speedLeft   = 10;
          speedRight  = 80;
        }
        if(LeftTarce == 1 && RightTarce == 1){
          //都遇到黑色
          speedLeft   = 0;
          speedRight  = 0;
        }
    }
    
}

motoc.c

#include "reg52.h"
#include "config.h"

void goForwardLeft()
{
    LeftCon1A = 0;    
    LeftCon1B = 1;
}

void goForwardRight()
{
    RightCon1A = 0;
    RightCon1B = 1;
}

void stopLeft()
{
    LeftCon1A = 0;    
    LeftCon1B = 0;
}

void stopRight()
{
    RightCon1A = 0;
    RightCon1B = 0;
}


void goBack()
{
    RightCon1A = 1;
    RightCon1B = 0;

    LeftCon1A = 1;    
    LeftCon1B = 0;
}
void goForward()
{
    RightCon1A = 0;
    RightCon1B = 1;

    LeftCon1A = 0;    
    LeftCon1B = 1;
}
void goRight()
{
    RightCon1A = 0;
    RightCon1B = 0;

    LeftCon1A = 0;    
    LeftCon1B = 1;
}
void goLeft()
{
    RightCon1A = 0;
    RightCon1B = 1;

    LeftCon1A = 0;    
    LeftCon1B = 0;
}
void stop()
{
    RightCon1A = 0;
    RightCon1B = 0;

    LeftCon1A = 0;    
    LeftCon1B = 0;
}

time.c

#include "reg52.h"
#include "motor.h"
sfr AUXR = 0x8e;

int cntLeft  = 0;
int cntRight = 0;
int speedLeft;
int speedRight;

void Timer0Init(void)        //500微秒@11.0592MHz
{
    AUXR &= 0x7F;        //定时器时钟12T模式
    TMOD &= 0xF0;        //设置定时器模式
    TMOD |= 0x01;        //设置定时器模式      
    TL0 = 0x33;        //设置定时初值
    TH0 = 0xFE;        //设置定时初值
    TF0 = 0;        //清除TF0标志
    TR0 = 1;        //定时器0开始计时
    EA  = 1;
    ET0 = 1;
}

void Timer1Init(void)        //500微秒@11.0592MHz
{
    AUXR &= 0x7F;        //定时器时钟12T模式
    TMOD &= 0x0F;        //设置定时器模式
    TMOD |= 0x20;        //设置定时器模式      
    TL1 = 0x33;        //设置定时初值
    TH1 = 0xFE;        //设置定时初值
    TF1 = 0;        //清除TF0标志
    TR1 = 1;        //定时器0开始计时
    EA  = 1;
    ET1 = 1;
}

void Time0Init() interrupt 1
{
        cntLeft++;       //统计爆表的次数     
        //重新给初值
        TL0 = 0x33;
        TH0 = 0xFE;
        if(cntLeft < speedLeft){
            goForwardLeft();
        }else{
            stopLeft();    
        }

        if(cntLeft == 80){
            cntLeft = 0;
        }
}

void Time1Init() interrupt 3
{
        cntRight++;       //统计爆表的次数     
        //重新给初值
        TL1 = 0x33;
        TH1 = 0xFE;
        if(cntRight < speedRight){
            goForwardRight();
        }else{
            stopRight();    
        }

        if(cntRight == 80){
            cntRight = 0;
        }
}

2. 跟随小车

2.1红外壁障模块分析

原理和寻线是一样的,寻线红外观朝下,跟随朝前

2.2跟随小车的原理

左边跟随模块能返回红外,输出低电平,右边不能返回,输出高电平,说明物体在左边,需要左转 右边跟随模块能返回红外,输出低电平,左边不能返回,输出高电平,说明物体在右边,需要右转

2.3代码-跟随小车

void main()
{
//左边跟随模块能返回红外,输出低电平,右边不能返回,输出高电平,说明物体在左边,需要左转
//右边跟随模块能返回红外,输出低电平,左边不能返回,输出高电平,说明物体在右边,需要右转
    while(1){
        if(LeftFollow == 0 && RightFollow == 0){
           goForward();
    
         }
        if(LeftFollow == 0 && RightFollow == 1){
            goLeft();
        }
        if(LeftFollow == 1 && RightFollow == 0){
             goRight();
        }
        if(LeftFollow == 1 && RightFollow == 1){
          stop();
         }
        }
}

3. 摇头测距小车

  • 1. 改装垃圾桶代码 2. 实现摇头功能,实现疯狂摇头

3.1上代码-疯狂摇头

#include "reg52.h"
#include "hc04.h"
#include "delay.h"
#include "sg90.h"
void main()
{
    Time0Init();
    Time1Init();
    //舵机的初始位置
    sgMiddle();
    Delay300ms();
    Delay300ms();
    while(1){
    sgLeft();
    Delay300ms();
    sgMiddle();
    Delay300ms();
    sgRight();
    Delay300ms();
    sgMiddle();
    Delay300ms();
    }
}


#include "reg52.h"
#include "delay.h"
sbit sg90_con = P1^1;
int jd;
int cnt = 0;
void Time0Init()
{
    //1. 配置定时器0工作模式位16位计时
    TMOD &= 0xF0; //设置定时器模式
    TMOD |= 0x01;
    //2. 给初值,定一个0.5出来
    TL0=0x33;
    TH0=0xFE;
    //3. 开始计时
    TR0 = 1;
    TF0 = 0;
    //4. 打开定时器0中断
    ET0 = 1;
    //5. 打开总中断EA
    EA = 1;
}

void sgMiddle()
{
    //中间位置
    jd = 3; //90度 1.5ms高电平
    cnt = 0;
}
void sgLeft()
{
    //左边位置
    jd = 5; //135度 1.5ms高电平
    cnt = 0;
}
void sgRight()
{
    //右边位置
    jd = 1; //0度
    cnt = 0;
}
void Time0Handler() interrupt 1
{
    cnt++; //统计爆表的次数. cnt=1的时候,报表了1
    //重新给初值
    TL0=0x33;
    TH0=0xFE;
    //控制PWM波
    if(cnt < jd){
        sg90_con = 1;
    }else{
        sg90_con = 0;
    }
    if(cnt == 40){//爆表40次,经过了20ms
        cnt = 0; //当100次表示1s,重新让cnt从0开始,计算下一次的1s
        sg90_con = 1;
    }
}

3.2 添加电机,实现测距摇头,“懂得避障”

main.c

void main()
{
    char dir;
    double disMiddle;
    double disLeft;
    double disRight;

    Time0Init();
    Time1Init();

    sgMiddle();
    Delay300ms();
    Delay300ms();
    dir = MIDDLE;
    while(1){
        
        disMiddle = get_distance();
        if(disMiddle > 20){
            //前进
            goForward();
            
        }
        else if(disMiddle < 7){
            goBack();
            Delay150ms();
            stop();
        }
        else{
            sgRight();
            Delay300ms();
            disRight = get_distance();

            sgMiddle();
            Delay300ms();
            disMiddle = get_distance();

            sgLeft();
            Delay300ms();
            dir = LEFT;
            disLeft = get_distance();

            if(disRight < disLeft){
                goLeft();
                Delay200ms();
                stop();
            }
            if(disRight > disLeft){
                goRight();
                Delay200ms();
                stop();
            }
            
        }
        if(dir != MIDDLE){
            sgMiddle();
            dir = MIDDLE;
            Delay300ms();
        }
    }                         
}

  • 0
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值