Explorer Pro HAT primitive intruder detector code

Firstly, the word “primitive” in the title describes my code and not this program’s ability to differentiate between primitive or advanced intruders.

The project uses the Explorer Pro HAT, three male to female jumper leads (one to 5v0, one to ground and one to input one), they, in turn, are connected to a £2 PIR sensor.

I have based my little project on a post by Gisky (so many thanks to him for the inspiration):-

I must admit the code is a total cut ‘n’ shut job and is cobbled together from the Explorer Pro’s test and welcome files and the post from Gisky.

If anyone has the time to clean it up, I’d be interested in seeing their results.

Nevertheless, it works on my B+ running Raspbian, so here it is. I hope you enjoy. The code will evolve over time, adding more features. The newer versions will be at the bottom of this page:-

import explorerhat
import time

explorerhat.light.off()

def alert(pin):
  print "*** WARNING!!! INTRUDER ALERT!!! ***"
  explorerhat.light.red.pulse()
  explorerhat.light.green.off()

  return

explorerhat.input.one.pressed(alert)

def zeroalert(pin):
  print "*** SYSTEM NORMAL ***"
  explorerhat.light.red.off()
  explorerhat.light.green.on()

explorerhat.input.one.released(zeroalert)

explorerhat.pause()
2 Likes

Yay! Really makes me happy to see sharing ‘n’ caring in the community- these kinds of post are the best. Thanks for sharing- and by extension thanks to Gisky too!

Most of my code is, as you put it, “a total cut ‘n’ shut job” ;) I think that’s how programming works. All the code you could ever want is just a few Google searches and copy pastes away.

God forbid what might happen if you combine intrusion detection with your tank…

2 Likes

I’ve edited your post to enable proper code highlighting. To do this you need to put 4 spaces before each line (or select the code and press Ctrl+K for the editor to insert them for you!). :-)

I’ve been playing with my Explorer Pro too. It’s great along with the breadboard base, I’ve been keeping the analog and 5v stuff up on the HAT, “reserving” a bar at each end for 5v and gnd rails, and putting my 3v3/I2C on the base. I don’t really know what I’m doing and wouldn’t suggest anyone copy this but here’s my work in progress (I had to switch a few jumpers around after this pic!).

(PIR is on Explorer digitial channel one, LDR is on Analog channel one, the two boards on the base are temp/barometric pressure and lux level)

Hi Jon,

As you know, my learning curve is vertical at the moment, so I am very grateful for your assistance.

I’ll make a note of your instructions and will try to implement them when I add code in the future.

You have a great team there at Pimoroni. Great products, great help and great community.

I’m very glad I found you.

Kind regards,
TankMan

Hi gadgetoid,

Fine praise indeed, thank you very much.

Gisky helped with a little issue I was having with with the pin.name function :-). Thank you again, Gisky.

I have updated libraries and all is well now.

Is there a way for me to know if and when the libraries are updated?

Kind regards,
TankMan

I’m not really up to speed on GitHub TankMan but this might help:

https://help.github.com/articles/receiving-email-notifications-for-pushes-to-a-repository/
https://help.github.com/articles/watching-repositories/

2 Likes

What @Gisky sky said :D

Subscribing to the GitHub repo is the best way to know when the main library is updated- but it wont tell you when I push a new library version up to PyPi ( for download from pip ). However I should generally announce such updates in the forum announcements thread!

1 Like

Thank you again, I am signed up and watching.

Thank you again, I am signed up and watching. I’ll keep an eye out for forum announcements.

Hi gadgetoid and @Gisky

I am progressing the idea of the “intruder detector” and have been attempting to include the use of a four-digit activation/deactivation code using the Explorer Pro’s keypad.

import explorerhat

print ("Input PIN number")

def one(channel, event):
    print("I got a touch on button: {}".format(channel))
explorerhat.touch.one.pressed(one)

def two(channel, event):
    print("I got a touch on button: {}".format(channel))
explorerhat.touch.two.pressed(two)

def three(channel, event):
    print("I got a touch on button: {}".format(channel))
explorerhat.touch.three.pressed(three)

def four(channel, event):
    print("I got a touch on button: {}".format(channel))
explorerhat.touch.four.pressed(four)

PIN = [one, two, three, four]

print(PIN)

As usual, my code is clumsy and, on this occasion, completely non-functioning.

The idea is that it offers a prompt to enter a PIN number, the keypad touches are detected and are printed on screen (this is initially as a feedback, so that I can see that something is actually happening). Then the four-digit code needs to be saved as a list (I guess) and can be used for deactivating the intruder detector.

I think a range function needs setting up somewhere to define the list as four digits, but have been unable to get this working.

I’d greatly appreciate if you can tell me where I am going wrong.

Many thanks, in anticipation,

TankMan

Hi TankMan, try adding this line at the end of your program:

explorerhat.pause()

