Paws for thought…

or how to wake the cats up from sleeping on our bed.

PIR Alarm System

PIR Movement Alarm System

OK, not really, but I thought I’d share with you the hardware complete home alarm system.  Code is still the same as before, so needs function added to text owners etc when the alarm sounds.  For now I just wanted to let you know the project still lives, and will start progressing again.

P.S.  Anyone know how to send texts from software?  If so, do get in touch.

P.P.S. The paws in question…

Bovril & Marmite

Bovril & Marmite

No Hesitation, Repetition or Deviation

Although neither the drone nor alarm pi projects are even phase 1 complete (phase 1 for the drone is safe automaton takeoff, hover and land, and for the alarm is independent alarm control), I’m strongly considering moving from the RPi.GPIO library to the RPIO library for a number of reasons:

  • RPIO interrupts can be used to wake socket.select() calls, whereas RPi.GPIO runs a separate thread which can only wake a socket.select() on the make thread by sending a SIGINT – functional but ugly
  • RPIO supports hardware PWM across any GPIO port whereas currently, I use I2C to connect to a PWN breakout chipset

While using the RPi.GPIO works fine, RPIO just feels better. So once phase 1 of both projects are complete, I’m going to add phase 1.5 which is the switchover to RPIO (or perhaps merge the best of both).

In passing, I’m also considering moving over to PiPi once it’s available in the Wheezy distro – the drone is running full speed currently with no sleeps. Moving to PiPi means I can start introducing time.sleep() as the precursor to TCP socket inputs via socket.select(). Currently the space in the CPU cycles from using interpreted Python is feeling a bit small to stably introduce remote control.

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.

What’s troubling me with the RPi.GPIO python library?

AlarmPi needs to monitor 2 inputs currently: the switch and the PIR.  Once the AlarmHub is finished, it needs to track a TCP socket as well so that when one Alarm goes off, the hub can tell all the others to go off too.

There are several ways for the RPi.GPIO library to monitor and report inputs:

  • RPi.GPIO.input(channel) but you’d need to poll frequently and would probably miss a change
  • RPi.GPIO.wait_for_edge() blocks, so you wouldn’t miss the event, but it can only track one channel; the Alarm + Hub needs at least 3
  • RPi.GPIO.edge_detected() doesn’t block, which means that although it still only covers 1 channel again, each could be checked in turn; in addition, the input is latched until read meaning it can’t be missed.  The downside is that you’d need to keep checking say once a second to detect switch and PIR changes
  • RPi.GPIO.add_event_detect() allows a callback to be made when an edge is detected; unfortunately this happens on a separate thread, and does not wake a sleeping main thread.  The only way to work around this is for the callback thread to send os.signal(signal.SIGINT) to wake the sleeping main thread via a signal handler, but that then makes it harder to use ctrl-C to stop the code.

AlarmPi currently uses this last option as the only one that can be made to work efficiently, but the code shows the messy interactions between callbacks, the main thread. and the signal handler. It’s also forced to have a super extended debounce selected (30s) on the switch callback; once the switch is turned on, it needs to beep / light the LED for 30s to allow the user to leave the room before the PIR is enabled. Because the switch callback doesn’t wake the main thread, this 30s processing takes place in the callback itself. To allow this to work, the callback bounce delay must be longer than 30s. If it isn’t, then when the alarm is turned on, any bounce in the switch is queued until the 30s callback has finished, and then it is processed, immediately toggling the switch off again disabling the PIR as though the user had turned it off. With this hacky debounce delay of 30s, this actually means once the hub exists that if you accidentally turn on the alarm, you can’t turn it off until the PIR is active, at which point attempting to turn off the alarm will trigger the PIR, and most likely deploy the CS gas, ring the police etc. Yet without the hacky fix, any switch bounce (likely) will automatically turn the alarm off immediately every time you try to turn it on; catch 22.

When the Hub comes along, the situation gets worse as the main thread would need to sleep until an intruder is detected, and then use a sockets.select() call for receiving data, meaning yet more messy interactions with callbacks and signal handlers.

