前言

大二时,我羡慕学长们在比赛中拿奖,于是跟着学点知识,报名参加吉林省人工智能创新大赛全地形赛道,想锻炼自己并加学分。无论结果如何,我都想总结这次经历分享给学弟学妹,让他们少走弯路。

另外,我也是个新手小白,要是有啥说错的地方,大家尽管提,我虚心接受!

封面

介绍


本项目小车的核心是用的Arduino Uno R3控制板,然后用L298N作为驱动模块。它主要是靠激光寻迹模块来感知地形的。激光寻迹模块会传回不同的信号,小车根据这些信号判断出不同的地形,然后做出相应的决策。

主要是完成如下赛道:
全地形地图

在比赛时候,大部分人都用的是履带小车,我做的是四轮小车。我的小车没有上中间的高台,不过最后还是拿到了省一等奖,还挺惊喜的!😁

全地形小车运行视频

一、硬件结构

1.整体结构展示

小车整体结构图
小车正面展示
小车侧视图

小车背面展示

小车底部

2.材料选型

  • 主控:Arduino UNO R3 一个
    arduino uno r3 开发板
  • 激光寻迹模块 五个
    激光寻迹模块
  • 分线端子 两个

分线端子

  • 减速直流电机 四个

电机

  • 2P 一个(多买点)

接线端子

  • 洞洞板 一个(多买点)

洞洞板

  • 降压模块 一个(多买点)

降压模块

电机驱动板模块

  • 导向轮 两个

导向轮

  • 12V锂电池 一个

电源

  • 小车底板 一个

小车底板

  • 排母若干

排母

  • 排针若干

排针

  • 铜线若干

黑红线

  • 轮胎和联轴器

越野轮胎

  • 开关

开关

除了主要部件,还用了铜柱、热缩管、标签贴纸、杜邦线、尼龙扎带、螺丝螺母等辅助材料。

3.洞洞板拖锡

为什么要用洞洞板拖锡?
因为作者不太熟练用嘉立创EDA😢,再加上时间特别紧张,等不及电路板寄到学校,所以只能选择拖锡了。好在之前买了好多洞洞板,刚好派上用场。

可以提前准备好下载好程序的备用主控板。这样在赛场上,如果哪个模块或者主板烧毁或者故障了,就不用再根据代码一点点重新连线了。直接用排针排母拔插的方式,快速替换掉有问题的模块就行。这样一来,引脚之间的连接会更稳定,不会出现接触不良的情况。而且在小车比赛行进或者被搬运的时候,也能减少因为飞线不稳导致的故障。

万用板焊接教学视频

  1. 在纸上把主控板和各个功能模块的引脚分配规划好
L298N 引脚 Arduino Uno R3 引脚
ENA 11
IN1 12
IN2 13
IN3 8
IN4 9
ENB 10

Arduino Uno R3 中带波浪线标注的引脚才具有PWM输出功能

激光寻迹模块 引脚 Arduino Uno R3 引脚
L1 2
L2 3
ME 4
R2 5
R1 6
  1. 把每个模块的电源供电安排好
模块种类 电压
Arduino Uno R3 5V(Vin)
L298N 12V
激光寻迹模块 5V

锂电池的12V直接接给L298N。尽量别用L298N输出的5V给主控芯片供电,因为那个电压不太稳。可以把锂电池的12V接到降压模块上,让降压模块输出5V,专门给单片机和5个激光寻迹模块供电(激光寻迹模块不能用单片机输出的电压供电哦)。激光寻迹模块单独供电的同时,要和Arduino Uno R3的信号口连接,并且所有模块要共地。L298N也得和Arduino Uno R3共地

电路拖锡图
上板面
小车内部

4.3D打印零件

五路激光寻迹模块支架

因为激光寻迹模块得倾斜摆放,才能发挥出最好的效果。不过,激光的具体倾斜角度要根据不同的小车模型来调整。

激光寻迹模块支架
导向轮支架

轻松过弯道,就算有时候激光寻迹模块识别不到亚克力板下面的黑线,它也能碰运气通过😴

