<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.geekworm.com/index.php?action=history&amp;feed=atom&amp;title=CommentStreams%3AC4473590b5c6d8cc05cca487c77ac93d</id>
	<title>CommentStreams:C4473590b5c6d8cc05cca487c77ac93d - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.geekworm.com/index.php?action=history&amp;feed=atom&amp;title=CommentStreams%3AC4473590b5c6d8cc05cca487c77ac93d"/>
	<link rel="alternate" type="text/html" href="https://wiki.geekworm.com/index.php?title=CommentStreams:C4473590b5c6d8cc05cca487c77ac93d&amp;action=history"/>
	<updated>2026-07-27T17:37:26Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.43.8</generator>
	<entry>
		<id>https://wiki.geekworm.com/index.php?title=CommentStreams:C4473590b5c6d8cc05cca487c77ac93d&amp;diff=32963&amp;oldid=prev</id>
		<title>37.19.221.52: Migrated comment #2952</title>
		<link rel="alternate" type="text/html" href="https://wiki.geekworm.com/index.php?title=CommentStreams:C4473590b5c6d8cc05cca487c77ac93d&amp;diff=32963&amp;oldid=prev"/>
		<updated>2022-12-26T00:44:03Z</updated>

		<summary type="html">&lt;p&gt;Migrated comment #2952&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;As others have mentioned, I was finding that the provided scripts were immediately shutting down the x728 but were not doing a safe shutdown of the raspberry pi.  The power was immediately being cut to the raspberry pi resulting in a crash.  &lt;br /&gt;
