How do I write code for rate of change in air pressure within a closed system

My fellow engineers and hobbyist, I'm at the point in my project with the code that I don't know what characters to enter or where in the code to place the characters. This is what I'm trying to achieve:

I'm working with a system that continuously samples air pressure twice per second. When my pressure transducer(100psi) reads a sustained drop exceeding a rate of 0.1 psi (0,007 bar) per second, as verified
by three consecutive samplings, the Arduino Uno signals a 24vdc solenoid to de-energize (go LOW) causing it to open releasing the remaining air pressure.

Can Somebody please assist me that's been coding for a long I'm still a novice code writer. I tried if statements and loops but I think this can be achieved with a calculus equation in a function? I really have no idea where to begin. I have the rest of my code written but don't know where to insert the code in the sketch. I could really use the help. Thank you.

And what is the actual, real-world precision of your sensor? 0.1PSI out of 100PSI is 0.1%. That's pretty precise. Most of the ones I've used are rated more like 1%, which means you'd need to take a lot of readings, over a period of time, and look for an average drop of 0.1PSI/second.

Regards,
Ray L.

int calculusEquationInAFunction(int readingOne, int readingTwo int readingThree) {
  static int previousAverage = 0;
  int currentAverage = (readingOne + readingTwo + readingThree) / 3
  if(previousAverage > currentAverage) {
    if(previousAverage - currentAverage >= maxDrop) {
      previousAverage = currentAverage;
      return LOW;
    }
  }
  previousAverage = currentAverage;
  return HIGH;
}

And what about the accuracy of your 1 second time frame? Can you use the Arduino to count 1000 milliseconds as one second, or do you need a real-time clock to tell when 1 second has elapsed? The answer will effect the accuracy you need as well as the repeatability of your measurements.

Paul

Hi Ray and thank you for the reply. You are correct and 0.25% or .25psi is the accuracy of the pressure transducer I need for this project. Do you have any idea how I would express this algebraically with ASCII characters in code.

chrisvoltamps2020:
Hi Ray and thank you for the reply. You are correct and 0.25% or .25psi is the accuracy of the pressure transducer I need for this project. Do you have any idea how I would express this algebraically with ASCII characters in code.

The UNO is missing an arithmetic logic unit. You will have to do your calculations in integral units.

chrisvoltamps2020:
Hi Ray and thank you for the reply. You are correct and 0.25% or .25psi is the accuracy of the pressure transducer I need for this project. Do you have any idea how I would express this algebraically with ASCII characters in code.

Then you cannot guarantee you can reliably detect 0.1PSI/second drop without actually measuring a larger drop over a longer period of time. BOTH accuracy AND repeatability need to be accounted for. Does it matter if you don't drain the tank until you've seen a drop of 1 PSI over 10 seconds, or 10 PSI over 100 seconds?

Regards,
Ray L.

Perehama:
The UNO is missing an arithmetic logic unit. You will have to do your calculations in integral units.

He can use floating point with absolutely no problems, if he wants to. It's not like his application requires anything close to the full bandwidth of the processor. More like a few %.

Regards,
Ray L.

Paul thank for the reply. I will need a RTC for accuracy.

chrisvoltamps2020:
Can Somebody please assist me that's been coding for a long I'm still a novice code writer. I tried if statements and loops but I think this can be achieved with a calculus equation in a function?

i thought this is just an issue of logic, once you know how to accurately measure the pressure

#define ButPin A1

float airPress = 14.7;

void monitor (void)
{
    static float airPressLst = 14.7;

    if (LOW == digitalRead (ButPin))
#define AirDrop 0.1
        airPress -= AirDrop;
    
    static int   cnt  = 0;
    if (airPress - airPressLst <= -AirDrop)  {
        Serial.println ("Drop");
        if (3 <= ++cnt)
            Serial.println ("Release");
    }
    else if (cnt) {
        Serial.println ("Reset");
        cnt = 0;
    }

    airPressLst = airPress;
}

void loop (void)
{
    static unsigned long msecLst = 0;
           unsigned long msec    = millis();

#define Period  1000
    if (msec - msecLst > Period)  {
        msecLst = msec;
        monitor ();
    }
}

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

    pinMode (ButPin, INPUT_PULLUP);
}

Perehama and gcjr,

Thank you for the replies as well. I much appreciate the calculus sample codes.

