pATAq 发表于 2022-2-12 13:39:18

跟着思兼学习Klipper(09)Klipper 温控风扇以及电源管理(部分)

## 控制 Gemini v1.1 CoreFan 以及 Klipper 电源管理

## 前言
原创文章,转载引用务必注明链接,水平有限,如有疏漏,欢迎指正交流。
手里拿到了 Fly3d Gemini v1.1 主板,原本云评测时对这种二合一主板的时候并不看好(轴少、外接WiFi、一坏俱坏,云云),实际用起来这种2合一主板太舒服了,如果测试的功能可以用的话,那就更香了。

【 如需查看文章更新请访问本文链接 -> [***DFRobot社区***](https://mc.dfrobot.com.cn/thread-312100-1-1.html#pid506233?fromuid=725344) 】

内容介绍:

* Moonraker 控制上位机主板 GPIO 状态
* Klipper 控制上位机、MCU GPIO 状态
* 主板温控风扇设置
* 添加 Klipper 物理关机按钮
* shell_cmd
* moonraker api

## 1、Core_Fan 的使用

## 1.1 使用 Moonraker 控制风扇启停

此引脚连接到上位机部分的 `gpiochip0/gpio3` (aka GPIOL3、355)

!(https://cdn.jsdelivr.net/gh/sjqlwy/blog_imgs@default/images/202112150853772.png)

前面 [***简明指南***](https://mc.dfrobot.com.cn/thread-311661-1-1.html?fromuid=725344) 说过,由于 MOSFET 导致 CoreFan 的使用有问题,这里我们试试它在 v1.1 上的表现。掏出我们的祖传 5v小风扇,反向不转。

1. 接线:左(-)右(+),跳帽不接

2. 修改 moonraker.cfg,设置 CoreFan 开关

   ```yaml
   # ~/klipper_config/moonraker.cfg
   
   type: gpio
   pin: gpiochip0/gpio3
   initial_state: off
   off_when_shutdown: False
   ```
   
3. 启用 Moonraker 的 GPIO 控制权限:
```shell
# 我们不建议把用户添加到root组,所以新建gpio组添加当前用户进去,重新登录 (Relogin) 生效
# Gemini bullseye 默认已启用
sudo groupadd gpio
sudo usermod -a -G gpio $USER
#####################################################
# 添加 /etc/udev/rules.d/60-gpiod.rules
sudo su
cat << _EOF_ > /etc/udev/rules.d/60-gpiod.rules
# udev rules for gpio port access through libgpiod
SUBSYSTEM=="gpio", KERNEL=="gpiochip", GROUP="gpio", MODE="0660"
_EOF_
# 重启 moonraker.service 并验证是否成功
systemctl restart moonraker
cat /sys/kernel/debug/gpio
```
!(https://cdn.jsdelivr.net/gh/sjqlwy/blog_imgs@default/images/20220212010032.png)

4. 实际测试,电机闸刀图标可以正常切换风扇开关了
   !(https://cdn.jsdelivr.net/gh/sjqlwy/blog_imgs@default/images/20220212010338.png)

5. 在 Klipper 里调用

```yaml
# printer.cfg

gcode:
{action_call_remote_method("set_device_power",
                           device="core_fan",
                           state="off")}
                           

gcode:
{action_call_remote_method("machine.services.restart",
                           service="moonraker")}
Traceback (most recent call last):
File "/home/fly/klipper/klippy/extras/gcode_macro.py", line 93, in _action_call_remote_method
    webhooks.call_remote_method(method, **kwargs)
File "/home/fly/klipper/klippy/webhooks.py", line 380, in call_remote_method
    raise self.printer.command_error(
gcode.CommandError: Remote method 'machine.services.restart' not registered
```
写进宏然后就可以在宏里面设置调用关闭/开启风扇了。

#### 番外

* 【灯光控制】由于这个引脚连接了mos管,可以提供一定的5v电流输出能力,所以也可以控制灯光,同时还可以联动12864屏幕点亮和自动熄灭,放出个参考,自己思考一下如何改动。

```yaml
####################################################################
#LCD12864 屏幕按钮联动自动关闭独立灯光 by 思兼
####################################################################


# 单色模型灯光,延时自动熄灭
pin: modellight_pin
value: 0


pins: EXP1_2


pin: ^!EXP1_2 #LIGHTControl
press_gcode:
LIGHTS_ON
UPDATE_DELAYED_GCODE ID=LIGHTS_OFF DURATION=60


gcode:
    SET_PIN PIN=modellight VALUE=1


initial_duration: 0.
gcode:
    SET_PIN PIN=modellight VALUE=0
```

当然,你也可以改成独立按钮控制灯光/风扇,通过按钮切换开/关。

* 【自动开关机】如果改成继电器/固态继电器,则在常规上位机+打印机主板的方案上,可以控制打完关机和上传切片文件自动开机的功能。

## 1.2 设置为 SoC 温控风扇
既然是Core_FAN,给上位机部分散热的,手动控制开关那肯定太LOW了,我们给他整成根据 SoC 温度自动控制启停的。
此时我们发现 Moonraker 毕竟不是干这活的,所以来到 Klipper 主场,但是此引脚属于上位机的引脚资源,想要在 Klipper 里进行控制,最简单的方法就是将上位机也作为 MCU 使用(host_as_mcu),将硬件资源统一管理,相信很多用过加速度计的小伙伴都会,具体参考文档 [*RPi microcontroller - Klipper documentation (klipper3d.org)*](https://www.klipper3d.org/RPi_microcontroller.html) 。同时注释掉上面提到的 Moonraker 配置,防止同时访问产生冲突。

```yaml
# printer.cfg


serial: /tmp/klipper_host_mcu

#####################################################################
#风扇控制 | Fan Controller
#####################################################################

# Temperature-triggered cooling fan | 温控风扇
pin: host:gpio3
kick_start_time: 0.500
sensor_type: temperature_host
control: watermark
# 高于以下温度启用风扇
target_temp: 50.0
# 允许的温度范围
min_temp: 0
max_temp: 90
# 调节最大风速以降低噪音
#max_speed: 1.0
#min_speed: 0.3
```

控制方法包括 `watermark` 和 `pid`,作为双线风扇,这里通过改变电压来调节转速不够精准,watermark 就足够了。pid 适用于四线可控风扇,调节更精确。可以通过降低目标温度进行测试,至此,我们的小风扇愉快地转起来了。

![](https://cdn.jsdelivr.net/gh/sjqlwy/blog_imgs@default/images/20220212011131.gif)

## 2、Klipper 电源管理

#### 原因:

从 Marlin 固件转到 Klipper 的朋友,很多关机操作都是习惯性直接断电。但是要知道,上位机(树莓派开发板等)实际上相当于一台小电脑(Single Board Computer,SBC),你家电脑关机靠拔电吗?如果每次关机都是直接断电,长此以往,上位机可能出现以下问题:

* 文件改动未保存,例如 printer.cfg 配置文件改了但是又没完全改
* 文件系统损坏,系统启动时间延长或者无法启动
* SD卡损坏

那么正确的关机方式是如何呢?本文就一一道来。

> 由于 Gemini 的上位机和 MCU 部分供电是一起的,故这里摘取一部分Gemini适用的内容。常用的打完关机、自动开机的功能难以完全实现。要不控制进入/退出 M112 急停状态凑合用?

## 2.1 常见的正常关机方法

1. 【网页关机】使用 Fluidd/Mainsail 网页前端右上角的关机按钮

> 注意:对于 Armbian 系统,常常需要修复 sudo 权限才可以生效。
>
> ```shell
> # Moonraker 已优化此脚本。提示重启(REBOOT)代表脚本已经正确执行。如果设置界面语言为中文,则需要修改脚本的返回信息。
> ~/moonraker/scripts/sudo_fix.sh
> ```

2. 【终端命令关机】使用 ssh-client 等方式登录上位机终端,手动执行以下命令安全关机,这里以全能好用的 `MobaXterm` 为例:

```shell
# 关机命令,也可以使用 sudo shutdown now 命令
sudo poweroff
```

!(https://cdn.jsdelivr.net/gh/sjqlwy/blog_imgs@default/images/20220212011523.png)

3. 【屏幕关机】使用 KlipperScreen 关机按钮,同 moonraker 需要添加环境变量后运行修复脚本。或者 12864 等 LCD 屏幕的菜单。

```shell
echo 'export PATH="/sbin:/usr/sbin:$PATH"' >> ~/.bashrc && source ~/.bashrc
~/KlipperScreen/scripts/sudo_fix.sh
```

`设置` ——> `系统` ——> `关闭系统`

似乎是 `/etc/sudoers` 中设置 `Defaults      secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"` 的问题。

4. 其他方式,如物理关机按钮等

!(https://gd4.alicdn.com/imgextra/i3/0/O1CN01Fx0vFL1rPqAb4dABv_!!0-item_pic.jpg)

本文会介绍使用物理按钮和12864命令菜单关机,分别对应 Moonraker API 和 shell_cmd component。

## 2.2 物理关机按钮

使用物理按钮的好处是想要关机的时候,不用打开 Fluidd 网页或者 SSH 软件登录终端执行命令了。

拢共分两步:

1. 监听按钮连接的**引脚状态**:Linux、Klipper、Moonraker 三种方式
2. 执行关机动作:调用 Moonraker API、使用 shell_cmd 调用系统关机命令两种方式

### 2.2.1 Linux 系统监听 GPIO 状态

![](https://i.all3dp.com/cdn-cgi/image/fit=cover,w=1000,gravity=0.5x0.5,format=auto/wp-content/uploads/2021/04/22145418/Button-Raspberry-Pi.jpg)

很多人实现过了,具体可以参考这篇文章 [*Raspberry Pi Shutdown / Restart Button*](https://www.hackster.io/glowascii/raspberry-pi-shutdown-restart-button-d5fd07)

**Linux** 下使用 Python + RPi.GPIO 库编写 **后台程序** 监听 GPIO 引脚状态并 **执行系统关机命令**。针对其他非树莓派设备,可能需要移植修改 GPIO 操作库。

### 2.2.2 使用 Klipper 监听按钮状态(需要 shell_cmd 组件)

* 可以监听 MCU 和 上位机 (host_as_mcu) 的引脚状态。
* 定义 [](https://www.klipper3d.org/Config_Reference.html#gcode_button) ,可以使用 `QUERY_BUTTON button=my_gcode_button` 命令测试。
* 需要 shell_cmd 组件调用系统关机命令,可以使用 kiauh 助手安装
* 由于 shell_cmd 组件需要 Python2,所以新版本 Klipper Python2 会有不支持中文 Gcode 文件的问题。
* shell_cmd 命令不支持需要输入用户密码的命令,所以要设置当前用户权限。(修改 /etc/sudoers 文件,修复之后好像就没问题了)
* 可以想想如何添加按钮防抖动和按下两次才执行的功能。
* 【注意!】Klipper 内部定义的资源在 Klipper 关闭状态下无法使用,所以想要实现开关机控制,只能通过 Moonraker。

```yaml
# ~/klipper_config/printer.cfg

# 定义物理按钮 【监听引脚状态】

# 按钮信号连接引脚
pin: host:gpio

# 按下时执行 gcode 宏命令
#press_gcode:

# 松开时执行 gcode 宏命令
release_gcode:
PowerOff_Host

# 定义 shell_cmd 命令 【执行关机操作】

command: sudo shutdown now
# timeout: 2.
# verbose: True


gcode:
    RUN_SHELL_COMMAND CMD=poweroff_host
```

### 2.2.3 使用 Moonraker 监听按钮状态 (推荐)

* 可以监听上位机 GPIO 的引脚状态。
* 定义 [](https://moonraker.readthedocs.io/en/latest/configuration/#button) 代码段
* 调用 Moonraker API 执行关机动作,支持 Moonraker Python3

```yaml
# ~/klipper_config/moonraker.cfg


type: gpio
pin: ~gpiochip1/gpio1
#      GPIO监听引脚,支持取反!和内部拉高^/拉低~(需要libgpiod 1.5)
min_event_time: .05
#   可用于按钮防抖动
# on_press:
on_release:
# 长按 1s 后才执行下述操作。machine.reboot 重启
{% if event.elapsed_time > 1.0 %}
    {% do call_method("machine.shutdown") %}
{% endif %}
```

## 3、实战 物理关机按钮

前面指南我们讲过上位机可以用的 GPIO 引脚,必要时查看 overlays 避免冲突。

![](https://cdn.jsdelivr.net/gh/sjqlwy/blog_imgs@default/images/202112151126241.png)

我们准备把魔爪伸向 UART1,查看 `/boot/armbianEnv.txt`,删除 `uart1` 字段以启用。

!(https://cdn.jsdelivr.net/gh/sjqlwy/blog_imgs@default/images/20220212020405.png)

## 3.1 引脚选择

我们设计使用 `UART2` 的 `RX` 脚连接按钮,默认拉高,但是似乎 **系统默认** `press` 为 HIGH,`release` 为 LOW,这会导致监听引脚默认为高电平时,press、release行为交换。这里我们选择 Rx 和 5V 引脚冒充一个物理按钮。

根据公式判定 RX 引脚号:

* UART2-RX = PA1

![](https://cdn.jsdelivr.net/gh/sjqlwy/blog_imgs@default/images/202112140438072.png)

* PA1 = 0+1 = 1

!(https://cdn.jsdelivr.net/gh/sjqlwy/blog_imgs@default/images/20220212022017.png)

* 1 = gpiochip1gpio1

故上述代码引脚号如此填写,测试时调用其他 [***Client API***](https://moonraker.readthedocs.io/en/latest/web_api/) 例如 `printer.objects.list`

```shell
# 查看日志,可以命令正常返回了系统信息。
cat ~/klipper_logs/moonraker.log | tail -n 50
```

!(https://cdn.jsdelivr.net/gh/sjqlwy/blog_imgs@default/images/20220212025905.png)

至此,我们已经成功为 Gemini 安装了物理关机按钮。还有其他功能,后面和大家分享。

## 4、添加 RGB mini12864 LCD 屏幕的关机菜单

To Be Continue 》》》目前采用 shell_cmd 的方式,未来会更改。

```yaml
# printer.cfg
### menu poweroff by 思兼 v1 ###

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()}
#   RUN_SHELL_COMMAND CMD=poweroff_host


type: command
name: YES
enable: {not printer.idle_timeout.state == "Printing"}
gcode:
RUN_SHELL_COMMAND CMD=poweroff_host
```

lemonszh 发表于 2022-5-24 10:59:29

type: gpio只要添加这个就提示警告。已经启用 Moonraker 的 GPIO 控制权限

pATAq 发表于 2022-5-24 22:25:23

lemonszh 发表于 2022-5-24 10:59
type: gpio只要添加这个就提示警告。已经启用 Moonraker 的 GPIO 控制权限

配置文件看看

lemonszh 发表于 2022-5-25 09:10:26

晚上静心研究了一下,搞定了。十分谢谢如此详细的教程!

pATAq 发表于 2022-5-25 10:54:41

lemonszh 发表于 2022-5-25 09:10
晚上静心研究了一下,搞定了。十分谢谢如此详细的教程!

花生编程 发表于 2023-8-3 22:50:40

厉害厉害

花生编程 发表于 2023-8-3 22:51:41

赞赞赞赞赞!!

三春牛-创客 发表于 2023-8-3 22:51:44

厉害厉害

三春牛-创客 发表于 2023-8-3 22:52:48

教程详细!

小希小希9527 发表于 2024-3-24 17:32:28

666啊大佬 还是论坛看着舒服 有气氛 可惜没落了

pATAq 发表于 2024-3-25 13:46:28

小希小希9527 发表于 2024-3-24 17:32
666啊大佬 还是论坛看着舒服 有气氛 可惜没落了

是的,本来视频就不如文字方便查阅,更适合演示,何况现在短视频更流行
页: [1]
查看完整版本: 跟着思兼学习Klipper(09)Klipper 温控风扇以及电源管理(部分)