Electric Imp Squirrel Trap

From Wiki
Jump to: navigation, search

I keep a Havahart live trap in my attic, due to the occasional squirrel incursion. Since I'd like to know when the trap fires without visually checking on it every day, I used an Electric Imp module to monitor it. The actual hardware is an "Imp card" and a "April Development Board" (links here). Power is provided by 6 AA lithium batteries.

The battery life has been far better than I expected. The original code connected to the server every hour and delivered a status report. I don't have the exact date that the batteries were first installed, but it was sometime before 2013/01/01. I used lithium batteries because the temperature in the attic can drop into the low 30's, and alkaline cells don't do well at low temperatures. As of 2013/11/30, the batteries are still showing over 9 volts. Pretty remarkable.

Below is the code the Imp runs to watch for a switch closure on the trap. The 'OutputPort' function creates a HTTP POST request with the variable 'Switch' set to 0 or 1, which is passed to my server. The PHP script logs the date, time and switch state to a file, and if 'Switch' is 1, also fires off an email to let me know the trap has activated.

The trapActivated code may seem a little complicated. Pin 1 on the Imp can wake the module from deep sleep when it's pulled high. However, this is level sensitive, not edge, so if the trap is activated, it caused the Imp to immediately wake-up again and send another email. This resulted in my GMail account being suspended for 24 hours.

To work around this, the pin 1 mode is changed once the trap activates. A counter is maintained in NVRAM, and incremented every time the Imp wakes up and pin 1 is high. If the counter value modulus 12 is 0, the Imp generates the URL request to my server. When pin 1 is high, the Imp sleeps for 300 seconds. 12 * 300 = 3600 seconds, which is 1 hour, so every hour it will remind me the trap has fired. Since this IS WiFi based, and my internet service is cable, this will cover the case where if the WiFi or internet is down, and I made only one request, I'd miss it.

The Imp wakes up every 300 seconds so when the trap is reset, it picks that up in short order, and goes back to waking up every 8 hours to let me know the trap is armed, along with configuring the pin to wake on a high level. The less we wake up the better, since it does connect to Electric Imp's servers any time it wakes up (that's the downside to these modules -- An Electric Imp module HAS to gateway through their servers, and cannot connect directly to my server).

The server.log() function adds a log entry to the log file that's maintained on the Electric Imp server. When the trap changes from an armed to activated state, the counter is reset to 0, and the log message indicates the initial activation. On subsequent one hour intervals, the log indicates it's a reminder.

// Squirrel trap monitor

local output = OutputPort ("Switch", "number");

//
//  If we're activated, see if we've already posted a message to the server. If
//  so, go back to sleep for 300 seconds, so we check for a re-arm. If not, post
//  a message to the server (this is to avoid flooding the server, and also so
//  we re-arm ourselves in a timely fashion). We have to do this because pin 1
//  wakes up when it's high when set for DIGITAL_IN_WAKEUP
//
function trapActivated ()
{
    if ((table ["msgsent"] % 12) == 0)
    {
        if (table ["msgsent"] == 0) {
            server.log ("Pin 1 high, trap activated");
        } else {
            server.log ("Pin 1 high, trap activated (reminder)");
        }
        
        output.set ("1");
    } 
    
    table ["msgsent"]++;
    hardware.pin1.configure (DIGITAL_IN_PULLDOWN);
    imp.onidle (function () { server.sleepfor (300); });
}

//
//  If we're still armed, go back to sleep for 8 hours
//
function trapArmed ()
{
    server.log ("Pin 1 low, trap armed");
    output.set ("0");
    imp.onidle (function () { server.sleepfor (3600 * 8); });
    table ["msgsent"] = 0;
}

//
//  If pin 1 high, it's because the switch is closed and the trap activated.
//
function checkPin1 ()
{
    if (hardware.pin1.read ()) {
        trapActivated ();
    } else {
        trapArmed ();
    }
}

//
//  Set pin 1 for wakeup on high level (trap activated), then check the pin
//
imp.configure ("Squirrel Trap Monitor", [], [output]);
hardware.pin1.configure (DIGITAL_IN_WAKEUP);

//
//  Load the persistent table that tells us if we sent a message or not
//
table <- server.load ();
    
if (!("msgsent" in table)) {
    table ["msgsent"] <- 0;
}

checkPin1 ();

server.save (table);