15min timer with disable and reset for relays

Hi guys!

so ive been using arduino for ages and made some cool projects now i want to make a project that i can sell as a kit only problem is i cant get some coding to work.

What i need is a twin relay set up which when you press one button it turns on for 15mins then turns off, but if i press another button it cancels the timer and keeps the relays on.

I've tried some example codes with no success as the enable/disable commands dont work.

I'm using serial for digital buttons and a mega for testing but will be using nano and push to make buttons for the final product.

ANSWERS ONLY!

Thanks!

(deleted)

I dont have any code yet as all i want is a timer code which i can turn on and off which i can then blend into other codes i have from previous projects

(deleted)

thank ive never heard of flags so im gunna look into that, heres the code i got so far: P.S. i cant find any real info on flags so i need some guidance on this please

const int button = 12;
const int brake = 13;
const int led = 14;
int bounceTime = 50;
int holdTime = 1500;
int doubleTime = 1000;
int lastReading = LOW;
int hold = 0;
int single = 0;
int LEDstate = 0;
long onTime = 0;
long lastSwitchTime = 0;
int incomingByte = 0;
int ledpin = 14;
char inData[50]; // Allocate some space for the string
char inChar = -1; // Where to store the character read
byte index = 0; // Index into array; where to store the character


void setup() {
 pinMode(button, INPUT);
 pinMode(brake, INPUT);
 pinMode(led, OUTPUT);
 digitalWrite(led, LOW);



 {
   pinMode(2, OUTPUT); // ON pin
   pinMode(3, OUTPUT); // START pin

   digitalWrite(2, HIGH);
   digitalWrite(3, HIGH);

 }
}

void loop()
{  
 int reading = digitalRead(button);

 //first pressed
 if (reading == HIGH && lastReading == LOW) {
   onTime = millis();
 }

 //held
 if (reading == HIGH && lastReading == HIGH) {
   if ((millis() - onTime) > holdTime) {
     invertLED();
     hold = 1;
   }
 }

 //released
 if (reading == LOW && lastReading == HIGH) {
   if (((millis() - onTime) > bounceTime) && hold != 1) {
     onRelease();
   }
   if (hold == 1) {
     digitalWrite(2, HIGH);
     digitalWrite(3, HIGH);
     delay(1000);
     digitalWrite(2, LOW);
     digitalWrite(3, LOW);
     delay(2000);
     digitalWrite(4, LOW);
     delay(1000);
     digitalWrite(4, HIGH);
     Serial.print("engine on");
     digitalWrite(13, HIGH);
     hold = 0;
   }
 }
 lastReading = reading;

 if (single == 1 && (millis() - lastSwitchTime) > doubleTime) {
   digitalWrite(2, HIGH);
   digitalWrite(3, HIGH);
   Serial.print("ign off");
   digitalWrite(13, LOW);
   delay(200);
   digitalWrite(13, HIGH);
   delay(200);
   digitalWrite(13, LOW);
   delay(200);
   digitalWrite(13, HIGH);
   delay(200);
   digitalWrite(13, LOW);
   delay(200);
   digitalWrite(13, HIGH);
   delay(200);
   digitalWrite(13, LOW);
   delay(200);
   digitalWrite(13, HIGH);
   delay(200);
   digitalWrite(13, LOW);
   single = 0;
 }

}


void onRelease() {

 if ((millis() - lastSwitchTime) >= doubleTime) {
   single = 1;
   lastSwitchTime = millis();
   return;
 }

 if ((millis() - lastSwitchTime) < doubleTime) {
   toggleLED();
   digitalWrite(13, HIGH);
   digitalWrite(13, LOW);
   digitalWrite(13, HIGH);
   digitalWrite(2, LOW);
   digitalWrite(3, LOW);
   Serial.print("ign on");
   single = 0;
   lastSwitchTime = millis();
 }
}

void toggleLED() {
 if (LEDstate == 0) {
   LEDstate = 1;
 } else {
   LEDstate = 0;
 }
 digitalWrite(led, LEDstate);
}

void invertLED() {
 if (LEDstate == 0) {
   digitalWrite(led, 1);
 } else {
   digitalWrite(led, 0);
 }
}

Moderator edit:
</mark> <mark>[code]</mark> <mark>

</mark> <mark>[/code]</mark> <mark>
tags added.

(deleted)

so.....how would i adapt this to working with timers?

