单片机交流
直播中

孙成红

7年用户 1366经验值
私信 关注
[问答]

怎么实现基于STC16F40K128循迹智能小车的设计?

怎么实现基于STC16F40K128循迹智能小车的设计?

回帖(1)

张玉珍

2021-10-12 10:40:57
硬件菜单




  • 单片机型号:STC16F40K128
  • 4路红外循迹模块
  • 小车底盘套件(一个底盘、两个TT马达、两个轮胎)
  • 12V航模电池
  • 降压模块
  • A4950双路电机驱动
  • 杜邦线等

硬件使用









  • 关于4路红外循迹模块的使用教程,我之前写过一篇博客,里面有详细的介绍。如果有不会的可以先去浏览学习一下。跳转至教程
  • A4950双路电机驱动使用方式不多说了,比较简单。大部分人应该都是用L298N的。

硬件组装











硬件组装大概按照上面两张图片组装就行。



  • 不过要注意的是红外传感器之间的距离和单个传感器的测量精度。在组装完成后,要通电试一试传感器的工作情况,用它检测黑线,康康是不是能够正常工作。如果无法正常工作需要及时调整传感器的精度或者其他东西。总之要保证传感器能正常检测黑线。
  • 另一点就是传感器的安装位置。受到传感器数量的限制,所以传感器的安装位置需要仔细考虑。我这里一共有4个传感器所以就像图中那样安装的。中间两个之间留有空隙,空隙的宽度大概为黑线宽度(可以稍微比黑线宽点),其他两个的位置也不要离得太远。具体为什么这样设计再后面讲解。

程序设计前的理解




  • 接上面挖下的坑,说一下中间两个传感器之间空隙的问题。

前提是小车在没有检测到黑线的时候会直线行驶。中间的空隙宽度略微大于黑线宽度,这样就可以满足当黑线处于这个缝隙间的时候传感器不会有反应,小车会直线行驶,在一定程度上满足循线的基础操作。肯定会出现黑线移出这个空隙的情况,这样的话黑线就会被两侧的传感器检测到,然后由单片机做出应对。如果是左侧的传感器检测到黑线(设定小车前进方向为正方向),代表车头右偏了,因此小车需要左转;于此类似,右侧的传感器也是一个道理。理解了这些就可以完成最基本的循线了。



  • 最外侧两个传感器的作用

因为传感器反应速度等等一系列可能的原因会出现黑线在移出中央空隙的时间很短导致传感器没有检测到等的情况,这样的话小车肯定会继续前进而导致无法继续循线。如果在中间两个传感器两侧又安装了两个传感器的话,这样就相当于多了一个保险,如果中间两个没有检测到的话,最外侧的传感器正常工作仍能让小车重新回到循线轨迹上来。不过要注意的是,因为当最外侧的传感器检测到黑线时就意味着车头已经偏的比较严重了,所以要想让车头偏正就需要给更大的“力”,也就是给更大的PWM。
程序代码


#include "headfile.h"




/*******************
* 用于初始化PWM的
*******************/
void All_Init(void)
{
        pwm_init(PWMA_CH1P_P60, 10000, 0);
        pwm_init(PWMA_CH2P_P62, 10000, 0);
        pwm_init(PWMA_CH3P_P64, 10000, 0);
        pwm_init(PWMA_CH4P_P66, 10000, 0);
}




/*******************
* 车子左转
*******************/
void turn_left(int duty)
{
        pwm_duty(PWMA_CH1P_P60, duty);
        pwm_duty(PWMA_CH2P_P62, 0);
        pwm_duty(PWMA_CH3P_P64, 0);
        pwm_duty(PWMA_CH4P_P66, duty);
}




/*******************
* 车子右转
*******************/
void turn_right(int duty)
{
        pwm_duty(PWMA_CH1P_P60, 0);
        pwm_duty(PWMA_CH2P_P62, duty);
        pwm_duty(PWMA_CH3P_P64, duty);
        pwm_duty(PWMA_CH4P_P66, 0);
}




/*******************
* 车子直行
*******************/
void go_straight(void)
{
        pwm_duty(PWMA_CH1P_P60, 7000);
        pwm_duty(PWMA_CH2P_P62, 0);
        pwm_duty(PWMA_CH3P_P64, 7000);
        pwm_duty(PWMA_CH4P_P66, 0);
}




/*******************
* 车子停止
*******************/
void go_stop(void)
{
        pwm_duty(PWMA_CH1P_P60, 0);
        pwm_duty(PWMA_CH2P_P62, 0);
        pwm_duty(PWMA_CH3P_P64, 0);
        pwm_duty(PWMA_CH4P_P66, 0);
}


/*****************************************
* OUT1 P27
* OUT2 P26
* OUT3 P25
* OUT4 P24
* 如图循迹小车2所示,从左到右分别为OUT1、2、3、4
* 检测到黑线或悬空LED灭,输出高电平
* 对单片机的IO口状态进行判断,这样可以得到是哪个
* 传感器检测到了黑线,然后再
* 做出相对应的行为。
*****************************************/
void scan(void)
{
        if ((P26 == 0)&&(P25 == 0)&&(P27 == 0)&&(P24 == 0))
        {
                // 未检测到黑线
                go_straight();
        }
        else if ((P26 == 1)&&(P25 == 1)&&(P27 == 1)&&(P24 == 1))
        {
                // 悬空
                go_stop();
        }
        else if ((P26 == 0)&&(P25 == 1)&&(P27 == 0)&&(P24 == 0))
        {
                // 车头右偏(相对于前进方向) 向左转(幅度较小)
                turn_left(7000);
        }
        else if ((P26 == 1)&&(P25 == 0)&&(P27 == 0)&&(P24 == 0))
        {
                // 车头左偏 向右转(幅度较小)
                turn_right(7000);
        }
        else if ((P26 == 0)&&(P25 == 0)&&(P27 == 1)&&(P24 == 0))
        {
                // 向左转(幅度较大)
                turn_left(9500);
        }
        else if ((P26 == 0)&&(P25 == 0)&&(P27 == 0)&&(P24 == 1))
        {
                // 向右转(幅度较大)
                turn_right(9500);
        }
}
void main()
{
        DisableGlobalIRQ();                //关闭总中断
       
        board_init();                        //初始化寄存器
        All_Init();
        //总中断最后开启
        EnableGlobalIRQ();                //开启总中断
    while(1)
        {
                scan();
  }
}
程序代码大概就像上面那样。其中有些参数,比如说小车行进速度和转弯占空比该给多少。这个东西需要自己测试然后填写,也就是自己慢慢调参测试,找到合适的数值就行。
举报

更多回帖

发帖
×
20
完善资料,
赚取积分