跟着思兼学习Klipper(13) 智能插座与 Gemini 主板[电源管理完结]
## Gemini 等主板比较完美的打完安全关机方案## 前言
原创文章,转载引用请务必注明链接,水平有限,如有疏漏,欢迎交流指正。
文章如有更新请访问 (https://mc.dfrobot.com.cn/thread-312418-1-1.html?fromuid=725344)。
欢迎对 Klipper 固件感兴趣,以及对改版 CNC 加工的 Voron 三叉戟、v0、v2.4 感兴趣的朋友加群交流(QQ Group:490111638)
我们约定:主板 指 MCU 部分,上位机 指运行 Klippy 的 MPU Linux 部分。
看过前文 [*Klipper 温控风扇以及电源管理(部分)*](https://mc.dfrobot.com.cn/thread-312100-1-1.html?fromuid=725344) 的朋友,一定了解到了安全关闭上位机系统的重要性,当然如果你是平日自家电脑关机靠直接拔电的壮士,下面的文章可以不用看了。
由于 Gemini 二合一主板的 MCU 和 MPU 是不是独立供电的,此外越来越多朋友的 3D 打印机为了好看,选择把上位机和主板一起封在电气箱内,通过总电源开关进行控制,所以就有了如何打完自动 **安全** 关机的必要性。注意,这里的安全是先关闭上位机电脑的 Linux 操作系统,再关闭总电源。
【更新 2022年3月18日】合并自动化规则,添加状态同步规则
## 1、手动安全关机方法的优化 —— 调用 Method
前文介绍过,手动关闭上位机系统有四种方式:物理关机按钮,网页关机按钮、KlipperScreen 彩色触摸屏按钮和 12864 等 LCD 屏幕菜单。
其中`使用 Klipper 监听按钮状态` 和 `mini12864 屏幕菜单` 两种方法都需要 shell_cmd 组件,而此组件的缺点也很明显:
* 需要 Klipper Python2 ,默认不支持中文 Gcode 文件
* shell_cmd 组件不支持需要输入用户密码的命令
* shell_cmd 造成系统安全性下降
* 该组件需要自行安装
那么有没有什么法子不安装额外的东西,即可以实现关闭系统吗?我们上面了解到 Moonraker (下文称 mrk) API 的 `machine.shutdown` 方法,而且 `Fluidd 网页`/`KlipperScreen 按钮` 关机的方法就是创建用户组 `mnrkrsudo、klipperscreensudo` ,执行一些系统命令不需要密码,如下所示:
```shell
fly@flygemini:~$ sudo ls /etc/sudoers.d/
020-sudo-for-moonraker021-sudo-for-klipperscreenREADME
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.1Klipper 全家桶 API 介绍
我们常见的有 (https://www.klipper3d.org/API_Server.html)、(https://moonraker.readthedocs.io/en/latest/web_api/) ,具体可以查看链接内文档,而其中的 [*machine.shutdown*](https://moonraker.readthedocs.io/en/latest/web_api/#shutdown-the-operating-system)就是属于 mrk api 。由此 mrk client 可以调用 klippy 提供的 API,同时可以被用户调用其 api。那么 klippy 可以调用 mrk api 来实现执行关机命令吗?也是可以的,还记得之前我们从 Klipper 内关闭打印机电源的示例吗,其有一个命令:`action_call_remote_method` ,查看 (https://www.klipper3d.org/Command_Templates.html?h=action#actions),是这么说的:
> - `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")`
!(https://cdn.jsdelivr.net/gh/sjqlwy/blog_imgs@default/images/20220313215837.png)
意思就是除了上面两种 API 之外,Moonraker 还可以在 Klippy 那注册一个方法,告诉它(Klippy):我(Mrk)这里有此方法,可以被调用。
!(https://cdn.jsdelivr.net/gh/sjqlwy/blog_imgs@default/images/20220313222554.png)
我们以已知方法(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日】**
>
> 笔者测试时还没有相关文档,(https://github.com/Arksine/moonraker/commit/65e76aeec8c81481fdd587b046504d63dff52870) 官方更新了 [此部分文档](https://moonraker.readthedocs.io/en/latest/configuration/#machine) ,并补充了注意事项,建议阅读。虽然如此,我们查找答案的方法还是有记录借鉴意义的。
## 1.2 调用 `Method` 实现关机
### 物理关机按钮:
```yaml
# ~/klipper_config/printer.cfg
gcode:
{action_call_remote_method("shutdown_machine")}
# 定义物理按钮 【监听引脚状态】
# 按钮信号连接引脚
pin: host:gpio
# 按下时执行 gcode 宏命令
#press_gcode:
# 松开时执行 gcode 宏命令
release_gcode:
SHUTDOWN
```
测试通过,控制台输入 `SHUTDOWN` 或者被调用即可以实现关闭系统指令。
### 12864 屏幕菜单关机:
```yaml
# printer.cfg
### menu poweroff by 思兼 v2 ###
type: list
enable: {not printer.idle_timeout.state == "Printing"}
name: PowerOff
type: command
name: NO
enable: {not printer.idle_timeout.state == "Printing"}
gcode:
{menu.back()}
type: command
name: YES
enable: {not printer.idle_timeout.state == "Printing"}
gcode:
SHUTDOWN
```
## 2、 传统打完关机方案
我们先说说传统的打完关机功能,适用于 **【上位机独立供电的情况】**,多数朋友借助原来 Marlin 上用的 `打完关机模块/继电器`,或者使用 `智能插座`,我们说说各自的优缺点:
!(https://cdn.jsdelivr.net/gh/sjqlwy/blog_imgs@default/images/20220313225817.png)
## 2.1 打完关机模块
### 优点:
* 可以利用原来的模块不浪费
* 支持断电检测
### 缺点:
* 接线麻烦
* 价格较高 (79 + 9元)
* 为了安全关闭上位机系统,需要上位机独立供电:
* 如果由上位机 GPIO 引脚控制,支持开、关机操作,上传打印任务后自动开机
* 如果由主板引脚控制,仅支持关机,且要求主板支持从上位机取电,但此时会造成 5v 和 VCC 混合供电,导致潜在的信号干扰
示例如下:
```yaml
# 上位机独立供电打完关机方案,by 思兼
#####################################################################
#方法1,打印机主板 PS_ON 接口
#####################################################################
# 使用主板 PS_ON 引脚,需要上位机通过 USB 接口为主板供电,但此时会出现 5v
# 和 12/24v 同时供电的问题
pin: PS_ON
pwm: False
value: 1
shutdown_value: 0
description: PowerOff
gcode:
M84
SET_PIN PIN=mks_pwc VALUE=0
#####################################################################
#方法2,上位机 GPIO 接口【推荐】
#####################################################################
# 使用上位机 GPIO 接口控制,支持开/关机,尤其适合上位机内置。需要额外修改
# moonraker.cfg 配置文件,可以手动在右上角菜单控制开关机
gcode:
{action_call_remote_method("set_device_power",
device="printer",
state="off")}
#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
# 以下为修改 moonraker.cfg内容,“printer”名称对应。以及不能使用 UART 等引脚
type: gpio
pin: gpio26
off_when_shutdown: True
initial_state: off
#####################################################################
#延时(挤出头降温)自动关机
#####################################################################
# 判断当前为空闲状态,才执行断电操作
initial_duration: 0.
gcode:
{% if printer.idle_timeout.state == "Idle" %}
M81
{% endif %}
# 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 智能插座
### 优点:
* 价格相对便宜(30~50元)
* 无需额外接线
* 支持电量统计(可选)
### 缺点:
使用方法有以下几种,各有其不足:
1. 预估打印完成时间定时关机 —— 不准确
2. 使用具有电量检测功能的插座,当打印机处于低耗电时,认为打印完成,实现关机 —— 相对准确,成本提高
3. 使用 Home Assistant 等智能家居系统,Klipper 打印完成后,调用 Moonraker 向 HA 发送关闭智能插座命令 —— 准确,但是需要 HA
其他用法欢迎补充。前两种方法自己从 APP 里设置即可,第三种方法我们下面一起介绍。
## 3、Gemini 等主板打完自动安全关机方案
此类主板的问题就是上位机和主板供电一起的,无论使用 `打完关机模块` 还是 `智能插座`:
* **先断电** | 导致系统意外断电关机
* **先关闭系统** | 导致模块无法收到断电指令
我们分析一下理想的关机断电方案(横轴为时间):
!(https://cdn.jsdelivr.net/gh/sjqlwy/blog_imgs@default/images/20220313233837.png)
之前想过用 `延时继电器` (加自锁?)实现,但是想想还是智能插座更方便。同样有三种方案:
## 3.1 TPLink 智能插座
无需烧录固件和搭建 HA 系统,可以直接被 mrk 调用,但是 (https://moonraker.readthedocs.io/en/latest/configuration/#tplink-smartplug-configuration) 之后有无法在局域网使用的可能。
## 3.2 智能插座烧录 Tasmota 固件
优缺点:
* 不需要家里有 HA 智能家居系统
* 需要拆开智能插座烧录固件,需要额外的工具,且有破拆外壳风险
* 仅支持 ESP8266/ESP32 等方案的智能插座,实测 ESP8266 烧录成功,ESP32 不行,需要进一步测试。
!(https://cdn.jsdelivr.net/gh/sjqlwy/blog_imgs@default/images/20220313235115.png)
目前了解到的是 `gosund` 和 `全橙` 的部分智能插座使用 ESP8266 芯片。tasmota 目前支持的设备列表可以在 [这里](https://templates.blakadder.com/) 查看。
### 3.2.1 为 ESP8266 设备烧录 Tasmota 固件
#### 烧录软件:
* [**ESP-Flasher**](https://github.com/Jason2866/ESP_Flasher) \- GUI flasher for Tasmota based on esptool.py for ESP82XX *and* ESP32. (Windows or Mac)
* [**Tasmotizer**](https://github.com/tasmota/tasmotizer) - flashing and firmware download tool *for ESP82XX only*. (Windows, Linux or Mac) | 只支持 ESP8266
* [**Tasmota Web Installer**](https://tasmota.github.io/install/) - flash Tasmota using a Chrome based browser for ESP82XX and ESP32 | 在线烧录页面
任选其一即可。
!(https://cdn.jsdelivr.net/gh/sjqlwy/blog_imgs@default/images/20220314000552.png)
#### 下载固件:
* 固件下载地址:https://tasmota.github.io/docs/Download/
* 点击 `Current release` ,选择 (http://ota.tasmota.com/tasmota/release/tasmota-CN.bin)
#### 烧录固件:
有的 ESP8266 模块自带串口芯片(如 NodeMCU),如果没有(如 Weduino)则自备 USB串口模块进行烧录。ESP8266 模块仅支持 3.3v,务必不要接错,建议独立供电,不建议由串口模块供电,烧录时 `GPIO0` 置于低电平进入烧写模式,借用一下老图。
!(http://ww1.sinaimg.cn/mw690/90fd3da6gy1fctldvibwwj21kw2t51l0)
!(http://ww1.sinaimg.cn/mw690/90fd3da6gy1fctogrg667j20pb0f6wi9)
#### 连接设置 Tasmota
烧录完成后,重新上电稍等片刻可以看到一个 `tasmota_XXXXXX-####` 的热点,连接上去并打开网址:`http://192.168.4.1` 即可进入 Tasmota 设置界面。
!(https://tasmota.github.io/docs/_media/wificonfig1.jpg)
**注意:**
* 热点只会存在 3分钟,需要重启模块才会再次出现。
* 新界面会提示你输入当前无线网络的用户名和密码,注意是 2.4GHz 的,ESP8266 不支持 5GHz 无线网络。
* 连接无线网络后分配的地址可以在路由器管理页面内或者使用 `Fing` 等局域网扫描软件查看。
进入后可以进行一些设置,这里我就不演示了。
### 3.2.2 设置 Moonraker
```yaml
# moonraker.cfg
type: tasmota
address: 192.168.0.201 # 请设置正确的设备 IP 地址
initial_state: on
off_when_shutdown: True
timer: 10 # 请设置合适的延时时间,单位 秒
```
注意这里一个官方文档里没有提到的隐藏参数:`timer` ,可以实现发送断电命令后,插座延时断电的功能。具体参考 [***power.py add parameter timer***](https://github.com/Arksine/moonraker/pull/139) 和源码。注意,这里的 `timer` 和 (https://moonraker.readthedocs.io/en/latest/configuration/#gpio-device-configuration) 里的作用不一样:
> A time (in seconds) after which the device will power off after being.switched on. This effectively turns the device into amomentary switch.This option is available for gpio, klipper_device, tplink_smartplug,shelly, and tasmota devices.The timer may be a floating point valuefor gpio types, it should be an integer for all other types.Thedefault is no timer is set.
后者实现的是类似开启后延时自动断开的功能,无法在触发条件后才断开。
!(https://cdn.jsdelivr.net/gh/sjqlwy/blog_imgs@default/images/20220314004756.png)
* 灯珠发绿色光为开启状态,蓝色为断开状态
* 设置断开后,延时 5s 才断开
## 3.3 使用 Home Assistant 控制智能插座
优缺点:
* 需要 HA 智能家居系统,如果之前家里就有就很方便
* 兼容性强,支持多种智能插座,大多数天猫精灵、小爱同学的都支持
* 不需要额外烧录固件,不需要拆开智能插座
整体来说,此方案更优秀。
### 3.3.1 搭建 Home Assistant 系统
方法众多,此处略去不表。我使用 树莓派4 + [中文镜像](https://www.hachina.io/hassos_hachina_img/) 进行测试。后续会在家里的软路由上进行安装,感觉树莓派镜像还挺麻烦的,由于国内网络不好导致安装体验差。[这个教程](https://pimylifeup.com/home-assistant-raspberry-pi/) 也有帮助。
### 3.3.2 添加智能插座设备
这里我以天猫精灵赠送的 `BroadLink SP mini 3` 为例:
!(https://cdn.jsdelivr.net/gh/sjqlwy/blog_imgs@default/images/20220314005451.png)
#### 添加智能插座
1. 下载 `博联智能` APP,在其中可以连接配置此智能插座并看到设备 MAC 地址。同时点击右上角 `...` 图标—— `属性` —— 关闭 `设备上锁`。同时根据 MAC 地址确认设备 IP 地址。
2. 打开 http://homeassistant.local:8123/ 管理页面,选择 `配置` —— `设备与服务` —— `添加集成`(右下角)—— `Broadlink`,输入设备 IP 即可连接。
!(https://cdn.jsdelivr.net/gh/sjqlwy/blog_imgs@default/images/20220314005702.png)
!(https://cdn.jsdelivr.net/gh/sjqlwy/blog_imgs@default/images/20220314010617.png)
如是即可在 HA 主面板控制智能插座开关了。
#### 延时关闭智能插座思路
由于我也是半路出家,第一次用 HA,网上搜到的都是开启后定时自动关闭,不是我想要的功能。思索一番,能想到的延时方法就是创建一个中间开关实体命名为 `Relay`,再为它创建一个自动化规则,当 Moonraker 发送关闭命令后:
* Condition:Relay 从 on 到 off
* Action:延时 10s,关闭智能插座
#### 创建 HA 辅助元素
!(https://cdn.jsdelivr.net/gh/sjqlwy/blog_imgs@default/images/20220314011215.png)
!(https://cdn.jsdelivr.net/gh/sjqlwy/blog_imgs@default/images/20220314011418.png)
* 开关名称随便起,这里是 `Gemini_Relay`
* 图标随便选
#### 创建自动化规则
同样界面选择 `自动化` 标签 —— `创建自动化` —— `从空的自动化开始`,右上角选择 `以 YAML 编辑`,你也可以事后查看图形化过程。
!(https://cdn.jsdelivr.net/gh/sjqlwy/blog_imgs@default/images/20220314011847.png)
输入以下内容:
```yaml
alias: 延时关闭插座
description: '收到 mrk 关闭指令,延时关闭智能插座'
trigger:
- platform: state
entity_id: input_boolean.gemini_relay
from: 'on'
to: 'off'
condition: []
action:
- delay:
hours: 0
minutes: 0
seconds: 10
milliseconds: 0
- type: turn_off
device_id: cbd09a4013a7cba034a1e42090227354
entity_id: switch.wi_fizhi_neng_cha_zuo_switch
domain: switch
mode: single
```
注意 `device_id` 和 `entity_id` 可以从图形界面直接选择。对应的正常打开智能插座配置如下,虽然用不上:
```yaml
alias: 正常打开智能插座
description: ''
trigger:
- platform: state
entity_id: input_boolean.gemini_relay
from: 'off'
to: 'on'
condition: []
action:
- type: turn_on
device_id: cbd09a4013a7cba034a1e42090227354
entity_id: switch.wi_fizhi_neng_cha_zuo_switch
domain: switch
mode: single
```
【V2】
```yaml
alias: 延时关闭智能插座
description: 收到 mrk 关闭指令,延时关闭智能插座。正常打开插座
trigger:
- platform: state
entity_id: input_boolean.gemini_relay
condition: []
action:
- choose:
- conditions:
- condition: state
entity_id: input_boolean.gemini_relay
state: 'on'
sequence:
- type: turn_on
device_id: cbd09a4013a7cba034a1e42090227354
entity_id: switch.wi_fizhi_neng_cha_zuo_switch
domain: switch
- conditions:
- condition: state
entity_id: input_boolean.gemini_relay
state: 'off'
sequence:
- delay:
hours: 0
minutes: 0
seconds: 15
milliseconds: 0
- type: turn_off
device_id: cbd09a4013a7cba034a1e42090227354
entity_id: switch.wi_fizhi_neng_cha_zuo_switch
domain: switch
default: []
mode: single
```
再创建一个同步插座状态的规则,因为有时候会手动通过插座按钮关闭。
```yaml
alias: 同步智能插座状态
description: ''
trigger:
- platform: device
type: changed_states
device_id: cbd09a4013a7cba034a1e42090227354
entity_id: switch.wi_fizhi_neng_cha_zuo_switch
domain: switch
condition: []
action:
- choose:
- conditions:
- condition: device
type: is_on
device_id: cbd09a4013a7cba034a1e42090227354
entity_id: switch.wi_fizhi_neng_cha_zuo_switch
domain: switch
sequence:
- service: input_boolean.turn_on
data: {}
target:
entity_id: input_boolean.gemini_relay
- conditions:
- condition: device
type: is_off
device_id: cbd09a4013a7cba034a1e42090227354
entity_id: switch.wi_fizhi_neng_cha_zuo_switch
domain: switch
sequence:
- service: input_boolean.turn_off
data: {}
target:
entity_id: input_boolean.gemini_relay
default: []
mode: single
```
!(https://cdn.jsdelivr.net/gh/sjqlwy/blog_imgs@default/images/20220314012744.png)
#### 创建 HA 长期访问令牌
!(https://cdn.jsdelivr.net/gh/sjqlwy/blog_imgs@default/images/20220314013152.png)
**注意:**
* 此令牌无法再次查看,请妥善保存
* **此令牌非常长**,复制的时候注意复制完全
#### 创建 Moonraker 配置
想要控制 HA 设备,需要用到上面 HA 创建的令牌(Token),官方给的 (https://moonraker.readthedocs.io/en/latest/configuration/#home-assistant-configuration-http) 直接控制智能插座,无法实现延时功能。我们照葫芦画瓢整一个:
```yaml
# moonraker.cfg
type: homeassistant
address: 【HA IP】
port: 8123
device:input_boolean.Gemini_Relay
domain: input_boolean
token: 【TOKEN】
```
**注意:**
* 请设置为你 HA 所在的设备 IP 地址
* 请设置为上面创建的令牌
*`homeassistant_switch` | 随便起,支持中文例如 `智能插座`
* `Gemini_Relay` | 请改为你创建的实体名称
!(https://cdn.jsdelivr.net/gh/sjqlwy/blog_imgs@default/images/20220314014036.png)
至此,我们的智能插座通过一个虚拟中继,比较完美的实现了 Gemini 之类的主板安全关机,同时我关于 Klipper 电源管理方面的文章也告一段落。 厉害厉害 厉害厉害 66666666666 呵呵呵呵 赞赞赞赞赞 哈哈哈哈哈哈 创建好了Moonraker配置,手动点击可以实现延时断电了,但是怎么让它打完自动触发?需要gcode添加什么代码吗? destinia 发表于 2022-8-24 14:23
创建好了Moonraker配置,手动点击可以实现延时断电了,但是怎么让它打完自动触发?需要gcode添加什么代码吗 ...
可以参考我的几篇文章,所有相关内容都有 跟着思兼大佬学到很多东西 根据教程完成了HA的自动关机,谢谢大佬
页:
[1]