0%

raspberrypi 关机开机按钮以及开关机指示灯

最近在做树莓派小车,用外接电源给树莓派供电,当需要关闭树莓派的时候总是在命令行关闭,然后等待关机,但是要想再开机就需要拔掉电源,感觉不是很方便,要是加个一键关机开机就好了.

正好手头上有一些四角按钮,可以在通电情况下,按下按钮开机或关机.

准备

  • 一个四角按钮
  • 一杜邦线
  • 一个100欧电阻
  • 一个led灯珠

四脚按钮:
button

四脚按钮的两边分别是接通的,在按钮按下的时候四个按钮都接通,弹起的时候恢复原样.

树莓派有提供dtoverlay指令配置,可以通过将某个pin的信号变为低电平信号(短接GDN)的方式,实现开关机.

树莓派的dtoverlay

在树莓派的boot/config.txt中,dtoverlay是一个指令,作用是配置Device Tree Overlay.

Device Tree Overlay是一种用于在树莓派系统内加载额外的驱动程序和配置的方法,它在树莓派的启动过程中被自动加载。通常在需要使用额外的硬件设备时使用该指令。

关于boot/overlay的文档有:boot/overlay/README

可以看到有关shutdown的描述:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
Name:   gpio-shutdown
Info: Initiates a shutdown when GPIO pin changes. The given GPIO pin
is configured as an input key that generates KEY_POWER events.

This event is handled by systemd-logind by initiating a
shutdown. Systemd versions older than 225 need an udev rule
enable listening to the input device:

ACTION!="REMOVE", SUBSYSTEM=="input", KERNEL=="event*", \
SUBSYSTEMS=="platform", DRIVERS=="gpio-keys", \
ATTRS{keys}=="116", TAG+="power-switch"

Alternatively this event can be handled also on systems without
systemd, just by traditional SysV init daemon. KEY_POWER event
(keycode 116) needs to be mapped to KeyboardSignal on console
and then kb::kbrequest inittab action which is triggered by
KeyboardSignal from console can be configured to issue system
shutdown. Steps for this configuration are:

Add following lines to the /etc/console-setup/remap.inc file:

# Key Power as special keypress
keycode 116 = KeyboardSignal

Then add following lines to /etc/inittab file:

# Action on special keypress (Key Power)
kb::kbrequest:/sbin/shutdown -t1 -a -h -P now

And finally reload configuration by calling following commands:

# dpkg-reconfigure console-setup
# service console-setup reload
# init q

This overlay only handles shutdown. After shutdown, the system
can be powered up again by driving GPIO3 low. The default
configuration uses GPIO3 with a pullup, so if you connect a
button between GPIO3 and GND (pin 5 and 6 on the 40-pin header),
you get a shutdown and power-up button. Please note that
Raspberry Pi 1 Model B rev 1 uses GPIO1 instead of GPIO3.
Load: dtoverlay=gpio-shutdown,<param>=<val>
Params: gpio_pin GPIO pin to trigger on (default 3)
For Raspberry Pi 1 Model B rev 1 set this
explicitly to value 1, e.g.:

dtoverlay=gpio-shutdown,gpio_pin=1

active_low When this is 1 (active low), a falling
edge generates a key down event and a
rising edge generates a key up event.
When this is 0 (active high), this is
reversed. The default is 1 (active low).

gpio_pull Desired pull-up/down state (off, down, up)
Default is "up".

Note that the default pin (GPIO3) has an
external pullup. Same applies for GPIO1
on Raspberry Pi 1 Model B rev 1.

debounce Specify the debounce interval in milliseconds
(default 100)

当GIPIO引脚发生变化时就启动或者关闭树莓派。

当树莓派关机后,可以通过给GIPO3低电平信号来上电达到树莓派开机的效果。

实际就是找到树莓派的GPIO3(物理引脚5),通过和树莓派的任何一个GDN引脚短接,就等于拉低电平。

开关机按钮实现

接线: GPIO3 -> button -> GDN

配置/boot/config.txt:

1
dtoverlay=gpio-shutdown

然后重启树莓派,但是发现关机不起作用,倒是在关机的时候就可以通过按下按钮来启动。很奇怪。

意识到当开启了I2C接口后,GPIO3会作为I2C的数据引脚。这个会不会影响到?

我特意去关了一下。

关闭I2C:

1
sudo raspi-config

选择”3 Interface Options”
选择”I4 I2C”
然后在接下来的界面里面选择disable。

然后重新启动树莓派。

结果还是无法用GPIO3关机。

找了很久,找到一个说要安装kmod-input-gpio-keys包的,但是我安装这个包又说找不到这个包,搜索一下发现这个包和openwrt有关系,但我又没用到openwrt,感觉是找偏了。

又费劲找各种轮胎,终于找到一个有用的:
gpio-shutdown isn’t working (Bookworm 64bit)

具体可以阅读man logind.conf:

1
2
3
4
5
6
7
8
9
$ man logind.conf

HandlePowerKey=, HandlePowerKeyLongPress=, HandleRebootKey=, HandleRebootKeyLongPress=, HandleSuspendKey=, HandleSuspendKeyLongPress=, HandleHibernateKey=,
HandleHibernateKeyLongPress=, HandleLidSwitch=, HandleLidSwitchExternalPower=, HandleLidSwitchDocked=

Controls how logind shall handle the system power, reboot and sleep keys and the lid switch to trigger actions such as system power-off, reboot or suspend. Can be
one of "ignore", "poweroff", "reboot", "halt", "kexec", "suspend", "hibernate", "hybrid-sleep", "suspend-then-hibernate", "lock", and "factory-reset". If "ignore",
systemd-logind will never handle these keys. If "lock", all running sessions will be screen-locked; otherwise, the specified action will be taken in the respective
event. Only input devices with the "power-switch" udev tag will be watched for key/lid switch events.

可以看到logind.conf里面控制登录者应如何处理系统电源、重新启动和睡眠,以及触发系统关机、重新启动或者挂起等操作,如果配置为ignoresystemd-logind永远不会处理这些键。

查看一下/etc/systemd/login.conf文件:

1
2
3
$ cat /etc/systemd/login.conf

HandlePowerKey=ignore

可以看到HandlePowerKey是配置为ignore,所以按下按钮关机是没有反应的。

将这个修改为:HandlePowerKey=poweroff.

可以顺利关机了。

我还特意尝试了一下,就算配置正确,如果打开I2C接口,那么还是无法用GPIO3关机。

那么假设我们要正常使用I2C接口,但是也要正常开关机按钮,那么应该怎么办?

我们可以定义一个GPIO17为关机的gpio_pin,接线:
GPIO3 + GPIO17 -> button -> GDN

设置如下:

/boot/config.txt里面修改设置:

1
dtoverlay=gpio-shutdown,gpio_pin=17,active_low=1,gpio_pull=up

接线可以GPIO17和GPIO3共地,然后按下按钮后会开机,在开机状态下,按下按钮会关机。

开机指示灯

当树莓派通电的时候,树莓派上会有个指示灯红灯亮,开机的时候,一个绿色的灯会闪烁,但是当开机放置一段时间后,信号灯不闪烁的时候我们也不知道树莓派的状态是开机还是关机,加一个开关机指示灯会比较好一点,可以明确的看到树莓派的开关机状态。

可以使用GPIO14 TXD (物理引脚8)做一个开机指示灯。

接线:
GPIO14 -> led -> 100Ω电阻 -> GDN

首先开启串口:

1
sudo raspi-config

选择:3 Interface Options
选择:I6 Serial Port

接下来的界面中都选择Yes。

然后重新启动树莓派:sudo reboot now

可以看到,当树莓派关机的时候,对应的led会灭,当树莓派开机的时候,对应的led会亮。

具体展示效果可以看:
树莓派-开关机按钮和开关机指示灯 - bilibili

码字辛苦,打赏个咖啡☕️可好?💘