So I’m looking at modifying the RPi.GPIO library.  Here’s my current plan:

  • Make the RPi.GPIO library more object oriented:
  • GPIO.setup() returns a gpio object representing a single channel / GPIO pin.  Errors are reported via Try: Except handlers
  • Currently, in the C library, each GPIO pin is accessed via a file descriptor (fd) passed to epoll() for input and write() for output – these would now be stored inside the GPIO class object, one per channel
  • A new python class function gpio.socket() returns the fd in a socket object.
  • In turn, this fd can be used by socket.select() (I hope!) just as other TCP sockets are used; the advantage here is that select can watch many fds at a time, sleep when nothing is happening, and wake when one or more sockets have something to report.
  • The current blocking functions RPi.GPIO.input and output would still be supported.
  • The current callbacks would become unnecessary, as would the wait_for_edge, edge_detected, and add_event_detect – the sockets solution provides a solution covering these and more, although support for them should be retained if at all possible for back-compatibility reasons.
  • In passing, I’ll also fix another restriction I hit in the Turtle project, where a GPIO output always is set up with default value 0; instead RPi.GPIO.setup() will carry an extra parameter, defaulted to 0, but allowing the user to specify 1 if needed.

The only problem is I have no idea how Python libraries really work.  I have the ‘C’ code for the RPi.GPIO library, and 22 years experience of writing C code.  I’m just not 100% confident that the GPIO fds can be used by socket.select (although I think it should work since select() uses epoll() under the surface) nor am I experienced in writing the C code to support the new python class required.

Sounds like an interesting challenge. Not sure whether I’m up to it, but I’ll give it a try in the background.

How to build an AlarmPi

Here’s the contents of the breadboard. Some of this stock was ordered from uk.farnell.com but was sent by Newark, their US partner. As a result, postage costs £16 per order, so make sure you include all you need. In my case it was

Here’s the code – you can tell from GPIO_SWITCH, GPIO_LED, GPIO_PIR and GPIO_SOUNDER which device (sensor or output) is connected to which pin on the breadboard Pi Cobbler.

Here’s a bigger pic of the breadboard.  +3.3v from Cobbler pin one is connected to both red lines.  Ground from Cobbler pins 6 & 9 are connected to both the blue rails.

AlarmPi breadboard

AlarmPi breadboard details

That’s all for now, both because I’m gonna have another shot (metaphorically for the moment) at the Drone, and also, there’s a minor restriction in the RPi.GPIO library which needs fixing (by me?) before I can progress on the hubs.  I’ll explain more in another post.

Say hello to AlarmPi…

This is my change is as good as a rest!  It took me probably 4 days, a couple of hours each day to create, once I had all the parts.

RaspberryPi Home Alarm System by pistuffing.co.uk from Andy Baker on Vimeo.

For now, that’s as far as this is going, I’m now motivated enough to spend a bit more time on DronePi, but keep watching as the next stage is going to be a big challenge for unexpected reasons…

A change is as good as a rest…

I’m really struggling to get this drone to hover stably, and in the mean time, some neighbo(u)rs of of ours were burgled.  And that got me thinking about home alarm systems, which rapidly led to a cunning plan:

  • Digital Passive Infra-Red (PIR) motion detection sensors are easily available
  • Combine one of those with a RaspberryPi Model B, a power supply, a switch, and a piezo sounder, and you have a standalone, per-room alarm system
  • Add in a power-line system (we already have one by TP-Link as our house is made of brick which WiFi does go through well), a PiCam per AlarmPi and an ethernet connection, and you can connect these AlarmPi’s together to a central control AlarmHubPi which could then do one of many things if an alarm was triggered such as
    • set off all the AlarmPi to shreik throught the house
    • text or phone the house owner
    • call the police or the neighbo(u)rs
    • video the intruders and post to the cloud as evidence
    • set off CS gas canisters in the rooms
    • lockdown (or electify) the house so the intruder is available for arrest.

With such a vast array of punishment available, you really need to make sure it doesn’t get dealt out to you.  Rather than a boring (and forgettable) number pad, how about face recognition provided by a PiCam at the AlarmHub?  That would mean anyone in a family, even remote, could, once the face recognistion is trained, disable the alarm simply by smiling at the hub?

I have Pi’s a plenty and other than the power-line ethernet connection, the rest of the kit is perhaps £25 per AlarmPi.  I have the hardware for the first standalone AlarmPi ready for building, so I think I’ll give the drone a break for a week or two.  Don’t worry, it’ll be back, but sometimes, direct thought fails, and only time-out leads to the epiphany.