royoung1:
so.....how would i adapt this to working with timers?

You are not working with a timer (I hope). You have a number of seconds/minutes/hours you want to count up to/down from.

If the "timer is running" flag is true, and a suitable interval has passed (one second/minute/hour), decrement (or increment) the (remaining) time and show the new value.

When you get to the limit, set the "timer is running" flag to false.

When you want to stop the timer, set the "timer is running" flag to false.

When you want to start/restart the timer, set the "timer is running" flag to true.

You have a number of inputs & outputs that you are using in loop() that do not match the names you created before setup() nor defined with pinMode( ) calls in setup().
You should fix those to be consistent, it will make debugging hardware/software problems easier later.

Review your Serial.print( ). I think many would benefit from being a Serial.println( ) so you get a carriage return/line feed on the serial monitor vs a big line of text that runs across and off the screen.

so in basic form it's

button 1 pressed > timer is running = true > relays on

button 2 pressed > timer is running = true > timer is running = false > relays on

or

button 1 pressed > timer is running = true > relays on

timer reached limit > timer is running = false > relays off

the serial print is only there for bench testing and wont be used in final product and the serial print makes a new line for me anyway

got it working on a 30 second delay for testing so ill try 15mins later but heres the code (and it only works in this order, ive tried different things and it either stops working or continuous loop)

 unsigned long Watch, _micro, time = micros();
unsigned int Clock = 0, R_clock;
boolean Reset = true, Stop = true, Paused = false;
volatile boolean timeFlag = true;
const int button = 12;
const int brake = 13;
const int led = 14;
int bounceTime = 50;
int holdTime = 1500;
int doubleTime = 1000;
int lastReading = LOW;
int hold = 0;
int single = 0;
int LEDstate = 0;
long onTime = 0;
long lastSwitchTime = 0;
int ledpin = 14;
int buttonState = 0;

void setup()
{
  Serial.begin(115200);
  SetTimer(0,0,30); // 10 seconds
  pinMode(button, INPUT);
  pinMode(brake, INPUT);
  pinMode(led, OUTPUT);
  digitalWrite(led, LOW);
   pinMode(5, OUTPUT); // ON pin
   pinMode(4, OUTPUT); // START pin
   pinMode(3, OUTPUT); // ON pin
   pinMode(2, OUTPUT); // START pin

    digitalWrite(5, HIGH);
    digitalWrite(4, HIGH);
    digitalWrite(3, HIGH);
    digitalWrite(2, HIGH);
}

void loop()
{
  int reading = digitalRead(button);

  //first pressed
  if (reading == HIGH && lastReading == LOW) {
    onTime = millis();
  }

  //held
  if (reading == HIGH && lastReading == HIGH) {
    if ((millis() - onTime) > holdTime) {
      invertLED();
      hold = 1;
    }
  }
   //released
  if (reading == LOW && lastReading == HIGH) {
    if (((millis() - onTime) > bounceTime) && hold != 1) {
      onRelease();
    }
    if (hold == 1) {
      
      hold = 0;
    }
  }
  lastReading = reading;

  if (single == 1 && (millis() - lastSwitchTime) > doubleTime) {
    digitalWrite(5, HIGH);
        digitalWrite(2, HIGH);
        delay(2000);
        digitalWrite(3, HIGH);
    single = 0;
  }
  
 
CountDownTimer(); // run the timer
 buttonState = digitalRead(brake);
  // this prevents the time from being constantly shown.
  if (TimeHasChanged() ) 
  {
    Serial.print(ShowHours());
    Serial.print(":");
    Serial.print(ShowMinutes());
    Serial.print(":");
    Serial.print(ShowSeconds());
    Serial.print(":");
    Serial.print(ShowMilliSeconds());
    Serial.print(":");
    Serial.println(ShowMicroSeconds());
    // This DOES NOT format the time to 0:0x when seconds is less than 10.
    // if you need to format the time to standard format, use the sprintf() function.
  }
}