&lt;br /&gt;
See the last command for an example&lt;br /&gt;
&lt;br /&gt;
pi@raspberrypi:~ $ last&lt;br /&gt;
...&lt;br /&gt;
reboot   system boot  5.15.76-v7l+     Wed Dec 31 18:00 - 10:22 (19348+16:22)&lt;br /&gt;
pi       pts/0        192.168.68.70    Thu Dec 22 09:48 - crash (-19348+15:48)&lt;br /&gt;
pi       tty7         :0               Thu Dec 22 09:47 - crash (-19348+15:47)&lt;br /&gt;
pi       tty1                          Thu Dec 22 09:47 - crash (-19348+15:47)&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
I created a new script to do a safe shutdown and while I was at it, I added functionality and made the script configurable so you can choose the behavior you want for a given system.  I also added a testing mode that provides more output, doesn&amp;#039;t do a shutdown and cleanly exits the GPIO settings for the next test run.&lt;br /&gt;
&lt;br /&gt;
I have created a bin directory in the pi home for testing.  The script can be setup in the root crontab as follows, which will create a log file in /home/pi/log.&lt;br /&gt;
&lt;br /&gt;
@reboot python -u /home/pi/bin/auto_shutdown.py &amp;gt;&amp;gt; /home/pi/log/auto_shutdown.log 2&amp;gt;&amp;amp;1&lt;br /&gt;
&lt;br /&gt;
You can then tail the logfile to see the current status.&lt;br /&gt;
&lt;br /&gt;
pi@raspberrypi:~/log $ tail -20f auto_shutdown.log&lt;br /&gt;
******************************************&lt;br /&gt;
12/24/2022, 21:38:02 : System Startup&lt;br /&gt;
12/24/2022, 21:38:02 : AC Power GOOD&lt;br /&gt;
12/24/2022, 21:38:02 : Battery Capacity Good (96.23%)&lt;br /&gt;
12/24/2022, 21:38:02 : Battery Voltage Good (4.22V)&lt;br /&gt;
12/25/2022, 09:26:47 : AC Power Lost - Shutdown in 15  minutes&lt;br /&gt;
12/25/2022, 09:28:47 : AC Power Restored - Shutdown cancelled&lt;br /&gt;
12/25/2022, 09:56:09 : AC Power Lost - Shutdown in 15  minutes&lt;br /&gt;
12/25/2022, 10:11:00 : Shutdown in progress due to AC power loss&lt;br /&gt;
******************************************&lt;br /&gt;
12/25/2022, 10:16:25 : System Startup&lt;br /&gt;
12/25/2022, 10:16:25 : AC Power GOOD&lt;br /&gt;
12/25/2022, 10:16:25 : Battery Capacity Good (98.77%)&lt;br /&gt;
12/25/2022, 10:16:25 : Battery Voltage Good (4.22V)&lt;br /&gt;
&lt;br /&gt;
As you can see, if power is restored prior to the automatic shutdown, it will return to it&amp;#039;s normal state.  This is to prevent unneeded shutdowns in the event the power is cycling as it is being restored from the grid.&lt;br /&gt;
&lt;br /&gt;
Here is the last command showing good shutdowns with this script.&lt;br /&gt;
&lt;br /&gt;
pi@raspberrypi:~ $ last&lt;br /&gt;
...&lt;br /&gt;
reboot   system boot  5.15.76-v7l+     Wed Dec 31 18:00 - 21:36 (19351+03:36)&lt;br /&gt;
pi       pts/0        192.168.68.70    Sat Dec 24 21:08 - 21:11  (00:03)&lt;br /&gt;
pi       tty7         :0               Sat Dec 24 21:07 - 21:11  (00:04)&lt;br /&gt;
pi       tty1                          Sat Dec 24 21:07 - down   (00:04)&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
I recommend using testing mode from the command line and then once you have all the configurations the way you want them, turn off testing mode and schedule in crontab.  Remember, testing mode will provide mush more output but will not trigger a shutdown.&lt;br /&gt;
&lt;br /&gt;
Here is the script.  Please use it at your own risk.  You will want to set the configurations appropriate for your raspberry pi purpose.  I am using all three triggers because I want a clean shutdown after 15 minutes or if there is an issue with the batteries so I&amp;#039;m triggering well before the batteries are drained.  I hope some find this helpful.&lt;br /&gt;
&lt;br /&gt;
pi@raspberrypi:~/bin $ cat auto_shutdown.py&lt;br /&gt;
#!/usr/bin/env python&lt;br /&gt;
import RPi.GPIO as GPIO&lt;br /&gt;
import time&lt;br /&gt;
import os&lt;br /&gt;
import datetime&lt;br /&gt;
import struct&lt;br /&gt;
import smbus&lt;br /&gt;
import sys&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
####################################&lt;br /&gt;
# Start Config&lt;br /&gt;
####################################&lt;br /&gt;
&lt;br /&gt;
SHUTDOWN_TRIGGER = &amp;quot;All&amp;quot;            # (AC Power,Capacity,Voltage,All) - determines what settings will trigger a shutdown.&lt;br /&gt;
AC_LOSS_WAIT_MINUTES = 15           # Number of minutes after power loss before shutdown is issued&lt;br /&gt;
CAPACITY_THRESHOLD = 50             # Shutdown will occur when capacity drops below the stated percentage&lt;br /&gt;
CAPACITY_STATUS_LOW = 20            # Low capacity warning below this level&lt;br /&gt;
VOLTAGE_THRESHOLD = 3.70            # Shutdown will occur when voltage drops below the stated percentage&lt;br /&gt;
VOLTAGE_STATUS_LOW = 3.50           # Low voltage warning below this level&lt;br /&gt;
TEST_MODE = &amp;quot;N&amp;quot;                     # (Y,N) - Will show extra output and will not perform shutdown when TEST_MODE = &amp;quot;Y&amp;quot;, normal operation TEST_MODE = &amp;quot;N&amp;quot;&lt;br /&gt;
BUZZER_ON = &amp;quot;N&amp;quot;                     # (Y,N) - BUZZER_ON = &amp;quot;Y&amp;quot; and buzzer will beep when power is initially lost and right before shutdown&lt;br /&gt;
BUZZER_SECONDS = 0.5                # Number of seconds the buzzer will sound&lt;br /&gt;
&lt;br /&gt;
####################################&lt;br /&gt;
# End Config&lt;br /&gt;
####################################&lt;br /&gt;
&lt;br /&gt;
WAIT_SECONDS = AC_LOSS_WAIT_MINUTES * 6&lt;br /&gt;
WAIT_STR = str(AC_LOSS_WAIT_MINUTES)&lt;br /&gt;
&lt;br /&gt;
GPIO_PORT = 26&lt;br /&gt;
I2C_ADDR = 0x36&lt;br /&gt;
&lt;br /&gt;
GPIO.setmode(GPIO.BCM)&lt;br /&gt;
GPIO.setup(GPIO_PORT, GPIO.OUT)&lt;br /&gt;
&lt;br /&gt;
PLD_PIN = 6&lt;br /&gt;
BUZZER_PIN = 20&lt;br /&gt;
GPIO.setwarnings(False)&lt;br /&gt;
GPIO.setmode(GPIO.BCM)&lt;br /&gt;
GPIO.setup(PLD_PIN, GPIO.IN)&lt;br /&gt;
GPIO.setup(BUZZER_PIN, GPIO.OUT)&lt;br /&gt;
GPIO.output(BUZZER_PIN, 0)&lt;br /&gt;
POWER_LOST_SEC = 0&lt;br /&gt;
&lt;br /&gt;
def soundBuzzer(BUZZER_ON,BUZZER_SECONDS,BUZZER_PIN):&lt;br /&gt;
    if ( BUZZER_ON == &amp;quot;Y&amp;quot; ):&lt;br /&gt;
        GPIO.output(BUZZER_PIN, 1)&lt;br /&gt;
        time.sleep(BUZZER_SECONDS)&lt;br /&gt;
        GPIO.output(BUZZER_PIN, 0)&lt;br /&gt;
