元器件 · 传感器

杠杆微动开关

杠杆微动开关是机器人保险杠背后的接触传感器。本文讲怎么把它接成故障安全的接法、为什么按一下会产生九个边沿,以及杠杆臂有什么用。

它是什么

杠杆微动开关——微型快动开关——小塑料壳里的机械触点,伸出一根金属杠杆。压杠杆内部弹簧啪地切过去;松开弹簧啪地回来。本库最老的零件之一,在机器人上最有用之一。

让它成机器人零件的是快动。触点不是随按渐合;在可重复的点跳变,咔哒一声。被动的机器人被撞上时,给你的是一个确定的是或否,而这时渐变型传感器给出的读数毫无意义。

上下两幅图。上图是约六毫秒内的开关信号:原始引脚拉低,然后 4.7 毫秒内高低抖九次才稳定拉低,消抖输出等窗口过去才干净拉低。下图是中断会计数的边沿数,随消抖窗口从零加到八毫秒从九阶梯降到一,4.7 毫秒处到一。
关于这个零件要知道的一件事:一次按压会产生约 4.7 ms 内的九次跳变。消抖窗口短于抖动本身,就会把抖动一起数进去;而窗口长到足以让抖动平息,付出的代价恰好就是它自身那么长的延迟。 下载 SVG

工作原理

三个端子:COM(公共)、NO(常开)、NC(常闭)。没按 COM 连 NC;按下啪地切到 NO。三个用两个,剩下一个无视。

机器人保险杠接 COM 接地、NO 接输入脚,开引脚内部上拉:

pinMode(BUMP_L, INPUT_PULLUP);              // idle HIGH
bool pressed = digitalRead(BUMP_L) == LOW;  // LOW means the bumper moved

这样接法是故障安全的:保险杠线断了读到 HIGH,也就是没按下。反过来接,断线就会骗机器人说它一直在碰撞。急停要用 NC——那边断线时就该停机。

杠杆拿力换行程。裸按柄约 1 N 走约 1 mm;杠杆臂放大行程,保险杠外壳走 3–5 mm、轻轻一碰就触发。端头滚轮减小斜着蹭过去的摩擦。

什么时候用它

机器人需要知道已经发生接触时用它:保险杠、机械臂或滑台的限位、盖子或抽屉的传感器、对接检测。它是最后一道保险的传感手段,这算是夸奖——黑色椅腿、玻璃窗,以及那些高度不对、让光学和声学传感器全都漏掉的障碍,它都能抓到。

它还是随机反弹式覆盖机器人唯一需要的传感手段。两个这样的开关加一个随机数发生器就能铺满整个房间,两个运动零件换来这么多行为,性价比相当惊人。

要躲开撞而不是发现撞看别处——超声或飞行时间干那个。两个都用:测距躲大多数,开关抓它看不见的。

常见坑

  • 按一下是九个边沿。给它消抖,而且绝不要挂会计数的中断——只挂置标志位或记录时间戳的那种。
  • **开关本体不是结构件。**给保险杠外壳加一个吃冲击的硬限位。开关壳会裂,这比触点磨损更早要它们的命。
  • **它自己的弹簧弹不回你的保险杠。**微动开关的回力是 50–100 g。回位用橡皮筋或轻压簧,开关只管传感。
  • **平板保险杠会漏掉斜撞。**外壳左右各包到至少 45°,每半各一个开关,代码才知道该往哪躲。
  • **长线拾电机噪声。**走线短、双绞,靠闭合时上拉的低阻抗。
  • **触点容量是给市电的,不是逻辑。**125 V AC 5 A 的开关这里过微安,容量对这活的寿命说明不了什么。预行程和动作力才说明。

接线

三个端子用两个,而用哪两个,决定了机器人出故障时是什么表现。

用途 COM 接 信号 空闲态 断线读到
保险杠 GND NO,引脚 INPUT_PULLUP HIGH 没按下——安全
急停 GND NC,引脚 INPUT_PULLUP LOW 按下——安全
都行,外上拉 GND NO 或 NC,10 kΩ 到 VCC — 同上

