简介:本资源为Marlin 1.1.9开源3D打印机固件完整源码包,面向FDM型3D打印机DIY爱好者、硬件调试工程师及嵌入式固件学习者,解决固件定制、功能升级与稳定性优化等核心需求。压缩包共554个文件,涵盖375个头文件(.h,定义硬件接口与核心参数)、51个C++源文件(.cpp,实现运动控制、温度管理、G代码解析等核心逻辑)、21个Markdown文档(.md,含配置指南与硬件适配说明),以及配套编译脚本(.bat/.sh)、字体工具(.fon)、SVG/PNG界面资源和AVR烧录配置文件等,结构完整、开箱即用。资源包大小为4.63MB,目录组织清晰,含多平台编译支持(Linux/macOS/Windows)及TMC2130、BLTouch等主流外设驱动示例。目前已有968人学习下载,读者可直接基于此包完成主板适配、LCD交互优化、静音驱动启用及自动调平等关键功能开发,是深入理解3D打印底层控制逻辑的优质实践素材。
1. 项目概述:为什么Marlin 1.1.9在今天依然值得深挖?
如果你手头有一台老旧的3D打印机,或者正在学习3D打印机的底层工作原理,那么“Marlin 1.1.9”这个固件版本号对你来说绝对不陌生。它不像最新的2.x版本那样拥有华丽的界面和高级功能,但在很多DIY玩家、教育机构甚至小规模的工作室里,基于Marlin 1.1.9的机器依然在稳定地服役。这个项目标题指向的,正是这个经典固件版本——Marlin 1.1.9的编译、配置与烧录全过程。它不仅仅是一个“刷机”动作,更是一次深入理解3D打印机如何“思考”和“行动”的绝佳机会。
为什么是1.1.9?在Marlin固件的发展史上,1.1.x系列是一个承上启下的稳定分支。它相较于更早的1.0.x版本,引入了更多现代功能的基础支持,比如更完善的温度控制算法、对LCD控制器的更好兼容性,以及更模块化的代码结构。而1.1.9又是这个分支里一个经过大量实践检验的、相对成熟的终点版本。对于使用ATMega2560(如Arduino Mega)配合RAMPS这类经典主板架构的打印机来说,1.1.9在功能、稳定性和资源占用上达到了一个很好的平衡。今天,虽然新硬件层出不穷,但理解如何为这些经典硬件配置和编译Marlin,依然是掌握3D打印核心技术的基石。这个过程会让你彻底明白步进电机脉冲、热床PID调谐、限位开关逻辑这些概念,而不是仅仅停留在切片软件里调整几个参数。
2. 核心需求解析:我们到底要解决什么问题?
表面上看,这个项目的需求是“得到一个能烧录进主板的Marlin 1.1.9固件.hex文件”。但拆解开来,这背后隐藏着几个不同层次的需求,对应着不同的用户场景。
2.1 场景一:老旧设备焕新与故障修复
很多用户手上的打印机可能已经服役多年,原厂固件可能存在Bug(比如热床加热不稳定、自动调平失灵),或者功能缺失(不支持SD卡打印、没有中文菜单)。通过自行编译Marlin 1.1.9,可以修复这些已知问题,甚至解锁被厂商屏蔽的功能(如线性推进)。这是最直接、最普遍的需求。
2.2 场景二:DIY组装与硬件升级
当你从零开始组装一台3D打印机,或者为现有打印机更换了主板(比如从Melzi换到RAMPS 1.4)、升级了挤出机(改为双挤出)、增加了自动调平探头(如BLTouch)时,原有的固件就无法识别和控制这些新硬件了。此时,你必须根据新的硬件清单,重新配置和编译Marlin固件,让主板“认识”并正确驱动每一个部件。
2.3 场景三:深度定制与功能学习
对于开发者或极客而言,标准固件的功能可能不够用。你可能想尝试不同的挤出算法、修改步进电机的加减速曲线以提升打印速度和质量、或者集成一些特殊的传感器。Marlin的开源特性允许你深入代码层进行修改。编译Marlin 1.1.9的过程,就是学习其代码架构、配置系统和工作流程的第一步。即使你不修改代码,通过研读Configuration.h和Configuration_adv.h这两个核心配置文件,也能极大地加深对3D打印过程控制的理解。
2.4 场景四:应对固件加密与供应链问题
从网络热词中可以看到“固件加密”、“查找同主板适配的专属固件”是常见痛点。部分厂商会对固件进行加密或绑定,导致用户无法自行升级或修复。而Marlin作为开源固件,完全避免了这个问题。掌握自行编译的能力,就意味着摆脱了对原厂固件包的依赖,即使未来厂商停止支持,你也能让自己的设备持续获得更新和维护。
3. 环境准备与工具链搭建
工欲善其事,必先利其器。编译Marlin 1.1.9固件,你需要准备好一个完整的开发环境。这个过程可能会让新手感到畏惧,但一步步来,其实很清晰。
3.1 获取源代码
首先,你需要Marlin 1.1.9的源代码。虽然官方GitHub仓库的主分支已经迭代到2.x,但1.1.9的版本依然可以找到。最可靠的方式是去Marlin的GitHub发布页面,找到1.1.9版本的发布包(通常是一个ZIP文件)并下载。不建议直接克隆最新代码然后切换分支,因为构建环境可能已发生变化。下载后解压到一个没有中文和空格的路径下,例如D:\Marlin-1.1.9。
3.2 选择并安装编译工具
Marlin 1.1.9主要针对8位AVR单片机(如ATmega2560)设计,因此我们需要AVR-GCC工具链。对于绝大多数用户,我强烈推荐使用PlatformIO IDE,而不是传统的Arduino IDE。
为什么是PlatformIO?
- 依赖管理自动化:PlatformIO能自动下载所需的核心、编译工具链和库文件,省去了手动配置的繁琐和可能出现的路径错误。
- 项目化管理:它天然支持多环境配置(例如,你可以为RAMPS 1.4和MKS Gen L两块不同主板创建不同的编译配置),管理起来非常清晰。
- 更专业的体验:内置终端、串口监视器、代码自动补全等功能,对后续调试更有帮助。
安装PlatformIO最简单的方式是将其作为插件安装到Visual Studio Code中。先去官网安装VS Code,然后在它的扩展商店里搜索“PlatformIO IDE”并安装。安装完成后,VS Code的侧边栏会出现一个蚂蚁头一样的PlatformIO图标。
3.3 创建PlatformIO项目
打开VS Code,通过PlatformIO的“PIO Home”界面,选择“New Project”。
- Name:给你的项目起个名,比如
MyMarlin119。 - Board:这里非常关键。你需要根据你的3D打印机主板来选择。例如:
- 最常见的RAMPS 1.4搭配Arduino Mega 2560,选择
Arduino Mega or Mega 2560 ATmega2560。 - 如果用的是Melzi板,选择
Sanguino ATmega644P or ATmega1284P(具体看板载芯片)。 - 其他主板如MKS Gen L,也通常对应
Arduino Mega 2560。
- 最常见的RAMPS 1.4搭配Arduino Mega 2560,选择
- Framework:选择
Arduino。 - Location:选择一个合适的文件夹。
点击“Finish”,PlatformIO会自动创建项目骨架并下载必要的工具链,这可能需要几分钟时间。
注意:创建项目时选择的板型(Board)决定了编译时使用的核心和引脚定义,如果选错,编译出来的固件可能无法运行或硬件控制错乱。不确定主板型号时,最直接的方法是打开打印机外壳,查看主控芯片上的丝印。
3.4 导入Marlin源代码
创建好项目后,你会发现项目文件夹里有一个src目录。你需要将下载的Marlin 1.1.9源代码中的所有文件和文件夹(除了Marlin主目录本身),复制到PlatformIO项目的src目录下。通常,Marlin源代码解压后,里面会有一个同名的Marlin文件夹,这个文件夹里才是真正的源码。你应该复制这个Marlin文件夹里的所有内容到src下。最终,你的src目录下应该直接包含Marlin.ino、Configuration.h、Configuration_adv.h以及各种.cpp和.h文件。
4. 核心配置文件详解与定制
Marlin固件的灵魂,几乎全部浓缩在Configuration.h和Configuration_adv.h这两个文件中。编译前99%的工作,就是正确地修改它们。我们不可能覆盖所有1700多行配置,但会聚焦最核心、最容易出错的部分。
4.1 基础信息与通信设置 (Configuration.h)
打开src目录下的Configuration.h,你会看到大量被//注释掉的代码和#define语句。Marlin通过启用(取消注释)或禁用(添加注释)这些#define来配置功能。
1. 串口波特率:
#define BAUDRATE 250000这是主板与电脑(或OctoPrint等主机软件)通信的速率。250000是通用且较高的速率。如果在上传固件或连接打印时出现乱码、超时,可以尝试改为115200。
2. 主板类型:
//#define MOTHERBOARD BOARD_RAMPS_14_EFB // 取消上一行的注释,并确保其与你硬件匹配。 #define MOTHERBOARD BOARD_RAMPS_14_EFB这是最关键的一步!你必须根据你的实际主板,找到并启用正确的BOARD_XXX定义。在Configuration.h中搜索“MOTHERBOARD”,附近会有一个很长的列表,列出了所有支持的主板。例如:
BOARD_RAMPS_14_EFB:RAMPS 1.4板,用于单挤出机带风扇。BOARD_RAMPS_14_EEB:RAMPS 1.4板,用于双挤出机。BOARD_AZTEEG_X5_GT:Azteeg X5 GT。BOARD_MELZI:Melzi板。
实操心得:新手最容易犯的错误就是主板类型选错。一个快速核对的方法是,去网上搜索你的主板型号加上“Marlin pin mapping”,通常能找到对应的
BOARD_定义名。选错会导致所有引脚定义混乱,步进电机不转、加热器失控等问题。
3. 温度传感器类型:
#define TEMP_SENSOR_0 1 #define TEMP_SENSOR_BED 1这里定义了热端和热床的温度传感器型号。数字代表类型:
1: 100k 热敏电阻,最常见的是EPCOS 100k (B57560G104F)。5: 100k 热敏电阻,ATC Semitec 104GT-2。8: 100k 热敏电阻,Generic 3950。67: 热床用PT100传感器(需要放大器)。
如果你发现温度读数严重不准(比如室温显示80度),或者加热时温度飙升(热失控),首先就要检查这里是否设置正确。通常主板上会标注热敏电阻型号,或者参考购买主板的商品页面说明。
4.2 机械尺寸与运动系统配置
这部分配置决定了打印机如何理解自身的物理结构。
1. 步进电机驱动与方向:
#define X_DIR_PIN 55 #define X_ENABLE_PIN 38 #define X_STEP_PIN 54这些引脚定义通常在你选择了正确的MOTHERBOARD后会自动设置好,一般无需改动。除非你做了特殊的接线修改。
#define INVERT_X_DIR false #define INVERT_Y_DIR true #define INVERT_Z_DIR false #define INVERT_E0_DIR false这些INVERT_*_DIR设置决定了电机正转的方向。如果编译烧录后,你通过控制面板让X轴往右移动,但它实际往左走,那么就把INVERT_X_DIR的值从false改为true,反之亦然。务必在首次移动任何轴之前,确认所有限位开关已安装且功能正常,并做好随时断电的准备,以防撞机。
2. 行程限位开关:
#define X_MIN_PIN 3 #define X_MAX_PIN 2 #define Y_MIN_PIN 14 #define Y_MAX_PIN 15 #define Z_MIN_PIN 18 #define Z_MAX_PIN 19引脚定义同样由主板类型决定。更重要的是开关的逻辑:
#define X_MIN_ENDSTOP_INVERTING false // 设置为 true 以反转末端开关的逻辑。通常,机械式微动开关在未触发时是常开(NO)状态,触发时闭合。对应的,信号引脚在未触发时为高电平(false),触发时为低电平(true)。如果你接的是常闭(NC)开关,或者发现归零时撞到限位开关还不停止,就需要反转这个逻辑(true和false互换)。现在更流行的做法是使用#define ENDSTOPPULLUPS并配合开关实际接线来调整,但理解基本逻辑是关键。
3. 运动范围与步进值:
#define X_MAX_POS 200 #define Y_MAX_POS 200 #define Z_MAX_POS 180这里定义的是打印机的最大可打印范围(单位:毫米)。根据你的机器实际尺寸填写。
#define DEFAULT_AXIS_STEPS_PER_UNIT { 80, 80, 400, 93 }这是另一个核心参数,它告诉固件,电机每走1毫米,需要发出多少个脉冲(步数)。格式是{ X, Y, Z, E }。
- X/Y轴:计算公式为
(电机每转步数 * 驱动器微步数) / 皮带轮齿数 / 皮带齿距。例如,使用1.8度电机(200步/转)、16倍微步、20齿GT2皮带轮、2mm齿距的皮带:(200 * 16) / 20 / 2 = 80。 - Z轴:计算公式为
(电机每转步数 * 驱动器微步数) / 丝杆导程。例如,使用T8丝杆(导程8mm):(200 * 16) / 8 = 400。 - E挤出机:这个值最需要校准。公式类似,但涉及挤出齿轮直径和耗材直径,初始值可参考93(MK8挤出机常见),但必须通过实际挤出长度来校准。
注意事项:错误的
steps_per_unit会导致打印尺寸严重失真。X/Y/Z轴错误,正方形会打成长方形;E轴错误,会导致挤出不足(模型疏松)或过度挤出(喷嘴积料)。校准E轴是调试打印质量的第一步。
4.3 温度控制与安全功能
1. PID调谐:
#define PIDTEMP #define DEFAULT_Kp 22.2 #define DEFAULT_Ki 1.08 #define DEFAULT_Kd 114启用PIDTEMP后,热端将使用PID算法进行温度控制,比简单的开关控制(Bang-Bang)稳定得多。上面的DEFAULT_Kp等值是示例,绝不能直接使用。你必须为你的特定热端和加热棒组合运行PID自动调谐,并将得到的新值更新到这里。可以通过打印机菜单或发送G-code命令M303 E0 S210 C8(对挤出机0在210度下运行8个循环)来调谐。
2. 热床加热控制:
//#define PIDTEMPBED对于热床,如果面积较大,PID控制也能显著改善温度均匀性。同样需要运行M303 E-1 S60 C8(注意E-1指代热床)来调谐。
3. 热失控保护:
#define THERMAL_PROTECTION_HOTENDS // 启用热端热失控保护 #define THERMAL_PROTECTION_BED // 启用热床热失控保护 #define THERMAL_PROTECTION_CHAMBER // 启用打印舱热失控保护(如果有)这些功能至关重要,必须启用!它们能在温度传感器故障或加热器持续加热时,自动切断加热,防止火灾风险。这是Marlin最重要的安全特性之一。
4.4 高级功能配置 (Configuration_adv.h)
这个文件包含了更多精细控制和实验性功能。
1. 线性推进:
//#define LIN_ADVANCE线性推进是一项高级功能,旨在改善挤出机在高速打印和加减速时的响应,减少角落的积料和缺料。启用它需要额外的K因子校准,过程较为复杂。对于新手,建议先关闭,待基本打印稳定后再尝试。
2. 步进电机驱动电流与静音配置:如果你使用的是TMC2208/TMC2209这类静音驱动,需要在此配置:
//#define HAVE_TMC2208 //#define HAVE_TMC2209启用对应的定义,并配置通讯引脚和电流值(CURRENT)。正确的电流设置既能保证电机力矩,又能防止驱动和电机过热。通常初始值设为电机额定电流的70%-80%,然后触摸电机微热但不烫手为宜。
3. 详细错误信息:
#define EXTENDED_CAPABILITIES_REPORT // 启用M115详细功能报告 #define M115_GEOMETRY_REPORT // 在M115中报告构建体积启用这些,当你通过串口发送M115命令时,会得到更详细的固件和打印机信息,便于调试。
5. 编译、烧录与首次上电调试
配置完成后,就可以进入编译和烧录阶段了。
5.1 编译固件
在VS Code中,确保打开了你的PlatformIO项目。在底部状态栏,你会看到一个类似“对勾”的编译按钮(或者从左侧PlatformIO图标进入,选择项目下的“Build”)。点击它。
PlatformIO会开始编译过程。如果一切配置正确,你会在终端窗口看到大量输出,最后以“SUCCESS”结尾,并生成firmware.hex或firmware.bin文件(位于.pio/build/你的板型名称/目录下)。如果出现错误,终端会明确提示错误所在行和原因,通常是语法错误、未定义的引用或引脚冲突。根据错误信息回头检查你的配置文件。
5.2 烧录固件到主板
烧录方法取决于你的主板:
- 带有USB接口的Arduino类主板(如Mega 2560):最简单。用USB线连接主板和电脑。在PlatformIO中,点击底部状态栏的“右箭头”上传按钮(Upload)。PlatformIO会自动调用avrdude工具完成烧录。
- 需要通过Bootloader烧录的主板:有些主板可能需要通过ISP编程器(如USBasp)来首次烧录Bootloader,之后才能通过USB更新。对于已有Bootloader的主板,上传方式同上。
- 某些集成主板(如MKS):可能要求将生成的
firmware.bin文件复制到SD卡根目录,然后插入主板卡槽上电,主板会自动烧录。
实操心得:烧录前,务必断开所有大功率负载,如热端、热床、步进电机的电源,只保留主板和控制电路的供电。防止烧录过程中电流波动导致失败,甚至损坏主板。烧录成功后,先别急着接负载,进行下一步的基础测试。
5.3 首次上电与基础测试
固件烧录成功后,重新为整个打印机上电。
1. 连接主机软件:使用Pronterface、OctoPrint或Cura的打印机监控功能,通过USB连接到打印机。设置正确的串口和波特率(与你配置文件中BAUDRATE一致)。连接成功后,你应该能看到欢迎信息,并且可以发送M115命令查看固件版本和配置摘要。
2. 测试温度传感器:发送M105命令,报告当前温度。观察热端和热床的温度读数是否接近室温。如果显示“0”、“-14”或“MAXTEMP”,说明温度传感器接线或配置有误。
3. 测试步进电机与方向:
- 断开挤出机电机连线:防止测试时意外挤出。
- 手动移动:通过主机软件或打印机LCD菜单,分别少量移动X、Y、Z轴(例如1mm)。观察电机转动方向是否与预期一致(通常面对电机轴,逆时针为正转)。如果方向反了,记下是哪个轴,稍后需要修改
INVERT_*_DIR并重新编译。 - 限位开关测试:手动触发各轴的限位开关(通常是最小限位),同时发送移动命令。打印机应无法向触发限位开关的方向移动,或者触发后自动停止。可以通过
M119命令查看所有限位开关的实时状态(TRIGGERED或open)。
4. 加热测试与PID调谐:
- 确认温度读数正常后,可以接上热端加热棒(热床可以先不接,因为功率大)。
- 发送
M104 S200命令,设置热端目标温度为200度。观察温度上升曲线。如果温度能稳定在200度附近小幅波动(±2°C内),说明基本加热和PID控制正常。 - 运行正式的PID调谐:
M303 E0 S210 C8。等待调谐完成,它会输出一组Kp, Ki, Kd值。用M301 P[Kp] I[Ki] D[Kd]命令设置新参数,并用M500保存到EEPROM。
5. 校准挤出机步进值(E Steps):这是保证打印质量的核心校准。
- 在挤出机上标记一段耗材(如距离进料口120mm处)。
- 预热热端到打印温度(如200°C)。
- 通过主机软件发送
G91(设置为相对坐标模式)。 - 发送
G1 E100 F100(挤出100mm,速度100mm/min)。 - 测量标记点实际移动的距离(比如只移动了95mm)。
- 计算新的E步进值:
新E值 = 旧E值 * (指令挤出长度 / 实际挤出长度) = 93 * (100 / 95) ≈ 97.89。 - 发送
M92 E97.89设置新值,然后M500保存。可以再挤出100mm验证,直到误差在1%以内。
6. 常见问题排查与实战技巧
即使按照指南操作,在实际编译和调试中依然会遇到各种问题。这里记录一些典型问题的排查思路。
6.1 编译失败问题
问题1:‘xxx’ was not declared in this scope
- 原因:通常是
Configuration.h中启用了某个功能(如BLTOUCH),但对应的引脚定义错误或缺失,或者依赖的库未正确引入。 - 解决:检查错误信息指向的功能,在配置文件中仔细核对相关引脚
#define。对于PlatformIO,确保platformio.ini文件中包含了必要的库依赖(Marlin 1.1.9通常不需要额外添加)。
问题2:region ‘text’ overflowed by xxxx bytes
- 原因:固件代码太大,超过了单片机(如ATmega2560)的Flash存储空间(256KB)。
- 解决:这是Marlin 1.1.9用户最常见的问题。必须精简功能:
- 禁用所有非必需的高级功能:如
SDSUPPORT(如果不用SD卡)、LCD(如果不用屏幕)、AUTO_BED_LEVELING(如果不用自动调平)、EEPROM_SETTINGS(如果不用可以禁用,但PID等参数无法保存)等。 - 减少语言:
#define LCD_LANGUAGE en只保留英文。 - 简化LCD菜单:禁用
MENU_ITEM相关的非核心功能。 - 每次禁用一项后重新编译,直到通过。
- 禁用所有非必需的高级功能:如
6.2 烧录与连接问题
问题:上传成功,但打印机无响应或无法连接
- 排查串口与波特率:确认电脑设备管理器中识别到的COM口号,并在主机软件中选择正确。尝试更换USB线或USB口。波特率尝试改为
115200。 - 检查主板供电:有些主板(如RAMPS)需要同时接入12V/24V电源和USB供电才能正常工作。仅USB供电可能不足以启动所有芯片。
- 查看主板指示灯:上电后,主控芯片和驱动板上的电源指示灯、状态指示灯是否正常亮起。
6.3 运动与硬件问题
问题:电机不动或只振动
- 检查使能信号:步进电机驱动需要使能引脚为低电平才工作。检查
X_ENABLE_PIN等定义,并确认X_ENABLE_ON的极性(通常是0)。可以用万用表测量驱动模块的EN引脚电压。 - 检查驱动与电流:驱动模块(如A4988)的Vref电压是否设置正确?电流过小会导致电机无力。参考驱动模块手册调节电位器。
- 检查接线:电机线序是否接对?可以交换同一电机的一组线圈(如A+和A-)来测试。
问题:限位开关始终显示触发或始终不触发
- 逻辑电平反了:修改
*_MIN_ENDSTOP_INVERTING或*_MAX_ENDSTOP_INVERTING的值。 - 硬件接线问题:开关是常开(NO)还是常闭(NC)?接线是否正确?可以用万用表通断档测试开关触发前后的状态。
- 上拉电阻:如果主板没有内置上拉电阻,需要在配置中启用
ENDSTOPPULLUPS,并在开关信号线与VCC之间连接一个10K电阻。
6.4 温度相关问题
问题:温度读数飘忽不定或为0
- 热敏电阻类型错误:这是最常见原因。核对
TEMP_SENSOR_0和TEMP_SENSOR_BED的值。 - 接线不良:热敏电阻的两根线接触不良或断开。其阻值随温度变化,室温下约100k欧姆,可以用万用表测量。
- 主板模拟输入端口故障:尝试更换测温端口(需要修改引脚定义并重新编译)。
问题:加热非常慢,或到达目标温度后剧烈振荡
- 加热棒功率不足或接线问题:检查加热棒电阻(12V系统通常约3-4欧姆,24V系统约12-15欧姆)。确认大电流线路连接牢固。
- PID参数不准:运行PID自动调谐获取新参数。确保调谐时风扇处于工作状态(如果打印时会开风扇)。
- 固态继电器(SSR)控制热床:如果热床通过SSR控制,需要启用
#define PIDTEMPBED,并且调谐时可能需要更长的周期(C10或更多)。
6.5 打印质量问题与固件参数微调
当基础功能都正常后,一些打印质量问题可以通过固件参数优化。
角落凸起或积料:除了调整切片设置,可以尝试启用并校准线性推进(Linear Advance)。这需要精确测试和K因子调整,但能显著改善挤出机在加减速时的响应。
层纹不齐或Z轴异响:检查并校准Z_STEPS_PER_UNIT。如果使用T型丝杆,可能存在反向间隙,可以尝试启用#define LEAD_SCREW_ADJUSTMENT(如果固件支持)或进行机械调整。
SD卡打印中断:如果使用SD卡打印时中途停止,可能是SD卡兼容性问题或文件系统错误。尝试使用品牌SD卡,并在电脑上格式化为FAT32(分配单元大小32KB)。在配置中,可以尝试降低SDCARD_SPI_SPEED。
最后,养成一个好习惯:任何对Configuration.h或Configuration_adv.h的修改,在编译烧录前,最好先用版本管理工具(如Git)做个提交,或者简单地将原文件备份。这样当修改导致无法编译或运行时,可以快速回退到上一个可用的状态。调试3D打印机固件是一个需要耐心和细致观察的过程,每次成功解决问题,你对这台机器的理解就会更深一层。当你的机器终于按照你的意志精确运动时,那种成就感,远非使用一台现成的商业打印机可比。
本文还有配套的精品资源,点击获取