Notice: Function _load_textdomain_just_in_time was called incorrectly. Translation loading for the simply-static domain was triggered too early. This is usually an indicator for some code in the plugin or theme running too early. Translations should be loaded at the init action or later. Please see Debugging in WordPress for more information. (This message was added in version 6.7.0.) in /var/www/html/wp-includes/functions.php on line 6121
给树莓派增加物理按钮一键开、关机

给树莓派增加物理按钮一键开、关机

一直以来,树莓派关机要么直接拔掉电源,要么登陆后执行shutdown命令关机。这两种方式,第一种简单粗暴,但是断电对树莓派的SD伤害非常大。第二种方式比较安全,但是很麻烦。树莓派其实支持物理按键开关机,介绍如下。

一、实现方式

/boot/config.txt 文件末尾添加一行代码:

dtoverlay=gpio-shutdown

保存,然后重启树莓派,在树莓派的GPIO3(BCM3)和GND引脚之间接一个按键。这时按下按键树莓派就关机了,再按一下按键,树莓派开机。

树莓派引脚

二、实现的原理

在树莓派的/boot/overlays/文件下,包含了大量的设备树,使得树莓派的内核支持大量的硬件配置,前提是要开启才行。 开启的方式也比较简单,只需要在/boot/config.txt文件中添加或者删除相应的命令即可。树莓派的/boot/config.txt文件相当于电脑的BIOS。 这里只看/boot/overlays/README中和本文相关的内容。

树莓派系统/boot/overlays/README文件中关于关机是这么描述的:

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"
        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.
Load:   dtoverlay=gpio-shutdown,<param>=<val>
Params: gpio_pin                GPIO pin to trigger on (default 3)
        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.

大概翻译以下:

在/boot/config.txt文件中添加“dtoverlay = gpio-shutdown”时,当GPIO引脚的电平状态发生变化时关闭树莓派,此时给定的GPIO引脚被配置为KEY_POWER事件的输入键,即不断的监控连接到GPIO引脚的按键是否被按下。

树莓派关机后,树莓派系统可以通过将GPIO3驱动为低电平再次开机。 因此如果连接了GPIO3和GND之间的按钮(40引脚接头连接器上的引脚5和6),你就获得了关机和开机按钮。

即添加代码后,树莓派的GPIO3会不断的检测电平状态,如果检测到GPIO3变为低电平(GPIO3连接到GND时),树莓派就会关机,关机后再次将GPIO3变为低电平,则树莓派会开机。 这样在树莓派的GPIO3和GPND之间连接一个按键,就能够实现树莓派的开关机功能。

dtoverlay=gpio-shutdown

注:该功能(开关机)的实现与I2C有部分冲突,要使用GPIO3实现开关机,则必须关闭I2C功能,如不关闭,则只能实现开机功能,而关机功能失效。如需在启用I2C的情况下一键实现开关机,则可以使用gpio_pin=17,即GPIO_0(物理引脚PIN11)做关机键,GPIO3做开机键,简单说就是GPIO3和GPIO17在开关侧并线,两键共地即可。修改如下:sudo nano /boot/config.txt

dtoverlay=gpio-shutdown

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

GPIO3与GPIO17并线,实现I2C开启情况下的一键开关机

即添加代码后,树莓派的GPIO3会不断的检测电平状态,如果检测到GPIO3变为低电平(GPIO3连接到GND时),树莓派就会关机,关机后再次将GPIO3变为低电平,则树莓派会开机。 这样在树莓派的GPIO3和GPND之间连接一个按键,就能够实现树莓派的开关机功能。 还可以按照以下格式进行自定义配置:

dtoverlay = gpio-shutdown,<param> = <val>

其中的 parm 和 val 的值可以选择的配置有:

        gpio_pin                打开触发功能的GPIO引脚(默认3)
        active_low              当它为1(低电平有效)时,下降边缘生成按下事
                                件,并且上升沿会产生按键上升事件。
                                当它是0(高电平有效)时,
                                这时和1的状态相反。默认值为1(低电平有效)。
        gpio_pull               所需的上拉/下拉状态(关闭,下拉,上拉)
                                默认为“上拉”。
                                请注意,默认引脚(GPIO3)具有一个
                                外部上拉。

Python实现

t = open("/boot/config.txt","a")
line_on = "dtoverlay=gpio-shutdown"               # 调用文件的 readline()方法
t.writelines(line_on+'\n')
line_off = "dtoverlay=gpio-shutdown,gpio_pin=17,active_low=1,gpio_pull=up"
t.writelines(line_off+'\n')
t.close()