Comparsion Operators

Hardware:
Arduino
Flow Meter

I am looking for guidance/suggestions on using comparison operators, I appreciate all suggestions and would ask that you steer me in the right direction and not just write the code for me so I can grow in this wonderfull hobby

Around line 60 of my sketch, I am trying to do the following:
Using an if statement I am trying to compare a value between two points & a set duration of time, 3 seconds
When both of these conditions are met then would like to execute the code in the if statement
My thought was to:

// If Water flow is between set pulses of 1-10 AND intervalLowFlowTime of 3 seconds, shut valve (possible leak)
 if (pulseCount >1 || pulseCount < 10 && currentTime >= (previousTime + intervalLowFlowTime)) { 
   shut valve etc.
}

What happens:
Regardless of that value or time-lapsed, it executes the code in the if statement as soon as it sees any value from (pulseCount) whether it's 5 or 175 & 1 second.

What have I tried to resolve the issue:
Arduino forum search, read up on comparison operators on the reference page
I have tried swapping around the comparison values i.e time then the pulsecount
Tried ( ) around the pulsecount thinking that it needed them, and that stopped the if statement from even excuting.

I have attached my sketch as well as a pic from the serial monitor showing that it hits a pulsecount value out side of the range that I wanted and executes the code by closing my valve

// Pin Declartions
byte flowsensor = 2;                     // Water Meter sensor pin attached to alo Intreupt # 0

// Motorized Valve Settings
byte valve = 8;                          // Setting valveClose Pin
byte valvePostionHighFlow;               // Variable to store valve closed on High flow rate
byte valvePostionLowFlow;                // Variable to store valve closed on Low flow rate
byte valveStatus;                        // Variable to store valve stats

// Global Variables
volatile int pulseCount;                 // ISR, Measures flow sensor pulses
volatile float totalFlowVol;             // ISR, Measures flow volume
float flowRateLM;                        // Variable storage, flowRate per min values
float previousVol;                       // Previous water volume value
float cycleVolT;                         // cycle Volume Total
float newVolTotal;                       // Storing previous value
float lastWaterCycle;                    // Variable, used for lastWaterCycle

// Timing Variables
unsigned long previousTime = 0;                           // Variable to store previous time value
unsigned long currentTime = 0;                            // Capturing currentTime in miliscondes
int interval = 1000;                                      // Setting for 1 second delay
int intervalLowFlowTime = (3000);                         // Setting 3 second delay for low flow readings

// Interrupt Service Retuine (ISR)
void flow () {
  pulseCount++;     // Incremeant to count pulses to figure out volume flowed
  totalFlowVol++;   // Incremeant to keep track of total volume flowed
}

void setup() {
  // Setting Pin Modes
  pinMode(flowsensor, INPUT_PULLUP);        // Setting pinmode, using internal resister (debounce reason)
  pinMode(valve, OUTPUT);                   // Setting valveClose

  // Starting Serial Mointor/LCD Screen
  Serial.begin(9600);                    // Used for debugging

  // Attaching interrupts
  attachInterrupt(digitalPinToInterrupt(flowsensor), flow, FALLING); // Setup Interrupt to catch sensor pulses on "falling" edge

} // End of Setup Loop

void loop () {
  currentTime = millis();                                      // Setting varibable with current run time
  
  if (currentTime >= (previousTime + interval)) {              // Making sure set time has gone by, set by "interval" variable
    previousTime = currentTime;                                // Updates previousTime for next cycle

    if (pulseCount != 0) {                                     // If flow meter pulseCount oppsite zero, then do this code, water flowing

      // Caulating flow rate in liters/mintue, Pulses x 3.5mL x 60 sec / 1000mL
      float flowRateLM = (pulseCount * 3.5 * 60 / 1000);
      Serial.print((String)"L/M = " + flowRateLM);

      // Print Pulse Count for trouble shooting reasons, 350 = 1 litre
      Serial.println((String)" Pulse Count = " + pulseCount);

      // If Water flow is between set pulses of 1-10 AND intervalLowFlowTime of 3 seconds, shut valve (possible leak)
      if (pulseCount >1 || pulseCount < 10 && currentTime >= (previousTime + intervalLowFlowTime)) { 
        digitalWrite(valve, HIGH);
        Serial.print("Closing Valve");
        delay(50);
        valvePostionLowFlow = digitalRead(valve);
        delay(6000);                                                // Manufacture says 5 seconds to close valve
      }// End of If Statement to close valve if flow rate low

    } // End of if statment "Pulsecount"

    // Displaying Information to Serial Montior or LCD Screen
    else {  // No Flow Else Statment

      newVolTotal = (totalFlowVol / 350);                            // Takeing totalFlowVol value from ISR and storing it in newVolTotal
      cycleVolT = (newVolTotal - previousVol);                       // Takeing newVoltTotal and subtracting previousVol that was carried through the loop
      previousVol = newVolTotal;                                     // Variable to capture total volume flowed and pass through cycle

      if (cycleVolT > 0) {
        lastWaterCycle =  cycleVolT;
      }

      // Serial Monitor Read out (debugging)
      Serial.print((String)" Total Vol " + newVolTotal + "L");       // Shows accumated litres since last reset
      Serial.print((String)" Cycle Vol " + lastWaterCycle);          // Show last cycle how many litres used
      Serial.println((String)" Valve " + valvePostionLowFlow);

    } // End of Else statment

    // Reseting ISR pulseCounter
    pulseCount = 0;

  } // End of if satment "Currenttime"

} // End of Loop

