前言
原创文章,转载引用请务必注明链接,水平有限,如有疏漏,欢迎交流指正。
文章如有更新请访问 DFRobot社区。
我们约定:主板 指 MCU 部分,上位机 指运行 Klippy 的 MPU Linux 部分。
看过前文 Klipper 温控风扇以及电源管理(部分) 的朋友,一定了解到了安全关闭上位机系统的重要性,当然如果你是平日自家电脑关机靠直接拔电的壮士,下面的文章可以不用看了。
由于 Gemini 二合一主板的 MCU 和 MPU 是不是独立供电的,此外越来越多朋友的 3D 打印机为了好看,选择把上位机和主板一起封在电气箱内,通过总电源开关一起控制,所以就有了如何打完自动 安全 关机的必要性。注意,这里的安全是先关闭上位机电脑的 Linux 操作系统,再关闭总电源。
1、手动安全关机方法的优化 —— 调用 API
前文介绍过,手动关闭上位机系统有四种方式:物理关机按钮,网页关机按钮、KlipperScreen 彩色触摸屏按钮和 12864 等 LCD 屏幕菜单。
其中 使用 Klipper 监听按钮状态
和 mini12864 屏幕菜单
两种方法都需要 shell_cmd 组件,而此组件的缺点也很明显:
- 需要 Klipper Python2 ,默认不支持中文 Gcode 文件
- shell_cmd 命令不支持需要输入用户密码的命令
- shell_cmd 造成系统安全性下降
- 该组件需要自行安装
那么有没有什么法子不安装额外的东西,即可以实现关闭系统吗?我们上面了解到 Moonraker (下文称 mrk) API 的 machine.shutdown
方法,而且 Fluidd 网页
/KlipperScreen 按钮
关机的方法就是创建用户组 mnrkrsudo、klipperscreensudo
,执行一些系统命令不需要密码,如下所示:
fly@flygemini:~$ sudo ls /etc/sudoers.d/
020-sudo-for-moonraker 021-sudo-for-klipperscreen README
fly@flygemini:~$ sudo cat /etc/sudoers.d/020-sudo-for-moonraker
### Elevate moonraker API rights
### Do NOT allow Command Parts only Full Commands
### for example
###
### /sbin/systemctl "reboot", /sbin/apt "update", .....
Defaults!/usr/bin/apt-get env_keep +="DEBIAN_FRONTEND"
Cmnd_Alias REBOOT = /sbin/shutdown -r now, /bin/systemctl "reboot"
Cmnd_Alias SHUTDOWN = /sbin/shutdown now, /sbin/shutdown -h now, /bin/systemctl "poweroff"
Cmnd_Alias APT = /usr/bin/apt-get
Cmnd_Alias SYSTEMCTL = /bin/systemctl
%mnrkrsudo ALL=(ALL) NOPASSWD: REBOOT, SHUTDOWN, APT, SYSTEMCTL
1.1 Klipper 全家桶 API 介绍
我们常见的有 Klipper API Server、Moonraker Client API ,具体可以查看链接内文档,而其中的 machine.shutdown 就是属于 mrk api 。由此 mrk client 可以调用 klippy 提供的 API,同时可以被用户调用其 api。那么 klippy 可以调用 mrk api 来实现执行关机命令吗?也是可以的,还记得之前我们从 Klipper 内关闭打印机电源的示例吗,其有一个命令:action_call_remote_method
,查看 Klipper 文档,是这么说的:
action_call_remote_method(method_name)
: Calls a method registered by a remote client. If the method takes parameters they should be provided via keyword arguments, ie: action_call_remote_method("print_stuff", my_arg="hello_world")
意思就是除了上面两种 API 之外,Moonraker 还可以在 Klippy 那注册一个方法,告诉它(Klippy):我(Mrk)这里有此方法,可以被调用。
我们以已知方法(method)set_device_power
为关键词搜索 mrk 源码,可知关键词为 register_remote_method
,再以此搜索即获得支持的方法如下:
- moonraker_test
- shutdown_machine
- reboot_machine
- process_gcode_response
- process_status_update
- pause_job_queue
- start_job_queue
- set_wled_state
- set_wled
- publish_mqtt_topic
- paneldue_beep
- set_device_power
至此我们找到了想要的两个可以被 Klipper 调用的方法。
【更新:2022年3月13日】
笔者测试时还没有相关文档,2022-02-26 官方更新了 此部分文档 ,并补充了注意事项,建议阅读。虽然如此,我们查找答案的方法还是有记录借鉴意义的。
1.2 调用 Method
实现关机
物理关机按钮:
# ~/klipper_config/printer.cfg
[gcode_macro SHUTDOWN]
gcode:
{action_call_remote_method("shutdown_machine")}
# 定义物理按钮 【监听引脚状态】
[gcode_button poweroff_button]
# 按钮信号连接引脚
pin: host:gpio
# 按下时执行 gcode 宏命令
#press_gcode:
# 松开时执行 gcode 宏命令
release_gcode:
SHUTDOWN
测试通过,控制台输入 SHUTDOWN
或者被调用即可以实现关闭系统指令。
12864 屏幕菜单关机:
# printer.cfg
### menu poweroff by 思兼 v2 ###
[menu __main __poweroff]
type: list
enable: {not printer.idle_timeout.state == "Printing"}
name: PowerOff
[menu __main __poweroff __no]
type: command
name: NO
enable: {not printer.idle_timeout.state == "Printing"}
gcode:
{menu.back()}
[menu __main __poweroff __yes]
type: command
name: YES
enable: {not printer.idle_timeout.state == "Printing"}
gcode:
SHUTDOWN
2、 传统打完关机方案
我们先说说传统的打完关机功能,适用于 【上位机独立供电的情况】,多数朋友借助原来 Marlin 上用的 打完关机模块
,或者使用 智能插座
,我们说说各自的优缺点:
2.1 打完关机模块
优点:
缺点:
- 接线麻烦
- 价格较高 (79 + 9元)
- 为了安全关闭上位机系统,需要上位机独立供电:
- 如果由上位机 GPIO 引脚控制,支持开、关机操作,上传打印任务后自动开机
- 如果由主板引脚控制,仅支持关机,且要求主板支持从上位机取电,但此时会造成 5v 和 VCC 混合供电,导致潜在的信号干扰
示例如下:
# 独立供电打完关机方案,by 思兼
#####################################################################
# 方法1,打印机主板 PS_ON 接口
#####################################################################
# 使用主板 PS_ON 引脚,需要上位机通过 USB 接口为主板供电,但此时会出现 5v
# 和 12/24v 同时供电的问题
[output_pin mks_pwc]
pin: PS_ON
pwm: False
value: 1
shutdown_value: 0
[gcode_macro M81]
description: PowerOff
gcode:
M84
SET_PIN PIN=mks_pwc VALUE=0
#####################################################################
# 方法2,上位机 GPIO 接口【推荐】
#####################################################################
# 使用上位机 GPIO 接口控制,支持开/关机,尤其适合上位机内置。需要额外修改
# moonraker.cfg 配置文件,可以手动在右上角菜单控制开关机
[gcode_macro M81]
gcode:
{action_call_remote_method("set_device_power",
device="printer",
state="off")}
#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
# 以下为修改 moonraker.cfg内容,“printer”名称对应。以及不能使用 UART 等引脚
[power printer]
type: gpio
pin: gpio26
off_when_shutdown: True
initial_state: off
#####################################################################
# 延时(挤出头降温)自动关机
#####################################################################
[delayed_gcode delayed_printer_off]
# 判断当前为空闲状态,才执行断电操作
initial_duration: 0.
gcode:
{% if printer.idle_timeout.state == "Idle" %}
M81
{% endif %}
[idle_timeout]
# https://www.klipper3d.org/Command_Templates.html?h=update_delayed_gcode#delayed-gcodes
# https://github.com/Klipper3d/klipper/issues/3865 | Firmware Restart 之后,要先home之后才会进入空闲状态
# 空闲状态360s后关闭电机和加热头,60s后关闭电源
gcode:
M84
TURN_OFF_HEATERS
UPDATE_DELAYED_GCODE ID=delayed_printer_off DURATION=60
timeout: 360
2.2 智能插座
优点:
缺点:
使用方法有以下几种,各有其不足:
- 预估打印完成时间定时关机 —— 不准确
- 使用具有电量检测功能的插座,当打印机处于低耗电时,认为打印完成,实现关机 —— 相比准确,成本提高
- 使用 Home Assistant 等智能家居系统,Klipper 打印完成后,调用 Moonraker 向 HA 发送关闭智能插座命令 —— 准确,但是需要 HA
其他用法欢迎补充。前两种方法自己从 APP 里设置即可,第三种方法我们下面一起介绍。