Countdown timer with cancel

i have been racking my head over this for a week i must be over complicating things. i would like a device code that can be executed by a pin, set another pin high, start a timer, and under normal circumstances shut off after a desired time has elapsed. i would also like to use a third pin to be able to cancel the first timer. im trying to use imp.wakeup and imp.cancelwakeup but im usually stuck with an error

`function button1(){
    if (hwlvl.read() == 1){
    if (pump.read() == 0)
    {
            pump.write(1);
            agent.send("pump", "on");
            server.log("Pump On")
            
            }}
    imp.wakeup(0.15, button1(),
                pump.write(0),server.log("pump off")
            )
}`
`function button1() {
   // imp.wakeup(pump_cyc_timer, button1)
        if (hwlvl.read() == 0){
            if ( pump.read() ==0)
      {
  //    function pumpcyctimer(){
 //       pump_cyc = imp.wakeup(pump_cyc_timer, function()
  //          {
                pump.write(1),
            agent.send("pump", "on");
            server.log("pump on")    
            }//)}

        }
        if (prs_sns.read() == 0)

    {
        if(pump_cyc) imp.cancelwakeup(pump_cyc)
        pump_cyc = imp.wakeup(pump_cyc_timer*60)
            pump.write(0),
            agent.send("pump", "off")
            server.log("pump off")
    }
}`

First up, you need to check how you invoke imp.wakeup(). It needs two arguments, a float and a function. Your code may compile, but will fail when the Squirrel interpreter tries to call it without the right arguments.

To help others read your code, please submit using the code blocks. Just select the code you’ve pasted in, and press Ctrl-O or click on the “C” in the menu.

code here

}`function button1() {
// imp.wakeup(pump_cyc_timer, button1)
if (hwlvl.read() == 0){
if ( pump.read() ==0)
{
// function pumpcyctimer(){
// pump_cyc = imp.wakeup(pump_cyc_timer, function()
// {
pump.write(1),
agent.send(“pump”, “on”);
server.log(“pump on”)
}//)}

    }
    if (prs_sns.read() == 0)

{
    if(pump_cyc) imp.cancelwakeup(pump_cyc)
    pump_cyc = imp.wakeup(pump_cyc_timer*60)
        pump.write(0),
        agent.send("pump", "off")
        server.log("pump off")
}

}`

this works but doesn’t cancel my timer as i hoped. it does suit my purpose. if someone would want to correct it with a imp.cancelwakup i would appreciate it

`
start <- hardware.pin1
led <- hardware.pin7
cancelbtn <- hardware.pinA

function startTimer(){

    if (start.read() == 1){   

        imp.wakeup((15), 
            function (){ 
                led.write(0)
                server.log("timer ended")
    })}
    if(cancelbtn.read() == 0){
        led.write(0)
        server.log("timer canceled")
    }
    if (start.read() == 0){
        led.write(1)
        server.log("timer started")
    }

}

start.configure(DIGITAL_IN_PULLUP, startTimer)
led.configure(DIGITAL_OUT)
cancelbtn.configure(DIGITAL_IN_PULLUP, startTimer)`

add the following line to the top of your code:

myTimer <- null

and replace your call to imp.wakeup with this:

myTimer = imp.wakeup(15,function(){/* your code.*/})

and this code to the code block that executes when your cancelbtn is pressed:

`if (myTimer!=null)
    imp.cancelwakeup(myTimer)`

Your code will turn on an LED when the start button is pressed, which will remain on until 15 seconds after it is released, or until the cancel button is pressed. However, what do you want to do if someone presses the start button while the timer is counting down the 15 seconds? Should the timer be reset?

yeah that’s exactly what i want. if the start button was held it would reset the timer. but at the same time if the cancel was pressed it could override the start button being held.

i’m not actually driving an LED i’m driving a pump via a relay as the first code stated. my start button is a float switch and i have a hardware fail-safe that controls my low water so my heating element doesn’t overheat. the timer is used to drain the bucket within a preset time and the low level switch interrupts the relay. the cancel function is actually controlled by the agent allowing me to cancel a pump cycle if i need to adjust the drain line for cleaning.

the whole system is a pump bucket for my home maple sugar project. here is a look at my sugar camp my first year and the epic fail of a pump bucket i bought from another sugarer. (now everything is food safe) http://youtu.be/_bW25qGIIcg

Maple syrup, yeah right. Meth lab, to my untrained eye. But mustn’t pry.

To reset the timer when the button is pressed again, add this to the code block when the timer is started:

`if (myTimer!=null)
    imp.cancelwakeup(myTimer)
`

Shhh. Don’t blow my cover. Lol

Thank you for your help coverdriven

you’re welcome.

just thought id show the finished code:

`start       <- hardware.pin1
led         <- hardware.pin7
cancelbtn   <- hardware.pinA
myTimer     <- null

function startTimer(){

        if (start.read() == 1){   
            myTimer = imp.wakeup(5,function(){
                led.write(0)
                server.log("timer ended")
        })}
        if(cancelbtn.read() == 0)
        if (myTimer!=null){
            imp.cancelwakeup(myTimer)
                led.write(0)
                server.log("timer canceled")
        }
        if (start.read() == 0)
        if (myTimer!=null){
            imp.cancelwakeup(myTimer)
            led.write(1)
            server.log("timer started")
        }
}

start.configure(DIGITAL_IN_PULLUP, startTimer)
led.configure(DIGITAL_OUT)
cancelbtn.configure(DIGITAL_IN_PULLUP, startTimer)`

