Mach3手摇脉冲发生器DIY:用Arduino Leonardo模拟USB键盘实现MPG手轮
2026/8/26 13:17:17 网站建设 项目流程

1. 为什么要给 Mach3 配一个手摇脉冲发生器

玩 CNC 的时间一长,你早晚会撞上同一个场景:对刀的时候右手要反复点屏幕上的 Jog 按钮,眼睛在刀尖和电脑屏幕之间来回跑,稍微一不留神按错方向,铣刀就撞上了虎钳。这时候你最想要的东西,就是一个能握在手里的“手轮”——也就是 CNC Pendant,中文圈一般叫手摇脉冲发生器或者 MPG 手轮。

Mach3 是目前国内 DIY 玩家和老式机床改造圈里使用率最高的控制软件之一,它的功能放在今天看依旧能打,但操作交互还停留在“键盘 + 鼠标 + 屏幕按钮”年代。你当然可以用键盘上的方向键去手动移动各轴,但方向键没有机械刻度感,按一下走多少全靠眼睛盯坐标,远不如转动手轮来得直观。手轮上典型的动作是:转一格,机床走一个设定好的最小增量;反过来转一格,机床就往反方向走一格。这个手感在加工铝件、石墨电极、或者做雷射对刀的时候特别重要,因为你可以用鼻子尖贴着手轮、眼睛盯着刀具下方的间隙,慢慢摇。

这篇东西我会把“从零做一个 Mach3 手轮”的完整流程拆给你看。不会假装很玄学,我用的方案是 Arduino Leonardo 模拟 USB 键盘,把 MPG 的旋转脉冲翻译成 Mach3 能识别的快捷键动作。这个方案有几个硬优点:不需要额外写 Mach3 插件、不需要动并口线、不用换运动控制卡,几根杜邦线加一个手轮就能跑起来。适合的人群很明确:有一定 Arduino 基础、机床控制柜已经跑通 Mach3、现在想把手动操作从键盘升级成手轮的 DIY 玩家。如果你完全没有用过 Mach3,建议先把基本走线和运动控制调好,再回来折腾这个,不然容易把两个问题混在一起。

2. 方案选型:手轮这东西到底该怎么做才靠谱

2.1 三种常见实现方案对比

在开始买零件之前,值得花两分钟把实现思路捋清楚。网上能搜到的手轮方案很多,但本质上只有三条路线。

第一种是“原生并口 MPG 输入”。Mach3 在 Ports & Pins 的 Input Signals 里预留了 MPG A、MPG B、MPG C 这类信号,如果你手里的运动控制板带光耦隔离的编码器输入,可以直接把手轮 A/B 相信号接进去,然后在 Mach3 里做映射。这个方案延时最低、手感最接近成品机床,但它要求你的软件版本、运动卡、针脚定义全都对得上。老式 DIY 机器用的并口板经常只有一个 25 针口,能用的输入点本来就紧张,再把 MPG 接进去就要牺牲掉限位开关或者主轴正反转信号,改起来容易乱。

第二种是“Modbus 或自定义插件方案”。你通过 Arduino 或者其他单片机读取手轮脉冲,再通过 USB 串口和 Mach3 插件通信,由插件直接调 Mach3 的 OEM 运动函数。这个方案功能上限最高,可以在插件里做到轴选择、倍率切换、绝对/相对坐标切换这些花活,但代价是你需要一个能写 C# 插件的人,或者找到完全开源的现成工程。我最早也考虑过这条路,后来发现自己不想为了一个手轮去维护一个只在老版本插件框架下能用的 DLL。

第三种就是我今天要详细讲的“USB 键盘模拟方案”。Arduino Leonardo 自带原生 HID 功能,也就是可以直接被 Windows 识别成键盘。我们把 MPG 手轮看作一个旋转编码器,每转一格就发一次方向键按键事件,Mach3 收到方向键按下后,会用当前界面上设置的 Jog Increment 来走一步。这个方案的好处是链路短:单片机不用理解 Mach3 的任何协议,只需要做“转了多少格”和“按下哪个键”之间的映射。成本低、调试容易,最适合作为第一个自制手轮方案。

