乐高 EV3 实验04 - 颜色传感器巡线

« 返回 LEGO 专题

实验04:颜色传感器巡线

这个实验做完你会得到什么

先做一个颜色识别器(把不同颜色的乐高件放到传感器下,手机报出颜色名); 再进阶到巡线小车 —— 车沿着黑色胶带自己走。

项目 说明
难度 ★★★☆☆
用时 约 50 分钟
前置 实验02:差速小车遥控

一、器材与接线

器材 数量 接到
EV3 主机 + 两个大型马达 1 马达接 B、C
EV3 颜色传感器 1 传感器接 S3
黑色电工胶带 1 卷 在白色地面贴一条闭合线路

传感器装在车头下方、朝向地面,离地约 5~10 毫米。太高读数弱,太低会蹭到地面。


二、三种工作模式

颜色传感器有三种模式,必须先设对模式再读数

模式 设置方法 读什么 用在哪
颜色模式 SetColorMode() 颜色编号 / 颜色名 识别色块
反射光模式 SetReflectedMode() 0~100 的反光百分比(读不到返回 -1) 巡线
环境光模式 SetAmbientMode() 0~100 的环境亮度 检测明暗

巡线要用反射光模式,不是颜色模式。颜色模式只能给出有限的几种颜色, 在黑白交界处会跳来跳去;反射光给的是连续值(白色 ~70、黑色 ~10), 能判断”压线多少”,控制才平滑。


三、界面组件

组件 命名 关键属性
按钮 按钮_识别颜色 文本「读一次颜色」
标签 标签_颜色 字号 28,文本「–」
标签 标签_反光 文本「反光值:–」
按钮 按钮_标定白 / 按钮_标定黑 文本「记录白」「记录黑」
按钮 按钮_巡线 文本「开始巡线」
计时器 计时器1 计时器启用取消勾选、间隔 100
EV3颜色传感器 EV3颜色传感器1 BluetoothClient = 蓝牙客户端1SensorPort = 3
EV3马达 EV3马达1 BluetoothClient = 蓝牙客户端1MotorPorts = BC

四、分步搭代码块

第 1 步:颜色识别

when 按钮_识别颜色.Click() {
  EV3颜色传感器1.SetColorMode()
  标签_颜色.Text = EV3颜色传感器1.GetColorName()
}

中途验证:把红/蓝/绿色的乐高件放到传感器下方,点按钮,显示对应颜色名。

GetColorName() 返回颜色名字符串,GetColorCode() 返回数字编号。 要做逻辑判断用编号更方便(不用比字符串)。

识别距离很关键:传感器要贴近物体(1 厘米内),远了全都读成 none

第 2 步:切到反射光模式,标定黑白

global 白值 = 70
global 黑值 = 10
global 反光 = 0

when 按钮_读反光.Click() {
  EV3颜色传感器1.SetReflectedMode()
  global 反光 = EV3颜色传感器1.GetLightLevel()
  标签_反光.Text = join("反光值:", 反光)
}

when 按钮_标定白.Click() {
  global 白值 = 反光
  标签_状态.Text = join("白值 = ", 白值)
}

when 按钮_标定黑.Click() {
  global 黑值 = 反光
  标签_状态.Text = join("黑值 = ", 黑值)
}

中途验证:传感器放白色地面上读一次点「记录白」,放黑胶带上读一次点「记录黑」。 两个值应该差 30 以上,差太小说明传感器离地太高或环境光太强。

一定要标定。教程里写的 70 和 10 只是典型值 —— 换个地面、换个灯光、 甚至白天晚上,读数都不一样。巡线失败十有八九是没标定。

第 3 步:单边巡线

最经典的巡线算法:盯着黑线的一条边走,压得多就往外拐,压得少就往里拐。

global 白值 = 70
global 黑值 = 10

when 按钮_巡线.Click() {
  EV3颜色传感器1.SetReflectedMode()
  计时器1.TimerEnabled = true
  标签_状态.Text = "巡线中…"
}

when 计时器1.Timer() {
  var 当前 = EV3颜色传感器1.GetLightLevel()
  var 中线 = (白值 + 黑值) / 2
  var 偏差 = 当前 - 中线
  var 转向 = max(-80, min(80, 偏差 * 2))
  标签_反光.Text = join("反光 ", 当前, " 转向 ", round(转向))
  EV3马达1.RotateSyncIndefinitely(35, round(转向))
}

when 按钮_停.Click() {
  计时器1.TimerEnabled = false
  EV3马达1.Stop(true)
  标签_状态.Text = "已停止"
}

中途验证:把车放在黑线边缘(传感器一半压着线),点「开始巡线」,车沿着线的边缘走。

原理:中线是黑白的中间值。压到白多(当前 > 中线)就朝一边拐, 压到黑多就朝另一边拐 —— 这就是最简单的比例控制(P 控制)

* 2 是比例系数,决定反应强度:太小转不过弯冲出线,太大来回蛇形摆动。 从 2 开始试,蛇行就调小、过不了弯就调大。

走反了怎么办偏差 * 2 改成 偏差 * -2 即可 —— 这取决于传感器压在线的 左边还是右边。

第 4 步:丢线保护(可选)

global 白值 = 70

when 计时器1.Timer() {
  var 当前 = EV3颜色传感器1.GetLightLevel()
  if 当前 > 白值 - 5 {
    EV3马达1.RotateSyncIndefinitely(30, 60)
    标签_状态.Text = "丢线,正在找回"
  }
}

完全读到白色说明车跑出线了。让它朝一个固定方向转圈找线, 通常几秒内就能重新压上。


五、排错表

现象 原因与处理
颜色一直读成 none 传感器离物体太远,凑近到 1 厘米内
反光值黑白差别很小 传感器离地太高(应 5~10 毫米);或环境光太强,关掉直射灯
车压着线不动 功率太低(<25 带不动);或计时器没启用
车蛇形剧烈摆动 比例系数太大,从 * 2 降到 * 1
车过不了弯直接冲出去 比例系数太小;或前进功率太高,降到 30
车朝反方向拐 比例系数取负,或把传感器移到线的另一侧
巡一会儿就丢线 没标定,或弯道太急。加第 4 步的丢线保护
换个房间就不灵 光照变了,重新标定
读到 -1 组件文档:读不到时返回 -1。传感器线松了或端口不对,别把 -1 当成有效亮度参与计算

六、下一步


相关文档

文档反馈