Countdown timer for Particle photon board

Hi, firstly I’m not a programmer by any means… I have a WiFi IoT Relay Controller for IFTTT with 4-Channel DPDT 5-Amp Relays + 4 Programmable GPIO using a Particle Photon board. The basic programming script includes basic functions like relay on, relay off, relay momentary etc. I would like to add a script with a countdown timer where I can add any time between 1 minute and 20 minutes e.g. once an IFTTT trigger activates a relay e.g. 1on I then want the countdown timer to initiate and once the time has elapsed I need it to trigger the relay off e.g. 1off. Below is the standard basic script…

SYSTEM_MODE(AUTOMATIC);

#include "NCD4Relay.h"

NCD4Relay relayController;
int triggerRelay(String command);
bool tripped[4];
int debugTrips[4];
int minTrips = 5;

/* This function is called once at start up ----------------------------------*/
void setup()
{
    Particle.function("controlRelay", triggerRelay);
    Serial.begin(115200);
    relayController.setAddress(0,0,0);
}

/* This function loops forever --------------------------------------------*/
void loop()
{
    int status = relayController.readAllInputs();
    int a = 0;
    for(int i = 1; i < 9; i*=2){
        if(status & i){
            debugTrips[a]++;
            if(debugTrips[a] >= minTrips){
                if(!tripped[a]){
                    tripped[a] = true;
                    //set input trip event to true
                    String eventName = "Input_";
                    eventName+=(a+1);
                    Particle.publish(eventName, "ON");
                    Serial.print("eventName: ");
                    Serial.println(eventName);
                    Serial.print("eventContents: ");
                    Serial.println("ON");
                }
            }
        }else{
            debugTrips[a] = 0;
            if(tripped[a]){
                tripped[a] = false;
                //set input trip event to false
                String eventName = "Input_";
                eventName+=(a+1);
                Particle.publish(eventName, "OFF");
                Serial.print("eventName: ");
                Serial.println(eventName);
                Serial.print("eventContents: ");
                Serial.println("OFF");
            }
        }
        a++;
    }
}

int triggerRelay(String command){
    if(command.equalsIgnoreCase("turnonallrelays")){
        relayController.turnOnAllRelays();
        return 1;
    }
    if(command.equalsIgnoreCase("turnoffallrelays")){
        relayController.turnOffAllRelays();
        return 1;
    }
    if(command.startsWith("setBankStatus:")){
        int status = command.substring(14).toInt();
        if(status < 0 || status > 255){
            return 0;
        }
        Serial.print("Setting bank status to: ");
        Serial.println(status);
        relayController.setBankStatus(status);
        Serial.println("done");
        return 1;
    }
    //Relay Specific Command
    int relayNumber = command.substring(0,1).toInt();
    Serial.print("relayNumber: ");
    Serial.println(relayNumber);
    String relayCommand = command.substring(1);
    Serial.print("relayCommand:");
    Serial.print(relayCommand);
    Serial.println(".");
    if(relayCommand.equalsIgnoreCase("on")){
        Serial.println("Turning on relay");
        relayController.turnOnRelay(relayNumber);
        Serial.println("returning");
        return 1;
    }
    if(relayCommand.equalsIgnoreCase("off")){
        relayController.turnOffRelay(relayNumber);
        return 1;
    }
    if(relayCommand.equalsIgnoreCase("toggle")){
        relayController.toggleRelay(relayNumber);
        return 1;
    }
    if(relayCommand.equalsIgnoreCase("momentary")){
        relayController.turnOnRelay(relayNumber);
        delay(300);
        relayController.turnOffRelay(relayNumber);
        return 1;
    }
    return 0;
}

What’s the question?

Sorry, I thought it was in my post i.e.
“I would like to add a script with a countdown timer where I can add any time between 1 minute and 20 minutes e.g. once an IFTTT trigger activates a relay e.g. 1on I then want the countdown timer to initiate and once the time has elapsed I need it to trigger the relay off e.g. 1off.”

Have you looked into software timers in the docs, or the many examples of millis timers here on the forum?

Kind of, but not being a programmer by any means, it’s difficult for me to find the correct code script which I can add to the standard code I posted

I took the liberty to remove all these extrac blank lines that just help obscuring the active code my stretching the code out to fit as little code into one screen as possible :wink:

