# Oxygen Concentrator valve timings

Hi everyone,
I am working on building oxygen concentrators. I have written a code for the valve sequence which is working properly. But if i want to change the ON timings of individual valves, I have to make changes in all the following sequence of valves. Is there a simpler way to do this? please help.

``````unsigned long Period = 200;
unsigned long currentMillis;
unsigned long current_time;
unsigned long alarmMillis;

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

bool SR1 = 0;
bool SR2 = 0;

void setup() {
Serial.begin(9600);

pinMode(6, OUTPUT);            // EQ Valve
pinMode(2, OUTPUT);            // RF Valve
pinMode(5, OUTPUT);            // LW Valve
pinMode(3, OUTPUT);            // LF Valve
pinMode(4, OUTPUT);            // RW Valve
}

void loop()
{
current_time = millis();
if (RF == 0 && LW == 0 && LF == 1 && RW == 0 && EQ == 1) {
RF = 1;
LF = 0;
//  Serial.println("RF=ON");
}
if (RF == 1 && LW == 0 && LF == 0 && RW == 0 && EQ == 1 && SR1 == 0 && current_time - currentMillis >= Period * 1) {
LW = 1;
EQ = 0;
//  Serial.println("LW=ON & EQ=OFF");
SR1 = 1;
}
if (RF == 1 && LW == 1 && LF == 0 && RW == 0 && EQ == 0  && current_time - currentMillis >= Period * 2) {
EQ = 1;
//  Serial.println("EQ=ON");
}
if (LW == 1 && RF == 1 && LF == 0 && RW == 0 && EQ == 1 && SR1 == 1 &&  current_time - currentMillis >= Period * 3) {
LW = 0;
//    Serial.println("LW=OFF");
}
if (LW == 0 && RF == 1  && LF == 0 && RW == 0 && EQ == 1 &&  current_time - currentMillis >= Period * 5)  {
RF = 0;
LF = 1;
//   Serial.println("RF=OFF & LF=ON");
}
if (LW == 0 && RF == 0  && LF == 1 && RW == 0 && EQ == 1 && SR2 == 0 && current_time - currentMillis >= Period * 6) {
RW = 1;
EQ = 0;
//  Serial.println("RW=ON & EQ=OFF");
SR2 = 1;
}
if (RF == 0 && LW == 0 && LF == 1 && RW == 1 && EQ == 0 &&  current_time - currentMillis >= Period * 7) {
EQ = 1;
//  Serial.println("EQ=ON");
}
if (LW == 0 && RF == 0  && LF == 1 && RW == 1 && EQ == 1 && SR2 == 1 && current_time - currentMillis >= Period * 8) {
RW = 0;
//    Serial.println("RW=OFF");
}
if (LW == 0 && RF == 0  && LF == 1 && RW == 0 && EQ == 1 &&  current_time - currentMillis >= Period * 10) {
//    Serial.println("LF=OFF");
current_time = 0;
currentMillis = millis();
SR1 = 0;
SR2 = 0;
}
if (EQ == 0) {
digitalWrite(6, HIGH);
}
else {
digitalWrite(6, LOW);
}

if (RF == 0) {
digitalWrite(2, LOW);
}
else {
digitalWrite(2, HIGH);
}

if (LW == 0) {
digitalWrite(5, LOW);
}
else {
digitalWrite(5, HIGH);
}

if (LF == 0) {
digitalWrite(3, LOW);
}
else {
digitalWrite(3, HIGH);
}

if (RW == 0) {
digitalWrite(4, LOW);
}
else {
digitalWrite(4, HIGH);
}
}
``````

That code is rather hard to follow. What is it supposed to do?

It is supposed to control valve ON and OFF timings. It's a sequence. There are 5 Valves.
Right Feed, Left feed, Right Waste, Left Waste, and equilizer valve.
The way I have written the code, it is difficult for me to control the valve timings individually. How do you normally write a code for a series of actions with time delays?

A state machine is a common solution. They're simple and powerful, but surprisingly difficult to comprehend the first time you try to use one.

What is the sequence on the valves?

For the same diagram in the previous reply.

Here the functional process in detail:
Ambient air gets into the concentrator via a foam dust filter. One part of the air enters the compressor trough another fine filter, the other part is needed to cool the compressor unit. Behind the compressor a cooling coil with a fan cools down the warm compressed air before it gets into the sieve tank system.