方案成本实现难度手感与响应灵活性
原生并口 MPG 输入低,但要硬件支持最好低,受输入点限制
Modbus/自定义插件中,额外电控板很好最高
USB 键盘模拟够用,有轻微键盘重复延迟

2.2 核心硬件清单与选型逻辑

动手之前先把料备齐。这是我用的清单,全部是淘宝或者立创商城能买到的常规件。

  • MPG 手轮本体,常见规格是 100 PPR / 25PPR。我推荐买 100 PPR 的,手感更细腻。注意要买带五个引脚的那种:A、B 两相信号,一个公共端,有的还带 C(零位指示)和背光。
  • Arduino Leonardo 开发板,或者任何 ATmega32U4 主控的板子。原因很简单,Leonardo 能直接当 USB HID 键盘用,不需要额外的串口转键盘芯片。Uno 虽然便宜,但那块板子的主控是 ATmega328P,没有原生 HID,需要额外刷 HoodLoader2 固件才能模拟键盘,复杂度上去了。
  • 轻触按钮若干,用来做轴选择、倍率切换、手轮使能。我建议至少四到六个:X、Y、Z、A 轴切换,再加一个强制急停(这个不是给信号用的,是给你心理安慰的)。
  • 一个急停按钮,必须选用带常闭触点的“自锁型急停”,并且要串进机床主回路里,不能只接给 Arduino。这个下面细说。
  • 一个 5V 供电模块,或者直接从控制柜里拉 5V 到 Arduino 的 5V 引脚。手轮一般也是 5V 供电,注意不要和电机驱动器的电源混在一起,尽量用隔离 DC-DC。
  • 少量电阻,10kΩ 上拉电阻若干,用于按钮和编码器输入。
  • 外壳,我用的 3D 打印的桌上小盒子,如果你手边有铝盒子会更好,因为金属外壳有屏蔽效果,能减少变频器和步进驱动器对手轮信号的干扰。

我见过不少人一上来就买那种工业成品手轮,比如带显示屏的、支持无线连接的。那个当然省心,但我自己做下来觉得,手轮最核心的价值不在屏幕,而在“旋钮手感”和“按键逻辑”。自己做一个,你可以把按键排布按照自己的操作习惯来定制,比如把急停放在大拇指够得着的位置,把倍率切换放在食指盲按的位置,这些体验是成品手轮给不了的。

2.3 硬件接线与安全回路设计

接线必须分成两套系统来想:信号系统和安全系统。

信号系统这边,MPG 手轮的五根线,一般红色接 5V,黑色接 GND,A/B 相是绿色和白色。A、B 两根信号线分别接到 Arduino 的 2 号和 3 号引脚,这两个引脚在 Leonardo 上支持外部中断,我们会在中断服务程序里读编码器状态。注意手轮内部是一个机械编码器,输出的是悬空的开漏信号,所以你必须在 Arduino 上把 A、B 引脚配置成 INPUT_PULLUP,也就是让单片机内部的上拉电阻把它顶到高电平,否则电平会乱跳。手轮的公共端如果是带集电极输出的那种,你可能需要在外部再接一个 10kΩ 的上拉电阻,具体看手轮内部的接口说明。

按钮的接法更简单,每个按钮一端接某个数字引脚,另一端接 GND,然后用 INPUT_PULLUP 引脚,按下时读到 LOW,平时读到 HIGH。

安全系统这边要单独强调一遍:Arduino 控制的任何按键都不能承担急停职责。急停按钮必须走串联常闭回路,直接串在步进驱动器的使能信号、主接触器线圈或者变频器禁止启动的回路里。按下急停,物理上切断驱动器的使能电源,让电机停住。如果你只是把急停接到 Arduino 上,通过发键盘事件让 Mach3 停止运动,万一单片机死机、USB 线松动、或者 Mach3 界面失去焦点,急停就报废了。我见过有人把急停按钮接到了并口板的输入脚上,本来想着省事,结果有一次 Mach3 占用率 100% 导致界面卡死,按急停完全没反应,差点撞断一把铣刀。从那以后我所有的急停回路都是硬线串联,Arduino 只负责发“软件暂停”之类的辅助信号。

3. 核心细节解析与实操要点

3.1 MPG 手轮的工作原理:它到底在输出什么