-Chris

// When my pressure transducer(100psi) reads a sustained drop exceeding a 
// rate of 0.1 psi (0, 007 bar) per second, as verified by three consecutive 
// samplings, the Arduino Uno signals a 24vdc solenoid to de - energize 
// (go LOW) causing it to open releasing the remaining air pressure.
void loop()
{
  unsigned long currentTime = millis();
  static unsigned long intervalStart = 0;
  static float pressureSamples[3]; 


  // samples air pressure twice per second.
  if (currentTime - intervalStart >= (1000 / 2))
  {
    intervalStart = currentTime;
    float pressurePSI = readPressurePSI();
    
    // three consecutive samplings
    pressureSamples[0] = pressureSamples[1];
    pressureSamples[1] = pressureSamples[2]
    pressureSamples[2] = pressurePSI;


    // "three consecutive samlings" = 2 intervals = 1 second.
    int dropPerSecondInPressure = pressureSamples[0] - pressureSamples[2];


    // drop exceeding a rate of 0.1 psi (0, 007 bar) per second,
    if (dropPerSecondInPressure > 0.1)
    {
       // signals a 24vdc solenoid to de-energize (go LOW)
       digitalWrite(RelayPin, LOW);
    }
  }
}

John Wasser, thank you for the sample code I'm very grateful.

Perehama:
The UNO is missing an arithmetic logic unit. You will have to do your calculations in integral units.

The UNO does have an ALU. Every digital computer has one. You probably meant an arithmetic co-processor.

aarg:
The UNO does have an ALU. Every digital computer has one. You probably meant an arithmetic co-processor.

You are correct. I mispoke. https://microchipdeveloper.com/8avr:alu

Hello John Wasser,

I tried your sample code and it won't let me compile it. I get an error saying "pressureSamples not declared in this scope." I thought all my characters were correct but how else or where am I supposed to declare pressureSamples. I tried different a few things but just keep getting errors when I try compiling. Any suggestions John?

Thanks again,

-Chris

It's hard to help with code we can't see.

Hi Farraday Member,

Please check it out an let me know what you think.

#include <Wire.h> //enables communication between I2C devices
#include <LiquidCrystal_I2C.h> //enables interface with LCD screen

const int pressureInput = A0; //selects the analog pin for the pressure transducer
const int pressureZero = 102.4; //analog reading of pressure transducer at 0psi
const int pressureMax = 921.6; //analog reading of pressure transducer at 100psi
const int pressuretransducermaxPSI = 100; //psi value of transducer being used
const int baudRate = 9600; //constant integer to set up baud rate for the serial monitor
const int sensorreadDelay = 250; //constant integer to set the sensor read delay in milliseconds

int RelayPin = 4; //This is the output valve on the Arduino
int dropPerSecondInPressure = pressureSamples[0] - pressureSamples[2];

unsigned long currentTime = millis();
static unsigned long intervalStart = 0;
static float pressureSamples[3];

// initial Time display is 12:59:45 PM
int h=12;
int m=59;
int s=45;
int flag=1; //PM

// Time Set Buttons
int button1;
int button2;
int hs=0;// pin 0 for Hours Setting
int ms=1;// pin 1 for Minutes Setting

float pressureValue = 0; //this is the variable to store the value coming from the pressure transducer

LiquidCrystal_I2C lcd(0x27, 20, 4); //sets the LCD I2C communication address; format(address, columns, rows)

void setup() // enter setup code here to run once when system is energized or reset
{
Serial.begin(baudRate); //initializes serial communication at set baud rate bits per second (bps)
lcd.begin(); //initializes LCD screen
pinMode(hs,INPUT_PULLUP);// no need of Pullup resistor for Button 1
pinMode(ms,INPUT_PULLUP);

pinMode(RelayPin, OUTPUT); //Sets the valve as an output
float pressurePSI;//Sets the valve as an output
}

