Running solenoid valve logic on Arduino based on time

I want to write a program to activate 5 relays connected to 5 solenoid valves based on a particular logic.
These relays are to be turned-on in specific intervals.
I am using Mega 2560. How do i set arduino pins high and low at different timings.

Please.

This can be extremely simple. I suggest you slow your roll a bit and work through the simple basic programs from the examples in the IDE.

Then give it a whirl. You could use LEDs to experiment instead of “real” solenoids.

Show us what you got working, or why you can’t make what you write work.

You can get help walking here, and running, too, but you kinda have to stand up on two feet youself first.

a7

#include "MCUFRIEND_kbv.h"
#include "TouchScreen.h"
#include "Adafruit_GFX.h"
MCUFRIEND_kbv tft;

#define LCD_CS A3
#define LCD_CD A2
#define LCD_WR A1
#define LCD_RD A0
#define LCD_RESET A4

#define MINPRESSURE 200
#define MAXPRESSURE 1000

const int XP = 6, XM = A2, YP = A1, YM = 7; //240x320 ID=0x3229
const int TS_LEFT = 864, TS_RT = 195, TS_TOP = 76, TS_BOT = 895;

TouchScreen ts = TouchScreen(XP, YP, XM, YM, 300);
TSPoint tp;
Adafruit_GFX_Button sub_btn, add_btn;

int pixel_x, pixel_y;
bool Touch_getXY()
{
  TSPoint p = ts.getPoint();
  pinMode(YP, OUTPUT);
  pinMode(XM, OUTPUT);
  digitalWrite(YP, HIGH);
  digitalWrite(XM, HIGH);
  bool pressed = (p.z > MINPRESSURE && p.z < MAXPRESSURE);
  if (pressed) {
    pixel_x = map(p.x, TS_LEFT, TS_RT, 0, tft.width());
    pixel_y = map(p.y, TS_TOP, TS_BOT, 0, tft.height());
  }
  return pressed;
}
#define BLACK   0x0000
#define BLUE    0x001F
#define RED     0xF800
#define GREEN   0x07E0
#define CYAN    0x07FF
#define MAGENTA 0xF81F
#define YELLOW  0xFFE0
#define WHITE   0xFFFF

int motor = 45;
int volt = 0;
int diff = 10;
int test = 53;
int V1;
int V2;

int a = 0;
int b = 0;
int c = 0;

long int time1;
long int time2;
long int interval;

void setup()
{
  Serial.begin(9600);
  uint16_t ID = tft.readID();
  tft.reset();
  tft.begin(0x3229);
  tft.setRotation(0);

  tft.setCursor(38, 5);
  tft.setTextColor(WHITE);
  tft.setTextSize(2);
  tft.print("PRECISION");

  tft.setCursor(13, 25);
  tft.setTextColor(WHITE);
  tft.setTextSize(2);
  tft.print("PRODUCTS PVT. LTD.");

  /*tft.setCursor(80, 35);
    tft.setTextColor(WHITE);
    tft.setTextSize(2);
    tft.print("PVT. LTD.");*/

  tft.setCursor(70, 50);
  tft.setTextColor(WHITE, RED);
  tft.setTextSize(3);
  tft.print("Oxygen");

  tft.setCursor(12, 80);
  tft.setTextColor(WHITE, RED);
  tft.setTextSize(3);
  tft.print("Concentrator");

  sub_btn.initButton(&tft,  37, 150, 70, 40, WHITE, CYAN, BLACK, "-", 3);
  add_btn.initButton(&tft, 203, 150, 70, 40, WHITE, CYAN, BLACK, "+", 3);
  sub_btn.drawButton(false);
  add_btn.drawButton(false);

  pinMode(motor, OUTPUT);
  pinMode(31, INPUT);
  pinMode(33, INPUT);
  pinMode(35, OUTPUT);
  pinMode(37, OUTPUT);
  digitalWrite(35, HIGH);
  digitalWrite(37, HIGH);
}
void loop()
{
  bool down = Touch_getXY();
  sub_btn.press(down && sub_btn.contains(pixel_x, pixel_y));
  add_btn.press(down && add_btn.contains(pixel_x, pixel_y));

  if (sub_btn.justReleased())
    sub_btn.drawButton();
  if (add_btn.justReleased())
    add_btn.drawButton();
  if (sub_btn.justPressed()) {
    sub_btn.drawButton(true);
    if (volt > 0) volt = volt - diff;
    Serial.print("no");
  }
  if (add_btn.justPressed()) {
    add_btn.drawButton(true);
    if (volt < 245) volt = volt + diff;
    Serial.print("yes");
  }
  tft.setCursor(72, 135);
  tft.setTextColor(TFT_RED, TFT_BLACK);
  tft.setTextSize(4);
  tft.print(volt);
  tft.print(" ");

  analogWrite(53, 25);
  int pressureValue = analogRead(44);
  // Convert the analog reading (which goes from 0 - 1023) to a voltage (0 - 5V):
  float pressure = pressureValue * (5.0 / 1023.0);

  tft.setCursor(70, 250);
  tft.setTextColor(TFT_RED, TFT_BLACK);
  tft.setTextSize(4);
  tft.print(interval);

  analogWrite(motor, volt);
  V1 = digitalRead(31);
  V2 = digitalRead(33);

  if (a < 1 & V1 == HIGH & V2 == LOW) {
    Serial.println("Time1");
    time1 = millis();
    Serial.println(time1);
    a++;
  }
  if (b < 1  & V2 == HIGH & V1 == LOW) {
    Serial.println("Time2");
    time2 = millis();
    Serial.println(time2);
    interval = time2 - time1;
    Serial.println(interval);
    b++;
  }
}