Did you try to understand what's going on in the code you posted?
We could hand you a working solution, but that's not the prime focus of this community. We'd rather enable people to do it themselves than spoon-feed solutions. And for that we need to know how much of the code you are already using is clear to you and how much not.
We rather point you the way than drive you there - the latter would get you there but wouldn't leave you any wiser.

Abstract:
triggerRelay() is the function you want to add a new action-command to which switches on the desired relay and starts a Software Timer (in one-shot mode) the turns the relay off when expired.
So your command string you pass to the function needs to take the action-command, the desired relay number and the number of minutes to set the timer to.

Hi, thanks for your advice / input. Although I don’t understand code at all, I managed to figure out the on, off and momentary scripts which I am using. I ‘bastardised’ the momentary script by increasing the time to try and get a few minutes instead of a few milliseconds, however I keep getting errors after it triggers, so doesn’t work well. So looks like I’ll get someone who knows code to write a script for me as per your suggestion.

Thanks

Sorry, but I think you missed the point of @Scruffr's suggestion. Getting someone else is opposite his suggestion.

He asked

The idea is for you to tell us how much you already know, so then he/we can direct you to do some learning for the next step. The idea is to help you do it yourself, with the community helping you with your learning, but never to do your project for you. In the end, the goal is for you to learn so you can have the accomplishment.

So, let us know what you tried when you modified the script, what exactly you want it to do and what the specific errors are.

1 Like

Hi All, I appreciate your help and suggestions, however I’m out of my depth here. I don’t know C++ or any coding languages and am just trying to fumble my way through by copying bits of code to attempt to alter outputs based on similar code. So I have this particle relay board which is triggered by different IFTTT inputs, and it works fine for the basic functions i.e. relay on, relay off, however I need a relay to operate for a set time once triggered by an IFTTT input e.g. using Weather Underground as an IFTTT trigger “If current temperature rises above 26 C, then irrigate for 6mins” Once triggered, relay 1 operates a solenoid which turns on my irrigation system. I ‘bastardised’ the code by extending the ‘momentary’ function from 300ms to 360,000 ms (6mins) but get an IFTTT error "“Particle error: Request Timed Out”. i.e.

// momentary 6mins
if(relayCommand.equalsIgnoreCase(“mom6”)){
relayController.turnOnRelay(relayNumber);
delay(360000);
relayController.turnOffRelay(relayNumber);
return 1;
}

So this is why I need a ‘proper’ timer code script to add to the whole script above. I’m so dumb when it comes to coding language that I don’t even know what commands to add! so commands like triggerRelay() and one-shot etc. are foreign to me. So instead of going on a full-on C++ course, I’m looking for a simple addition in the above code to enable a timer. It’s not as if I’m now going to start full on coding or anything :slight_smile:
Thanks…

Agreed that you are not going to start full-on coding tomorrow, but it is possible to eventually do that.
For now, the goal is to learn enough to solve the problem you have now.

For now, you have a great start since you are able to describe the desired behaviour:

Based on your very good description, it appears that the delay for 6 minutes is the issue.
This is something we can help you with.
What happens is your code ties up the Photon and prevents it from doing anything for 6 minutes.
6 minutes is a long time and the System part of your Photon gets out of sync.
The Particle cloud may think your device has gone off-line during that time.

So, you need a solution other than delay for 6 minutes.
@Scruffr gave you a really good hint:

Try researching Software Timers, try a couple of things and let us know when you are stuck again.

1 Like

What @cyclin_al is exactly my point.
You need to trust in yourself, this will open places in your mind you never new were there :wink:

For the error you see: When you issue a function request in the cloud, the cloud wants to know whether or not the request was successfully services or not. And as it happens that’s done when the function callback (e.g. triggerRelay()) hits a return x statement. But this has to happen within a few seconds of the request otherwise the caller assumes the request was not successful.

And there comes in your long delay as it also delays the execution of the following return statement.
And exactly that’s the reason why I suggested a one-shot Software Timer to cater for the time difference between the closing and the opening action.
The one-shot part can be achieved either by constructing the timer with four-parameter overload setting the fourth parameter true or by just calling timer.stop() inside the timer callback function.

Abstract:

  • declare a global Timer timer(....) object
  • declare a callback function for that timer that switches off the relay - when called
  • call timer.start() inside the respective branch of triggerRelay()
  • optionally add a second Particle.function() to receive, parse and set the variable delay time via timer.changePeriod() or incorporat that into your triggerRelay() as extra parameter (e.g. #momentary=ttt)