void loop() //loop routine runs repeatedly forever
{
unsigned long currentTime = millis();
static unsigned long intervalStart = 0;
static float pressureSamples[3];
int readPressurePSI();
int pressureSamples;

if (currentTime - intervalStart >= (1000 / 2)) // samples air pressure twice per second.
{
intervalStart = currentTime;
float pressurePSI = readPressurePSI();

pressureSamples[0] = pressureSamples[1];
pressureSamples[1] = pressureSamples[2];
pressureSamples[2] = pressurePSI;

int dropPerSecondInPressure = pressureSamples[0] - pressureSamples[2]; // "three consecutive samlings" = 2 intervals = 1 second.

if (dropPerSecondInPressure > 0.1) // drop exceeding a rate of 0.1 psi (0, 007 bar) per second,
{
digitalWrite(RelayPin, LOW); // signals a 24vdc solenoid to de-energize (go LOW)
}

{
pressureValue = analogRead(pressureInput); //reads given value from input pin and assigns it to a variable
pressureValue = ((pressureValue-pressureZero)*pressuretransducermaxPSI)/(pressureMax-pressureZero); //this is the conversion equation used to convert analog readings to psi
Serial.print(pressureValue, 1); //this prints the value from the previous line to serial
Serial.println("psi"); //this prints the label to serial
lcd.setCursor(0,8); //sets the cursor to column 0, row 8
lcd.print("Pressure:"); //prints the label
lcd.print(pressureValue, 1); //prints the pressure value to the LCD screen 1 digit on float
lcd.print("psi"); //prints the lable after value
lcd.print(" "); //clears the display after large values or negatives
delay(sensorreadDelay); //is a delay in milliseconds between read values

lcd.setCursor(0,2); // Print TIME in Hour, Min, Sec + AM/PM
lcd.print("Time:");
if(h<10)lcd.print("0"); // always 2 digits
lcd.print(h);
lcd.print(":");
if(m<10)lcd.print("0");
lcd.print(m);
lcd.print(":");
if(s<10)lcd.print("0");
lcd.print(s);

if(flag==0) lcd.print("AM");
if(flag==1) lcd.print("PM");

lcd.setCursor(0,4);// for Line 2
lcd.print(" QRS/Dump Valve II ");

// Set loop execution time to 1000ms
// This makes also the LCD display freeze for 1000ms

delay(987);// gives the 1 sec tick ( take account of loop time, so delay is not 1000 )

// this method of measuring time cannot gives a good accuracy
// expect max. drift of 1/1000 , max 3.6 Sec per hour
// measured drift 1.3 s per hour

s=s+1; //increment sec. counting lcd.clear(); not needed

/-------Time setting-------/
button1=digitalRead(hs);

if(button1==0) h=h+1;
button2=digitalRead(ms);

if(button2==0){
s=0;
m=m+1;
}

/* ---- manage seconds, minutes, hours am/pm overflow ----*/
if(s==60){
s=0;
m=m+1;
}
if(m==60){
m=0;
h=h+1;
}
if(h==13){
h=1;
flag=flag+1;

if(flag==2)flag=0;
}
}
}
}

Hello all,