This is what I have written till now. The code consists of some text, number value with inc/dec touch buttons, time value between two inputs. But how do I keep turning on and off outputs continuously, following a particular sequence. Should I use millis function?

here is a demo-code that shows the principle of non-blocking timing.

If you find this code difficult to understand please read the tutorials about timing with millis()
These tutorials use more words to explain in detail how it works

unsigned long currentMillis;

unsigned long Period = 1000; // after 1000 milliseconds a "period" has passed by
unsigned long LastTime_Period_Elapsed;

unsigned long SlowDownPeriod = 20;  // print a new character every 20 milliseconds so your eyes can follow the serial-output
unsigned long LastTime_SlowDownPeriod_Elapsed;

unsigned long DoubleCrossPeriod = 5 * SlowDownPeriod; // every 5th character shall be a #
unsigned long LastTime_DoubleCrossPeriod_Elapsed;

int NumberOfElapsedPeriods = 0;

const char dot = '.';
const char doubleCross = '#';
char CharToPrint;

void setup() {
  Serial.begin(115200);
  LastTime_Period_Elapsed = millis();
  LastTime_SlowDownPeriod_Elapsed = millis();
  LastTime_DoubleCrossPeriod_Elapsed = millis();
}

void loop() {  // main-loop is running at high speed
  currentMillis = millis(); // update timing-variable each time the main-loop starts again

  visualiseLooping();       // this function gets called with every run of the loop
                            // but contains logic to execute parts of its code 
                            // only if a certain amount of time has passed by


  // this part shows the same principle check if a certain amount of time has passed by
  // if yes execute commands inside the if-condition

  // the variable period contains the number of milliseconds
  // if THIS number of milliseconds has passed by the if-condition becomes true
  // ==> the code inside the if-condition is executed 
  
  if (currentMillis - LastTime_Period_Elapsed >= Period) { 
    LastTime_Period_Elapsed = currentMillis; // first thing to do is updating this variable 
    NumberOfElapsedPeriods ++;
    Serial.println();
    Serial.print(NumberOfElapsedPeriods);
    Serial.println(" period is over");
  }
}



// every time a certain amount of time has passed by a character is printed to the serial monitor
// for your application you just put your code that shall be executed in such a timing-pattern 
// inside the if-condition that checks the time that has passed by

void visualiseLooping() {
  if (currentMillis - LastTime_DoubleCrossPeriod_Elapsed >= DoubleCrossPeriod) {
    LastTime_DoubleCrossPeriod_Elapsed = currentMillis;
    CharToPrint = doubleCross;
  }
  else {
    CharToPrint = dot;
  }

  if (currentMillis - LastTime_SlowDownPeriod_Elapsed >= SlowDownPeriod) {
    LastTime_SlowDownPeriod_Elapsed = currentMillis;
    Serial.print(CharToPrint);
  }  
}

best regards Stefan

But how do I keep turning on and off outputs continuously, following a particular sequence.

is a still more or less unprecise description of what should happen.
Best thing would be to draw a diagram that has a line for each of your 5 channels and the diagram shows an example
how all these five channels shall switch ON/OFF

Add information if all channels should work independent of each other or if you want to have the channels be in some kind of synchronisation like "each time channel 3 switches OFF channel 1 shall switch ON after an additional time of x seconds

best regards Stefan

#include "MCUFRIEND_kbv.h"
MCUFRIEND_kbv tft;

unsigned long Period = 1000;
unsigned long currentMillis;
unsigned long current_RF;
unsigned long lasttime_RF;
unsigned long current_LW;
unsigned long lasttime_LW;

bool RF = 0;
bool LW = 0;
bool LF = 0;
bool RW = 0;
bool EQ = 1;

bool SR1 = 0;
bool SR2 = 0;

