Current version of the OpenAuto Pro is 6.1
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Graceful delayed shutdown with timer and 1 relay
#1
After my Mausberry power supply failed (a common scenario apparently) I needed to find an alternate. 

My solution is based on this video - https://www.youtube.com/watch?v=rknBevexOcU on the Automate Everything channel and utilises a single SPST NC 12V relay and a programmable 12V timer. 


Overview

In short the timer provides power to the RPi and in my case peripherals (e.g. powered USB hub, external BT dongle, external sound card, reverse CAM etc.) when the IGN is on. When the IGN is switched off the timer continues to provide power to the RPi for a configurable amount of time before switching off (e.g. 15 mins). In tandem with this the relay closes when the IGN is switched off and sets a monitored GPIO pin low. A script on the RPi monitors the status of the GPIO pin and ensures that the RPi shuts down before the timer cuts power to the RPi (e.g. 14 minutes).

The advantages of this solution is that it is relatively simple, is straightforward to wire / connect and doesn't take up too much space. The disadvantage is that the timer is relatively expensive at €16 plus shipping (other suitable, less expensive timers may be out there - I didn't search). Also there is a very small chance that the script fails to shut down the RPi before the timer switches off. While idle (IGN off) the timer does consume 0.3 ma.



Setup diagram



Parts list:

Timer - https://www.amazon.com/gp/product/B015Z2...ct_title_1
12v - 5v buck converter - https://www.ebay.com/itm/24V-12V-to-5V-5...3349930955
Powered USB hub (optional) - https://www.amazon.fr/gp/product/B074VZD...le_o05_s01



I would recommend configuring and testing on the bench before installing in the car. This makes troubleshooting (IMO) a lot easier.



1. Detail

When IGN is switched on the timer switches on it's output which powers the 12V - 5V converter (which in turn powers the RPi and in my case an external USB hub - used for BT, sound card, reverse cam and charging phone etc.). 

When IGN is switched off the timer starts it's countdown timer (timer is configurable - e.g. 15 mins), when countdown is complete the timer switches off the output which powers off the 12V - 5V converter which in turn powers off the RPi, USB hub and peripherals. If the IGN is switched back on before the countdown finishes then the timer resets / cancels the countdown timer.

When the timer is off it draws a very small current (0.3 ma in low power mode [the default] when idle). The 10 amp version of the timer apparently draws zero current when idle but is more expensive at 19€.

The timer requires programming before use - see below and / or refer to https://www.youtube.com/watch?v=rknBevexOcU (Automate Everything)

To enable a graceful shutdown of the RPi (i.e. for the RPi to shutdown before the timer) I use a python script (running as a service on the RPi) which monitors the state of a GPIO pin (e.g. GPIO 17). A standard 12V SPST NC relay connected to the ignition controls the state of the monitored GPIO pin.

When the ignition is switched off the GPIO pin is set low by the relay which connects / shorts GND to GPIO 17. The scripts detects this and after a configurable delay initiates a graceful shutdown. To ensure that the RPi shuts down prior to the timer the configurable shutdown delay is less than the shutdown delay configured for the timer (e.g. 14 mins). If the ignition is turned back on the script detects this and no shutdown occurs.

The script and service definition file along with installation instructions are below.



2. Timer programming

Before use the timer must be programmed so that it powers off it's load x (e.g. 15) minutes after power (IGN) is lost.

This involves 

- setting the required shutdown delay (e.g. 15 minutes) on the timer
- setting timer function to #12
- setting timer trigger to #2

Refer to example 11 in the timer cook book / programming guide - http://timers.shop/Timer-Cook-Book_ep_43...#example11 for more detail on how to program the timer (or to the Automate Everything video - https://www.youtube.com/watch?v=rknBevexOcU)

I highly recommend purchasing (or making your own) timer configuration button board to save frustration when programming - http://timers.shop/Timer-configuration-b..._p_18.html.



3. Relay wiring

Pin 86 of the relay is connected to the ignition and pin 85 to ground. 
Pin 30 (COM) is connected to GPIO GND and pin 87A (NC) to the monitored GPIO pin (e.g. GPIO 17). 