区别很重要。保险杠接 NO,故障安全时读到“没撞”,这是对的——保险杠线断了的机器人应该继续走,而不是僵在原地。急停接 NC,故障安全时读到“已停止”,这也是对的,只是原因正好相反。

用内部上拉。不要钱,不要零件,空闲态确定。悬空 INPUT 加开关,开关断开脚浮空,浮空脚读周围电气噪声——满车电机,噪声管够。

消抖,正确做法

一次按压,触点吸合又回弹,在约 4.7 ms 内产生九次跳变。天真地直接读引脚的软件,会以为发生了九次按压。

const int BUMP_L = 2, BUMP_R = 3;
const unsigned long DEBOUNCE_MS = 8;      // longer than the ~5 ms bounce

struct Bumper {
  uint8_t pin;
  bool stable;            // the debounced state
  bool lastRead;
  unsigned long changedAt;
};

Bumper left  = {BUMP_L, true, true, 0};
Bumper right = {BUMP_R, true, true, 0};

// Returns true on the frame the bumper newly closes.
bool update(Bumper &b) {
  bool now = digitalRead(b.pin);          // HIGH = open, with INPUT_PULLUP
  if (now != b.lastRead) {
    b.lastRead = now;
    b.changedAt = millis();               // restart the timer on any edge
    return false;
  }
  if (millis() - b.changedAt >= DEBOUNCE_MS && b.stable != now) {
    b.stable = now;
    return (now == LOW);                  // newly pressed
  }
  return false;
}

void setup() {
  pinMode(BUMP_L, INPUT_PULLUP);
  pinMode(BUMP_R, INPUT_PULLUP);
}

void loop() {
  if (update(left))  { backUp(); turnRight(); }
  if (update(right)) { backUp(); turnLeft(); }
}

关键的结构在于计时器在每个边沿都重新计时,而不是采样一次然后干等。固定采样再等待的做法可能正好落在抖动区间里,锁存下错误的值;而重启窗口意味着只有等引脚安静了整整一段时间,状态才会被接受。

为什么不用中断

保险杠上中断是坑,具体:

  • **绝不挂计数的中断。**九个边沿变九次计数,ISR 里消抖要 millis(),AVR 上 ISR 里 millis() 不走。
  • 置标志位的中断没问题,只要消抖放在主循环里。不过以 100 Hz 轮询开关不花任何代价,而且机器人的主循环本来就在跑。
  • Uno 上 D2、D3 留给编码器。仅有的两个外部中断脚,编码器真需要,保险杠不需要。

唯一值得用中断的场景是硬急停——即使主循环已经卡死也必须切断电机;而这个问题更好的解法是把开关串进电机驱动的使能线,这样不靠任何软件也有效。

安装:真正决定成败的部分

上面这些全是有确定答案的问题;保险杠的成败在于机械设计。

**外壳吃冲击,不是开关。**微动开关的壳体是薄塑料,受到直接撞击就会裂。做一个能绕轴转动或能滑动的保险杠外壳,给它一个吃力的硬限位,让开关只在这段行程的末尾感知一点小位移。

**把外壳包起来。**平板前保险杠会漏掉所有斜着撞上来的碰撞——而靠测距导航的机器人,大多是斜着撞上的,因为正对着过来的障碍早就被发现了。左右各包到至少 45°。

**两个开关,不是一个。**左右各一个,装在外壳的两半后面。一个开关只能告诉你撞到了东西,两个才能告诉你该往哪边转。行为上的差别非常明显,而多花的钱大约只有两毛。

开关数 机器人知道 能做的行为
1,中间 撞了 倒车,随机转
2,左右 哪边撞的 倒车,背向转
3,加尾 还知道倒车撞了 被夹住能逃

**保险杠用自己的弹簧回位。**微动开关内部弹簧回力 50–100 g,转轴有摩擦的外壳可靠复位不够。用橡皮筋或轻压簧,开关只管传感。

**把预行程留好,让外壳先动、开关别顶死。**开关在 1–3 mm 处动作,之后还有一点越程;外壳的硬限位必须落在这段越程之内,否则冲击就会由开关内部的机构来承受。

选哪个