My project will not compile - I keeping getting errors for missing declarations. ('pressureSamples' was not declared in this scope") I'm trying to open a solenoid in a pressurized closed loop air system when all arithmetic and clock functions have been met. Can you please check out my below code and let me know what you think. It could be a simple mistake but I'm open to criticism if it is haha. I'm still new to programming and like to learn from my mistakes ..please help if you can:

#include <Wire.h> //enables communication between I2C devices
#include <LiquidCrystal_I2C.h> //enables interface with LCD screen

const int pressureInput = A0; //selects the analog pin for the pressure transducer
const int pressureZero = 102.4; //analog reading of pressure transducer at 0psi
const int pressureMax = 921.6; //analog reading of pressure transducer at 100psi
const int pressuretransducermaxPSI = 100; //psi value of transducer being used
const int baudRate = 9600; //constant integer to set up baud rate for the serial monitor
const int sensorreadDelay = 250; //constant integer to set the sensor read delay in milliseconds

int RelayPin = 4; //This is the output valve on the Arduino
int dropPerSecondInPressure = pressureSamples[0] - pressureSamples[2];

unsigned long currentTime = millis();
static unsigned long intervalStart = 0;
static float pressureSamples[3];

// initial Time display is 12:59:45 PM
int h=12;
int m=59;
int s=45;
int flag=1; //PM

// Time Set Buttons
int button1;
int button2;
int hs=0;// pin 0 for Hours Setting
int ms=1;// pin 1 for Minutes Setting

float pressureValue = 0; //this is the variable to store the value coming from the pressure transducer

LiquidCrystal_I2C lcd(0x27, 20, 4); //sets the LCD I2C communication address; format(address, columns, rows)

void setup() // enter setup code here to run once when system is energized or reset
{
Serial.begin(baudRate); //initializes serial communication at set baud rate bits per second (bps)
lcd.begin(); //initializes LCD screen
pinMode(hs,INPUT_PULLUP);// no need of Pullup resistor for Button 1
pinMode(ms,INPUT_PULLUP);

pinMode(RelayPin, OUTPUT); //Sets the valve as an output
float pressurePSI;//Sets the valve as an output
}

void loop() //loop routine runs repeatedly forever
{
unsigned long currentTime = millis();
static unsigned long intervalStart = 0;
static float pressureSamples[3];
int readPressurePSI();

int dropPerSecondInPressure = pressureSamples[0] - pressureSamples[2]; // "three consecutive samplings" = 2 intervals = 1 second.

if (currentTime - intervalStart >= (1000 / 2)) // samples air pressure twice per second.
{
intervalStart = currentTime;
float pressurePSI = readPressurePSI();

pressureSamples[0] = pressureSamples[1];
pressureSamples[1] = pressureSamples[2];
pressureSamples[2] = pressurePSI;

if (dropPerSecondInPressure > 0.1) // drop exceeding a rate of 0.1 psi (0, 007 bar) per second,
{
digitalWrite(RelayPin, LOW); // signals a 24vdc solenoid to de-energize (go LOW)
}

{
pressureValue = analogRead(pressureInput); //reads given value from input pin and assigns it to a variable
pressureValue = ((pressureValue-pressureZero)*pressuretransducermaxPSI)/(pressureMax-pressureZero); //this is the conversion equation used to convert analog readings to psi
Serial.print(pressureValue, 1); //this prints the value from the previous line to serial
Serial.println("psi"); //this prints the label to serial
lcd.setCursor(0,8); //sets the cursor to column 0, row 8
lcd.print("Pressure:"); //prints the label
lcd.print(pressureValue, 1); //prints the pressure value to the LCD screen 1 digit on float
lcd.print("psi"); //prints the lable after value
lcd.print(" "); //clears the display after large values or negatives
delay(sensorreadDelay); //is a delay in milliseconds between read values

lcd.setCursor(0,2); // Print TIME in Hour, Min, Sec + AM/PM
lcd.print("Time:");
if(h<10)lcd.print("0"); // always 2 digits
lcd.print(h);
lcd.print(":");
if(m<10)lcd.print("0");
lcd.print(m);
lcd.print(":");
if(s<10)lcd.print("0");
lcd.print(s);

if(flag==0) lcd.print("AM");
if(flag==1) lcd.print("PM");

lcd.setCursor(0,4);// for Line 2
lcd.print(" QRS/Dump Valve II ");

// Set loop execution time to 1000ms
// This makes also the LCD display freeze for 1000ms

delay(987);// gives the 1 sec tick ( take account of loop time, so delay is not 1000 )

// this method of measuring time cannot gives a good accuracy
// expect max. drift of 1/1000 , max 3.6 Sec per hour
// measured drift 1.3 s per hour

s=s+1; //increment sec. counting lcd.clear(); not needed

/-------Time setting-------/
button1=digitalRead(hs);

if(button1==0) h=h+1;
button2=digitalRead(ms);

if(button2==0){
s=0;
m=m+1;
}

/* ---- manage seconds, minutes, hours am/pm overflow ----*/
if(s==60){
s=0;
m=m+1;
}
if(m==60){
m=0;
h=h+1;
}
if(h==13){
h=1;
flag=flag+1;

if(flag==2)flag=0;
}
}
}
}

static float pressureSamples[3];

An array named pressureSamples with global scope

void loop() //loop routine runs repeatedly forever
{
  unsigned long currentTime = millis();
  static unsigned long intervalStart = 0;
  static float pressureSamples[3];

A completely different array named pressureSamples whose scope is the loop() function

The compiler is confused as to which one you want to use in

int dropPerSecondInPressure = pressureSamples[0] - pressureSamples[2];

and seems to have chosen the one that is not in scope. In any case doing that calculation is meaningless before you have stored meaningful values in the array even though you do it all over again in loop() and declare another variable named dropPerSecondInPressure

You need to do some reading on the scope of variables in C/C++