Reinventing the wheel…

The first draft code for the AlarmPi was flawed due to restrictions in the GPIO library as previously explained. The main one was that the switch debounce had to be set to longer than the amount of processing in the switch event callback, but that meant that the switch was disabled for a long period (until the PIR was active in fact) so it was impossible to turn the alarm off until it was fully activated, meaning the alarm went off while it was turned off.

I’ve coded around this now by putting all the processing in the main thread, with an internal FSM (finite state machine). All the callbacks do now is set the next input for the state machine, and wake the main thread with an os.kill(os.getpid(), signal.SIGINT). It’s still not how I’d like it, but it works, and means I can get on with the drone rather than having to rework the RPi.GPIO library.

There’s nothing wrong with this semantically, it’s just the pedantic side of me who’d like either single threaded interrupts, or an ability to wait on the GPIO file descriptors at the same time as sockets fd’s in a single main-thread socket.select() call. I have a enough pieces of jigsaw to test whether that’s possible, but this has now been deferred because this new AlarmPi code avoids the problem altogether.

3 thoughts on “Reinventing the wheel…

  1. Hi Nick,

    I think something like this should do it – this just extends the ACT_INTRUDER_ALERT processing:


    if fsm_action == ACT_INTRUDER_ALERT:
    #-----------------------------------------------------------------------------------
    # Intruder alert, disable the PIR, beep annoyingly for 1 minute, then reset
    #-----------------------------------------------------------------------------------
    logger.info("!!!!!!!!!!!!Intruder Alert!!!!!!!!!!!!")
    GPIO.output(GPIO_SOUNDER, not GPIO.input(GPIO_SOUNDER))
    GPIO.remove_event_detect(GPIO_PIR)
    sleep_time = 1.0

    #--------------------------------------------------------------------------
    # Just spotted the intruder for the first time, save the time this happens, so we can beep
    # until a minute (60s) has passed
    #--------------------------------------------------------------------------
    if new_intruder:
    detection_time = time.time()
    fsm_input = INPUT_PIR
    new_intruder = False
    intruder_count += 1

    #--------------------------------------------------------------------------
    # The alarm has been beeping for a minute, so shut it up, and rearm the PIR, unless
    # this is the 3th time, in which case, turn this detector off, bypassing this zone.
    #--------------------------------------------------------------------------
    else if time.time() - detection_time > 60.0:
    if intruder_count == 3:
    fsm_input = INPUT_SWITCH
    intruder_count = 0
    new_intruder = True
    else:
    fsm_input = INPUT_TIMER

    You’ll need to add “new_intruder = True” and “intruder_count = 0” immediately before the “while keep_spinning:” line higher up also.

    Cheers,

    Hove

    • Thanks so much Hove! I’m still working on the code. A few problems with indentation and the else if time.time() – getting a syntax error, I tried elif. I’m very new to python so its a bit of a learning curve. I’ve got it to run with no errors but having no luck with the output restarting once tripped, I probably have indentation in the wrong place. Hopefully I can sort it all out. Thanks so much for your time and your help!!!

      I’m using this for a security system for a koi pond. I have a blue heron picking off my koi. I’m using a laser, bouncing off mirrors to a photoresistor with a transistor to input into the Pi. I only need the trips for short periods to activate a water valve to turn on the sprinkler. The bypass is just incase the laser drifts off, or a mirror gets condensation on it,,, this way the water wouldn’t be running all day. I do plan on adding a PIR to the system in the future.

  2. Greetings, I’ve been working on an alarm for the Pi and decided to scrap it just now after seeing your code. I spent the entire day yesterday trying to figure it out, I didn’t get very far being a newbie. I’m trying to add a function to yours but totally clueless as how to go about it. I’m trying to add: the alarm will reset after a minute of being tripped and that if it trips 3 consecutive times after rearming it will bypass that zone.

    If you have the time and insight – much appreciated!! Thanks!

Leave a Reply

Your email address will not be published. Required fields are marked *