A cyclic timer program with input dependent condition

It's a cyclic timer program code, which will give continuous 1.5 sec on, 2.5 seconds off cycle. I want to add two digital inputs, 1. If input 1 is off it should stop the cycle and output. When it becomes on, cycle restarts again.
2. Second digital input if remains off during on period, the cycle should continue on/off, if Second digital input is "on" during on time, then cycle should stop and output remains "on" until digital input "1" is on or digital input "2" is off.
If digital input "1" is on, then cycle should stop until it goes off.
Note: I am using Arduino Uno R3

const int RELAY_PIN = A5;  // the Arduino pin, which connects to the IN pin of relay
int inputPin_1 = 2;
int inputPin_2 = 3;
int Val_1 = LOW;
int Val_2 = HIGH;
float lastTimerTime = millis();

// the setup function runs once when you press reset or power the board
void setup() {
  // initialize digital pin A5 as an output
  pinMode(RELAY_PIN, OUTPUT);
  pinMode(inputPin_1, INPUT);
  pinMode(inputPin_2, INPUT);
}

// the loop function runs over and over again forever
void loop() {
  // conditions can be given as
  Val_1 = digitalRead(inputPin_1);
  Val_2 = digitalRead(inputPin_2);

  if (Val_1 == LOW) {
    return;
  }
  else if (Val_1 == HIGH) {
    //do you stuff here 1000 is 1 second
    // 1000 x 60 is one minute
    // 60000 x 1.5 minutes is 90000 milliseconds

    if ((millis() - lastTimerTime) > 90000) {
      digitalWrite(RELAY_PIN, HIGH);
      lastTimerTime = millis(); // reset the timer
      if (Val_2 == LOW) {
        digitalWrite(RELAY_PIN, HIGH); // turn on pump 1.5 seconds
        delay(1500);
        digitalWrite(RELAY_PIN, LOW);  // turn off pump 2.5 seconds
        delay(2500);
      }
      else {
        if (Val_1 == LOW || Val_2 == HIGH) {
          digitalWrite(RELAY_PIN, HIGH);
        }
        else{
          return;
        }
      }
    }
  }
}

The code is compiled and uploaded successfully but there's no output. I am new in Arduino Programming so can't figure out where is the problem.

You didn't mention it in your problem description, but are you waiting the requisite 90 seconds your code requires before doing anything with the relay?

I put that condition because i wanted to check the Value of input 2 between the time period when Relay_pin is High. I didn't know that it is causing the program to wait for 90 seconds before doing anything.

