找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 743|回复: 1
收起左侧

大一新生第一辆循迹小车,问问大佬们怎么优化调试小车啊,小车不能稳定循迹,崩溃....

[复制链接]
ID:1136591 发表于 2024-11-16 15:44 | 显示全部楼层 |阅读模式
主函数
#include <REGX52.H>
#include "MotorTurn.h"
#include "State.h"
#include "Timer.h"
#include "Infrared.h"

void main()
{
        Timer0_Init();
        EA=1;
        while(1)
        {
                Track();
        }
}

定时器
#include <REGX52.H>

sbit ENA=P2^3;
sbit ENB=P2^5;

extern unsigned char CompareR;
extern unsigned char CompareL;
extern unsigned char Counter;

void Timer0_Init(void)         //100us
{
        TMOD &= 0xF0;                        
        TMOD |= 0x01;                        
        TL0 = 0xA4;                                
        TH0 = 0xFF;                        
        TF0 = 0;                                
        TR0 = 1;        
        ET0=1;
        EA=1;
        PT0=0;

}

void Timer0_Routinue() interrupt 1
{
        TL0 = 0xA4;        
        TH0 = 0xFF;
        
        Counter++;
        Counter%=100;
        if(Counter<CompareR)
        {
                ENB=1;
        }else{
                ENB=0;
        }
        if(Counter<CompareL)
        {
                ENA=1;
        }else{
                ENA=0;
        }
}

小车状态
#include <REGX52.H>
#include "MotorTurn.h"
#include "Timer.h"


void Forward()
{
        RightForward();
        LeftForward();
}

void Back()
{
        RightBack();
        LeftBack();
}

void TurnRight()
{
        RightStop();
        LeftForward();
}

void TurnLeft()
{
        LeftStop();
        RightForward();
}

void Stop()
{
        RightStop();
        LeftStop();
}

红外循迹
#include <REGX52.H>
#include "MotorTurn.h"
#include "State.h"
#include "Timer.h"
#include "Delay.h"

sbit D4=P1^4;   
sbit D3=P1^5;   
sbit D2=P1^6;   
sbit D1=P1^7;  

unsigned char CompareR;
unsigned char CompareL;
unsigned char Counter;
        
void Track()
{
        if(D2==1&&D3==1)              //小车停止
        {
                CompareR=0;
                CompareL=0;
                Stop();
        }
        
        if(D2==1&&D3==0)              //小车稍微左转
        {
                CompareR=12;
                CompareL=0;
                Forward();
                if(D2==0&&D3==0)             //小车前进
                {  
                        CompareR=15;
                        CompareL=15;
                        Forward();
                }
        
        }
        
        if(D2==0&&D3==1)             //小车稍微右转
        {
                CompareR=0;
                CompareL=12;
                Forward();
                if(D2==0&&D3==0)             //小车前进
                {  
                        CompareR=15;
                        CompareL=15;
                        Forward();
                }
        }
        
        if(D2==0&&D3==0)             //小车前进
        {  
                CompareR=15;
                CompareL=15;
                Forward();
         }
        
}
回复

使用道具 举报

