I also need to add a button for graceful shutdown of my headless Rock Pi 4 project.
I believe we need to configure GPIO appropriately, have a script running to check button state, and perform gracious shutdown when it is changed. I’m leaning towards using a locking button, or switch, over momentary button.
I’ll post my solution once I figure it, but it is not a priority for me right now, busy with internal design and exposing IO ports. Would appreciate to see yours if you implement it earlier.
It uses mraa library to set ISR for a button. Not sure if it would be possible to power up after shutdown with this method. Anyway I am trying this approach at the moment and will update if I achieve any progress.
For my use case of locking mechanical switch, can I just use some pin with internal pull-up resistor, e.g. pin 5, and use the switch to tie it to GND without any additional resistors?
This is the script I’ve come up with:
import mraa
import time
import os
mygpio = mraa.Gpio(5)
mygpio.dir(mraa.DIR_IN)
while True:
time.sleep(10)
val = mygpio.read()
time.sleep(10)
if val > 0:
os.system("shutdown now -h")
Are my ideas correct, or do I need to adjust something?
Clone MRAA to your system git clone https://github.com/eclipse/mraa
Install dependencies (removed nodejs-dev because it was giving error) sudo apt-get install git build-essential swig3.0 python-dev cmake libjson-c-dev
Modify gpio_advanced.c example to use your pin and your command
cd mraa/examples/c
sudo nano gpio_advanced.c
Modify #define GPIO_PIN 6
to pin that you want (not all pins work, pins 13, 22, 23, 24 seem to work).
Now lets modify interrupt code to use your command:
int_handler(void* args)
{
fprintf(stdout, "ISR triggered\n");
// Add your command here, I used: system("shutdown now");
}
In the bottom of the file, there is following line:
/* wait 30 seconds isr trigger */
sleep(30);
Modify it to be
while(1) {
sleep(30);
}
Build mraa by following commands:
cd mraa
mkdir build
cd build
cmake ..
make
Enable the pin that you used in the gpio_advanced.c example by doing following:
cd /sys/class/gpio
su root
echo 23 > export
after this command, when you type ls, pin23 should be visible.
Run the program
su rock
cd mraa/build/examples/c
sudo ./gpio_advanced
If it gives you error, try other pin.
If it works, let me know. I can also show how to automate it inside shell script/service.
@igorp Thank you for your reply. But I am not sure what you mean with the link you provided because there is no Armbian bug. I wrote to the forum to get help on the topic.
I understand. Just giving you few hints to have better chances of success. There are a lot of technical issues / challenges and very little people that can do something about.
It is valuable and useful that you shared your research but people tend to skip if they don’t see logs from the actual device. If you manage to get this working, you are welcome to integrate it into Armbian. This step is also important as many solutions people find and share are otherwise lost in black hole called forums …
Thank you. I will try through that link too. If it would work in the end, at least I will try to make some kind of tutorial for the button functionality.
As I have understood from this post, in order to add wake-up functionality, we can convert dtb file to dts, modify device tree, and then convert dts to dtb again via device tree compiler.
In Armbian, go to
/boot/dtb/rockchip
Here you can see many dtb files for various devices, in my case:
rk3399-rock-pi-4b.dtb
is used. There is also a generic file rk3399-rock-pi-4.dtb, but it is not being used (I moved it to another location and device was booting, while when I removed file ending with 4b, system stopped working).
As I understood, dts file will be generated based on the dtb file. We can modify
device settings by editing the dts file. After we are done, we can run following command to generate dtb file again:
Next step is to learn what modifications to make on the dts file and find out if any other system modifications will be required for the changes to take effect. Still working on it, let me know if you can find out anything useful.
@jack Could you please help? What should be done in order to wake the system (from shutdown or low power state) by a button press? We are able to put the system into shutdown/low power state with a method mentioned above.
I’m using a Radxa Rock Pi 4 SE board on Debian and I need to have a “Power” button. Have you found a solution to turn off the debian but also to turn it on without having to unplug it with the same button?
Does modifying the device tree work? If so, can you give any other indications on what enabled you to achieve this?
I believe device tree is the correct way to do it, but I am beginner in device tree stuff, and what I tried only gave errors or didn’t have any effect. I was looking for device tree button implementations on other RK3399 devices, and was trying to replicate it.
In the end, I can only turn-off the device and in order to turn it on I have to replug the cable.
I wrote Radxa about this issue, this is their reply:
Power off is possible via GPIO, but power on is not possible because power on is hardware trigger. The user will have to unplug and plug the power cable.
I suggest you switch to ROCK 4C+, which has a hardware on/off switch. You can just use it.
I was just wondering whether you’d made any progress on figuring out the device tree. I’m also in a similar situation wanting to try and get this working to power on a 4b, but also on a 5b. Or is this just not possible at all?
But if it is mandatory to achieve proper button functionality in your project, you can achieve it with an external small microcontroller. The MCU will read GPIOs and Power pins of rock, and will enable/disable power to Rock though a MOSFET.
Draft implementation:
Case 1: Button pressed when Rock is off
After button is pressed, program in MCU can check the power pins of Rock to verify that it is not active. This means that button is intended to turn it on. So, it will send the appropriate signal to the MOSFET control pin, and enable power connection to rock. Since rock automatically boots when powered, you achieve turn-on function.
Case 2: Button pressed when Rock is on.
Rock gets powered off with the method already discussed in previous comments. State of power pin on Rock changes, and triggers interrupt on MCU, which will cut the power through MOSFET.
Just need to ensure which power pins have required behavior on rock(some stay active even when we do sudo shutdown now), and select an MCU which could handle the voltage of these pins as GPIO.