1. 项目概述与核心价值
作为一个在创客和物联网领域折腾了十多年的老玩家,我经手过不少自动化监控项目。今天想和大家深入聊聊一个特别实用,也特别有“创客精神”的小玩意儿:基于ESP8266的3D打印完成通知系统。说白了,这就是给你的3D打印机装上一个“小秘书”,它会在打印任务完成的瞬间,给你的手机发一条推送通知,让你不用再时不时跑到打印机旁边盯着看,或者担心打印完太久没人处理导致模型粘在热床上取不下来。
这个项目的核心价值在于它的普适性和低成本。它不挑打印机品牌,无论是高端的Prusa MK4,还是任何一台接入了Octoprint(一个运行在树莓派等设备上的开源3D打印机管理软件)的普通打印机,都能被它监控。其硬件核心只是一块像火柴盒大小的ESP8266开发板(比如常见的WeMos D1 Mini或NodeMCU),成本极低。整个系统的工作原理清晰而经典:ESP8266作为“侦察兵”,定期去询问打印机的状态;一旦侦察到“打印完成”的信号,它就立刻作为“传令兵”,通过网络调用一个部署在服务器上的PHP脚本;这个PHP脚本则扮演“邮差”的角色,向预设的邮箱发送一封通知邮件;最终,你手机上的邮件客户端弹出通知,任务完成。这种“嵌入式硬件抓取状态 + 网络服务触发通知”的模式,是物联网实现设备状态远程感知和自动化响应的一个典型范例,理解了这个,你就能举一反三应用到很多其他监控场景里。
2. 系统架构与核心组件选型解析
2.1 整体工作流设计
在动手焊任何一根线之前,我们必须把整个系统的工作流想明白。这决定了后续的硬件连接、代码逻辑和服务器配置。整个系统的数据流可以概括为以下闭环:
- 状态感知层:ESP8266通过Wi-Fi接入本地网络,按照设定的时间间隔(例如每30秒),向目标3D打印机或Octoprint服务器发起HTTP请求,查询其当前打印状态(如打印进度、是否完成)。
- 逻辑判断层:ESP8266上运行的固件(Firmware)解析从打印机返回的JSON格式状态数据。其核心逻辑是持续监测,当检测到状态从“打印中”转变为“已完成”或“已停止”时,触发事件。
- 通知触发层:一旦事件触发,ESP8266将构建一个包含打印机编号、完成时间等信息的HTTP请求,发送给一个预先配置好的、始终在线的Web服务器上的特定PHP脚本(例如
sendmail.php)。 - 消息传递层:服务器上的PHP脚本接收到请求后,提取参数,调用服务器本身的邮件发送功能(如PHP的
mail()函数,或更可靠的SMTP库),撰写一封包含详细信息的邮件,发送到你的个人邮箱。 - 用户接收层:你的智能手机或电脑上的邮件客户端(如Gmail App、Outlook)收到新邮件,通过推送服务弹出通知。
注意:这里选择“邮件通知”而非更直接的“App推送”(如Pushbullet、Bark),主要基于通用性和零成本考量。邮件协议(SMTP)是互联网最基础的服务之一,任何服务器、任何邮箱都支持,无需注册第三方推送服务的API,也没有调用次数限制,隐私性也相对更好。对于个人用户来说,这是最稳妥、最省事的方案。
2.2 核心硬件组件详解
硬件清单很简单,但每一样的选择都有讲究:
- 主控:WeMos D1 Mini 或 NodeMCU
- 为什么是ESP8266?ESP8266是一款集成了Wi-Fi功能的低成本、高性能微控制器。对于这个项目,我们需要设备能连接Wi-Fi、发起HTTP请求,ESP8266完美胜任。相比更强大的ESP32,它价格更低、功耗更小,对于这个简单的轮询任务绰绰有余。
- D1 Mini vs NodeMCU:两者核心都是ESP8266。D1 Mini体积更小巧,适合放入定制外壳;NodeMCU的引脚更多,扩展性稍强。本项目对GPIO需求很少(仅用于驱动LED),因此D1 Mini是更优选择,更省空间。
- 状态指示:LED与限流电阻
- 每个被监控的打印机对应一个LED。LED的作用是提供本地物理状态指示。当ESP8266成功连接到某台打印机并监测其状态时,对应的LED常亮或慢闪;当检测到该打印机完成打印时,LED可以快速闪烁几次作为本地提示。这是一个非常重要的冗余设计:即使网络或邮件服务暂时故障,你也能在现场通过LED知道打印已完成。
- 220欧姆电阻是必须的。ESP8266的GPIO输出电压通常为3.3V,而普通LED的工作电压一般在1.8-2.2V,直接连接会因电流过大烧毁LED或损坏GPIO口。串联一个220欧姆的电阻,可以将电流限制在安全范围内(约(3.3V - 2.0V) / 220Ω ≈ 6mA)。
- 外壳与结构件
- 项目提供了OpenSCAD源文件,这比直接给STL文件要友好得多。OpenSCAD是一种通过代码生成3D模型的工具,你可以轻松修改参数来改变外壳尺寸、LED孔的数量和位置、以及面板上的文字。例如,如果你只想监控2台打印机,就可以在代码里把LED数量从4改为2,然后重新渲染生成STL文件,实现完全的自定义。
- M2.5的铜柱和螺丝用于固定上下盖,这是3D打印件装配的常用方式。
2.3 软件与服务依赖
- 打印机端:
- 原生网络打印机(如Prusa MK4):需要打印机本身支持网络访问并提供了状态查询API。通常打印机固件会内置一个简单的Web服务器。
- Octoprint:对于绝大多数没有网络功能的打印机,这是必选方案。Octoprint不仅提供了强大的远程控制界面,更重要的是它暴露了一套完整、稳定的RESTful API,让我们可以非常方便地通过HTTP GET请求获取打印状态、进度等信息。这是本项目能兼容几乎所有打印机的关键。
- 服务器端:
- 你需要一个支持PHP且能够发送邮件的Web服务器。这可以是:
- 虚拟主机/VPS:如阿里云、腾讯云的轻量应用服务器,这是最稳定可靠的选择。
- 家庭内网服务器:如果你有常年开机的NAS(如群晖)或小型服务器,并且配置好了能从内网向外网发送邮件(这涉及家庭宽带封禁25端口、配置SMTP中继等问题,对新手不友好),也可以使用。
- 核心是PHP脚本的执行能力和邮件发送能力。很多廉价虚拟主机都满足这个条件。
- 你需要一个支持PHP且能够发送邮件的Web服务器。这可以是:
3. 硬件制作与电路连接实操
3.1 外壳的打印与准备
拿到OpenSCAD文件(ProjectCase.scad)后,不要急于直接切片打印。首先用OpenSCAD软件打开它。
- 自定义修改:在代码开头部分,你通常会找到一些可定义的变量,比如
num_leds = 4;(LED数量)、text_label = “3D Print Notifier”;(前面板文字)。根据你的实际监控打印机数量修改num_leds。你也可以调整外壳的尺寸(case_width,case_height,case_depth)以适应你的D1 Mini安装方式。 - 渲染与导出:修改完成后,点击“F6”键(或菜单中的“Design -> Render”)进行渲染。渲染成功后,分别选中“Top”、“Bottom”、“FrontPanel”、“BackPanel”等模块(可能需要注释/取消注释代码中的相应部分),使用“File -> Export -> Export as STL”导出各个部件的STL文件。
- 切片与打印:将STL文件导入切片软件(Cura、PrusaSlicer等)。建议使用PLA材料,填充率15%-20%即可。打印时注意:
- 面板文字:如果面板上有凸起的文字,建议将文字面朝上打印,以获得最好的表面效果。
- 螺丝孔:M2.5的螺丝孔在切片时可能会被识别为很小的洞,确保切片软件没有将其忽略。打印后,如果螺丝拧入稍紧,可以用M2.5的丝锥或直接用螺丝轻轻攻一下丝。
3.2 电路焊接与连接
电路非常简单,但焊接和走线需要细心,确保可靠。
- 准备LED单元:将每个220Ω电阻的一只引脚与LED的短脚(阴极,通常对应LED内部较大的电极,或引脚较短的一侧)焊接在一起。然后用热缩管或绝缘胶带包好焊点。这样就做成了一个“LED-电阻”组合件,其剩余的两根引线(电阻的自由端和LED的长脚)就是连接线。
- 连接至D1 Mini:
- LED阳极(长脚):连接到D1 Mini的某个GPIO口(例如,打印机1的LED接
D1(GPIO5),打印机2接D2(GPIO4),以此类推)。在代码中需要与这些引脚定义对应。 - 电阻端(即LED阴极通路):连接到D1 Mini的任何一个GND(接地)引脚。
- 接线图示意:
D1 Mini GPIO5 (D1) ----> LED1阳极 LED1阴极 ---- 220Ω电阻 ---- D1 Mini GND (同理连接LED2、3、4到GPIO4、0、2等引脚和GND)
- LED阳极(长脚):连接到D1 Mini的某个GPIO口(例如,打印机1的LED接
- 安装与布线:将焊接好的LED从外壳内部穿过前面板对应的孔固定(可以使用一点热熔胶)。将D1 Mini用螺丝或胶柱固定在外壳底板上。将所有导线整理整齐,避免短路。USB电源线从后面板预留的孔位引出。
实操心得:在将电路板装入外壳前,务必先进行通电测试!用Arduino IDE写一个简单的测试程序,让每个LED依次点亮、闪烁。确认所有LED连接正确、亮度正常后再封盖,否则后期排查问题极其麻烦。
4. 固件(Firmware)配置与烧录详解
这是项目的“大脑”,所有的逻辑都在这里。你需要从项目Github仓库下载PrintNotifier.ino文件,并用Arduino IDE打开。
4.1 关键配置项解析与填写
打开代码后,首先关注开头的配置区域,这里需要你填入个性化的信息。
// ************************** 配置区域 ************************** const char* ssid = “Your_WiFi_SSID”; // 你的Wi-Fi名称 const char* password = “Your_WiFi_Password”; // 你的Wi-Fi密码 // 打印机配置结构体数组 Printer printers[] = { // { 打印机名称, API地址, API密钥, 状态LED引脚 } {“Printer_1”, “http://192.168.1.100/api/printer”, “OCTOPRINT_API_KEY_HERE”, D1}, {“Printer_2”, “http://192.168.1.101/api/v1/status”, “PRUSA_API_KEY_HERE”, D2}, // 最多可以添加4台 }; // 服务器上的PHP脚本地址 const char* serverUrl = “http://yourwebsite.com/path/to/sendmail.php”; // ************************** 配置结束 **************************- Wi-Fi信息:填写你的2.4GHz Wi-Fi网络信息(ESP8266通常不支持5GHz)。
- 打印机配置:这是核心。
- 打印机名称:自定义,用于在邮件中标识,如“书房MK4”、“车库Ender3”。
- API地址:
- 对于Octoprint:格式通常是
http://[Octoprint的IP地址]/api/printer。例如http://192.168.1.50/api/printer。你需要先在Octoprint的Web界面中生成一个API密钥(Settings -> API)。 - 对于Prusa MK4(或其他自带网络的打印机):你需要查阅其官方文档,找到状态查询API的端点。可能是
http://prusa.local/api/v1/status之类的地址。API密钥也可能在打印机网页设置中生成。
- 对于Octoprint:格式通常是
- API密钥:将对应的长字符串密钥填入。务必妥善保管,不要泄露。
- 状态LED引脚:与之前硬件连接时定义的GPIO引脚对应,如
D1。
- 服务器脚本地址:填写你即将部署的
sendmail.php脚本的完整可访问URL。
4.2 核心逻辑代码浅析
即使你不打算修改代码,理解其工作原理也助于调试。
- 初始化与连接:
setup()函数中,设备连接Wi-Fi,初始化LED引脚为输出模式,并尝试连接所有配置的打印机(测试API可达性)。 - 主循环:
loop()函数是核心。它遍历printers数组,对每台打印机:- 发送HTTP GET请求到其API地址(携带API密钥)。
- 解析返回的JSON数据。关键字段是
state.text(Octoprint)或status(Prusa),其值可能是“Printing”、“Operational”(完成)、“Error”等。 - 状态机判断:代码内部会为每台打印机维护一个状态变量(如
lastState)。当检测到当前状态从“打印中”变为“已完成”时,才触发通知。这是为了防止打印机空闲时被反复误报。
- 触发通知:当满足触发条件时,代码会构建一个HTTP GET或POST请求到
serverUrl,参数中会包含打印机名称和完成时间戳。然后,控制对应的LED快速闪烁几下作为本地确认。
4.3 烧录固件到D1 Mini
- 在Arduino IDE中,安装ESP8266开发板支持包(“文件 -> 首选项 -> 附加开发板管理器网址”中添加
http://arduino.esp8266.com/stable/package_esp8266com_index.json,然后在“工具 -> 开发板 -> 开发板管理器”中搜索安装)。 - 选择开发板:“WeMos D1 R2 & mini” 或 “NodeMCU 1.0”。
- 选择正确的端口。
- 点击“上传”按钮。首次上传可能需要按住D1 Mini上的“FLASH”或“BOOT”按钮再接通电源进入下载模式。
- 上传成功后,打开串口监视器(波特率115200),你将看到设备启动、连接Wi-Fi、尝试连接打印机的日志信息,这是最重要的调试窗口。
5. 服务器端PHP脚本部署与配置
现在,我们需要让ESP8266有一个可以“汇报”的地方。
5.1 PHP脚本解析与定制
下载项目提供的sendmail.php文件。它的核心逻辑很简单:
- 从
$_GET或$_POST超全局变量中获取ESP8266传递过来的参数(如printer_name,timestamp)。 - 使用这些参数拼接一封邮件的主题和正文。
- 调用PHP的
mail()函数或更强大的库(如PHPMailer)将邮件发送到指定邮箱。
你需要修改的地方通常包括:
$to = ‘your-email@example.com’; // 你的接收邮箱 $subject = “3D Print Job Completed: “ . $_GET[‘printer_name’]; $message = “Hello!nYour 3D printer ‘“ . $_GET[‘printer_name’] . “‘ has finished its job at “ . $_GET[‘timestamp’] . “.nPlease go and check on it.”; // 以及可能的发件人地址($from)和邮件头设置。重要提示:很多共享主机或云服务器出于反垃圾邮件策略,禁用或限制了原生
mail()函数。如果你发现邮件发不出去,强烈建议使用PHPMailer库通过SMTP方式发送,这是最可靠的方法。你需要从Github下载PHPMailer,将其包含在你的脚本中,并配置你的邮箱SMTP信息(如smtp.gmail.com:587,需要应用专用密码)。
5.2 服务器部署与安全考量
- 上传:将修改好的
sendmail.php文件通过FTP或文件管理器上传到你的网站目录下,例如public_html/3dnotifier/。 - 测试:在浏览器中直接访问这个脚本的URL,并附带测试参数,例如:
http://yourwebsite.com/3dnotifier/sendmail.php?printer_name=Test×tamp=2023-10-27%2014:30。检查你的邮箱是否收到了测试邮件。这是验证服务器端是否正常工作的关键一步。 - 基础安全:
- 这个脚本被公开访问,可能会被恶意调用发送垃圾邮件。可以增加简单的认证机制,例如在ESP8266代码和PHP脚本中约定一个共享密钥(Token),每次请求时携带并验证。
- 在PHP脚本开头添加:
if ($_GET[‘token’] != ‘YourSecretToken’) { die(‘Unauthorized’); }。 - 同时在ESP8266代码中,在请求URL后加上
&token=YourSecretToken。
6. 系统集成、调试与故障排除实录
当硬件、固件、服务器都准备好后,进入最关键的联调阶段。
6.1 上电与初始化检查
- 给组装好的设备上电。观察LED指示灯:
- 电源指示灯(D1 Mini板载LED)应亮起。
- 连接Wi-Fi时,板载LED可能会闪烁。连接成功后,你为每台打印机配置的LED应该会常亮或慢闪(取决于代码设计),这表示ESP8266已经成功连接到该打印机并开始监控。
- 打开Arduino IDE的串口监视器,查看启动日志。你应该能看到连接Wi-Fi成功的提示,以及尝试访问各打印机API的日志。如果出现连接失败,日志会给出HTTP错误代码(如404、403、500),这是排查问题的重要依据。
6.2 常见问题与解决方案速查表
以下是我在部署和帮助他人时遇到的最典型问题:
| 问题现象 | 可能原因 | 排查步骤与解决方案 |
|---|---|---|
| ESP8266无法连接Wi-Fi | SSID/密码错误;路由器屏蔽2.4G;信号太弱。 | 1. 检查串口日志确认错误信息。 2. 确保SSID和密码正确,且网络是2.4GHz。 3. 将设备靠近路由器测试。 |
| 串口显示打印机API连接失败(如HTTP 404) | API地址错误;打印机/Octoprint未开机或网络不通。 | 1. 在电脑浏览器中手动访问配置的API地址,看是否能返回JSON数据。 2. 检查打印机IP地址是否变更。 3. 对于Octoprint,确保API密钥正确且在设置中启用了API。 |
| 串口显示打印机API连接失败(HTTP 401/403) | API密钥错误或过期。 | 1. 重新生成API密钥(Octoprint中可重新生成)。 2. 在浏览器中访问API地址时,尝试在URL后加 ?apikey=YOUR_KEY测试。 |
| 打印机完成打印,但未收到邮件 | 1. ESP8266未检测到状态变化。 2. 服务器脚本URL错误。 3. 服务器邮件发送失败。 | 1.查ESP日志:看打印完成后,串口是否有“Print finished detected”和“Sending notification to server”的日志。 2.查服务器访问:在ESP日志中查看调用服务器URL的返回状态码。如果是200,说明ESP任务完成;否则检查URL。 3.查服务器日志:查看网站的错误日志(如Apache的error.log),看PHP脚本是否有语法错误或执行错误。 4.手动测试脚本:如前所述,在浏览器中测试 sendmail.php。 |
| 收到邮件,但内容为空或错误 | PHP脚本解析参数错误。 | 检查PHP脚本中获取参数的变量名($_GET[‘printer_name’])是否与ESP代码中发送的参数名完全一致。 |
| LED指示灯行为异常 | 接线错误;代码中引脚定义错误。 | 1. 使用一个简单的LED测试程序,单独测试每个GPIO引脚是否能正常控制对应的LED。 2. 确认代码中 printers数组里每个打印机的LED引脚定义与物理连接一致。 |
6.3 优化与扩展思路
系统稳定运行后,可以考虑一些优化和扩展:
- 降低轮询频率:默认可能每10-30秒查询一次。对于长时间打印,可以改为每分钟查询一次,减少对打印机和网络的微小压力。
- 增加本地蜂鸣器:除了LED,可以连接一个无源蜂鸣器,在打印完成时发出“滴滴”声,作为更强烈的本地提醒。
- 多通知渠道:修改PHP脚本,除了发邮件,还可以集成Telegram Bot或企业微信/钉钉机器人的API,实现更即时、更不易被淹没的App推送。
- 状态面板Web界面:让ESP8266本身作为一个Web服务器,在同一个局域网内,你可以通过浏览器访问一个简单的网页,实时查看所有打印机的状态(打印中、已完成、空闲)和进度条。这需要编写更复杂的固件,但可玩性更高。
- 使用平台化服务:进阶玩法是让ESP8266将状态数据发布到MQTT服务器(如自建的Mosquitto或云服务),然后由Node-RED这样的自动化流程工具来订阅消息,并灵活地分发到邮件、推送、短信等多个渠道。这实现了硬件与业务逻辑的解耦,是更专业的物联网架构。
这个项目麻雀虽小,五脏俱全,它串联起了硬件焊接、嵌入式编程、网络通信、服务器脚本和API调用等多个环节。成功实现它,不仅能解决3D打印看守的实际问题,更能让你对物联网系统的全链路有一个非常扎实的实践理解。我在自己的工作室里部署了这个系统,监控着三台打印机,它已经稳定运行了超过一年,让我再也没错过任何一次打印完成。希望这份详细的指南也能帮你打造出属于自己的自动化小助手。