MPG 手轮本质上是一个手动旋转编码器。你转一格,内部金属刷子和触点接触,A、B 两相会输出两路相位差 90° 的方波。两路信号的相对相位关系决定了旋转方向:正转时 A 相领先 B 相,反转时 B 相领先 A 相。单片机要做的不是数脉冲个数就够了,而是通过状态机识别“当前 A/B 状态”和“上一个 A/B 状态”,每变化一个边沿就判断一次方向,得到一个 +1 或 -1 的增量。

100 PPR 的手轮,内部编码器转一圈输出 100 个脉冲,但每个脉冲在 A/B 两相上会组合出 4 个边沿,所以如果你在两相上都做了 CHANGE 中断,一圈能读到 400 个“边沿计数”。很多人第一次测试的时候发现屏幕上的计数乘了四倍,就是没做边沿归一化。我们把脉冲数除以 4,才是真正的手轮“格数”。

代码里我直接用了一个 4x4 的状态表,记录上一次 A/B 组合状态和当前 A/B 组合状态,查表得到增量。这个表很容易记忆:只有在编码器状态从 00→01→11→10→00 这种合法顺序变化时才输出增量,其他非法跳转一律归零。这样做的好处是抗抖动能力非常强,哪怕手轮在格点上轻微晃动,也不会产生错误计数。

3.2 按键防抖与扫描策略

按键看起来简单,但做出来最容易被吐槽的就是“咔哒一下,轴切换了两次”。机械按钮普遍存在 5ms 到 20ms 的抖动,直接用 digitalRead 判断按下会发生多次触发。我在 loop 里用一个 20ms 扫描周期,按下判定加入“斜坡触发”逻辑:只有当检测到从高电平变为低电平,并且持续了至少 20ms,才算有效按下。对于倍率按键,我实现的是循环切换,按一下切一档,如果按住超过一秒钟,就让它连续切换,方便在 0.001、0.01、0.1、1 四档之间快速跳转。

轴选择按钮逻辑上要处理一个特殊问题:当前选中的轴必须有清晰的视觉反馈。我调试的时候最头疼的就是忘了自己在选 X 还是选 Y,结果摇手轮动了不该动的轴。后来我在代码里做了一个简单的 OLED 显示,用 I2C 接口的 0.96 寸小屏显示当前轴、倍率和坐标方向,塞在外壳顶面。成本十几块钱,但用起来安心太多。如果你不想加屏幕,至少也要用不同颜色的 LED 灯来标示当前轴。

3.3 主循环里的键盘映射与响应速度权衡

主循环读完手轮增量之后,接下来就是把它翻译成键盘事件。Mach3 里方向键的默认映射是:左右键控制 X 轴、上下键控制 Y 轴、PageUp/PageDown 控制 Z 轴、Insert/Delete 控制 A 轴。我在代码里做了一个简单的 switch,根据当前选中的轴,把正转和反转分别映射到对应的方向键按下/释放事件。

这里有个非常关键的取舍:按键事件是“按下 + 释放”成对出现的,而且两次事件之间必须保留足够的时间间隔,否则 Windows 会自动启用“按住重复”功能,导致按键按一次触发好几步动作。实测下来,每次按下-释放间隔至少需要 5ms 到 10ms。这意味着你的手轮最高有效转速大约在每秒 100 格以内。100 PPR 的手轮,如果按每秒两圈来转,每秒就是 200 格,这时候键盘模拟方案就跟不上,事件会被 Windows 的输入队列吃掉,表现为你转了但机器没走多少。解决办法有两个:一个是放慢手轮转速,另一个是给 Mach3 设置较大的 Jog Increment,让“一格”对应更大的移动量,减少需要发送的按键次数。这个取舍在机器上实际用的时候问题不大,因为手轮本身就是精细操作工具,没人会握着它高速猛摇。

3.4 把倍率、轴选择做到 Mach3 里还是做到固件里

一个常见的问题:手轮上的倍率切换,到底是 Mach3 自己管,还是单片机管。