1. Inlet valve V2 is open. Pressurized air from the compressor of 1.4-2 bar (20-30 psi)
enters sieve tank 1.
2. Oxygen passes through filter 1 but nitrogen accumulates at the filter intake.
3. The oxygen gets through a restrictor into the reservoir tank. Through another restrictor a
part of the oxygen enters sieve tank 2 through the outlet.
4. The trapped nitrogen of sieve tank 2 is flushed through the intake and gets through the
open exhaust valve V3 and the muffler out of the concentrator.
5. After 7-8 sec V1 and V3 close and the equalization valve V5 opens for 1 sec. The different
pressures of the sieve tanks get balanced.
6. Now V4 and V1 open. Air gets into sieve tank 2, oxygen from sieve tank 2 fills the
reservoir tank and sieve tank 1 gets flushed.

Actually, a dirty way to do it is to create a Period variable (or better constant) for each valve. Is there some reason that the delays all need to be multiples?

No the delays need not be multiplies.
Furthermore, I want to be able to change the delays as and when the flow changes.

What tells you the flow rate?

A flow sensor

Have you figured out how the Arduino is going to read it?

Hi wildbill,
Yes. And I also figured out the sequence code. Just check it and tell me if i can improvise it, on the basis of reducing scan time or unnecessary lines.

``````#include <OneWire.h>
#include <DallasTemperature.h>

/***************** Temperature Initialization ************************************************************/
#define ONE_WIRE_BUS 8
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

/***************** Datatype Initialization ************************************************************/
unsigned long Period = 500;
unsigned long currentMillis = 0;
unsigned long current_time;
unsigned long alarmMillis;
unsigned long a;
unsigned long b;
unsigned long c;
unsigned long d;
unsigned long e;
unsigned long f;
unsigned long g;
unsigned long h;

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

int SR = 0;

int val = 0;
int val1 = 0;
int val2 = 0;
int val3 = 0;

/*************** Buzzer *******************************************************************************/

//int ledPin =  13;
int ledState = LOW;
unsigned long previousMillis2 = 0;
unsigned long currentMillis2 = 0;
unsigned long Period2 = 100;
int count = 0;
bool BZR = 0;

void setup()
{
Serial.begin(9600);
sensors.begin();

pinMode(12, OUTPUT);            // Buzzer Output
pinMode(7, OUTPUT);            // Motor Output
pinMode(6, OUTPUT);            // EQ Valve
pinMode(2, OUTPUT);            // RF Valve
pinMode(5, OUTPUT);            // LW Valve
pinMode(3, OUTPUT);            // LF Valve
pinMode(4, OUTPUT);            // RW Valve
pinMode(9, OUTPUT);            // LED
}

void loop()
{

val1 = analogRead(A1);                                           // Flow (LPM)

/*********************** Display Values *************************************************************/

float oxy = val * (100.0 / 512.0);                       // Convert to percentage
Serial.println("OXY");
Serial.println(oxy);

float Flow = val1 * (10.0 / 512.0);                      // Convert to Flow/Minute
Serial.println("Flow");
Serial.println(Flow);

Seq ();
Valves();
//  Buzzer();
Temp();
motor1();
}

