How to stop a timer delay using millis() from executing with NRF24L01 Network

Hello,
what i have in my circuit is 2 push buttons, the first for starting a timer of 3 seconds which then when the timer is done it sends a 1 to the NRF24L01 which turn a relay on for a specific time which is 3 seconds then turn it off by sending 0 to NRF24L01. The second button is reset button which if the timer did not finish, it prevents the 1 from being sent through the NRF24L01. My connection are good I tested them separately and they are working well and my NRF24L01 code is good it sends data that i want, my only problem is how to stop the timer from being executed if the 1 has not been sent means if the relay is not on but if the relay is on and i clicked reset, I don't want this reset to stop the relay which is working to finish it's time which is 3 seconds on.

here is my code so far:

#include <SPI.h>
#include <RF24.h>
#include <RF24Network.h>

RF24 radio(9, 10);               // nRF24L01 (CE,CSN)
RF24Network network(radio);      // Include the radio in the network
const uint16_t this_node = 00;   // Address of this node in Octal format ( 04,031, etc)
const uint16_t node01 = 01;


int relayButtonPin = A2;
int resetButton = 8;


boolean lastRelay5_pb = LOW;
boolean currentRelay5_pb = LOW;
boolean relay5PushBOn = false;
int relay5NumClicks = 0;
boolean relay5Working = false;
int relay5Data;


boolean okToPrint = true;

boolean lastReset = LOW;
boolean currentReset = LOW;
boolean resetPushBOn = false;
int resetNumClicks = 0;
boolean resetWorking = false;

unsigned long interval = 3000;
unsigned long startClickTime;
unsigned long startResetTime;



void setup()
{
  // put your setup code here, to run once:
  Serial.begin(9600);
  pinMode(relayButtonPin, INPUT);


  SPI.begin();
  radio.begin();
  network.begin(90, this_node);  //(channel, node address)
  radio.setDataRate(RF24_2MBPS);
}

void loop()
{
  // This is for the Relay 5 Push button connected to A2 ---------------------------------------
  currentRelay5_pb = debounce(lastRelay5_pb, relayButtonPin);
  if (lastRelay5_pb == LOW && currentRelay5_pb == HIGH)
  {
    relay5PushBOn = !relay5PushBOn;
    relay5NumClicks++;
    
    okToPrint = true;
  }
  lastRelay5_pb = currentRelay5_pb;

  if(relay5Working == false && relay5NumClicks >= 2){
    relay5Working = true;
    startClickTime = millis();
    relay5Data = 1;
  }

  if(relay5Working == true){
    relay5NumClicks = 0;
    
  }
  
  // This is for reset button
  currentReset = debounce(lastReset, resetButton);
  if (lastReset == LOW && currentReset == HIGH)
  {
    resetPushBOn = !resetPushBOn;
    resetNumClicks++;
    
  }
  lastReset = currentReset;

  if(resetWorking == false && resetNumClicks >= 1){
    resetWorking = true;
    okToPrint = false;
    startResetTime = millis();
    relay5Data = 0;
  }

  if(resetWorking == true){
    resetNumClicks = 0;
  }
  Serial.print("Print: ");
  Serial.println(relay5Data);
  if(millis() - startResetTime > interval){
    okToPrint = true;
  }
  
  if (millis() - startClickTime > interval){
    if (okToPrint)
    {
      Serial.print("ok send: ");
      Serial.println(relay5Data);
      
    }
  }

  bool ok1 = network.write(header1, &relay5Data, sizeof(relay5Data)); // Send the data
}

// Debouncing function
boolean debounce(boolean last, int switchPin)
{
  boolean current = digitalRead(switchPin);
  if (last != current)
  {
    delay(5);
    current = digitalRead(switchPin);
  }
  return current;
}

You need to do more of a state machine sort of thing... [untested]

#include <SPI.h>
#include <RF24.h>
#include <RF24Network.h>

RF24 radio(9, 10);               // nRF24L01 (CE,CSN)
RF24Network network(radio);      // Include the radio in the network
const uint16_t this_node = 00;   // Address of this node in Octal format ( 04,031, etc)
const uint16_t node01 = 01;

const int relayButtonPin = A2;
const int resetButton = 8;

int relay5Data;

const unsigned long armDelay = 3000;
const unsgined long relayOnDelay = 3000;
unsigned long startArmTime;
unsigned long startOnTime;