So now I’m playing with matt-haines’s ElectricImp-PowerSwitch code I got from github. I’m trying to make a password protected geocache. the power switch was a bit too basic for me. I need to add a timer to protect my solenoid lock from overheating. I added this timer into the code and I cant seem to call it. It seems to me that the timer device code is looking for a 1 or 0 and the agent code is always providing a 1 or 0 depending on the last state similar to a floating input without a pullup.

AGENT
`const html = @"

Welcome to the Dennis Estates
<link rel='stylesheet' href='https://netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css'>

Welcome to the Dennis Estates

If it is night please leave your parking lights on

Please enter the password

UNLOCK LOCK

Hint:

The password is 3 uppercase characters

Log:

function setState(s) { var pw = $('#pw').val(); var url = document.URL + '?pw=' + pw + '&power=' + s;
        if (pw) {
            $.get(url)
                .done(function(data) {
                    $('#logs').prepend('<span style=\\'color: blue;\\'>' + new Date().toLocaleString() + '</span><span> - ' + data + '</span><br />'); 
                 }) 
                .fail(function(data) {
                    alert('ERROR: ' + data.responseText);
                });
        } else {
            alert('Please enter a password and try again');
        }
    }
</script>
"

const PASSWORD = “RGB”

// agent code:
function httpHandler(request, response) {
try {
// if they passed a power parameter
if (“power” in request.query) {
// add the ajax header
response.header(“Access-Control-Allow-Origin”, “*”);

        // password variable
        local pw = null;
        
        // if they passed a password
        if ("pw" in request.query) {
            // grab the pw parameter
            pw = request.query["pw"];
        }

        // if the password was wrong
        if (pw != PASSWORD) {
            // send back an angry message
            response.send(401, "INCORRECT PASSWORD");
            return;
        }

        // grab the power parameter
        local powerState = request.query["power"].tointeger();
        if (powerState == 0 || powerState == 1) {
            // send it to the device
           //server.log("actuator:" + seconds);
            device.send("power", powerState);

/----------SNACKBOT----------------------------------------------
device.send(“dispense”, 0.4);
----------------------------------------------------------------
/

            // finally, send a response back to whoever made the request
            response.send(200, powerState == 0 ? "Locked" : "Unlocked");
            return;
        } else {
            // if powerState isn't valid, send back an error message
            response.send(500, "Invalid power parameter. Please pass 1 or 0 and try again.");
            return;
        }
    } else {
        // if power wasn't specified, send back the HTML page
        response.send(200, html);
        return;
    }
}
catch (ex) {
    // if there was an error, send back a response with the error
    response.send(500, ex);
    return;
}

}

// run httpHandler whenever a request comes into the Agent URL
http.onrequest(httpHandler);

`

DEVICE
`//constants
myTimer <- null
//power <- null
led <- hardware.pin9
cancelbtn <- hardware.pinA
led.configure(DIGITAL_OUT)
cancelbtn.configure(DIGITAL_IN_PULLUP)

//------------Device Code Start------------------------------------------------------

function powerHandler(state) {
if (state == 0){
myTimer = imp.wakeup(1, function(){
led.write(0)
server.log(“timer ended”)
})}

    if(cancelbtn.read() == 0)
    if (myTimer!=null){
        imp.cancelwakeup(myTimer)
            led.write(0)
            server.log("timer canceled")
    }
    if (state == 1)
    if (myTimer!=null){
        imp.cancelwakeup(myTimer)
        led.write(1)
        server.log("timer started")
    }

}
agent.on(“power”, powerHandler)`

just so you know you can add more buttons and powerstates here
<input type='password' class='form-control' style='margin-top:15px; text-align:center;' id='pw' placeholder='Password'> </div> <button type='button' class='btn btn-default' onclick='setState(0);'>Lock</button> <button type='button' class='btn btn-default' onclick='setState(1);'>Unlock</button> <button type='button' class='btn btn-default' onclick='setState(2);'>Something1</button> <button type='button' class='btn btn-default' onclick='setState(3);'>Something2</button>

Then you add the conditional here to transfer them out. You can choose to send it in the same device.send (powerstate…) or you can add another conditional here and device.send/agent.on another variable instead.Whatever is easier to implement on the device side

// grab the power parameter local powerState = request.query["power"].tointeger(); if (powerState == 0 || powerState == 1) { // send it to the device //server.log("actuator:" + seconds); device.send("power", powerState); if (powerState == 2 || powerState == 3) { // send it to the device //server.log("something else here:" + seconds); device.send("somethingelse", powerState);
I point this out in case you want to take a shot at your pump control from the web as well. (HA HA HA)

So personally, I would rather sort what mode the lock is supposed to be in from the agent.on function (IE LOCK or UNLOCK). And then have that call another function that takes care of the solenoid timing always returning it to a safe state. I would hate to have a bad post or some goofy error over heat the solenoid. But that is my personal preference.

just so you know you can add more buttons and powerstates here
THANK YOU HYPERONE this is a great help for some other projects i have been playing with.