void Seq ()
{
if (SR == 0) {
current_time = millis();
Serial.println("SR0");
}
if (RF == 0 && LW == 0 && LF == 1 && RW == 0 && EQ == 1 && SR == 0) {
RF = 1;
LF = 0;
SR = 1;
currentMillis = millis();
Serial.println("RF=ON & LF=OFF");
}

if (SR == 1) {
a = millis();
Serial.println("SR1");
}
if (RF == 1 && LW == 0 && LF == 0 && RW == 0 && EQ == 1 && SR == 1 && a - currentMillis >= 1000) {
LW = 1;
EQ = 0;
currentMillis = millis();
SR = 2;
Serial.println("LW=ON & EQ=OFF");
}

if (SR == 2) {
b = millis();
Serial.println("SR2");
}
if (RF == 1 && LW == 1 && LF == 0 && RW == 0 && EQ == 0 && SR == 2 && b - currentMillis >= 1000) {
EQ = 1;
currentMillis = millis();
SR = 3;
Serial.println("EQ=ON");
}

if (SR == 3) {
c = millis();
Serial.println("SR3");
}
if (LW == 1 && RF == 1 && LF == 0 && RW == 0 && EQ == 1 && SR == 3 && c - currentMillis >= 1000) {
LW = 0;
currentMillis = millis();
SR = 4;
Serial.println("LW=OFF");
}

if (SR == 4) {
d = millis();
Serial.println("SR4");
}
if (LW == 0 && RF == 1  && LF == 0 && RW == 0 && EQ == 1 && SR == 4 && d - currentMillis >= 1000)  {
RF = 0;
LF = 1;
currentMillis = millis();
SR = 5;
Serial.println("RF=OFF & LF=ON");
}

if (SR == 5) {
e = millis();
Serial.println("SR5");
}
if (LW == 0 && RF == 0  && LF == 1 && RW == 0 && EQ == 1 && SR == 5 && e - currentMillis >= 1000) {
RW = 1;
EQ = 0;
currentMillis = millis();
SR = 6;
Serial.println("RW=ON & EQ=OFF");
}

if (SR == 6) {
f = millis();
Serial.println("SR6");
}
if (RF == 0 && LW == 0 && LF == 1 && RW == 1 && EQ == 0 && SR == 6 && f - currentMillis >= 1000) {
EQ = 1;
currentMillis = millis();
SR = 7;
Serial.println("EQ=ON");
}

if (SR == 7) {
g = millis();
Serial.println("SR7");
}
if (LW == 0 && RF == 0  && LF == 1 && RW == 1 && EQ == 1 && SR == 7 && g - currentMillis >= 1000) {
RW = 0;
currentMillis = millis();
SR = 8;
Serial.println("RW=OFF");
}

if (SR == 8) {
h = millis();
Serial.println("SR8");
}
if (LW == 0 && RF == 0  && LF == 1 && RW == 0 && EQ == 1 && SR == 8 && h - currentMillis >= 1000) {
current_time = 0;
currentMillis = millis();
SR = 0;
Serial.println("LF=OFF");
}
}
void Valves()
{
if (EQ == 0) {
digitalWrite(6, HIGH);
}
else {
digitalWrite(6, LOW);
}

if (RF == 0) {
digitalWrite(2, LOW);
}
else {
digitalWrite(2, HIGH);
}

if (LW == 0) {
digitalWrite(5, LOW);
}
else {
digitalWrite(5, HIGH);
}

if (LF == 0) {
digitalWrite(3, LOW);
}
else {
digitalWrite(3, HIGH);
}

if (RW == 0) {
digitalWrite(4, LOW);
}
else {
digitalWrite(4, HIGH);
}
}

void Temp() {
Serial.print(" Requesting temperatures...");
sensors.requestTemperatures(); // Send the command to get temperature readings
Serial.println("DONE");
Serial.print("Temperature is: ");
Serial.print(sensors.getTempCByIndex(0)); // Why "byIndex"?
}

/*void Buzzer()  {
currentMillis2 = millis();

if (Alarm1 == HIGH) {
count = 2;
}
if (Alarm2 == HIGH) {
count = 4;
}
if (Alarm3 == HIGH) {
count = 6;
}
if (Alarm4 == HIGH) {
count = 8;
}
if (Alarm5 == HIGH) {
count = 10;
}
if (Alarm6 == HIGH) {
count = 12;
}
if (Alarm1 == HIGH or Alarm2 == HIGH or Alarm3 == HIGH or Alarm4 == HIGH or Alarm5 == HIGH or Alarm6 == HIGH) {   //& address <= count & currentMillis - previousMillis >= interval) {
Serial.println("if11");
Serial.println(count);

if (address <= count && currentMillis2 - previousMillis2 >= Period2) {
previousMillis2 = currentMillis2;
Serial.println("if22222");
if (ledState == HIGH && BZR == 0) {
ledState = LOW;
BZR = 1;

} else {
ledState = HIGH;
BZR = 0;
}

}
if (address >= count + 1) {
ledState = HIGH;
BZR = 0;
}
if (address >= count + 1 && currentMillis2 - previousMillis2 >= Period2 * 15) {
BZR = 0;
ledState = HIGH;
}
}
else //if (Alarm1 <= 1019 and Alarm2 <= 1019 and Alarm3 <= 1019 and Alarm4 <= 1019 and Alarm5 <= 1019 and Alarm6 <= 1019)
{ ledState = HIGH;
BZR = 0;
//Serial.println(count);
}
digitalWrite(ledPin, ledState);
if (BZR == 0) {
digitalWrite(23, HIGH);
}
else {
digitalWrite(23, LOW);
}
}*/
void motor1()
{
digitalWrite(9, HIGH);
digitalWrite(7, HIGH);
}
``````

Take a look here: Naming.

I was going to type some commentary on good naming, but @StefanL38 did it for me earlier and as a programmer, I like reuse

It seems that at its core, your program goes through a number of stages, controlled by elapsed time and at each stage turns valves on and off.

As I said before, a state machine is one way to do this, but equally an array of structs would be handy too. Each struct can specify the desired state of each valve for that stage and how long it should last. Then all that repetition goes away and your code is a for loop and some check to see if it's time for the change to a new state.

Okay, Thank you.

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