4. Timer wiring

POWER (red wire) - connected to an always live +12V
TRIGGER (blue wire) connected to the IGN line 
LOAD (yellow) - the output of the timer - this is connected to the 12V - 5V buck converter (which in turns powers the RPi and USB hub and peripherals)
GROUND (black) - vehicle ground

The green and white programming wires should be shielded / insulated.



Disclaimer: I am neither a developer or automotive electrician - YMMV



5. Python script / service installation

Script

i. Create file /home/pi/power-monitor.py - >touch /home/pi/power-monitor.py
ii. Copy and paste script (belowto /home/pi/power-monitor.py and then save the file - >nano [b][i]/home/pi/power-monitor.py[/i][/b]
iii. Create directory /opt/power-monitor - >sudo mkdir /opt/power-monitor
iv. Copy script to /opt/power-monitor/power-monitor.py >sudo cp /home/pi/power-monitor.py /opt/power-monitor/
v. Set owner - >sudo chown root:root /opt/power-monitor/power-monitor.py
vi. Add execute attribute to script - >sudo chmod +x /opt/power-monitor/power-monitor.py
vii. Set required GPIO pin (PORT) and shutdown delay (SHUTDOWN_DELAY) in script ->sudo nano /opt/power-monitor/power-monitor.py


Service

i. Create file /home/pi/power-monitor.py - >touch /home/pi/power-monitor.service
ii. Copy and paste service definition file (below) to /home/pi/power-monitor.service and then save the file >nano [b][i]/home/pi/power-monitor.service[/i][/b]
iii. Copy service definition file to /etc/systemd/system/power-monitor.service ->sudo cp /home/pi/power-monitor.service /etc/systemd/system/
iv Set owner - >sudo chown root:root /etc/systemd/system/power-monitor.service
v. Install service - >sudo systemctl enable power-monitor.service
vi. Start service - >sudo systemctl start power-monitor.service
vii. Check status of service - > sudo systemctl status power-monitor.service


Testing / debugging 

i. In the script set the DEBUG variable to 1 - >sudo nano /opt/power-monitor/power-monitor.py
ii. Restart the service - >sudo systemctl restart power-monitor.service
iii. Debug output is directed to /var/log/daemon - view with >tail -f /var/log/daemon
iv. When finished set the DEBUG variable in the script back to 0 >sudo nano /opt/power-monitor/power-monitor.py


Service definition file - power-monitor.service

Code:
[Unit]
Description=Script to monitor ignition status
ConditionPathExists=/opt/power-monitor/power-monitor.py
After=multi-user.target

[Service]
Type=simple
ExecStart=/usr/bin/python3 -u /opt/power-monitor/power-monitor.py
Restart=on-failure
StartLimitInterval=60
RestartSec=5
StartLimitBurst=3

[Install]
WantedBy=multi-user.target


Script - power-monitor.py

Code:
#!/usr/bin/python3 -u

import RPi.GPIO as GPIO
import time
import subprocess

DEBUG = 0

# GPIO / BCM 17 - physical pin 11
PORT = 17

# Shutdown delay in seconds
# 14.5 minutes
SHUTDOWN_DELAY = 870

# No. of seconds after ignition returns to cancel shutdown
CANCEL_SHUTDOWN = 5

IGN_STATUS = 1
SHUTDOWN = 0
IGN_OFF_TIME = 0
IGN_OFF_LAST_SEEN = 0
NOW = 0


# specify pin numbering format
GPIO.setmode(GPIO.BCM)

# set pin to input, set pull up resistor so it reads high
GPIO.setup((PORT), GPIO.IN, pull_up_down=GPIO.PUD_UP)


while True:
    
    NOW = time.time()

    # Get the status of the ignition
    IGN_UP = GPIO.input(PORT)

    # Ignition switched off? then set shutdown flag and igntion off time 
    if not IGN_UP and not SHUTDOWN:
        SHUTDOWN = 1
        IGN_OFF_TIME = NOW
        print("Ignition switched off, shutdown flag set!")

    # Increment this counter while ignition is off
    if not IGN_UP and SHUTDOWN:
        IGN_OFF_LAST_SEEN = NOW

    # if igntion is off check if shutdown delay time reached
    if (SHUTDOWN and not IGN_UP and ((NOW - IGN_OFF_TIME) > SHUTDOWN_DELAY)):
        print("Shutdown delay of", SHUTDOWN_DELAY, "seconds reached, shutting down!")
        try:
            STATUS = subprocess.check_output(["shutdown", "-h", "now", "--no-wall"])
        except subprocess.CalledProcessError as shutdowncmd:
            print("Shutdown failed with error code: ", shutdowncmd.returncode)
            break    
    
    # Cancel shutdown if power has been back for CANCEL_SHUTDOWN seconds
    if ((NOW - IGN_OFF_LAST_SEEN) >= CANCEL_SHUTDOWN ) and SHUTDOWN:
        print("Ignition has been back for : ", CANCEL_SHUTDOWN, " seconds - shutdown flag reset")
        SHUTDOWN = 0
        IGN_OFF_TIME = 0
        IGN_OFF_LAST_SEEN = 0


    if DEBUG:
        STATUS = GPIO.input(PORT)
        print("Pin status is: ", STATUS)
        print("IGN_UP is set to: ", IGN_UP)
        print("SHUTDOWN is set to: ", SHUTDOWN)
        if SHUTDOWN:
            print("Igntion off time is: ", IGN_OFF_TIME)
            print("Igntion off last seen time is: ", IGN_OFF_LAST_SEEN)
            print("Current time is : ", NOW)
            print("Elapsed time is : ", (NOW - IGN_OFF_TIME))


    time.sleep(1)

if DEBUG:
    print("Exiting")

GPIO.cleanup()
Reply
#2
Thank you for posting this clear guide! I am hoping to configure the same way and this fills in some of the gaps. This is a similar setup to @Hisma /AutomateEverything, correct? Can anyone elaborate on how this differs from the "three relay solution" floating around the forums and what the advantages/disadvantages of either might be? Thank you.
Reply
#3
This in my opinion is better than my "3 relay solution" because it takes less space.
Maybe the only two disadvantages of this solution is that there is always some current drawn. And that rpi will get power cut when timer ends even if it somehow fails to shutdown, but on the other way this might be good.

In my case this solution is much more expensive, because to get this timer would cost me €16 + €19shipping + €9 inport taxes.
Reply
#4
Yes the timer makes it a more expensive solution. Shipping could be cheaper if purchased via amazon.com?

The timer draws 0.3 ma in low power mode (the default) when idle.

The 10 amp version of the timer apparently draws zero current when idle but is more expensive at 19€.
Reply
#5
Awesome. I had this solution in my car for a long time and it never gave me any issues. This solution is very robust, but it's also slightly more expensive. The benefit with this solution is less parts & less complicated wiring which should lead to higher reliability. The downside is cost and the difficulty in programming the timer itself (but it's not hard if you follow my instructions... just takes some "practice").
Cool to see other implementations of this design.
Reply
#6
(09-17-2019, 02:56 AM)Hisma Wrote:  I had this solution in my car for a long time and it never gave me any issues.  
Thanks for the feedback and confirmation.   If you don't mind me asking, what do you use now? From your post it sounded like you may have switched to some other strategy?  (happy to continue my daily routine of refreshing the AutomateEverything Youtube page to find out).
Reply
#7
(09-19-2019, 01:02 AM)ORIF Wrote:
(09-17-2019, 02:56 AM)Hisma Wrote:  I had this solution in my car for a long time and it never gave me any issues.  
Thanks for the feedback and confirmation.   If you don't mind me asking, what do you use now? From your post it sounded like you may have switched to some other strategy?  (happy to continue my daily routine of refreshing the AutomateEverything Youtube page to find out).