void setup() {
  tft.begin(0x3229);
  tft.setRotation(0);
  tft.fillScreen(TFT_BLACK);
  Serial.begin(9600);
  currentMillis = millis();
  tft.fillRect(205, 260, 40, 40, TFT_GREEN);
}
void loop()
{
  RFLW ();
}
void RFLW ()
{
  current_RF = millis();
  if (RF == 0 & LW == 0 & LF == 0 & RW == 0 & EQ == 1 & current_RF - currentMillis >= Period * 2) {
    RF = 1;
    tft.fillRect(5, 260, 40, 40, TFT_GREEN);
    Serial.println("RF=ON");
  }
  if (RF == 1 & LW == 0 & LF == 0 & RW == 0 & EQ == 1 & SR1 == 0 & current_RF - currentMillis >= Period * 3) {
    LW = 1;
    tft.fillRect(55, 260, 40, 40, TFT_GREEN);
    EQ = 0;
    tft.fillRect(205, 260, 40, 40, TFT_RED);
    Serial.println("LW=ON");
    SR1 = 1;
  }
  if (RF == 1 & LW == 1 & LF == 0 & RW == 0 & EQ == 0  & current_RF - currentMillis >= Period * 4) {
    EQ = 1;
    tft.fillRect(205, 260, 40, 40, TFT_GREEN);
    Serial.println("EQ=ON");
  }
  if (LW == 1 & RF == 1  & LF == 0 & RW == 0 & EQ == 1 & SR1 == 1 &  current_RF - currentMillis >= Period * 5) {
    LW = 0;
    tft.fillRect(55, 260, 40, 40, TFT_RED);
    Serial.println("LW=OFF");
  }
  if (LW == 0 & RF == 1  & LF == 0 & RW == 0 & EQ == 1 &  current_RF - currentMillis >= Period * 6)  {
    RF = 0;
    tft.fillRect(5, 260, 40, 40, TFT_RED);
    LF = 1;
    tft.fillRect(105, 260, 40, 40, TFT_GREEN);
    Serial.println("RF=OFF");
  }
  if (LW == 0 & RF == 0  & LF == 1 & RW == 0 & EQ == 1 & SR2 == 0 & current_RF - currentMillis >= Period * 7) {
    RW = 1;
    tft.fillRect(155, 260, 40, 40, TFT_GREEN);
    EQ = 0;
    tft.fillRect(205, 260, 40, 40, TFT_RED);
    Serial.println("EQ=OFF");
    SR2 = 1;
  }
  if (RF == 0 & LW == 0 & LF == 1 & RW == 1 & EQ == 0 &  current_RF - currentMillis >= Period * 8) {
    EQ = 1;
    tft.fillRect(205, 260, 40, 40, TFT_GREEN);
    Serial.println("LW=ON");
  }
  if (LW == 0 & RF == 0  & LF == 1 & RW == 1 & EQ == 1 & SR2 == 1 & current_RF - currentMillis >= Period * 9) {
    RW = 0;
    tft.fillRect(155, 260, 40, 40, TFT_RED);
    Serial.println("RW=OFF");
  }
  if (LW == 0 & RF == 0  & LF == 1 & RW == 0 & EQ == 1 &  current_RF - currentMillis >= Period * 10) {
    LF = 0;
    tft.fillRect(105, 260, 40, 40, TFT_RED);
    Serial.println("LF=OFF");
    current_RF = 0;
    currentMillis = millis();
    SR1 = 0;
    SR2 = 0;
  }
}

This is what I've written.
It works but are there better ways to write this code? Easier and efficient.

I'm wondering that your code is working because you use the bitwise AND-operator "&" a single "&"

usially in if-conditions thet check for multiple conditions like

(RF == 0 & LW == 0

the logical AND "&&" a double "&&" is used.

so your if-condition would look like this

if (RF == 0 && LW == 0 && LF == 0 && RW == 0 && EQ == 1 && current_RF - currentMillis >= Period * 2) {

a comparison like "RF == 0" results in true or false. As your variables are of type boolean you can use
the variables itself and in case of 0 with the not-operator

if (!RF && !LW && !LF && !RW && EQ && (current_RF - currentMillis >= Period * 2) ) {

The timing-pattern is mutliples of period. This could be coded with using arrays which would shorten the code
but is harder to read and understand.

More efficient to maintain is using self-explaining names. If you want to modify this code in half a year or later
I estimate you have difficulties to remember what was "RF" for?? what was "EQ" for ??

Your brain has to do a lot of additional translations instead of reading a selfexplaining name

It works to assign boolean variables the integernumbers 0 and 1.
Usually the are assigned true and false which indicates that the variable is of type boolean so you don't have to look up the variable type

best regards Stefan

Thankyou Stefan.
I used single "&" and its working correctly.
I'll modify the code and get back if needed.
Once again thank you.