ID:404160 发表于 2024-11-16 17:22 | 显示全部楼层
可能导致不稳定循迹的问题及优化调试建议
(一)硬件相关
红外传感器布局与安装角度:
问题:如果红外传感器安装得不够水平或者与地面的距离不一致,可能会导致不同传感器接收到的反射光强度有较大差异,从而影响对黑线的准确检测。
调试建议:仔细检查红外传感器的安装情况,确保它们在同一水平面上且与地面的距离合适(一般几毫米到一厘米左右,具体可根据实际情况调整)。可以使用一些辅助工具如水平仪等来保证安装的准确性。
电机性能差异:
问题:左右电机的转速、扭矩等性能可能不完全一致,即使定时器设置相同的时间来控制电机转动,也可能导致小车行驶轨迹出现偏差。
调试建议:单独测试左右电机,在相同的输入条件下(如相同的电压、相同的控制信号持续时间等),观察它们的转速和转动情况是否一致。如果存在明显差异,可以考虑更换电机或者在软件上进行一些补偿性的调整(比如根据实际测试结果,对左右电机的控制参数CompareR和CompareL进行微调)。
电源稳定性:
问题:如果电源电压不稳定,可能会导致电机转速波动,进而影响小车的循迹稳定性。
调试建议:使用万用表等工具监测电源电压,确保在小车运行过程中电压保持在稳定的范围内。如果电压波动较大,可以考虑增加稳压电路来改善电源的稳定性。
(二)软件相关
红外传感器读取的防抖处理:
问题:在代码中直接根据红外传感器引脚的当前读取值来判断小车的位置状态,但是在实际环境中,由于电磁干扰、传感器本身的特性等原因,传感器的读取值可能会出现短暂的抖动(即瞬间的误读),这可能会导致小车做出错误的动作决策。
调试建议:可以在读取红外传感器值后增加防抖处理逻辑。例如,连续多次读取传感器的值(比如读取 5 - 10 次),然后根据多数值的情况来确定最终的传感器状态。示例代码如下(以D2传感器为例):
c
复制
unsigned char ReadD2Stable()
{
    unsigned char readValues[10];
    unsigned char i;
    unsigned char countOn = 0;

    for (i = 0; i < 10; i++)
    {
        readValues[i] = D2;
    }

    for (i = 0; i < 10; i++)
    {
        if (readValues[i] == 1)
        {
            countOn++;
        }
    }

    if (countOn >= 5)
    {
        return 1;
    }
    else
    {
        return 0;
    }
}
然后在Track函数中,将原来对D2和D3的直接读取改为调用上述防抖处理函数,比如:
c
复制
if (ReadD2Stable() == 1 && ReadD3Stable() == 1)  // 小车停止
{
    CompareR = 0;
    CompareL = 0;
    Stop();
}
循迹算法的优化:
问题:当前的循迹算法相对比较简单,只是根据D2和D3两个传感器的状态进行了几种基本情况的判断和处理。在实际的循迹场景中,可能会遇到更复杂的路况(如弯道较急、黑线不连续等),这种简单的算法可能无法很好地应对。
调试建议:
考虑增加更多的传感器或者利用现有的传感器获取更多的信息。例如,可以同时考虑D1和D4传感器的状态,综合四个传感器的信息来更准确地判断小车的位置和前方路况,从而做出更合理的动作决策。
对于不同的传感器状态组合,可以设计更细致的动作策略。比如,当D2和D3之间的状态切换频繁时(可能表示小车即将进入弯道或者已经在弯道中),可以适当降低车速(通过调整CompareR和CompareL的值),以提高循迹的稳定性。
可以采用一些智能的循迹算法,如 PID 控制算法。PID 算法可以根据小车当前位置与期望位置(沿着黑线行驶)的偏差,实时调整电机的控制参数,从而实现更精准的循迹。不过,实现 PID 算法相对复杂一些,需要对 PID 原理有一定的了解并进行相应的代码编写和参数调试。
全局变量的保护与一致性:
问题:代码中使用了一些全局变量如CompareR、CompareL和Counter,在多函数共享这些变量的情况下,如果没有适当的保护机制,可能会出现意外的修改,导致程序逻辑混乱,影响小车的循迹效果。
调试建议:
尽量减少全局变量的使用,如果可能的话,可以将一些变量改为局部变量,并通过函数参数传递的方式在不同函数之间共享必要的数据。
如果必须使用全局变量,可以考虑使用互斥锁等机制来保护它们。在 51 单片机中,虽然没有像操作系统那样完善的互斥锁机制,但可以通过一些简单的标志位和逻辑判断来实现类似的功能。例如,在修改某个全局变量之前,先检查一个特定的标志位是否允许修改,如果允许则进行修改,并在修改完成后设置标志位为不允许修改状态,直到下一次合适的时机再允许修改。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表