2

I've got an alarm system with 3 inputs and 3 outputs. But so far each input is controlling the outputs from it's own script. I did this because I wanted to get one thing at a time working on its own. It should be in one script though shouldn't it.

Inputs

PIR Motion Sensor, Push Button, 4x4 Matrix Keypad

Outputs

4 LEDS, Active Buzzer, I2C LCD Display

Functionality

So the idea is that, if the motion sensor is tripped, a button is pushed or a wrong password entered, the alarm sounds. The buzzer and LEDS blink for 0.3 seconds, the display prints a message. If the button is pushed again or a correct password entered, the alarm turns off, the displays prints a new message.

Questions

Do I create an alarm script and import the other scripts or just put each input as its own function in the alarm script?

That's the first question.

The second is, as you can see on all the scripts, the while loop when the alarm is activated just runs forever, I cannot figure out how to make that stop. It would be simple if it was just on but the blinking for 0.3 seconds makes it way more difficult.

So how do I turn them off?

Link Schematics and Breadboard Diagram

https://imgur.com/a/zb4rQBJ

Link to actual alarm system images

https://imgur.com/gallery/RAJwmpI

MotionSensorScript

import RPi.GPIO as GPIO
import time
import I2CLCD1602

ledPin = [37,35,33]  # define the ledPin
blueLed = 29
sensorPin = 7    # define the sensorPin
buzzer = 15

def setup():
    GPIO.setmode(GPIO.BOARD)       # Numbers GPIOs by physical location
    GPIO.setup(ledPin, GPIO.OUT)
    GPIO.setup(blueLed, GPIO.OUT)
    GPIO.setup(buzzer, GPIO.OUT)
    GPIO.setup(sensorPin, GPIO.IN)

current_state = 0

def motion():
    global current_state
    time.sleep(0.1)
    current_state = GPIO.input(sensorPin)
    if current_state == 1:
        print("GPIO pin %s is %s" % (sensorPin, current_state))
        I2CLCD1602.up()
        GPIO.output(blueLed, False)
        while current_state ==1:
            GPIO.output(buzzer, True)
            GPIO.output(ledPin, True)
            time.sleep(0.3)
            GPIO.output(buzzer, False)
            GPIO.output(ledPin, False)
            time.sleep(0.3)
    else:
        I2CLCD1602.down()
        print("GPIO pin %s is %s" % (sensorPin, current_state))
        GPIO.output(blueLed, True)

def loop():
    motion()

try:
    setup()
    while True:
       loop()

except KeyboardInterrupt:
    GPIO.output(ledPin, False)
finally:
    GPIO.cleanup()

KeypadScript

import RPi.GPIO as GPIO
import time
import matrixKeyboard
import threading
import I2CLCD1602

ledPin = [37,35,33]  # define the ledPin
buzzer = 15
blueLed = 29

def setup():
    GPIO.setmode(GPIO.BOARD)       # Numbers GPIOs by physical location
    GPIO.setup(ledPin, GPIO.OUT)
    GPIO.setup(buzzer, GPIO.OUT)
    GPIO.setup(buzzer, GPIO.LOW)
    GPIO.setup(blueLed, GPIO.OUT)



def keyPad():
        key = matrixKeyboard.main()
        if key == 1:
             I2CLCD1602.up()
             GPIO.output(blueLed, False)
             while key == 1:
                 GPIO.output(ledPin, True)
                 GPIO.output(buzzer,True)
                 time.sleep(0.3)
                 GPIO.output(ledPin, False)
                 GPIO.output(buzzer,False)
                 time.sleep(0.3)
        elif key == 2:
            I2CLCD1602.down()
            GPIO.output(blueLed, True)
            GPIO.output(ledPin, False)
            GPIO.output(buzzer,False)


def loop():
    keyPad()

try:
    setup()
    #keypad_thread = threading.Thread(target=keyPad)
    #keypad_thread.start()
    while True:
        loop()