我的做法是让 Mach3 的 Jog Increment 始终保持在一个固定的小值,比如 0.001mm,然后在固件里做倍率。转一格,如果当前倍率是 x1,就发 1 个按键事件;如果倍率是 x10,就发 10 个按键事件;倍率是 x100,就发 100 个按键事件。这样做的原因是 Mach3 的方向键没有直接的“倍率切换”快捷键,你很难从固件里去控制 Mach3 的界面参数。反过来,在固件里做倍率,逻辑完全可控,而且倍率切换的反馈可以显示在 OLED 上。

但这里又牵出一个性能问题:如果倍率选到 x100,一格发 100 个键盘事件,每秒 100 格就是每秒 10000 个事件,USB HID 根本发不过来。所以我给倍率上限做了限制,最高只做到 x100,而且代码里一次循环最多发 32 个事件,剩下的放到下一次循环继续发。实际体验是,你快速转一整圈手轮,机器会持续匀速运动一段时间,并不会丢步,只是运动有几十毫秒的滞后,这个滞后在手动操作时可以接受。如果你接受不了这种手感,那真的应该去研究 Modbus 插件方案,而不是死磕键盘模拟。

4. 实操过程与核心环节实现

4.1 固件完整代码:基于 Arduino Leonardo

下面这段固件是我在项目里实际跑过的版本,做了精简,去掉了一些无关显示代码,保留了核心的编码器读取、按钮扫描和键盘映射逻辑。你需要先安装 Arduino IDE,然后在 Boards Manager 里选 Arduino Leonardo,再把下面代码烧录进去。

// Mach3 Pendant - Arduino Leonardo USB HID Keyboard Emulation // A/B signals on pin 2 and pin 3 (interrupt capable) // Buttons: X, Y, Z, A axis selection on pins 4-7 // Buttons: inc1, inc2, inc3, inc4 on pins 8-11 #include <Keyboard.h> #define MPG_A 2 #define MPG_B 3 const int axisBtnPins[4] = {4, 5, 6, 7}; const int incBtnPins[4] = {8, 9, 10, 11}; volatile int32_t mpgPos = 0; volatile uint8_t prevEncState = 0; // 4x4 state table for encoder direction // index = previous_state * 4 + current_state // legal sequences: 0,1,3,2,0 => counterclockwise // 0,2,3,1,0 => clockwise const int8_t encTable[4][4] = { {0, -1, 1, 0}, {1, 0, 0, -1}, {-1, 0, 0, 1}, {0, 1, -1, 0} }; void isrEncoder() { uint8_t a = digitalRead(MPG_A); uint8_t b = digitalRead(MPG_B); uint8_t state = (a << 1) | b; int8_t delta = encTable[prevEncState][state]; if (delta != 0) { mpgPos += delta; } prevEncState = state; } int axis = 0; // 0=X, 1=Y, 2=Z, 3=A int incIndex = 1; // 0=x1, 1=x10, 2=x100 void setup() { pinMode(MPG_A, INPUT_PULLUP); pinMode(MPG_B, INPUT_PULLUP); for (int i = 0; i < 4; i++) { pinMode(axisBtnPins[i], INPUT_PULLUP); pinMode(incBtnPins[i], INPUT_PULLUP); } attachInterrupt(digitalPinToInterrupt(MPG_A), isrEncoder, CHANGE); attachInterrupt(digitalPinToInterrupt(MPG_B), isrEncoder, CHANGE); Keyboard.begin(); } void loop() { // simple button scan with debounce static unsigned long lastBtnScan = 0; static int lastAxisBtn = -1; static int lastIncBtn = -1; if (millis() - lastBtnScan > 20) { for (int i = 0; i < 4; i++) { if (digitalRead(axisBtnPins[i]) == LOW && lastAxisBtn != i) { axis = i; lastAxisBtn = i; } if (digitalRead(incBtnPins[i]) == LOW && lastIncBtn != i) { incIndex = i; lastIncBtn = i; } } if (digitalRead(axisBtnPins[axis]) != LOW) { lastAxisBtn = -1; } if (digitalRead(incBtnPins[incIndex]) != LOW) { lastIncBtn = -1; } lastBtnScan = millis(); } noInterrupts(); int32_t count = mpgPos; mpgPos = 0; interrupts(); if (count == 0) return; int detents = count / 4; // normalize quadrature edges to detents if (detents == 0) return; int sign = detents > 0 ? 1 : -1; int pulses = abs(detents); // multiply by increment index: x1, x10, x100 int multiplier = 1; if (incIndex == 1) multiplier = 10; if (incIndex == 2) multiplier = 100; long totalSteps = pulses * multiplier; if (totalSteps > 256) totalSteps = 256; // cap burst to avoid flooding the HID queue // send key events as a sequence of press/release for (long i = 0; i < totalSteps; i++) { switch (axis) { case 0: Keyboard.press(sign > 0 ? KEY_RIGHT_ARROW : KEY_LEFT_ARROW); Keyboard.release(sign > 0 ? KEY_RIGHT_ARROW : KEY_LEFT_ARROW); break; case 1: Keyboard.press(sign > 0 ? KEY_UP_ARROW : KEY_DOWN_ARROW); Keyboard.release(sign > 0 ? KEY_UP_ARROW : KEY_DOWN_ARROW); break; case 2: Keyboard.press(sign > 0 ? KEY_PAGE_UP : KEY_PAGE_DOWN); Keyboard.release(sign > 0 ? KEY_PAGE_UP : KEY_PAGE_DOWN); break; case 3: Keyboard.press(sign > 0 ? KEY_INSERT : KEY_DELETE); Keyboard.release(sign > 0 ? KEY_INSERT : KEY_DELETE); break; } delay(5); } }