Well unfortunately my work has relocated me to China for the next 1.5-2 years Sad.  So I am living in China now & have no car out here (I still have my car back home sitting in a garage).  That is the reason why I have not had any updates to my channel in a long time.  My goal was to do a step-by-step video on canbus integration, but I ran out of time.  I did get canbus working on a basic level using a pican2, but never had time to integrate it with OAP.  

I honestly don't know when I will have any follow-up videos.  I want to continue doing things, but can't really do anything car-related for a while, which seems to be my most popular content.  I'm looking at getting an ESP8266/32 & some various IO to play around with.  Lots of cool stuff you can do with those.
Reply
#8
Just want to say thanks for this timer find! I am just putting the finishing touches to my install and this I had puzzled over.

I am going to add to your shutdown script with the option to disconnect bluetooth when the car is turned off and then on car power on, connect back to my phone.
Then when I walk away from my car, say to go to the store for 10 minutes, the phone disconnects and reconnects when the car restarts.
Reply
#9
(09-14-2019, 07:19 PM)765GHF Wrote: After my Mausberry power supply failed (a common scenario apparently) I needed to find an alternate. My solution is based on this video - https://www.youtube.com/watch?v=rknBevexOcU on the Automate Everything channel.


To get the same functionality as the Mausberry power supply I used a 12V relay and a 12V timer. 