&lt;br /&gt;
def acPower(PLD_PIN):&lt;br /&gt;
&lt;br /&gt;
    AC_STATUS = &amp;quot;GOOD&amp;quot;&lt;br /&gt;
    i = GPIO.input(PLD_PIN)&lt;br /&gt;
    if ( i == 0 ):&lt;br /&gt;
        AC_STATUS = &amp;quot;GOOD&amp;quot;&lt;br /&gt;
    elif ( i == 1 ):&lt;br /&gt;
        AC_STATUS = &amp;quot;LOST&amp;quot;&lt;br /&gt;
    return AC_STATUS&lt;br /&gt;
&lt;br /&gt;
def readVoltage(bus,VOLTAGE_STATUS_LOW):&lt;br /&gt;
&lt;br /&gt;
    address = I2C_ADDR&lt;br /&gt;
    read = bus.read_word_data(address, 2)&lt;br /&gt;
    swapped = struct.unpack(&amp;quot;&amp;lt;H&amp;quot;, struct.pack(&amp;quot;&amp;gt;H&amp;quot;, read))[0]&lt;br /&gt;
    VOLTAGE = swapped * 1.25 /1000/16&lt;br /&gt;
    VOLTAGE_STATUS = &amp;quot;Good&amp;quot;&lt;br /&gt;
    if ( VOLTAGE &amp;lt;= VOLTAGE_STATUS_LOW ):&lt;br /&gt;
        VOLTAGE_STATUS = &amp;quot;Low&amp;quot;&lt;br /&gt;
    return VOLTAGE,VOLTAGE_STATUS&lt;br /&gt;
&lt;br /&gt;
def readCapacity(bus,CAPACITY_STATUS_LOW):&lt;br /&gt;
&lt;br /&gt;
    address = I2C_ADDR&lt;br /&gt;
    read = bus.read_word_data(address, 4)&lt;br /&gt;
    swapped = struct.unpack(&amp;quot;&amp;lt;H&amp;quot;, struct.pack(&amp;quot;&amp;gt;H&amp;quot;, read))[0]&lt;br /&gt;
    CAPACITY = swapped/256&lt;br /&gt;
    CAPACITY_STATUS = &amp;quot;Good&amp;quot;&lt;br /&gt;
    if ( CAPACITY &amp;gt;= 100 ):&lt;br /&gt;
        CAPACITY_STATUS = &amp;quot;Full&amp;quot;&lt;br /&gt;
    elif ( CAPACITY &amp;lt;= CAPACITY_STATUS_LOW ):&lt;br /&gt;
        CAPACITY_STATUS = &amp;quot;Low&amp;quot;&lt;br /&gt;
    return CAPACITY,CAPACITY_STATUS&lt;br /&gt;