Screenshot 2021-04-02 210257.jpg

Flow_Meter_Help.ino (4.57 KB)

Screenshot 2021-04-02 210257.jpg

// If Water flow is between set pulses of 1-10 AND intervalLowFlowTime of 3 seconds, shut valve (possible leak)
 if (pulseCount >1 || pulseCount < 10 && currentTime >= (previousTime + intervalLowFlowTime)) {
   shut valve etc.
}

Write this out in plain english and I think you will see the problem.

"if pulseCount >1 OR <10"

Means, any value for pulseCount will be true.

Use parenthesis to order the math:

 if ((pulseCount >1 && pulseCount < 10) && currentTime >= (previousTime + intervalLowFlowTime)) {

Thanks, Steve for that quick reply, but I'm sorry I'm not following your lesson.

When you say "any value for pulseCount will be true" Are you meaning between 1-10? That's what I was aiming for + set elapsed time.

I did try putting in the code snip you supplied, and it never executed the if statement regardless of the value
of pulseCount

I did try this, and was able to get the if statement code to work, but can't figure out how to also include the elasped time

if (pulseCount >=1 && pulseCount <= 10){

It has to do with the order in which operators are applied in an expression, not what the operators do in this case. You have to adhere to the compiler order of arithmetic which includes comparison operators and more. Pick a number say 33. Well, your test says x>1 or x<10 then 33>1 or 33<10, actually the result is when 33>1, the result is automatically true, the other test x<10 doesn't matter.

There is an example of how to integrate the time in reply #1.

// If Water flow is between set pulses of 1-10 AND intervalLowFlowTime of 3 seconds, shut valve (possible leak)
 if (pulseCount >1 || pulseCount < 10 && currentTime >= (previousTime + intervalLowFlowTime)) {
   shut valve etc.
}

|| is 'OR' so every number is either >1 OR <10. You want && (AND). You only want numbers that are both >1 AND < 10.

// If Water flow is between set pulses of 1-10 AND intervalLowFlowTime of 3 seconds, shut valve (possible leak)
 if (pulseCount >1 && pulseCount < 10 && currentTime >= (previousTime + intervalLowFlowTime)) {
   shut valve etc.
}

When testing a time interval, the correct way is:

currentTime - previousTime >= intervalLowFlowTime
// If Water flow is between set pulses of 1-10 AND intervalLowFlowTime of 3 seconds, shut valve (possible leak)
 if (pulseCount > 1 && pulseCount < 10 && currentTime - previousTime >= intervalLowFlowTime)) {
   shut valve etc.
}

Be sure that 'currentTime' and 'previousTime' are both of type 'unsigned long' (or the equivalent 'uint32_t').

Thank you, everyone. I understand now why my OR operator selection was wrong to use and can get my valve to shut now if pulseCount is between my values of 1-10 but I'm still hung up on the time elapsed,

No matter what I try it just ignores the time value, as soon as I get within the range of 1-10 whether it be 3 second or 5 min. It will not execute the if statement & close the valve while I have the following code includeded for time elapsed

 if ((pulseCount >1 && pulseCount <10)&& currentTime - previousTime >= intervalLowFlowTime) {
close valve etc. }

Or this code

 if ((pulseCount >1 && pulseCount <10)&& currentTime >= (previousTime + intervalLowFlowTime)) { 
close valve etc.}

We need to see your code.

// Pin Declartions
byte flowsensor = 2;                     // Water Meter sensor pin attached to alo Intreupt # 0

// Motorized Valve Settings
byte valve = 8;                          // Setting valveClose Pin
byte valvePostionHighFlow;               // Variable to store valve closed on High flow rate
byte valvePostionLowFlow;                // Variable to store valve closed on Low flow rate
byte valveStatus;                        // Variable to store valve stats

// Global Variables
volatile int pulseCount;                 // ISR, Measures flow sensor pulses
volatile float totalFlowVol;             // ISR, Measures flow volume
float flowRateLM;                        // Variable storage, flowRate per min values
float previousVol;                       // Previous water volume value
float cycleVolT;                         // cycle Volume Total
float newVolTotal;                       // Storing previous value
float lastWaterCycle;                    // Variable, used for lastWaterCycle

// Timing Variables
unsigned long previousTime = 0;                           // Variable to store previous time value
unsigned long currentTime = 0;                            // Capturing currentTime in miliscondes
int interval = 1000;                                      // Setting for 1 second delay
int intervalLowFlowTime = (3000);                         // Setting 3 second delay for low flow readings

// Interrupt Service Retuine (ISR)
void flow () {
  pulseCount++;     // Incremeant to count pulses to figure out volume flowed
  totalFlowVol++;   // Incremeant to keep track of total volume flowed
}

void setup() {
  // Setting Pin Modes
  pinMode(flowsensor, INPUT_PULLUP);        // Setting pinmode, using internal resister (debounce reason)
  pinMode(valve, OUTPUT);                   // Setting valveClose

  // Starting Serial Mointor/LCD Screen
  Serial.begin(9600);                    // Used for debugging

  // Attaching interrupts
  attachInterrupt(digitalPinToInterrupt(flowsensor), flow, FALLING); // Setup Interrupt to catch sensor pulses on "falling" edge

} // End of Setup Loop

void loop () {
  currentTime = millis();                                      // Setting varibable with current run time
  
  if (currentTime >= (previousTime + interval)) {              // Making sure set time has gone by, set by "interval" variable
    previousTime = currentTime;                                // Updates previousTime for next cycle

    if (pulseCount != 0) {                                     // If flow meter pulseCount oppsite zero, then do this code, water flowing

      // Caulating flow rate in liters/mintue, Pulses x 3.03mL x 60 sec / 1000mL
      float flowRateLM = (pulseCount * 3.5 * 60 / 1000);
      Serial.print((String)"L/M = " + flowRateLM);

      // Print Pulse Count for trouble shooting reasons, 350 = 1 litre
      Serial.println((String)" Pulse Count = " + pulseCount);
//
      // If Water flow is between set pulses of 1-100 AND intervalLowFlowTime of 3 seconds, shut valve (possible leak)
      if ((pulseCount >1 && pulseCount <10) && currentTime >= (previousTime + intervalLowFlowTime)) { 
        digitalWrite(valve, HIGH);
        Serial.print("Closing Valve");
        delay(50);
        valvePostionLowFlow = digitalRead(valve);
        delay(6000);                                                // Manufacture says 5 seconds to close valve
      }// End of If Statement to close valve if flow rate low

    } // End of if statment "Pulsecount"

    // Displaying Information to Serial Montior or LCD Screen
    else {  // No Flow Else Statment

      newVolTotal = (totalFlowVol / 350);                            // Takeing totalFlowVol value from ISR and storing it in newVolTotal
      cycleVolT = (newVolTotal - previousVol);                       // Takeing newVoltTotal and subtracting previousVol that was carried through the loop
      previousVol = newVolTotal;                                     // Variable to capture total volume flowed and pass through cycle

      if (cycleVolT > 0) {
        lastWaterCycle =  cycleVolT;
      }

      // Serial Monitor Read out (debugging)
      Serial.print((String)" Total Vol " + newVolTotal + "L");       // Shows accumated litres since last reset
      Serial.print((String)" Cycle Vol " + lastWaterCycle);          // Show last cycle how many litres used
      Serial.println((String)" Valve " + valvePostionLowFlow);

    } // End of Else statment

    // Reseting ISR pulseCounter
    pulseCount = 0;

  } // End of if satment "Currenttime"

} // End of Loop

You set previoustime to currenttime too soon. When execution reaches the if that compares them, they will be the same, or close to it.

wildbill:
You set previoustime to currenttime too soon. When execution reaches the if that compares them, they will be the same, or close to it.

Ok, I get that then, but my understanding was that it would continue to check the time "dealy" for lack of a better word that I had set "intervalLowFlowTime" 3 seconds. Once current time + my time is true & my set range of 1-10 was true then it would execute the if statement. What am I missing to understand here?

acode777:
Once current time + my time is true & my set range of 1-10 was true then it would execute the if statement.

You have explicitly coded your program so that will never be true. This bit:

  if (currentTime >= (previousTime + interval))                // Making sure set time has gone by, set by "interval" variable
  {
    previousTime = currentTime;                                // Updates previousTime for next cycle

Ensures that previousTime and currentTime are the same. Very shortly afterwards, this check happens:

     if ((pulseCount > 1 && pulseCount < 10) && currentTime >= (previousTime + intervalLowFlowTime))

Which is much the same as checking whether currentTime >= (currentTime+3000). Not likely to ever be true (If we ignore the ~49 day overflow effects).

I GET IT NOW wild Bill, thank you. As your previous post said, it's too close in the loop.

Without directly writing the code, I want to figure out the code myself, could you give an example of how to go about this then.

Don't do this:

    previousTime = currentTime;                                // Updates previousTime for next cycle

Until after you have done this:

     if ((pulseCount > 1 && pulseCount < 10) && currentTime >= (previousTime + intervalLowFlowTime))

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