except KeyboardInterrupt:
    GPIO.output(ledPin, False)
finally:
    GPIO.cleanup()

ButtonScript

import RPi.GPIO as GPIO
import time
import I2CLCD1602

ledPin = [37,35,33]  # define the ledPin
blueLed = 29
button = 31
buzzer = 15

def setup():
    GPIO.setmode(GPIO.BOARD)       # Numbers GPIOs by physical location
    GPIO.setup(ledPin, GPIO.OUT)
    GPIO.setup(button, GPIO.IN, pull_up_down = GPIO.PUD_UP)
    GPIO.setup(buzzer, GPIO.OUT)
    GPIO.setup(blueLed, GPIO.OUT)


Led_status = 0
def swLed(ev=None):
    global Led_status
    Led_status = not Led_status
    #GPIO.output(ledPin, Led_status)
    #GPIO.output(buzzer, Led_status)# switch led status(on-->off; off-->on)
    if Led_status == 1:
        print ('led on...')
        I2CLCD1602.up()
        GPIO.output(blueLed, False)
        while Led_status == 1:
            GPIO.output(ledPin, True)
            GPIO.output(buzzer, True)
            time.sleep(0.3)
            GPIO.output(ledPin, False)
            GPIO.output(buzzer, False)
            time.sleep(0.3)
    else:
        print ('...led off')

def destroy():
    GPIO.output(ledPin, False)
    GPIO.output(buzzer, False)

def loop():
     GPIO.output(blueLed, True)
     I2CLCD1602.down()
     GPIO.add_event_detect(button, GPIO.FALLING, callback=swLed, bouncetime=200)
     while True:
         pass# wait for falling
try:
    setup()
    while True:
        loop()

except KeyboardInterrupt:
    destroy()

finally:
    GPIO.cleanup()

So yeah, any advice on the best way to approach this and how to turn the outputs off. I'm not use if I need to use threading to have the 3 input functions running at the same time? Each input should should be able to interrupt the others while loop.

If the alarm is on then the button or keypad should turn it off, can that even work with imported scripts?

TIA!

  • "I did this because I wanted to get one thing at a time working on its own. It should be in one script though shouldn't it." -> This implies it A) Works as is, and B) Has a natural form of organisation. So maybe rethink whatever reason you have for believing it should be in one script. If that reason is convenience of use, the answer is you add a layer of abstraction to deal with that (e.g., a shell script you can call to execute everything properly), not knock all the walls in your house down (that said, note I'm not much of a python user and did not closely read the sources here) – goldilocks May 19 at 10:41
  • @goldilocks: What I mean is, the 3 scripts are running completely independent of each other. Not so much of an alarm system. It's more 3 individual components/scripts that do pretty much the same thing but each need to be running. I cannot run 3 scripts at once can I? I want it as one system and was looking for advice on how best to do that. :) – DaviebPrime May 19 at 10:50
  • There may be some complications with the gpio library initialization, but as long as you are not using the same pins in two scripts that should be fine. In fact, it's fine playing with the same pins from two processes as long as the basic function is the same (e.g., everyone regards it as output). If they are both setting off the same events in response to the same events it will get silly. At a glance I'm guessing you are using the outputs the same way but the input triggers are different, which may or may not require synchronisation... – goldilocks May 19 at 11:24
  • ...If so, you could use something like a tmp file to maintain/check state; as long as the information in it is not too long (a number in string form is fine) reads/writes with it will be atomic (the issue is then a race condition of the state, e.g., if you set the value in the file to indicate you want to lock the use of something, there's a race condition even though all transactions are atomic). Synchronising stuff in a single script/thread of execution is easier, but that does not mean necessary (or better, depending). – goldilocks May 19 at 11:24
  • Regarding code duplication (looks like you have a lot of it), you can put duplicate routines into a common source file and import that in any number of concurrent scripts. – goldilocks May 19 at 11:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.