这段代码有几个细节值得你上手之后自己调。第一是每发一个按键事件之后那个 delay(5),不要随便删掉。键盘模拟最怕的就是事件发得太快,Windows 会把它们合并成“同一按键的长按”,结果你就发现按键一次触发了好几格。第二是 count 对 4 取整之前的余数要不要丢。我直接丢掉了,这意味着如果你恰好停在某个边沿中间,会丢失不到四分之一个格子的计数,对手动操作来说无感。第三是 totalSteps 的 256 上限,这是我根据 USB 传输速率压出来的经验值,超过这个值就很容易出现按键堆积。

4.2 Mach3 端配置与快捷键验证

固件烧录完之后,先不要急着上机床。把 Arduino 插到电脑上,随便打开一个记事本,转动 MPG 手轮,你应该能看到光标输出一大堆方向键的内容。这一步只是为了验证键是否正确发出。然后最小化记事本,打开 Mach3。

Mach3 的主界面上有一个 Jog 区域,里面有 X、Y、Z、A 按钮和步进增量选择。用键盘模拟方案的时候,你需要在 Jog 区域先指定一个基础步进增量,比如 0.001mm。然后点击一下 Jog 区域的空白处,确保这个面板获得了键盘焦点,再转手轮。你会发现每转一格,坐标值按设定的增量变化。

我给这条链路做了个快速测试表,每一步过了再往下走。可以先检查 Arduino 在设备管理器里是否被识别为“键盘”。然后打开记事本验证方向键事件。接着打开 Mach3 的 Diagnostics 页面,手动按键看看有没有触发对应的 Jog 动作。最后才把机床使能打开,以很低的进给速度测试实际运动方向。

验证层级工具预期结果
HID 设备识别Windows 设备管理器出现 Keyboard 设备
事件发送记事本方向键光标移动
Mach3 按键映射Mach3 Jog 面板点击目标轴后,方向键能动坐标
实机运动CNC 系统步进电机按预期方向移动

Mach3 的方向键映射在绝大多数版本里是开箱即用的,但如果你用的是被改过的界面方案,最好在 Config > System Hotkeys 里打开看一下,把方向键和 Jog 动作的绑定关系确认一遍。老版本 Mach3 可能会有“Jog 按键只在特定页面生效”的情况,如果你发现按键只在 MDI 页面有反应,多半是界面皮肤的焦点问题,我后面会在常见问题里展开。

4.3 机箱与线材处理

手轮是握在手里的东西,我强烈建议不要裸板飞线。一个常见的教训是:手轮在机箱外悬着,线材经常被电机电缆缠住,或者被切削液溅到,信号时好时坏。我的做法是设计一个分体式结构:手轮本体固定在一个 3D 打印的底座里,底座引出一条航空插头线,通过一个四芯防水插座连接到控制柜内的 Arduino 模块。控制柜内部 Arduino 到计算机用一根短 USB 线。这样手轮可以随意摆放在桌面或挂在机床侧边,不用每次插拔 USB。