enum { RELAY_OFF, RELAY_ARMED, RELAY_ON };
int state = RELAY_OFF;

void setup()
{
  // put your setup code here, to run once:
  Serial.begin(9600);
  pinMode(relayButtonPin, INPUT);
  pinMode(resetButtonPin, INPUT);

  SPI.begin();
  radio.begin();
  network.begin(90, this_node);  //(channel, node address)
  radio.setDataRate(RF24_2MBPS);
}

void loop()
{
  // check relay button
  int currentRelayState = digitalRead(relayButtonPin);
  if (lastRelayState != currentRelayState ) {
    if ( currentRelayState == HIGH ) {
      // we just got a button push
      switch (state) {
        case RELAY_OFF:
          // start the countdown to relay activation
          startClickTime = millis();
          state = RELAY_ARMED;
          Serial.print("Armed");

          break;

        case RELAY_ARMED:
          // already waiting so reset the time to begin again
          startArmTime = millis();
          Serial.print("ReArmed");
          break;

        case RELAY_ON:
          // relay has already been actived, ignore button press
          break;
      }
    }
    delay(50);
  }
  lastRelayState = currentRelayState;

  // check reset button
  int currentResetState = digitalRead(resetButtonPin);
  if (lastResetState != currentResetState ) {
    if ( currentResetState == HIGH ) {
      // we just got a button push
      switch (state) {
        case RELAY_OFF:
          // nothing to reset
          break;

        case RELAY_ARMED:
          // waiting to activate relay to cancel
          state = RELAY_OFF;
          Serial.print("Reset");
          break;

        case RELAY_ON:
          // relay has already been actived, ignore button press
          break;
      }
    }
    delay(50);
  }
  lastResetState = currentResetState;

  // check our current state
  switch (state) {
    case RELAY_OFF:
      // nothing to do
      break;

    case RELAY_ARMED:
      // waiting for timer to expire
      if ( millis() - startArmTime >= armDelay ) {
        // turn relay on
        //bool ok1 = network.write(header1, &relay5Data, sizeof(relay5Data)); // Send the data
        state = RELAY_ON;
        startOnTime = millis();
        Serial.print("On");
      }
      break;

    case RELAY_ON:
      // waiting for timer to expire
      if ( millis() - startOnTime >= relayOnDelay ) {
        // turn relay off
        //bool ok1 = network.write(header1, &relay5Data, sizeof(relay5Data)); // Send the data
        state = RELAY_OFF;
        Serial.print("Off");
      }
      break;
  }
}

Typically you add a timerRunning variable to keep track of that.
I use my millisDelay class that keep track of that internally so I can just call
timer.stop();
See my tutorial How to write Timers and Delays in Arduino

thank you everyone so much for your help, today i started a new job, so when i come back from work i will check your solutions and test them :slight_smile:

but i have another question, i learned today that there is something about millis() reseting to 0 after 49 days ? but i did not understand what it would affect the program if it resets to 0, i mean if the millis() record a value of 1000ms that wouldn't create a problem if i understood how the reset works, would it ?

The reset to zero is not a problem if you use millis() properly by which I mean you use subtraction of period start time from current time to determine whether the required period has elapsed

mllis() returns an unsigned long, but the reason why the reset to zero does not matter is easier to understand using smaller numbers such as 0 to 255 held by a byte variable

Suppose the start value is 230 and the current value is 240. The elapsed period is therefore 240 - 230, ie 10. OK so far

Suppose that the start value is 250, the variable value rolls over and the current value is now 5. At first sight the elapsed period is 5 - 250, ie -245. However, the variable is unsigned, so the actual elapsed period is 5 - 250 +255 (because of the rollover), ie 10

The important thing is that the values are unsigned

UKHeliBob:
The reset to zero is not a problem if you use millis() properly by which I mean you use subtraction of period start time from current time to determine whether the required period has elapsed

mllis() returns an unsigned long, but the reason why the reset to zero does not matter is easier to understand using smaller numbers such as 0 to 255 held by a byte variable

Suppose the start value is 230 and the current value is 240. The elapsed period is therefore 240 - 230, ie 10. OK so far

Suppose that the start value is 250, the variable value rolls over and the current value is now 5. At first sight the elapsed period is 5 - 250, ie -245. However, the variable is unsigned, so the actual elapsed period is 5 - 250 +255 (because of the rollover), ie 10

The important thing is that the values are unsigned

i see, ok thank you :slight_smile:

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.