乐高 EV3 实验05 - 陀螺仪精确转向

« 返回 LEGO 专题

实验05:陀螺仪精确转向

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

点一个按钮,小车精确转 90 度然后停下 —— 不管电池满不满、地面滑不滑,角度都准。 再让它自己走一个正方形。

前面用时间控制转向(转 600 毫秒)根本不准:电池电量、地面摩擦、负载轻重都会影响。 这一篇改成闭环控制 —— 一边转一边看陀螺仪,到角度就停。

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

一、器材与接线

器材 数量 接到
EV3 主机 + 两个大型马达 1 马达接 B、C
EV3 陀螺仪传感器 1 传感器接 S2

陀螺仪要装平(和地面平行),装歪了测出来的不是水平转角。


二、两种模式

模式 设置方法 读到的是
角度模式 SetAngleMode() 累计转过的角度(度),会一直累加
速率模式 SetRateMode() 当前角速度(度/秒)

本篇用角度模式

⚠️ 陀螺仪会漂移:静止不动时读数也会慢慢变化,这是这类传感器的固有特性。 每次转向前重新读一次基准角,用差值而不是绝对值,就能把漂移的影响降到最低。


三、界面组件

组件 命名 关键属性
标签 标签_角度 字号 40,文本「0°」
按钮 按钮_归零 / 按钮_读角度 「角度归零」「读一次」
按钮 按钮_转90 文本「右转 90°」
按钮 按钮_走方形 文本「走一个正方形」
计时器 计时器1 计时器启用取消勾选、间隔 50
EV3陀螺仪传感器 EV3陀螺仪传感器1 BluetoothClient = 蓝牙客户端1SensorPort = 2
EV3马达 EV3马达1 BluetoothClient = 蓝牙客户端1MotorPorts = BC

四、分步搭代码块

第 1 步:先看角度在不在动

when 按钮_归零.Click() {
  EV3陀螺仪传感器1.SetAngleMode()
  标签_角度.Text = "0°"
  标签_状态.Text = "已归零"
}

when 按钮_读角度.Click() {
  标签_角度.Text = join(EV3陀螺仪传感器1.GetSensorValue(), "°")
}

中途验证:点「归零」,然后用手把车转 90 度,点「读一次」应该显示 ±90 左右。 读数不变就别往下做 —— 检查 SensorPortBluetoothClient

顺时针是正还是负,取决于陀螺仪的安装方向。先转一下看符号。 本文的判断用了绝对值,正负都成立。

第 2 步:闭环转 90 度

global 目标角 = 90
global 起始角 = 0

when 按钮_转90.Click() {
  EV3陀螺仪传感器1.SetAngleMode()
  global 起始角 = EV3陀螺仪传感器1.GetSensorValue()
  global 目标角 = 90
  EV3马达1.RotateSyncIndefinitely(30, 100)
  计时器1.TimerEnabled = true
  标签_状态.Text = "转向中…"
}

when 计时器1.Timer() {
  var 已转 = abs(EV3陀螺仪传感器1.GetSensorValue() - 起始角)
  标签_角度.Text = join(round(已转), "°")
  if 已转 >= 目标角 - 3 {
    EV3马达1.Stop(true)
    计时器1.TimerEnabled = false
    标签_状态.Text = join("完成,实际转了 ", round(已转), "°")
  }
}

中途验证:点「右转 90°」,车原地转四分之一圈后停下。用地砖缝对齐着看,误差应在几度内。

- 3 是提前量:从发现”到了”到马达真正停下有延迟(蓝牙往返 + 机械惯性), 不提前一点会转过头。转速越快提前量要越大 —— 功率 30 时 3 度左右合适, 功率 50 就要提前 8~10 度。

abs(当前 - 起始) 而不是直接读绝对值:这样不管陀螺仪之前累计到多少、 也不管转向正负,逻辑都成立。

第 3 步:走一个正方形

global 边数 = 0
global 起始角 = 0

when 按钮_走方形.Click() {
  global 边数 = 0
  走一条边()
}

procedure 走一条边() {
  EV3马达1.RotateSyncInDistance(40, 40, 0, true)
  EV3陀螺仪传感器1.SetAngleMode()
  global 起始角 = EV3陀螺仪传感器1.GetSensorValue()
  EV3马达1.RotateSyncIndefinitely(30, 100)
  计时器1.TimerEnabled = true
}

when 计时器1.Timer() {
  var 已转 = abs(EV3陀螺仪传感器1.GetSensorValue() - 起始角)
  标签_角度.Text = join(round(已转), "°")
  if 已转 >= 87 {
    EV3马达1.Stop(true)
    计时器1.TimerEnabled = false
    global 边数 = 边数 + 1
    标签_状态.Text = join("已完成 ", 边数, " 条边")
    if 边数 < 4 {
      走一条边()
    }
  }
}

中途验证:车走出一个大致方正的正方形,最后回到出发点附近。

RotateSyncInDistance阻塞式的:走完 40 厘米(该方法的距离单位是 cm)才继续往下执行, 所以直线段和转向段自然分开,不用自己加延时。

回不到原点很正常 —— 轮子打滑、直线段本身有偏差,误差会累积。 这正是竞赛机器人要不断用传感器重新校正的原因,而不是一路盲走。


五、排错表

现象 原因与处理
角度读数一直是 0 SensorPort 不对;② BluetoothClient 没设;③ 传感器线松
读到 -1 组件文档:读不到时返回 -1。检查接线,别让 -1 参与角度计算
静止时角度慢慢变 陀螺仪漂移,正常。每次转向前重新取基准角
每次转的角度都不一样 提前量没调好;或功率太高惯性大,降到 30
转过头很多 提前量太小,或计时器间隔太大(50 毫秒较合适)
转不到位就停 提前量太大
走方形越走越歪 误差累积,正常。要闭合得靠外部参照(巡线、超声波测墙距)
转向时车在原地画圈而不是转 转向比不是 100。原地转必须用 ±100

六、下一步


相关文档

文档反馈