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
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