导向轮支架
导向轮安装


二、软件思路

1.控制思路

根据寻迹模块检测到黑线的次数,调用对应的障碍子函数,每种障碍都有自己的处理逻辑。

首先得确定小车的行走路线,然后根据路线里障碍的顺序来写代码。
我的思路是先写好小车前进、后退、左转、右转这些基本动作的子函数。在速度控制方面,我设计了低速、中速、高速三种前进模式,还有小速度和大速度下的左右转。此外,还写了后退、停止的子函数,以及针对特定地形的速度函数,比如上台阶和通过U型管道的速度肯定是不一样的。

流程图

速度子函数代码示例:

void W()  //正常速度模式
{
  digitalWrite(IN1, 1);
  digitalWrite(IN2, 0);
  analogWrite(ENA, 140);//PWM值根据不同转速而定
  digitalWrite(IN3, 1);
  digitalWrite(IN4, 0);
  analogWrite(ENB, 140);
}

设置变量n来进行不同状态之间的转换。
像是通过小台阶,我将通过小台阶的方法,写成了两个部分分别是小台阶上和小台阶下两个子函数,之后再小台阶上下的子函数里面,进行速度的配置,其他障碍依次类推,越复杂的障碍对应的子函数越多配置速度更加详细。
使用多个变量(如 n、j、t、Q 等)作为计时器或状态转换的条件,用于控制模式的切换和特定动作的执行。

Serial.println(“在调试过程中,最好加上输出语句或者设置断点,这样能清楚地了解代码的执行情况");

U型管模块代码示例:

void U() 
{
  int L1_V = digitalRead(L1); 
  int L2_V = digitalRead(L2);
  int ME_V = digitalRead(ME);
  int R2_V = digitalRead(R2);
  int R1_V = digitalRead(R1);

  if (L1_V == 1 && L2_V == 1 && ME_V == 1 && R2_V == 1 && R1_V == 1)  //1 1 1 1 1
  {
    LW();
    n=6;
  } else if (L1_V == 0 && L2_V == 0 && ME_V == 1 && R2_V == 0 && R1_V == 0)  //0 0 1 0 0
  {
    LW();
  } else if (L1_V == 0 && L2_V == 1 && ME_V == 0 && R2_V == 0 && R1_V == 0)  //0 1 0 0 0
  {
    XZ();
  } else if (L1_V == 0 && L2_V == 0 && ME_V == 0 && R2_V == 1 && R1_V == 0)  //0 0 0 1 0
  {
    XY();
  } else if (L1_V == 0 && L2_V == 0 && ME_V == 0 && R2_V == 0 && R1_V == 0)  //0 0 0 0 0
  {
    LW();
  }
}

状态机代码示例:

 switch (n) {
    case 0:
      {
        while (1) {
          jiansudai();
          Serial.println("减速带");
          if (n >= 4) {
            n = 3;
            Serial.println("改变的n");
            Serial.println(n);
            break;
          }
        }
      }
      break;
    case 3:
      {
        while (1) {
          caodi();
          Serial.println("草地");
          Serial.println(n);
          if (n >= 7) { 
            Serial.println(">=8");
            Serial.println(n);
            n = 4;
            break;
          }
        }
      }
      break;
    default:
      Serial.println("未知状态");
      break;
  }

2.代码烧录

下载Arduino IDE,安装后连接开发板,选择对应的开发板和端口,编写代码并上传

Arduino IDE下载图片

4.资源下载

资料包内容如下:

材料清单


三、经验教训

小车的结构一定要稳定,速度再快也得稳!重要的事情说三遍:稳定、稳定、稳定!轮子最好换成窄一点的,这样通过U型管道和方形隧道会更方便。比赛情况千变万化,可能会有大灯干扰,地形也可能和在学校模拟的时候不一样,所以一定要做好十足的准备!

总结

如果需要资料,可以通过上面的视频链接找到我的主页私信我,也可以直接私信我哦!
最后祝大家比赛顺利,小车一路畅通无阻!😁
视频主页

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