drohl
Posts: 4
Joined: Sat Feb 21, 2015 5:16 pm

Restarting crashed python script (or preventing crash)

Thu Apr 23, 2015 10:47 pm

I have a script that uses 16 GPIO pins as inputs and 16 pins of an MCP23017 chip as outputs. Users can press a button, and each button's toggle function will alternate turning its light on or off. After 30 seconds of inactivity, the outputs all turn off. This much is working.

However, on occasion (sometimes with large amounts of button presses, other times less-predictably), the script will become unresponsive. So I created a restart_program() function which kicks everything off again at the end of the 30-second limit. This way, if things freeze, all will be well 30 seconds later. That worked fine for a couple of days, but now I've been getting this error after any range of 5-75 minutes of the script running:

Code: Select all

RuntimeError: Failed to add edge detection
And the script crashes out, right back to the command prompt in the terminal.

Is there something I can do to re-launch the script if it crashes? Or, even better, how do I keep the script from crashing?

Code: Select all

import sys
import os
import RPi.GPIO as GPIO
from Adafruit_MCP230xx import *
from time import sleep
from datetime import datetime

print 'Program running at'+str(datetime.now())

#Configuration
SWITCH1=40
SWITCH2=38
SWITCH3=36
SWITCH4=32
SWITCH5=22
SWITCH6=18
SWITCH7=16
SWITCH8=12
SWITCH9=7
SWITCH10=11
SWITCH11=13
SWITCH12=15
SWITCH13=29
SWITCH14=31
SWITCH15=33
SWITCH16=35
OnTimeInSeconds=30

mcp = Adafruit_MCP230XX(address = 0x20, num_gpios = 16) # MCP23017

#End Configuration

Counter=0
GPIO.setmode(GPIO.BOARD)
GPIO.setwarnings(False)