Timer - http://timers.shop/Multi-Functional-3V-1..._p_12.html 
12v - 5v buck converter - https://www.ebay.com/itm/24V-12V-to-5V-5...3349930955

Setup diagram


The timer is connected directly to the battery as well to the IGN line. A 12V - 5V converter is connected to the output of the timer (the converter has 4 USB A outputs). 

When IGN is on the timer switches on it's output which powers the 12V - 5V converter (which in turn powers the RPi and an external USB hub - used for BT, sound card, reverse cam and charging phone etc.). 

When IGN goes off the timer starts it's countdown timer (timer is configurable - e.g. 15 mins), when countdown is complete it switches off the output which powers off the 12V - 5V converter which in turn powers off the RPi and USB hub. When the timer is off it draws a very small current.

The timer requires programming before use - see below and / or refer to https://www.youtube.com/watch?v=rknBevexOcU (Automate Everything)



To enable a graceful shutdown of the RPi (i.e. for the RPi to shutdown before the timer) I use a python script (running as a service on the RPi) which monitors the state of a GPIO pin (e.g. GPIO 17). A standard 12V SPST NC relay connected to the ignition controls the state of the monitored GPIO pin.

Pin 86 of the relay is connected to the ignition and pin 85 to ground. 
Pin 30 (COM) is connected to GPIO GND and pin 87A (NC) to the monitored GPIO pin (e.g. GPIO 17). 

When the ignition is switched off the GPIO pin is set low by the relay which connects / shorts GND to GPIO 17. The scripts detects this and after a configurable period initiates a graceful shutdown. If the ignition is turned back on the script detects this and no shutdown occurs.

The script is below.



Timer programming - set required shutdown delay, set function to #12 and set trigger to #2 - refer http://timers.shop/Timer-Cook-Book_ep_43...#example12 

I highly recommend purchasing the timer configuration button board to save frustration when programming - http://timers.shop/Timer-configuration-b..._p_18.html



Disclaimer: I am neither a developer or automotive electrician - YMMV



Service definition file - power-monitor.service

Code:
[Unit]
Description=Script to monitor ignition status
ConditionPathExists=/opt/power-monitor/power-monitor.py
After=multi-user.target

[Service]
Type=simple
ExecStart=/usr/bin/python3 -u /opt/power-monitor/power-monitor.py
Restart=on-failure
StartLimitInterval=60
RestartSec=5
StartLimitBurst=3

[Install]
WantedBy=multi-user.target


Script - power-monitor.py

Code:
#!/usr/bin/python3 -u

import RPi.GPIO as GPIO
import time
import subprocess

DEBUG = 0

# GPIO / BCM 17 - physical pin 11
PORT = 17

# Shutdown delay in seconds
# 14.5 minutes
SHUTDOWN_DELAY = 870

# No. of seconds after ignition returns to cancel shutdown
CANCEL_SHUTDOWN = 5

IGN_STATUS = 1
SHUTDOWN = 0
IGN_OFF_TIME = 0
IGN_OFF_LAST_SEEN = 0
NOW = 0


