简介:一套超迷你写字机器人的完整设计资料,集成软件、电路与结构三大核心模块,面向嵌入式开发者、机器人爱好者和电子工程学生,适合用于学习小型机器人从算法到硬件的全流程设计。压缩包内共170个文件,以C语言源文件(.c/.h)为主,数量过百,包含STM32F10x标准外设库、G代码解析、步进电机控制等关键代码;配套Keil工程文件、原理图与PCB设计文档、3D结构模型及少量辅助说明文件,包体约10.66MB,整体结构清晰便于检索。该项目源自X-Bot-master开源方案,软件部分涵盖定时器、ADC、USART等外设驱动,电路部分包含电源管理、电机驱动等模块,结构部分提供机械模型可供直接查看,能够帮助用户理解写字机器人的完整实现思路,并进行二次开发或功能扩展。目前已有57人浏览学习,对于希望快速上手小型智能硬件项目的读者来说,是一份兼具参考性与实践性的资源。
1. 超迷你写字机器人:从 ZIP 里的三件套到桌面上的小型数控设备
一个自己设计的超迷你写字机器人,听起来像儿童玩具,实际上是一台桌面级的微型数控平台。像 pgj.zip 这样的项目包虽然解压出来文件不少,核心通常就三样东西:C 语言写的下位机控制程序、电路原理图和 PCB、结构件图纸。它解决的问题很具体:让一支圆珠笔像打印机一样,把文字和线条按顺序写到纸上。适合的人群是电子、软件、机械都想沾一遍的从业者和进阶爱好者,新手能照着方案复现,老手可以换电机、换固件、改笔架做自己的版本。这里我先说一个反直觉结论:多数人复现失败,不是电机不转,而是笔画顺序乱、抬笔高度不对、固件参数根本没按结构算。
2. 机械结构这样选:超迷你机身的三种布局与传动参数怎么定
2.1 三种布局谁更适合写字:小车式、CoreXY 与迷你龙门
写字机器人对机械结构的要求说起来很简单:两轴垂直度要好、运动部件要轻、回程间隙要小。写字用的笔尖只要错开 0.2mm,5mm 高的小字就看得出歪斜,所以结构选型比电机功率重要得多。市面上最常见的 DIY 布局有三类,我分别说清它们的边界,你在画结构图之前就能定方向。
第一种是小车式,也叫白俄罗斯结构:固定两根互相垂直的滑轨,笔架放在交叉点,两个电机各拉一根同步带,带动笔架在两方向上移动。优点是零件少、机身极小、成本最低,一张 A5 纸的写字范围只要 200mm 见方的底板;缺点是笔架悬在交叉点上,刚性差,加上自带抬笔机构后会明显变重,中文这种笔画密集的字一跑快就糊。
第二种是 CoreXY,两个电机都固定在机身上,皮带绕成 8 字,X、Y 运动由两电机协同完成。它的运动惯量最小,看起来最“高级”,也是很多 3D 打印机改写字机的首选。但 CoreXY 的皮带张力和绕法对装配精度很敏感,两边松紧不一致时,写出来的字会从矩形变成平行四边形,排查起来相当花时间。
第三种是迷你龙门,更像桌面雕刻机的缩小版:X 轴是一根光轴加滑块,笔架在上面移动;Y 轴靠底板前后运动;Z 轴直接装在笔架上。刚性最好,加舵机抬笔或电磁铁落笔都容易,超迷你机型用 2020 铝型材加 3D 打印件就能搭。缺点是多了一组导轨,重量和成本比小车式高一点。如果目标是“认真写字而不是证明它能动”,我更推荐迷你龙门。
从复现角度看,我的选型建议是:第一次做,只写英文和数字,小车式完全够用;想写中文、画复杂线条,或者以后改成小雕刻机,直接上迷你龙门。CoreXY 适合已经有皮带调校经验的人,新手第一台就不建议碰,否则你分不清写字抖是机械问题还是皮带绕法问题。
2.2 脉冲当量与速度换算:先把 0.0125mm/步 算明白再切料
结构布局定完,下一个不能跳过的计算是脉冲当量——每个步进脉冲让笔尖移动多少毫米。这个数直接决定 GRBL 固件里的$100、$101参数,算错了字会整体变形。超迷你写字机最常见的传动组合是:GT2 同步带,齿距 2mm;20 齿带轮,转一圈走 40mm;步进电机用 NEMA14 或 NEMA17,1.8° 步距角,200 整步一圈;驱动细分 16。这样每一步位移就是 40 / (200×16) = 0.0125mm。
下面这张表是不同细分下的每步位移,方便你对照自己的配置:
| 细分 | 每转需要的脉冲数 | 带轮 20 齿(周长 40mm)每步位移 |
|---|---|---|
| 1 | 200 | 0.200mm |
| 8 | 1600 | 0.025mm |
| 16 | 3200 | 0.0125mm |
| 32 | 6400 | 0.00625mm |
细分不是越高越好。16 细分下 0.0125mm 已经能写出干净的字,32 细分会让电机力矩下降,在迷你机身这种轻负载上是白白增加固件计算量。很多写字机器人翻车就是因为照抄网上 3D 打印机的$100=80,没意识到那是别的带轮直径算出来的。
速度换算公式也一并记住:速度(mm/min) = 脉冲频率(Hz) × 每步位移(mm) × 60。比如想要 3000mm/min 的快速移动,在 0.0125mm/步 下需要 4000Hz 的脉冲频率,GRBL 的$110就填 3000。加速度我一般先用 150mm/s²,跑起来如果起步不丢步再往上加,不要一次性冲到 300。迷你结构的刚性扛不住过大的起步冲击,这也是很多人写字写到一半突然整体偏移几毫米的直接原因。
3. 电路与驱动板怎么搭:从 GRBL 固件到限位开关去抖
3.1 控制板走哪条路:Arduino+CNC Shield 还是自己写 C 固件
电路部分的核心职责是细分步进电机的激励信号、产生抬笔动作、读取限位开关,并且和上位机通过串口交互。对着手复现的人来说,第一台一定先走 Arduino Nano + CNC Shield v3 + 两个步进驱动(X、Y)的老路。这个组合的优点是:GRBL 固件是现成的,引脚映射是固定的,CNC Shield 上的细分拨码开关直接对应电机驱动倍数,几乎不需要你自己画电路。
关于固件,GRBL 源码是用 C 语言写的,编译流程也不复杂。如果你在 VSCode 里配置过 C/C++ 环境,打开源码用 avr-gcc 编译大概就几分钟。没有这个环境也没关系,Arduino IDE 里也有 GRBL 的板卡包可以直接烧。关键是正视自己画的电路板:自己画 STM32 板并不难,难的是没有示波器时,步进丢步你根本分不清是驱动芯片焊接问题还是固件时序问题。所以我建议先把成熟的方案跑通,再逐步替换模块。
如果你就是想深入固件,下面这段是下位机 C 语言驱动步进的骨架。它做的事情是:定时器每 40us 翻转一次 STEP 引脚,产生 25kHz 的步进脉冲输出。
// 假设 SysTick 已配置为 10us 中断一次 volatile uint32_t tick_count = 0; void SysTick_Handler(void) { tick_count++; if ((tick_count % 4) == 0) { // 每 40us 翻转一次:25kHz 脉冲 GPIOA->ODR ^= GPIO_PIN_1; // PA1 作为 STEP 输出 } }这段只是演示脉冲节奏,真正生产环境要用环形缓冲区加梯形加减速,这也是 GRBL 里最核心的部分。参数上要注意,25kHz 对 16 细分、0.0125mm/步来说理论速度是 18.75m/min,对写字机器人太快了,实际通过降频或者改倍率实现 1500~3000mm/min 即可。别直接拿这个架构去写正式固件,除非你想体会一把“自己写固件到底有多少坑”。
3.2 电机接线、电流限制与限位开关:三个影响复现率的位置
CNC Shield v3 的引脚映射基本固定:X 步进接 D2、方向接 D3,Y 步进接 D4、方向接 D5,Z 步进接 D6、方向接 D7,限位开关分别接 D9、D10、D11。第一次接线最容易出的问题不是接反,而是步进电机的 A+、A-、B+、B- 四根线里有一组对调,结果是电机一顿一顿但不转。这种情况先对调任意一组线,而不是怀疑驱动坏了。
电流限制是另一个被很多人忽略的细节。A4988 驱动板上通常有电流检测电阻 Rs,限流公式是 I = Vref / (8×Rs)。比如 Rs = 0.1Ω,想让电机工作在 0.8A,Vref 就调到 0.64V。用万用表量 Vref 时,把表笔接在驱动板电位器中间脚和 GND 之间,一边调一边量,调到目标值后装回去试走。电机温度超过 60℃ 说明电流太大,马上降压。
限位开关如果不处理抖动,写字机一触发归位就可能原地抽搐,甚至把坐标原点跑飞。硬件上我给每个开关并联 0.1uF 电容并加 10kΩ 上拉,软件里再做一个简单的连续采样消抖:
// 连续读到 5 次低电平才确认限位触发 uint8_t debounce_limit(uint8_t sample) { static uint8_t cnt = 0; if (sample) { cnt = 0; return 0; } if (cnt < 5) cnt++; return (cnt >= 5) ? 1 : 0; }这段代码的逻辑是:任何一次高电平都会把计数清零,只有连续 5 次读到低电平才输出触发信号。参数 5 是经验值,配合 0.1uF 电容,对机械开关几十毫秒的抖动足够;如果你的开关特别老,改成 10 次即可。开关类型也注意:GRBL 默认支持常开接地,如果你买的是常闭开关,需要改$5参数,否则上电就报限位触发。
4. 软件链路与参数调校:把文字变成笔尖能走的 G 代码
4.1 笔画转 G 代码:用 Python 把一条条笔画送到写字机器人嘴里
写字机器人上位机软件的核心不是“把字显示出来”,而是把一串文字拆成一个个连续的笔画,再转成 G 代码。图纸、字库或者手写轨迹最终都要落到一张坐标表上。常见做法有两种:一是用矢量字库导出 SVG path,再解析 path 的点;二是用点阵字库或手写轨迹,先做骨架细化,再把骨架折线按固定步长采样。前者适合打印体,后者适合手写体,我建议第一版都用手动定义好的笔画点集,先把链路跑通再上升到自动拆字。
以下函数把一组笔画点转成 G 代码,它假设你已经拿到了每个笔画的坐标序列:
def strokes_to_gcode(strokes, feed=1500, z_up=3.0, z_down=0.0): out = ["G21", "G90", "G94", f"F{feed}", f"G00 Z{z_up:.3f}"] for stroke in strokes: if len(stroke) < 2: continue x0, y0 = stroke[0] out.append(f"G00 X{x0:.3f} Y{y0:.3f}") out.append(f"G00 Z{z_up:.3f}") out.append(f"G01 Z{z_down:.3f} F{feed * 0.6:.0f}") for x, y in stroke[1:]: out.append(f"G01 X{x:.3f} Y{y:.3f}") out.append(f"G00 Z{z_up:.3f}") out.append("G00 X0 Y0") return "\n".join(out) + "\n"逻辑说明:每条笔画先快速移动到起点上方,再垂直下笔,笔尖接触纸面后按 feed 的 60% 画线,画完抬笔。这里控制的核心是抬笔动作,G00 Z不是走到纸面而是走到安全高度。参数方面,feed=1500对应第 2 章算过的 1500mm/min,第一次跑建议降到 600;z_up是抬笔高度,对迷你机 3mm 够用;z_down是落笔深度,0 表示刚好接触纸面,具体偏差放到校准环节处理。
4.2 下位机参数表:脉冲当量、速度和加速度先设对
拿到 G 代码之后,下位机参数如果是从网上抄的,前面所有计算全白费。GRBL 里最敏感的几项是$100、$101、$110、$111、$120、$121。继续用第 2 章的配置:带轮周长 40mm、电机 200 整步、驱动 16 细分,那么每毫米步数是 3200 / 40 = 80,所以$100=80,$101=80。
| GRBL 参数 | 含义 | 建议初始值 |
|---|---|---|
| $100 / $101 | X / Y 轴每毫米步数 | 80.000(由传动比计算) |
| $110 / $111 | X / Y 最大进给,mm/min | 1500~3000 |
| $120 / $121 | X / Y 加速度,mm/s² | 150 |
| $0 | 步进脉冲宽度,us | 10 |
| $3 | 方向端口反相 | 0,接错方向时改 1 |
| $5 | 限位开关常开/常闭 | 0 常开,1 常闭 |
我把 $100 和常见的每步位移 mm 放在一起解释,因为网上教程里两种说法混着写,照着填很容易差 80 倍。判断方式很简单:写一个 10mm 方形,用卡尺量实际尺寸,如果实际是 10mm 就是参数对了,如果是 80mm 或 0.125mm,就是步数/位移单位搞混了。
抬笔动作如果你用的是舵机,GRBL 原版并不能直接输出舵机 PWM,需要改动固件或用一个单独单片机做舵机控制,上位机在 G 代码里判断 Z 值变化后发串口指令给舵机。常见替代方案是用电磁铁,把 GRBL 的 spindle enable 信号通过 MOS 管驱动电磁铁,落笔电磁铁断电靠弹簧压住笔,抬笔通电吸起。我第一版图省事用了舵机,结果笔尖绕支点转动导致落笔点偏差,后来换成了垂直升降才稳定。这个选择在你画电路板之前就要定,不然后面改机架很痛苦。
4.3 从 SVG 到纸面的完整命令流:第一次跑通的最小步骤
把上面的内容串起来,完整步骤如下:先在 Inkscape 里输入文字,转路径,导出 SVG;再运行转换脚本处理成 G 代码;然后用串口工具逐行发送。命令流大概是这样的:
# 1. 转换 SVG 路径为 G 代码(脚本自己维护) python3 svg2gcode.py input.svg output.gcode # 2. 开机后先发送归零命令,让固件知道原点 echo 'G92 X0 Y0' > /dev/ttyUSB0 # 3. 逐行发送 G 代码 python3 send_gcode.py /dev/ttyUSB0 output.gcode这里每一步都有对应的失败点:svg2gcode 脚本只识别直线段路径的话,遇到贝塞尔曲线会把笔画切碎,输出大量 G01 小段,写字速度骤降且字迹抖动;G92 归零是手动对刀的基础,如果你的机器有限位开关,也可以发$H做硬归位;send_gcode 脚本里,最关键的是每发一行必须等固件回“ok”再发下一行,GRBL 缓冲区很小,一次性丢一堆命令会丢命令,轻则笔画断,重则整段轨迹跑飞。
5. 自己搭迷你写字机避坑:六个高发故障现象与排查顺序
5.1 字迹拖线、笔画顺序乱和字整体偏斜:看得见的三个现象
现象一:字写完后,每笔之间都有一条细细的拖线,整张纸像被圆珠笔漏墨扫过。原因:抬笔高度太低,笔尖在快速移动到下一笔画起点时还在纸面上滑动。解决:把 z_up 从 1mm 提高到 3mm,并在 G00 指令前先加一段很小的抬笔方向补偿,让笔尖离开纸面后再水平移动。改完再观察,如果还有细线,说明你的抬笔机构行程本身不够。
现象二:写出来的字不是按设计顺序一笔一笔出现,而是笔在纸上乱跳,或者同一笔反复描。原因:笔画拆分脚本把轮廓当成单笔画处理了,一个闭合轮廓会先画外圈再画内圈,看起来像乱序;也可能是 G 代码里落笔和抬笔状态搞反了。解决:在生成器里按“先左后右、从上到下”对笔画排序,并在每条笔画开始时强制加一条 G00 Z 抬笔,而不是依赖上一笔的状态。
现象三:字能写出来,但整体是斜的,或者矩形笔画变成了平行四边形。原因:两轴不垂直,皮带轮固定块有角度偏差,或者同步带一侧张紧不够。解决:松开 Y 轴导轨固定螺丝,画一个大正方形,用手微调导轨角度,直到对角线基本相等;再用百分表顶住笔架检查垂直度。这一步是装配功夫,软件补偿只能治标,治本就是重新调结构。
5.2 丢步、限位抖动与串口卡死:看不见的三个电气陷阱
现象四:写短文本正常,写到第三四行时整个图形开始逐渐偏移,横线长度也不对。原因:步进电机丢步,通常不是电机坏了,而是电流不足或加速度太大。解决:先按 3.2 节的公式把电流调到电机额定值;再把 $120 加速度降到 100mm/s²,并重新确认带轮顶丝锁紧在电机轴上。还有一个容易被忽略的细节:步进驱动板和电机的连接端子松了,走线一抖就虚接,所以检查顶丝之前先检查接线端子是否有松动。
现象五:按限位开关归位时,坐标原点每次都不同,甚至一碰开关机器就乱走。原因:机械开关触点抖动,固件把一次按下的几十毫秒抖动当成多次触发。解决:硬件加 0.1uF 电容,软件做连续采样消抖,代码在 3.2 节给过。这里多说一句:开关线要远离步进电机线,电机线里的电流突变会通过感应耦合干扰限位信号,线走一起时我见过每周五下午必出问题的玄学故障,其实是电机线扭矩折弯把信号线磨破了。
现象六:串口发送 G 代码中途卡住,等了十几秒才继续,或者直接停止。原因:GRBL 缓冲区被塞满后,上位机没有按“收到 ok 再发下一条”的协议等待。解决:用 4.1 的 send_gcode 逐行发送并等待“ok”;发送频率也要控制,不要用 cat 一次把整个文件灌进串口。验证方法是打开串口监视器,看到每条命令都应答一次 ok,就说明链路是干净的。
6. 把“能写”升级为“写得稳”:脉冲当量反推与一页校准网格
6.1 一页校准网格,解决“为什么每次写出来尺寸都不一样”
校准页不需要复杂排版:A5 纸面上打 4 个角点、一个 60mm 方形、一条 10mm 的十字尺标,再加两行 5mm 高的文字。每次改机械或参数,先在角落写这三样,用卡尺量一次,再对比上一次的结果。不要直接拿一页长文做测试,那只会让你分不清是哪一段出的问题。
脉冲当量精确反推的方法也很简单。用当前参数写一个 10mm 方形,卡尺量出实际尺寸,比如 10.18mm,说明 $100 偏小,因为走同样的步数实际距离变长了。新的 $100 = 旧值 × 实际尺寸 / 目标尺寸,也就是 80 × 10.18 / 10 = 81.44,写入后重写一次方形验证。这个操作叫比例反推,我自己每次换皮带、换带轮、换电机后必做一遍,成本一分钟,省得后面所有调试都在错误基础上打转。
我个人的习惯是:任何一次只改一个变量,改完统一跑同一页校准网格。改加速度、改抬笔高度、换笔芯、加纸垫,都分开验证,不叠在一起。因为写字机器人是机电软三合一的系统,同时改两个参数出了毛病,除了盲猜没有别的办法。希望帮到你。
本文还有配套的精品资源,点击获取