and then you should be able to see which buttons you are pressing :)

(to quite out press ctrl-c)

Hi Gisky,

Thanks for getting back to me so quickly.

I tried adding:

explorerhat.pause()

but all it did was prevent the keyboard interrupt.

The result that I was initially receiving from running the programme was:

Explorer HAT Pro detected...
Input PIN number
[<function one at 0xb5133ef0>, <function two at 0xb51509b0>, <function three at 0xb515aef0>, <function four at 0xb515af30>]
>>> I got a touch on button: 1
I got a touch on button: 2
I got a touch on button: 3
I got a touch on button: 4

But what I actually want is for the inputs from the keypad to be stored in the list “PIN”. It appears to be storing information from the four defined functions (in a format which I don’t understand). I was expecting the PIN list to be presented as “1,2,3,4” or whatever four-digit key combination was entered.

So, think of a burglar alarm. The PIN is entered to activate and the sensor is armed. Then the PIN is entered again to deactivate and disarm the system.

I hope this clarifies my intentions.

Kindest regards,
TankMan

That strange, did you post your complete function? I cut and pasted your original code and ran it but it just exits right away, which is what I’d expect. I needed the pause to make the program stick around and wait for input.

Currently I think you’re storing references to your functions in the PIN list, which is why when you print it you’re seeing references to those functions. How about using .append within your event handlers to add the pin that was pressed to a list?

It strikes me that this would make a really great example once it’s up and running- I think it’s clear that the event-driven programming is tripping @TankMan up, which is absolutely to be expected since it’s such a total paradigm shift from “procedural” code.

As a pointer in the right direction, the code you need at the bottom of this script would be something like:

while len(PIN) < 4:
    print(PIN)

This checks your PIN array, which should begin empty, to see if it contains 4 items, IE: a completed code and then exits, printing the code when that condition is met.

With that, and @Gisky’s input you should be good to go- I don’t want to help too much and interrupt your learning journey though :D

2 Likes

Hi Gisky,

Yes the function is complete.

I am running XWindows and have launched Python with sudo idle from LXTerminal.

I then create a new window and run the code from that window in Python. After the references to the functions appear, the programme waits and will then print whichever keypad has been pressed.

I think you are right that the line:

PIN = [one, two, three, four]

is incorrectly storing the actual functions in the list, rather than a keypad number.

I’ll read more on the use of lists and .appends and ranges (and find out what an event handler is) in Python and see if I can nail this.

Many thanks for all of your kind help.
TankMan

ah ok, IDLE is the difference probably, I’m just running from the command line. Your functions, .e.g.

def three(channel, event):

are event handlers, as they’re being called to handle events (in this case a touch pad being pressed). The line

explorerhat.touch.three.pressed(three)

is hooking up the predefined (by the explorerhat library) “event” called pressed on the touchpad “three” to your handler (which you’ve also called “three”). It might be less confusing to call it:

def threePressed(channel, event):

have fun!

1 Like

Hi Gisky and @gadgetoid,

You both are a great help. I had been trying to define PIN with a range, which I now see was wrong.

Thank you both very much for your patience while I try to confuse myself and everyone else.

import explorerhat

PIN = []

def onePressed(channel, event):
    print("I got a touch on button: {}".format(channel))
    PIN.append("1")
explorerhat.touch.one.pressed(onePressed)

def twoPressed(channel, event):
    print("I got a touch on button: {}".format(channel))
    PIN.append("2")
explorerhat.touch.two.pressed(twoPressed)

def threePressed(channel, event):
    print("I got a touch on button: {}".format(channel))
    PIN.append("3")
explorerhat.touch.three.pressed(threePressed)

def fourPressed(channel, event):
    print("I got a touch on button: {}".format(channel))
    PIN.append("4")
explorerhat.touch.four.pressed(fourPressed)

print ("Input PIN number")

while len(PIN) < 4:

    if len(PIN) == 4:
            print(PIN)

This produces the result as follows:

================================ RESTART ================================

Explorer HAT Pro detected…
Input PIN number
I got a touch on button: 3
I got a touch on button: 4
I got a touch on button: 2
I got a touch on button: 3
[‘3’, ‘4’, ‘2’, ‘3’]

Which is the closest thing to a headache cure that I’ve found today.

The only remaining issue is that it still awaits a keypad press event after filling the PIN list and continues to print the presses made. But I think it is very nearly there.

I will attempt to bolt this on to the front of the intruder alarm code and write the final bit of code which will disarm the program once the PIN is re-entered.

Great fun indeed.

Kindest regards,
TankMan

1 Like

Nice! Looking back at my code, it should probably have been:

while len(PIN) < 4:
    pass

Or tidier still:

while len(PIN) < 4:
    pass

explorerhat.touch.pressed(None)
PIN = PIN[0:4] # Get first 4 digits only
print(PIN)

I don’t know how I got it so wrong :D