GPIO.setup(SWITCH1, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(SWITCH2, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(SWITCH3, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(SWITCH4, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(SWITCH5, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(SWITCH6, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(SWITCH7, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(SWITCH8, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(SWITCH9, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(SWITCH10, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(SWITCH11, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(SWITCH12, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(SWITCH13, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(SWITCH14, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(SWITCH15, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(SWITCH16, GPIO.IN, pull_up_down=GPIO.PUD_UP)

# Set MCP pins 0-15 to output (you can set pins 0..15 this way)
mcp.config(0, mcp.OUTPUT)
mcp.config(1, mcp.OUTPUT)
mcp.config(2, mcp.OUTPUT)
mcp.config(3, mcp.OUTPUT)
mcp.config(4, mcp.OUTPUT)
mcp.config(5, mcp.OUTPUT)
mcp.config(6, mcp.OUTPUT)
mcp.config(7, mcp.OUTPUT)
mcp.config(8, mcp.OUTPUT)
mcp.config(9, mcp.OUTPUT)
mcp.config(10, mcp.OUTPUT)
mcp.config(11, mcp.OUTPUT)
mcp.config(12, mcp.OUTPUT)
mcp.config(13, mcp.OUTPUT)
mcp.config(14, mcp.OUTPUT)
mcp.config(15, mcp.OUTPUT)

''' For reference, the MCP output pins are connected to the LEDs as follows:
    [ 0] [ 1] [ 2] [ 3]
    [ 4] [ 5] [ 6] [ 7]
    [ 8] [ 9] [10] [11]
    [12] [13] [14] [15]
'''

mcp.output(0, 0)
mcp.output(6, 0)
mcp.output(9, 0)
mcp.output(15, 0)

state1=0
state2=0
state3=0
state4=0
state5=0
state6=0
state7=0
state8=0
state9=0
state10=0
state11=0
state12=0
state13=0
state14=0
state15=0
state16=0

def restart_program():
    python = sys.executable
    os.execl(python, python, * sys.argv)

def Tick():
    global Counter
    if (Counter<OnTimeInSeconds-1):
        Counter+=1
    else:
        global state1
        global state2
        global state3
        global state4
        global state5
        global state6
        global state7
        global state8
        global state9
        global state10
        global state11
        global state12
        global state13
        global state14
        global state15
        global state16
        mcp.output(0, 0)
        mcp.output(1, 0)
        mcp.output(2, 0)
        mcp.output(3, 0)
        mcp.output(4, 0)
        mcp.output(5, 0)
        mcp.output(6, 0)
        mcp.output(7, 0)
        mcp.output(8, 0)
        mcp.output(9, 0)
        mcp.output(10, 0)
        mcp.output(11, 0)
        mcp.output(12, 0)
        mcp.output(13, 0)
        mcp.output(14, 0)
        mcp.output(15, 0)
        state1=0
        state2=0
        state3=0
        state4=0
        state5=0
        state6=0
        state7=0
        state8=0
        state9=0
        state10=0
        state11=0
        state12=0
        state13=0
        state14=0
        state15=0
        state16=0
#        GPIO.cleanup()
        restart_program()

def Cleanup():
    GPIO.cleanup()
    mcp.output(0,0)
    mcp.output(0, 0)
    mcp.output(1, 0)
    mcp.output(2, 0)
    mcp.output(3, 0)
    mcp.output(4, 0)
    mcp.output(5, 0)
    mcp.output(6, 0)
    mcp.output(7, 0)
    mcp.output(8, 0)
    mcp.output(9, 0)
    mcp.output(10, 0)
    mcp.output(11, 0)
    mcp.output(12, 0)
    mcp.output(13, 0)
    mcp.output(14, 0)
    mcp.output(15, 0)

def Mainloop():
    while True:
        sleep(1)
        Tick()
        print Counter

def Toggle1(Channel):
    global state1
    global Counter
    Counter=0
    if state1 == 0:
        mcp.output(0, 1)
        state1 = 1
        print('LED 1 On')
    else:
        mcp.output(0, 0)
        state1 = 0
        print ('LED 1 Off')

def Toggle2(Channel):
    global state2
    global Counter
    Counter=0
    if state2 == 0:
        mcp.output(1, 1)
        state2 = 1
        print('LED 2 On')
    else:
        mcp.output(1, 0)
        state2 = 0
        print ('LED 2 Off')

def Toggle3(Channel):
    global state3
    global Counter
    Counter=0
    if state3 == 0:
        mcp.output(2, 1)
        state3 = 1
        print('LED 3 On')
    else:
        mcp.output(2, 0)
        state3 = 0
        print ('LED 3 Off')
        
def Toggle4(Channel):
    global state4
    global Counter
    Counter=0
    if state4 == 0:
        mcp.output(3, 1)
        state4 = 1
        print('LED 4 On')
    else:
        mcp.output(3, 0)
        state4 = 0
        print ('LED 4 Off')

def Toggle5(Channel):
    global state5
    global Counter
    Counter=0
    if state5 == 0:
        mcp.output(4, 1)
        state5 = 1
        print('LED 5 On')
    else:
        mcp.output(4, 0)
        state5 = 0
        print ('LED 5 Off')

def Toggle6(Channel):
    global state6
    global Counter
    Counter=0
    if state6 == 0:
        mcp.output(5, 1)
        state6 = 1
        print('LED 6 On')
    else:
        mcp.output(5, 0)
        state6 = 0
        print ('LED 6 Off')

def Toggle7(Channel):
    global state7
    global Counter
    Counter=0
    if state7 == 0:
        mcp.output(6, 1)
        state7 = 1
        print('LED 7 On')
    else:
        mcp.output(6, 0)
        state7 = 0
        print ('LED 7 Off')

def Toggle8(Channel):
    global state8
    global Counter
    Counter=0
    if state8 == 0:
        mcp.output(7, 1)
        state8 = 1
        print('LED 8 On')
    else:
        mcp.output(7, 0)
        state8 = 0
        print ('LED 8 Off')

def Toggle9(Channel):
    global state9
    global Counter
    Counter=0
    if state9 == 0:
        mcp.output(8, 1)
        state9 = 1
        print('LED 9 On')
    else:
        mcp.output(8, 0)
        state9 = 0
        print ('LED 9 Off')

def Toggle10(Channel):
    global state10
    global Counter
    Counter=0
    if state10 == 0:
        mcp.output(9, 1)
        state10 = 1
        print('LED 10 On')
    else:
        mcp.output(9, 0)
        state10 = 0
        print ('LED 10 Off')

def Toggle11(Channel):
    global state11
    global Counter
    Counter=0
    if state11 == 0:
        mcp.output(10, 1)
        state11 = 1
        print('LED 11 On')
    else:
        mcp.output(10, 0)
        state11 = 0
        print ('LED 11 Off')

def Toggle12(Channel):
    global state12
    global Counter
    Counter=0
    if state12 == 0:
        mcp.output(11, 1)
        state12 = 1
        print('LED 12 On')
    else:
        mcp.output(11, 0)
        state12 = 0
        print ('LED 12 Off')

def Toggle13(Channel):
    global state13
    global Counter
    Counter=0
    if state13 == 0:
        mcp.output(12, 1)
        state13 = 1
        print('LED 13 On')
    else:
        mcp.output(12, 0)
        state13 = 0
        print ('LED 13 Off')
        
def Toggle14(Channel):
    global state14
    global Counter
    Counter=0
    if state14 == 0:
        mcp.output(13, 1)
        state14 = 1
        print('LED 14 On')
    else:
        mcp.output(13, 0)
        state14 = 0
        print ('LED 14 Off')

def Toggle15(Channel):
    global state15
    global Counter
    Counter=0
    if state15 == 0:
        mcp.output(14, 1)
        state15 = 1
        print('LED 15 On')
    else:
        mcp.output(14, 0)
        state15 = 0
        print ('LED 15 Off')

def Toggle16(Channel):
    global state16
    global Counter
    Counter=0
    if state16 == 0:
        mcp.output(15, 1)
        state16 = 1
        print('LED 16 On')
    else:
        mcp.output(15, 0)
        state16 = 0
        print ('LED 16 Off')

GPIO.add_event_detect(SWITCH1,GPIO.FALLING,callback=Toggle1,bouncetime=200)
GPIO.add_event_detect(SWITCH2,GPIO.FALLING,callback=Toggle2,bouncetime=200)
GPIO.add_event_detect(SWITCH3,GPIO.FALLING,callback=Toggle3,bouncetime=200)
GPIO.add_event_detect(SWITCH4,GPIO.FALLING,callback=Toggle4,bouncetime=200)
GPIO.add_event_detect(SWITCH5,GPIO.FALLING,callback=Toggle5,bouncetime=200)
GPIO.add_event_detect(SWITCH6,GPIO.FALLING,callback=Toggle6,bouncetime=200)
GPIO.add_event_detect(SWITCH7,GPIO.FALLING,callback=Toggle7,bouncetime=200)
GPIO.add_event_detect(SWITCH8,GPIO.FALLING,callback=Toggle8,bouncetime=200)
GPIO.add_event_detect(SWITCH9,GPIO.FALLING,callback=Toggle9,bouncetime=200)
GPIO.add_event_detect(SWITCH10,GPIO.FALLING,callback=Toggle10,bouncetime=200)
GPIO.add_event_detect(SWITCH11,GPIO.FALLING,callback=Toggle11,bouncetime=200)
GPIO.add_event_detect(SWITCH12,GPIO.FALLING,callback=Toggle12,bouncetime=200)
GPIO.add_event_detect(SWITCH13,GPIO.FALLING,callback=Toggle13,bouncetime=200)
GPIO.add_event_detect(SWITCH14,GPIO.FALLING,callback=Toggle14,bouncetime=200)
GPIO.add_event_detect(SWITCH15,GPIO.FALLING,callback=Toggle15,bouncetime=200)
GPIO.add_event_detect(SWITCH16,GPIO.FALLING,callback=Toggle16,bouncetime=200)
Counter=0

try:
    Mainloop()

except KeyboardInterrupt:
    Cleanup()

Return to “Troubleshooting”