This?

 if ((millis() - lastTimerTime) > 90000) {

Do your inputs have pull-up or pull-down resistors installed? Your code demands it. A more common approach it to declare them as INPUT_PULLUP and connect one side to ground and the other to the input pin. Reading LOW means the switch is closed.

Ok​:+1:t2::+1:t2: let me try this.

Do you want input 1 to wait for the cycle to complete until it is off and hold it off, or chop it to off immediately?

Do you want input 2 to wait for the cycle to complete until is is or, or immediately turn the output to on?

who wins if input 1 and input 2 are both in effect at once?

Don’t say you’ll never do both input 1 and 2, ir is better to have a known outcome in that circumstance than to promise that the circumstance will not arise.

a7

1 Like

Actually I want the inputs to be changed manually regardless of these conditions.
Until now I have not defined the output for the condition you have mentioned.
My measure problem is that how to check the value of input 2 in between the On cycle, and to decide what will happen next according to the value of input 2.

In order for your inputs to be acted upon immediately, you have to get rid of those delay() functions and just track elapsed time. Look at the Blink Without Delay example in the IDE (File->examples->02.Digital->Blink Without Delay). You should also debounce your inputs and detect when a switch changes state, not just what state it is in. File->Examples->02.Digital->State Change Detection.

Then, you get something like this (untested):
(and you didn't say if you have pullup resistors on those inputs)

const int RELAY_PIN = A5;  // the Arduino pin, which connects to the IN pin of relay
const int inputPin_1 = 2;
const int inputPin_2 = 3;
unsigned long lastTimerTime;
const unsigned long onPeriod = 1500;  // on time in milliseconds
const unsigned long offPeriod = 2500;
unsigned long cyclePeriod;
bool isCycleOn = false;

int prevVal_1;
int prevVal_2;

enum { RELAY_OFF, RELAY_ON, RELAY_CYCLE };
int state;

// the setup function runs once when you press reset or power the board
void setup() {
  // initialize digital pin A5 as an output
  pinMode(RELAY_PIN, OUTPUT);
  digitalWrite( RELAY_PIN, LOW );
  state = RELAY_OFF;
  pinMode(inputPin_1, INPUT);
  pinMode(inputPin_2, INPUT);
  prevVal_1 = digitalRead(inputPin_1);
  prevVal_2 = digitalRead(inputPin_2);
}


void loop() {
  // read pins to see if anything has changed
  int Val_1 = digitalRead(inputPin_1);
  int Val_2 = digitalRead(inputPin_2);
  int oldState = state;

  /*
     read inputs and update state
     and debounce any pin changes so relay
     doesn't toggle back and forth
  */

  if (Val_1 != prevVal_1) {
    // switch one has changed state
    if (Val_1 == LOW) {
      // relay is off
      state = RELAY_OFF;
    }
    else {
      // relay depends on Val_2, assume normal
      state = RELAY_CYCLE;
    }
    delay(20);  // debounce switch 1
    prevVal_1 = Val_1;
  }

  if (Val_2 != prevVal_2) {
    // switch two has changed state
    if (Val_2 == LOW) {
      // normal relay cycling
      state = RELAY_CYCLE;
    }
    else {
      // relay always on
      state = RELAY_ON;
    }
    delay(20);  // debounce switch 2
    prevVal_2 = Val_2;
  }

  /*
     if the state has changed, do anything
     required to start the new state
  */

  if ( state != oldState ) {
    switch (state) {
      case RELAY_OFF:
        digitalWrite(RELAY_PIN, LOW);
        break;

      case RELAY_ON:
        digitalWrite(RELAY_PIN, HIGH);
        break;

      case RELAY_CYCLE:
        digitalWrite(RELAY_PIN, HIGH);
        lastTimerTime = millis();
        isCycleOn = true;
        cyclePeriod = onPeriod;
    }
  }

  /*
     Update based on elapsed time and state we are in
  */

  switch (state) {
    case RELAY_OFF:
      // nothing more to do
      break;

    case RELAY_ON:
      // nothing more to do
      break;

    case RELAY_CYCLE:
      if ( millis() - lastTimerTime >= cyclePeriod ) {
        // time to toggle the relay
        lastTimerTime = millis();
        if (isCycleOn) {
          cyclePeriod = offPeriod;
          digitalWrite(RELAY_PIN, LOW);
          isCycleOn = false;
        }
        else {
          cyclePeriod = onPeriod;
          digitalWrite(RELAY_PIN, HIGH);
          isCycleOn = true;
        }
      }
  }
}

I got your point. Let me test it. Thank you for helping.

This has confused me. Please confirm:

  • One input can immediately stop the cyclic timer and take the relay to OFF.

  • The other input will stop the cyclic timer and take the relay to ON, but the relay will not go to the ON condition until it would have anyway due to the cyclic timing. Then it stays on as long as the second input is unchanged.

The asymmetry of these requirements is confusing. It would help everyone, well me least, if you explained why you need it to be just this way, or correct any mistakes I have made interpreting your prose.

Perhaps a more careful description of the desired functions. And you could draw a timing diagram.

It doesn't seem like you ever care about the transition of the inputs, only their level. It still means you need debouncing, but you do not (seem) to need edge detection.

Do you care that with the button that can stop and take the relay OFF immediately you can end up with very short ON period?

When the cyclic behaviour resumes, where in the ON and OFF cycle should it restart at, for each input when the input is changed to free the cyclic timer?

a7

Hello
Post a timing diagram for your sketch to clarify the input to output behaiviour.
And describe this in simple words and very simple.

This code solved my problem. Thank you.

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