机箱内部走线有一点特别重要:编码器 A/B 信号属于高速脉冲信号,要跟电机驱动线、变频器输出线保持至少 5cm 的间距,如果做不到,就要用屏蔽双绞线。我第一次做的时候图便宜用了普通的杜邦线,开机后手轮的计数经常莫名跳动,后来才知道是隔壁步进驱动器的脉冲线串扰。换成了屏蔽双绞线之后,问题立刻消失。如果你想彻底杜绝干扰,可以在 Arduino 输入端加一个 6N137 光耦隔离,但那样功耗和复杂度都会上升,个人玩家其实没必要。

4.4 校准与手感调优

机器装好之后,不要直接开始加工,先做一轮手感调优。倍率 x1、x10、x100 三档之间最直观的区别是:x1 时转一格走 0.001mm,非常细腻;x100 时转一格走 0.1mm,适合从远处快速移动到工件附近。你需要在实际加工前确认每个倍率下的步进方向是一致的,特别是如果哪天你换了方向键映射,很容易按下 x100 后一个误操作就撞机。

我个人的校准流程是:先装上一块废料,画一个简单的方形轮廓。然后用手轮手动走一遍 X/Y 轴,观察实际移动方向和手轮转向是否一致。如果方向反了,可以在编码器状态表里把正负号反过来,不要在 Mach3 里改方向,因为 Mach3 反转方向会影响软限位和回零逻辑。这样只改手轮本体的方向,机器其他所有参数都保持不变。

5. 常见问题与排查技巧实录

5.1 光标乱跳、计数丢失,通常是“信号抖动 + 边沿处理”两个坑

这是 DIY 手轮第一大坑。如果你发现转动一格但记事本里出现了好几个按键,或者反过来转了好几格才触发一个,先检查 A/B 相有没有接反,然后重点看状态表。我调试的时候遇到过“同一方向连续转,偶尔倒退一格”的诡异问题,最后发现是手轮公共端虚焊,导致高电平不稳,编码器状态机把非法跳转变成了反向计数。解决办法是把信号线重新焊一遍,并在公共端到 GND 之间加一个 0.1uF 滤波电容。这个电容不要加在 A/B 信号上,那会破坏相位关系,只加在电源和地之间。

5.2 Mach3 完全不响应方向键

如果你在记事本里验证过按键没问题,但 Mach3 没反应,九成是焦点问题。Mach3 的某些界面上,Jog 面板并不总是持有键盘焦点,尤其当你切到 Diagnostics 或者 Toolpath 页面后,方向键可能被当成快捷键做别的事,或者根本没被响应。我的习惯是每次开始动手轮之前,先拿鼠标点一下 Jog 区域的某个增量单选按钮,确保焦点在 Jog 面板上,然后再转手轮。这个习惯听起来很傻,但实际加工中能避免很多次“手轮转了半天机器没动”的慌张。

另一个可能原因是 Mach3 的安全设置里没有把 Jog 键映射到“增量模式”。老版本 Mach3 默认方向键是“连续 Jog”,也就是按住才动,松开就停。但我们键盘模拟发的是按下后立刻释放,如果你处于连续模式,就会表现为“点一下就动一小丝”而不是按步距走。要解决,需要把 Mach3 的 Jog 模式切到 Step 模式,也就是界面上那个 Step 单选按钮选上,并在增量框里设置一个基础值。

5.3 为什么手轮转到高速时机器跟不上

我在前面提过,键盘模拟方案的瓶颈不在 Arduino 不在手轮,而在 Windows USB HID 的按键事件吞吐。每秒超过 200 个按键事件的时候,系统会开始合并、延迟甚至丢弃。这时候你会看到手轮转得飞起,但坐标只在慢慢爬。这种场景我建议你把倍率切到 x1,转慢一点,用物理手感去适应机器速度;别指望手轮当快速进给的手柄用。如果你真的很需要“摇快一点走多一点点”的体验,可以考虑后面升级到 Modbus 插件方案,那个就完全是另一套东西了。