boolean CountDownTimer()
{
  static unsigned long duration = 1000000; // 1 second
  timeFlag = false;

  if (!Stop && !Paused) // if not Stopped or Paused, run timer
  {
    // check the time difference and see if 1 second has elapsed
    if ((_micro = micros()) - time > duration ) 
    {
      Clock--;
      timeFlag = true;

      if (Clock == 0) // check to see if the clock is 0
        Stop = true; // If so, stop the time

         if (buttonState == HIGH)
              Stop = true;

              if (buttonState == HIGH)
              digitalWrite(2, LOW);

            if(Clock == 0)
             digitalWrite(5, HIGH);
             if(Clock == 0)
             digitalWrite(3, HIGH);
             if(Clock == 0)
             digitalWrite(2, HIGH);



     // check to see if micros() has rolled over, if not,
     // then increment "time" by duration
      _micro < time ? time = _micro : time += duration; 
    }
  }
  return !Stop; // return the state of the timer


      
}
void onRelease() {

  if ((millis() - lastSwitchTime) >= doubleTime) {
    single = 1;
    lastSwitchTime = millis();
    return;
  }

  if ((millis() - lastSwitchTime) < doubleTime) {
    toggleLED();
    ResetTimer();
    delay(1000);
    digitalWrite(3, LOW);
    digitalWrite(5, LOW);
    delay(500);
    digitalWrite(4, LOW);
    delay(500);
    digitalWrite(4, HIGH);
    single = 0;
    lastSwitchTime = millis();
  }
}

void toggleLED() {
  if (LEDstate == 0) {
    LEDstate = 1;
  } else {
    LEDstate = 0;
  }
  digitalWrite(led, LEDstate);
}

void invertLED() {
  if (LEDstate == 0) {
    digitalWrite(led, 1);
  } else {
    digitalWrite(led, 0);
  }
}
void ResetTimer()
{
  SetTimer(R_clock);
  Stop = false;
}

void StartTimer()
{
  Watch = micros(); // get the initial microseconds at the start of the timer
  Stop = false;
  Paused = false;
}

void StopTimer()
{
  Stop = true;
}

void StopTimerAt(unsigned int hours, unsigned int minutes, unsigned int seconds)
{
  if (TimeCheck(hours, minutes, seconds) )
    Stop = true;
}

void PauseTimer()
{
  Paused = true;
}

void ResumeTimer() // You can resume the timer if you ever stop it.
{
  Paused = false;
}

void SetTimer(unsigned int hours, unsigned int minutes, unsigned int seconds)
{
  // This handles invalid time overflow ie 1(H), 0(M), 120(S) -> 1, 2, 0
  unsigned int _S = (seconds / 60), _M = (minutes / 60);
  if(_S) minutes += _S;
  if(_M) hours += _M;

  Clock = (hours * 3600) + (minutes * 60) + (seconds % 60);
  R_clock = Clock;
  Stop = false;
}

void SetTimer(unsigned int seconds)
{
 // StartTimer(seconds / 3600, (seconds / 3600) / 60, seconds % 60);
 Clock = seconds;
 R_clock = Clock;
 Stop = false;
}

int ShowHours()
{
  return Clock / 3600;
}

int ShowMinutes()
{
  return (Clock / 60) % 60;
}

int ShowSeconds()
{
  return Clock % 60;
}

unsigned long ShowMilliSeconds()
{
  return (_micro - Watch)/ 1000.0;
}

unsigned long ShowMicroSeconds()
{
  return _micro - Watch;
}

boolean TimeHasChanged()
{
  return timeFlag;
}

// output true if timer equals requested time
boolean TimeCheck(unsigned int hours, unsigned int minutes, unsigned int seconds) 
{
  return (hours == ShowHours() && minutes == ShowMinutes() && seconds == ShowSeconds());
}
  SetTimer(0,0,30); // 10 seconds

Really?

void SetTimer(unsigned int hours, unsigned int minutes, unsigned int seconds)
{
  // This handles invalid time overflow ie 1(H), 0(M), 120(S) -> 1, 2, 0
  unsigned int _S = (seconds / 60), _M = (minutes / 60);
  if(_S) minutes += _S;
  if(_M) hours += _M;

  Clock = (hours * 3600)

If hours is greater than 11, you'll overflow. You need to handle THAT overflow, too.

Is it really too much trouble to declare ONE variable per line?

CountDownTimer(); // run the timer
 buttonState = digitalRead(brake);
  // this prevents the time from being constantly shown.
  if (TimeHasChanged() )
  {

What was the point of reading the pin? Why is buttonState global? You don't use the value in loop()? Why does buttonState hold the value of the brake pin? Wouldn't brakeState be more appropriate? Why do you have a brake on the clock? Does it have a parking brake too?

Or was that supposed to be break?

Use Tools + Auto Format before posting any more crappily indented code.