# specify pin numbering format
GPIO.setmode(GPIO.BCM)

# set pin to input, set pull up resistor so it reads high
GPIO.setup((PORT), GPIO.IN, pull_up_down=GPIO.PUD_UP)


while True:
    
    NOW = time.time()

    # Get the status of the ignition
    IGN_UP = GPIO.input(PORT)

    # Ignition switched off? then set shutdown flag and igntion off time 
    if not IGN_UP and not SHUTDOWN:
        SHUTDOWN = 1
        IGN_OFF_TIME = NOW
        print("Ignition switched off, shutdown flag set!")

    # Increment this counter while ignition is off
    if not IGN_UP and SHUTDOWN:
        IGN_OFF_LAST_SEEN = NOW

    # if igntion is off check if shutdown delay time reached
    if (SHUTDOWN and not IGN_UP and ((NOW - IGN_OFF_TIME) > SHUTDOWN_DELAY)):
        print("Shutdown delay of", SHUTDOWN_DELAY, "seconds reached, shutting down!")
        try:
            STATUS = subprocess.check_output(["shutdown", "-h", "now", "--no-wall"])
        except subprocess.CalledProcessError as shutdowncmd:
            print("Shutdown failed with error code: ", shutdowncmd.returncode)
            break    
    
    # Cancel shutdown if power has been back for CANCEL_SHUTDOWN seconds
    if ((NOW - IGN_OFF_LAST_SEEN) >= CANCEL_SHUTDOWN ) and SHUTDOWN:
        print("Ignition has been back for : ", CANCEL_SHUTDOWN, " seconds - shutdown flag reset")
        SHUTDOWN = 0
        IGN_OFF_TIME = 0
        IGN_OFF_LAST_SEEN = 0


    if DEBUG:
        STATUS = GPIO.input(PORT)
        print("Pin status is: ", STATUS)
        print("IGN_UP is set to: ", IGN_UP)
        print("SHUTDOWN is set to: ", SHUTDOWN)
        if SHUTDOWN:
            print("Igntion off time is: ", IGN_OFF_TIME)
            print("Igntion off last seen time is: ", IGN_OFF_LAST_SEEN)
            print("Current time is : ", NOW)
            print("Elapsed time is : ", (NOW - IGN_OFF_TIME))


    time.sleep(1)

if DEBUG:
    print("Exiting")

GPIO.cleanup()


Script and service install

Copy and paste service definition file (above) to /home/pi/power-monitor.service
Copy and paste script (above) to /home/pi/power-monitor.py

Create directory /opt/power-monitor - >sudo mkdir /opt/power-monitor
Copy script to /opt/power-monitor/power-monitor.py >sudo cp /home/pi/power-monitor.py /opt/power-monitor/
Set owner - >sudo chown root:root /opt/power-monitor/power-monitor.py
Add execute attribute to script - >sudo chmod +x /opt/power-monitor/power-monitor.py
Set required GPIO pin (PORT) and shutdown delay (SHUTDOWN_DELAY) in script ->sudo nano /opt/power-monitor/power-monitor.py


Service
Copy service definition file to /etc/systemd/system/power-monitor.service ->sudo cp /home/pi/power-monitor.service /etc/systemd/system/
Set owner - >sudo chown root:root /etc/systemd/system/power-monitor.service
Install service - >sudo systemctl enable power-monitor.service
Start service - >sudo systemctl start power-monitor.service
i have the exact setup... although i built the programming button myself... definitely recommend the timer relay...makes life easy
Reply
#10
(09-29-2019, 11:43 AM)crizco Wrote: Just want to say thanks for this timer find! I am just putting the finishing touches to my install and this I had puzzled over.

I am going to add to your shutdown script with the option to disconnect bluetooth when the car is turned off and then on car power on, connect back to my phone.
Then when I walk away from my car, say to go to the store for 10 minutes, the phone disconnects and reconnects when the car restarts.

Were you able to accomplish this? And if so, do you mind sharing?
Reply


Forum Jump:


Users browsing this thread: 2 Guest(s)