5.4 急停回路失效,这是绝对不能“将就”的问题

我有一次在给朋友装机的时候发现,那个自称“急停”的按钮,只是给 Arduino 发了个 LOW 信号,然后 Arduino 发键盘事件让 Mach3 停止。我当时直接把他机器的使能继电器拆了,费了好大劲说服他改线。原因很简单:Mach3 本身经常因为 Windows 后台更新、屏幕保护、或者某个驱动卡死而失去响应,如果急停只依赖软件,那软件挂掉的时候急停也挂掉。正确接线是:急停常闭触点串联在主接触器线圈回路里,串在伺服使能回路里,甚至串在 24V 控制电源的输入端。按下急停,物理断开,所有驱动器和主轴一起断电,和 Mach3 一点关系都没有。如果你做的 Pendant 上带急停按钮,那就让它直接驱动一个继电器,把这个继电器触点串进主回路,而不是让它跟 Arduino 通讯。

5.5 顺带说一句:老电脑跑 Mach3 的 ddraw 显示补丁

网上搜“cnc ddraw补丁”的人很多,这个补丁主要是解决 Mach3 在 Windows 10/11 上画面残留、菜单闪黑、或者鼠标拖影的问题,属于显示兼容层补丁。很多朋友误以为装了这个补丁就能解决手轮或者 USB 通信问题,其实完全不是一回事。d3d 补丁只影响 Mach3 的图形界面渲染,不参与运动控制。如果你装了补丁之后手轮按键时好时坏,问题大概率不在补丁,而是在 USB 供电、主板 XHCI 握手或者 HID 队列,别走错排查方向。

5.6 传 G 代码文件需要专门的软件吗

经常有人在群里问“CNC 电脑传程序要下什么软件”,其实这跟手轮是两码事。Mach3 本身就支持 G 代码文件的加载和 DNC 传输,你只需要把 G 代码文件放到本地磁盘或共享目录,然后点了 Mach3 的 Load G-Code 按钮即可,不需要装额外的传输软件。网上说需要装特殊串口传程序工具的,一般是老式雕铣机没有 USB,只能靠 RS232 传:O0001格式的代码,那套协议跟现代 Mach3 用法完全不同。你如果已经能正常用 U 盘拷贝一个.tap或者.nc文件,那就已经是最标准的传程序方式了,看到那些“传程序软件”的推荐可以直接忽略。

6. 升级到半专业手轮的几个思路

如果你把上面的键盘模拟手轮用顺了,想体验更接近工业成品的感受,有几个低成本升级方向。第一个是加一块 OLED 显示屏,把轴位置、倍率、手轮计数实时显示出来。手轮的机械反馈加上视觉反馈,操作体验完全不一样。第二个是增加一个“使能开关”,平时手轮处于休眠状态,只有按下使能按钮并且听到了物理咔哒声,手轮转动才会触发按键事件。这样能防止误触,尤其是手轮放在桌面上被胳膊碰到的时候。第三个是把轴选择按钮改成旋转编码器开关,逻辑上更贴近数控机床原装手轮的操作逻辑。

另外我还想提醒一下:你不需要把手轮做成“全功能”。很多人一开始就想着把主轴启停、冷却泵、循环启动、进给保持全塞进手轮,结果按键太多、代码太长、最后哪个都不可靠。我的经验是,手轮的最佳状态是“三个旋钮、四个按键”:一个 MPG 手轮、一个倍率旋钮、一个轴选择旋钮,加上急停、使能、程序暂停、对刀确认。把这一套做到绝对可靠,比做一个占用双手的遥控器有价值得多。

在键盘模拟这条路上,我自己正式用了半年,平时一个三轴小雕刻机对刀、手动锪孔、试切都靠这个手轮。它被我的学生摔过、被切削液溅过,换过三次航空插头,但 Arduino 本体和代码从来没让我失望过。要说最大的体会,反而是“别追求一次做完所有功能,先把最基本的转一格走一格做扎实”。手轮这个东西,一旦用惯了,你就不想再回到鼠标点 Jog 按钮的日子了。如果你也在做 Mach3 的手动操作体验升级,先从这套键盘模拟方案上路,跑通之后再按需加功能,是最稳妥的路线。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询