&lt;br /&gt;
def safeShutdown(GPIO_PORT):&lt;br /&gt;
&lt;br /&gt;
    GPIO.output(GPIO_PORT, GPIO.HIGH)&lt;br /&gt;
    os.system(&amp;#039;sudo shutdown -h now&amp;#039;)&lt;br /&gt;
    time.sleep(3)&lt;br /&gt;
    GPIO.output(GPIO_PORT, GPIO.LOW)&lt;br /&gt;
&lt;br /&gt;
bus = smbus.SMBus(1) # 0 = /dev/i2c-0 (port I2C0), 1 = /dev/i2c-1 (port I2C1)&lt;br /&gt;
&lt;br /&gt;
now = datetime.datetime.now()&lt;br /&gt;
date_time = now.strftime(&amp;quot;%m/%d/%Y, %H:%M:%S&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
AC_STATUS = acPower(PLD_PIN)&lt;br /&gt;
VOLTAGE,VOLTAGE_STATUS = readVoltage(bus,VOLTAGE_STATUS_LOW)&lt;br /&gt;
CAPACITY,CAPACITY_STATUS = readCapacity(bus,CAPACITY_STATUS_LOW)&lt;br /&gt;
&lt;br /&gt;
print (&amp;quot;******************************************&amp;quot;)&lt;br /&gt;
print(date_time + &amp;quot; : System Startup&amp;quot;)&lt;br /&gt;
print(date_time + &amp;quot; : AC Power &amp;quot; + AC_STATUS)&lt;br /&gt;
print(date_time + &amp;quot; : Battery Capacity &amp;quot; + CAPACITY_STATUS + &amp;quot; (&amp;quot; + str(round(CAPACITY,2)) + &amp;quot;%)&amp;quot; )&lt;br /&gt;
print(date_time + &amp;quot; : Battery Voltage &amp;quot; + VOLTAGE_STATUS + &amp;quot; (&amp;quot; + str(round(VOLTAGE,2)) + &amp;quot;V)&amp;quot; )&lt;br /&gt;
if ( TEST_MODE == &amp;quot;Y&amp;quot; ):&lt;br /&gt;
    print(date_time + &amp;quot; : Started in Test Mode, No actual shutdown will occur, program will exit after shutdown triggered.&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
while True:&lt;br /&gt;
&lt;br /&gt;
#    print (&amp;quot;******************************************&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    now = datetime.datetime.now()&lt;br /&gt;
    date_time = now.strftime(&amp;quot;%m/%d/%Y, %H:%M:%S&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    AC_STATUS = acPower(PLD_PIN)&lt;br /&gt;
    VOLTAGE,VOLTAGE_STATUS = readVoltage(bus,VOLTAGE_STATUS_LOW)&lt;br /&gt;
    CAPACITY,CAPACITY_STATUS = readCapacity(bus,CAPACITY_STATUS_LOW)&lt;br /&gt;
&lt;br /&gt;
    if ( SHUTDOWN_TRIGGER == &amp;quot;AC Power&amp;quot; or SHUTDOWN_TRIGGER == &amp;quot;All&amp;quot; ):&lt;br /&gt;
        if ( AC_STATUS == &amp;quot;GOOD&amp;quot; ):&lt;br /&gt;
            if ( POWER_LOST_SEC &amp;gt; 0 ):&lt;br /&gt;
                print(date_time + &amp;quot; : AC Power Restored - Shutdown cancelled&amp;quot;)&lt;br /&gt;
                POWER_LOST_SEC = 0&lt;br /&gt;
            else:&lt;br /&gt;
                if ( TEST_MODE == &amp;quot;Y&amp;quot; ):&lt;br /&gt;
                    print(date_time + &amp;quot; : AC Power &amp;quot; + AC_STATUS)&lt;br /&gt;
        elif ( AC_STATUS == &amp;quot;LOST&amp;quot; ):&lt;br /&gt;
            if ( TEST_MODE == &amp;quot;Y&amp;quot; ):&lt;br /&gt;
                print(date_time + &amp;quot; : AC Power &amp;quot; + AC_STATUS)&lt;br /&gt;
            POWER_LOST_SEC += 1&lt;br /&gt;
            if ( POWER_LOST_SEC == 1 ):&lt;br /&gt;
                print(date_time + &amp;quot; : AC Power Lost - Shutdown in &amp;quot; + str(AC_LOSS_WAIT_MINUTES) + &amp;quot;  minutes&amp;quot;)&lt;br /&gt;
                soundBuzzer(BUZZER_ON,BUZZER_SECONDS,BUZZER_PIN)&lt;br /&gt;
            if ( POWER_LOST_SEC &amp;gt;= WAIT_SECONDS ):&lt;br /&gt;
                print(date_time + &amp;quot; : Shutdown in progress due to AC power loss&amp;quot;)&lt;br /&gt;
                soundBuzzer(BUZZER_ON,BUZZER_SECONDS,BUZZER_PIN)&lt;br /&gt;
                if ( TEST_MODE != &amp;quot;Y&amp;quot; ):&lt;br /&gt;
                    safeShutdown(GPIO_PORT)&lt;br /&gt;
                else:&lt;br /&gt;
                    print(date_time + &amp;quot; : Started in Test Mode, No actual shutdown will occur, program will exit.&amp;quot;)&lt;br /&gt;
                    break&lt;br /&gt;
&lt;br /&gt;
    if ( SHUTDOWN_TRIGGER == &amp;quot;Capacity&amp;quot; or SHUTDOWN_TRIGGER == &amp;quot;All&amp;quot; ):&lt;br /&gt;
        if ( CAPACITY &amp;gt; CAPACITY_THRESHOLD ):&lt;br /&gt;
            if ( TEST_MODE == &amp;quot;Y&amp;quot; ):&lt;br /&gt;
                print(date_time + &amp;quot; : Battery Capacity &amp;quot; + CAPACITY_STATUS + &amp;quot; (&amp;quot; + str(round(CAPACITY,2)) + &amp;quot;%)&amp;quot; )&lt;br /&gt;
        elif ( CAPACITY &amp;lt;= CAPACITY_THRESHOLD ):&lt;br /&gt;
            print(date_time + &amp;quot; : Battery Capacity &amp;quot; + CAPACITY_STATUS + &amp;quot; (&amp;quot; + str(round(CAPACITY,2)) + &amp;quot;%)&amp;quot; )&lt;br /&gt;
            print(date_time + &amp;quot; : Shutdown in progress due to battery Capacity below &amp;quot; + str(CAPACITY_THRESHOLD) + &amp;quot;% threshold&amp;quot;)&lt;br /&gt;
            soundBuzzer(BUZZER_ON,BUZZER_SECONDS,BUZZER_PIN)&lt;br /&gt;
            if ( TEST_MODE != &amp;quot;Y&amp;quot; ):&lt;br /&gt;
                safeShutdown(GPIO_PORT)&lt;br /&gt;
            else:&lt;br /&gt;
                print(date_time + &amp;quot; : Started in Test Mode, No actual shutdown will occur, program will exit.&amp;quot;)&lt;br /&gt;
                break&lt;br /&gt;
&lt;br /&gt;
    if ( SHUTDOWN_TRIGGER == &amp;quot;Voltage&amp;quot; or SHUTDOWN_TRIGGER == &amp;quot;All&amp;quot; ):&lt;br /&gt;
        if ( VOLTAGE &amp;gt; VOLTAGE_THRESHOLD ):&lt;br /&gt;
            if ( TEST_MODE == &amp;quot;Y&amp;quot; ):&lt;br /&gt;
                print(date_time + &amp;quot; : Battery Voltage &amp;quot; + VOLTAGE_STATUS + &amp;quot; (&amp;quot; + str(round(VOLTAGE,2)) + &amp;quot;V)&amp;quot; )&lt;br /&gt;
        elif ( VOLTAGE &amp;lt;= VOLTAGE_THRESHOLD ):&lt;br /&gt;
            print(date_time + &amp;quot; : Battery Voltage &amp;quot; + VOLTAGE_STATUS + &amp;quot; (&amp;quot; + str(round(VOLTAGE,2)) + &amp;quot;V)&amp;quot; )&lt;br /&gt;
            print(date_time + &amp;quot; : Shutdown in progress due to battery Voltage below &amp;quot; + str(VOLTAGE_THRESHOLD) + &amp;quot;V threshold&amp;quot;)&lt;br /&gt;
            soundBuzzer(BUZZER_ON,BUZZER_SECONDS,BUZZER_PIN)&lt;br /&gt;
            if ( TEST_MODE != &amp;quot;Y&amp;quot; ):&lt;br /&gt;
                safeShutdown(GPIO_PORT)&lt;br /&gt;
            else:&lt;br /&gt;
                print(date_time + &amp;quot; : Started in Test Mode, No actual shutdown will occur, program will exit.&amp;quot;)&lt;br /&gt;
                break&lt;br /&gt;
&lt;br /&gt;
    time.sleep(10)&lt;br /&gt;
GPIO.cleanup()&amp;lt;!-- migrated from Comments; original IP: 37.19.221.52 --&amp;gt;&lt;/div&gt;</summary>
		<author><name>37.19.221.52</name></author>
	</entry>
</feed>