杠杆类型 动作力 适合
无杠杆(裸按柄) 约 1 N 走约 1 mm 机构精确的限位
短直杠杆 0.5–0.8 N 通用保险杠
长直杠杆 0.2–0.5 N 轻保险杠外壳,轻触
滚轮杠杆 0.5–1 N 斜蹭而非直压的场合
仿滚轮(折弯) 0.5–1 N 滚轮的便宜替代

**触点容量在这里无关紧要。**一只标称 125 V AC、5 A 的开关,在这里只需要向上拉电阻传几微安。真正要紧的是机械规格:动作力、预行程,以及额定机械寿命(10⁵–10⁷ 次操作)。一趟跑撞一百下的机器人,跑一千趟就到 10⁵ 次,所以机械寿命实际上等于无限——开关会先因为外壳裂掉而报废。

故障排查

现象 可能原因 解决
按一下触发好几次 无消抖 上面模式,8 ms 窗口
一直读按下 接到 NC 而不是 NO 换 NO 端子
没碰随机读 脚浮空 INPUT_PULLUP,或外 10 kΩ
电机一跑误触发 长裸线拾噪声 线短双绞;脚对地加 100 nF 电容
保险杠弹不回 指望开关自己的弹簧 加橡皮筋或回位簧
撞几次开关裂了 冲击走开关本体 外壳先撞硬限位
斜着撞上来时漏检 平板保险杠 外壳左右包到 45°
倒车撞同一个 一个开关无方向信息 两个开关,背向转
台架好装车跪 保险杠几何,不是电路 多角度手推外壳看脚

这便宜零件凭什么占位

车上每个其他传感器都有看不见的表面。超声波看不见帘子和大角度的墙。VL53L0X看不见黑哑光、镜子、烈日下的东西。相机要光。

微动开关没有这样的清单。碰到保险杠,开关就闭合。所以它是最后一道保险的传感手段,而在一台必须无人值守运行的机器人上,它是最便宜的可靠性来源——两个开关、两个引脚,大约四毛钱。

值得惊讶的是,它自己就够用。两个保险杠开关加上“撞到就随机转向”,时间足够就能铺满整个房间——第一代扫地机器人就是这么工作的。在伸手去用更复杂的方案之前,值得先弄明白这一点。

探索关联图谱

用到它的搭建

包含 杠杆微动开关 的项目、学习路线和模拟器。

问题

杠杆微动开关 常见问题

杠杆微动开关在机器人上有什么用?

它是保险杠背后的传感器。机器人前部横着一块带弹簧的外壳,机器人一碰到东西,外壳就压下开关,给代码一个毫不含糊的比特——“我撞上东西了”——这是任何光学或声学传感器都无法同样可靠地提供的。正是它让机器人能发现黑色的椅腿、一块玻璃,或者一个高度不对、测距传感器照不到的障碍物。

开关应该接成常开还是常闭?

对保险杠来说,把常开触点接地,引脚上拉。这样一来,断线时读到的是“没按下”,一根断掉的引线就不会让机器人误以为自己一直在碰撞。急停则应改用常闭触点,因为那里安全的失效方式正好相反——断线就应该让机器停下来。

为什么按一下会被记成好几下?

这是触点抖动。金属触点接触后会形变、分开、再接触,在最初几毫秒里反复好几次,而以兆赫兹速度采样的单片机会把每一次都当成真实的边沿。按模型计算,一只杠杆开关在约 4.7 ms 内会产生九次跳变。请用软件消抖:接受一次变化之后,在一个时间窗口内忽略后续的边沿;并且绝不要挂会计数的中断。

杠杆臂到底起什么作用?

它用力换行程。裸按柄需要 1 到 1.5 N 的力,行程约 1 mm;杠杆把位移放大,让外壳可以移动 3 到 5 mm,而且只需轻得多的推力就能触发。这一点很重要,因为保险杠外壳既要移动得足够远才能可靠触发,又要足够轻,才不会在触发之前就把小障碍物推来推去。

需要上拉电阻吗?

不需要——用 INPUT_PULLUP 启用单片机的内部上拉即可。它不花钱,也不需要在机器人最容易受磕碰的角落多装一个零件;而且开关闭合时通往地的低阻抗通路,正是防止长长的保险杠引线从旁边的电机驱动拾取噪声的关键。

延伸阅读

参考资料