控制 Gemini v1.1 CoreFan 以及 Klipper 电源管理
前言
原创文章,转载引用务必注明链接,水平有限,如有疏漏,欢迎指正交流。
手里拿到了 Fly3d Gemini v1.1 主板,原本云评测时对这种二合一主板的时候并不看好(轴少、外接WiFi、一坏俱坏,云云),实际用起来这种2合一主板太舒服了,如果测试的功能可以用的话,那就更香了。
【 如需查看文章更新请访问本文链接 -> DFRobot社区 】
内容介绍:
- Moonraker 控制上位机主板 GPIO 状态
- Klipper 控制上位机、MCU GPIO 状态
- 主板温控风扇设置
- 添加 Klipper 物理关机按钮
1、Core_Fan 的使用
1.1 使用 Moonraker 控制风扇启停
此引脚连接到上位机部分的 gpiochip0/gpio3
(aka GPIOL3、355)
前面 简明指南 说过,由于 MOSFET 导致 CoreFan 的使用有问题,这里我们试试它在 v1.1 上的表现。掏出我们的祖传 5v小风扇,反向不转。
-
接线:左(-)右(+),跳帽不接
-
修改 moonraker.cfg,设置 CoreFan 开关
# ~/klipper_config/moonraker.cfg
[power core_fan]
type: gpio
pin: gpiochip0/gpio3
initial_state: off
off_when_shutdown: False
-
启用 Moonraker 的 GPIO 控制权限:
# 我们不建议把用户添加到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[0-4]", GROUP="gpio", MODE="0660"
_EOF_
# 重启 moonraker.service 并验证是否成功
systemctl restart moonraker
cat /sys/kernel/debug/gpio
-
实际测试,电机闸刀图标可以正常切换风扇开关了
-
在 Klipper 里调用
# printer.cfg
[gcode_macro POWEROFF_CORE_FAN]
gcode:
{action_call_remote_method("set_device_power",
device="core_fan",
state="off")}
[gcode_macro restart_serv]
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屏幕点亮和自动熄灭,放出个参考,自己思考一下如何改动。
####################################################################
# LCD12864 屏幕按钮联动自动关闭独立灯光 by 思兼
####################################################################
[output_pin modellight]
# 单色模型灯光,延时自动熄灭
pin: modellight_pin
value: 0
[duplicate_pin_override]
pins: EXP1_2
[gcode_button LIGHTControl]
pin: ^!EXP1_2 #LIGHTControl
press_gcode:
LIGHTS_ON
UPDATE_DELAYED_GCODE ID=LIGHTS_OFF DURATION=60
[gcode_macro LIGHTS_ON]
gcode:
SET_PIN PIN=modellight VALUE=1
[delayed_gcode LIGHTS_OFF]
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) 。同时注释掉上面提到的 Moonraker 配置,防止同时访问产生冲突。
# printer.cfg
[mcu host]
serial: /tmp/klipper_host_mcu
#####################################################################
# 风扇控制 | Fan Controller
#####################################################################
[temperature_fan host_fan] # 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 适用于四线可控风扇,调节更精确。可以通过降低目标温度进行测试,至此,我们的小风扇愉快地转起来了。
2、Klipper 电源管理
原因:
从 Marlin 固件转到 Klipper 的朋友,很多关机操作都是习惯性直接断电。但是要知道,上位机(树莓派开发板等)实际上相当于一台小电脑(Single Board Computer,SBC),你家电脑关机靠拔电吗?如果每次关机都是直接断电,长此以往,上位机可能出现以下问题:
- 文件改动未保存,例如 printer.cfg 配置文件改了但是又没完全改
- 文件系统损坏,系统启动时间延长或者无法启动
- SD卡损坏
那么正确的关机方式是如何呢?本文就一一道来。
由于 Gemini 的上位机和 MCU 部分供电是一起的,故这里摘取一部分Gemini适用的内容。常用的打完关机、自动开机的功能难以完全实现。要不控制进入/退出 M112 急停状态凑合用?
2.1 常见的正常关机方法
- 【网页关机】使用 Fluidd/Mainsail 网页前端右上角的关机按钮
注意:对于 Armbian 系统,常常需要修复 sudo 权限才可以生效。
# Moonraker 已优化此脚本。提示重启(REBOOT)代表脚本已经正确执行。如果设置界面语言为中文,则需要修改脚本的返回信息。
~/moonraker/scripts/sudo_fix.sh
- 【终端命令关机】使用 ssh-client 等方式登录上位机终端,手动执行以下命令安全关机,这里以全能好用的
MobaXterm
为例:
# 关机命令,也可以使用 sudo shutdown now 命令
sudo poweroff
- 【屏幕关机】使用 KlipperScreen 关机按钮,同 moonraker 需要添加环境变量后运行修复脚本。或者 12864 等 LCD 屏幕的菜单。
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"
的问题。
- 其他方式,如物理关机按钮等
!([img]https://gd4.alicdn.com/imgextra/i3/0/O1CN01Fx0vFL1rPqAb4dABv_!!0-item_pic.jpg)
本文会介绍使用物理按钮和12864命令菜单关机,分别对应 Moonraker API 和 shell_cmd component。
2.2 物理关机按钮
使用物理按钮的好处是想要关机的时候,不用打开 Fluidd 网页或者 SSH 软件登录终端执行命令了。
拢共分两步:
- 监听按钮连接的引脚状态:Linux、Klipper、Moonraker 三种方式
- 执行关机动作:调用 Moonraker API、使用 shell_cmd 调用系统关机命令两种方式
2.2.1 Linux 系统监听 GPIO 状态
很多人实现过了,具体可以参考这篇文章 Raspberry Pi Shutdown / Restart Button
Linux 下使用 Python + RPi.GPIO 库编写 后台程序 监听 GPIO 引脚状态并 执行系统关机命令。针对其他非树莓派设备,可能需要移植修改 GPIO 操作库。
2.2.2 使用 Klipper 监听按钮状态(需要 shell_cmd 组件)
- 可以监听 MCU 和 上位机 (host_as_mcu) 的引脚状态。
- 定义 [gcode_button] ,可以使用
QUERY_BUTTON button=my_gcode_button
命令测试。
- 需要 shell_cmd 组件调用系统关机命令,可以使用 kiauh 助手安装
- 由于 shell_cmd 组件需要 Python2,所以新版本 Klipper Python2 会有不支持中文 Gcode 文件的问题。
- shell_cmd 命令不支持需要输入用户密码的命令,所以要设置当前用户权限。(修改 /etc/sudoers 文件,修复之后好像就没问题了)
- 可以想想如何添加按钮防抖动和按下两次才执行的功能。
- 【注意!】Klipper 内部定义的资源在 Klipper 关闭状态下无法使用,所以想要实现开关机控制,只能通过 Moonraker。
# ~/klipper_config/printer.cfg
# 定义物理按钮 【监听引脚状态】
[gcode_button poweroff_button]
# 按钮信号连接引脚
pin: host:gpio
# 按下时执行 gcode 宏命令
#press_gcode:
# 松开时执行 gcode 宏命令
release_gcode:
PowerOff_Host
# 定义 shell_cmd 命令 【执行关机操作】
[gcode_shell_command poweroff_host]
command: sudo shutdown now
# timeout: 2.
# verbose: True
[gcode_macro PowerOff_Host]
gcode:
RUN_SHELL_COMMAND CMD=poweroff_host
2.2.3 使用 Moonraker 监听按钮状态 (推荐)
- 可以监听上位机 GPIO 的引脚状态。
- 定义 [button] 代码段
- 调用 Moonraker API 执行关机动作,支持 Moonraker Python3
# ~/klipper_config/moonraker.cfg
[button poweroff_button]
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 避免冲突。
我们准备把魔爪伸向 UART1,查看 /boot/armbianEnv.txt
,删除 uart1
字段以启用。
3.1 引脚选择
我们设计使用 UART2
的 RX
脚连接按钮,默认拉高,但是似乎 系统默认 press
为 HIGH,release
为 LOW,这会导致监听引脚默认为高电平时,press、release行为交换。这里我们选择 Rx 和 5V 引脚冒充一个物理按钮。
根据公式判定 RX 引脚号:
-
PA1 = 0+1 = 1
-
1 = gpiochip1gpio1
故上述代码引脚号如此填写,测试时调用其他 Client API 例如 printer.objects.list
# 查看日志,可以命令正常返回了系统信息。
cat ~/klipper_logs/moonraker.log | tail -n 50
至此,我们已经成功为 Gemini 安装了物理关机按钮。还有其他功能,后面和大家分享。
4、添加 RGB mini12864 LCD 屏幕的关机菜单
To Be Continue 》》》目前采用 shell_cmd 的方式,未来会更改。
# printer.cfg
### menu poweroff by 思兼 v1 ###
[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()}
# RUN_SHELL_COMMAND CMD=poweroff_host
[menu __main __poweroff __yes]
type: command
name: YES
enable: {not printer.idle_timeout.state == "Printing"}
gcode:
RUN_SHELL_COMMAND CMD=poweroff_host