A condition waiting until another condition becomes true

Hello, everyone!

I'm a newbie in terms of programming and have very little knowledge about it. I just want to ask for some help about our project:

  • We have two tanks or storage where water is kept. Each of them has an ultrasonic sensor serving as a water level sensor. I have already defined two values (lowWaterLevel & workingIrrigation) serving as thresholds where a pump and solenoid valves will depend for their working state.

  • I have already created a code for the basics where if the distance outputted by the sensor is greater than or equal to the lowWaterLevel value, the pump and solenoid valves will cease to work. If the distance is less than or equal to the lowWaterLevel value, the pump and solenoid valves will be able to work again. However, I need the pumps and valves to be not working abruptly due to the lowWaterLevel threshold. So, I have thought that the workingIrrigation threshold will help with that. Once the water reaches the lowWaterLevel value, the pump and solenoid valves will not work until it reaches again the workingIrrigation value.

I'm very sorry if this explanation and code are messy. Hoping for your insightful comments. Thank you very much!

I know that the code is not doing what the comment says. I'm hoping for suggestions on what logic or function should I use for what I intended to do. Thanks again!

This is the part of the code that I'm talking about:

    if ((distanceT1 < lowWaterLevel) && (distanceT2 > lowWaterLevel)) {
      Serial.println("Water pump and solenoid valves will work");
    } else if ((distanceT2 < lowWaterLevel) && (distanceT1 > lowWaterLevel)) {
        Serial.println("Water pump and solenoid valves will work");
    } else if ((distanceT2 < lowWaterLevel) && (distanceT1 < lowWaterLevel)) {
        Serial.println("Water pump and solenoid valves will work");
    } else {
        Serial.println("Water pump and solenoid valves will not work"); // once the distance is greater than lowWaterLevel value,
    }                                                                   // the pump and solenoid valves will cease to work until
                                                                        // the water rises up again to the workingIrrigation value.

hi welcome to the forum.

I'm in transit, so can only recommend that you look into hysteresis, which form your prose seems you already have or have attempted.

It's dead simple, here's how it would work for heating:

if the temperature is above the high threshold, turn off the heat

if the temperature is below the low threshold, turn in the heat

Two if statements, no connection between them and no other logic.

Your home thermostat lets you dial in a number, then the high and low thresholds might be that number plus or minus a delta that makes the thresholds.

In the tank, low might be 1 foot of water and high 9 feet.

When I'm not moving, I'll look at the code, maybe this is all in there.

A brief glance makes me think there should be separation of the two things that logic is dealing with, and if they need combining, a separate section.

a7

1 Like

I think your code above is equivalent to this, do you agree?

    if (distanceT1 < lowWaterLevel or distanceT2 < lowWaterLevel) {
      Serial.println("Water pump and solenoid valves will work");
    } else {
        Serial.println("Water pump and solenoid valves will not work"); // once the distance is greater than lowWaterLevel value,
    }                                                                   // the pump and solenoid valves will cease to work until
                                                                        // the water rises up again to the workingIrrigation value.

In your code, you detect 3 different conditions, but the outcome is the same for each of them. Only the final/else condition is different. So it can be simplified as above.

But is that truly the correct logic? If one tank is below low water level, so long as the other tank is above low water level, keep pumping? A tank could run completely dry and allow air into the pipes, because the other tank is still above low water level?

This workingIrrigation water level, can either tank or both reach this level before the pump is allowed to operate again?

1 Like

Hello! Thank you for the reply.

There is actually no 'high' threshold because there is an overflow pipe. As the water rises up to the very top, the excess water will go out the tank.

The two threshold or values are just there to give enough time for the pumps to work, and not work, and not abruptly work. The lowWaterLevel = 72.5 cm and workingIrrigation = 62.5 cm. The tanks are full of water, so the pump will be able to work. Once it drains up to the lowWaterLevel value, the pump will cease to work. The pump will be able to work again if the water rises up again to the workingIrrigation value, and so then it loops.

Actually, yes. Simpler and more readable. Thank you for that!

Yes, as long as one tank is above the low water level and workingIrrigation, the pump will work.

The tank will not be completely out of water. The value of the lowWaterLevel is actually made for it to still have a little amount of water left.

I'll put it into an example for a more understandable explanation:

  • The tanks are full of water, so the pump will be able to work. Once it drains up to the lowWaterLevel value, the pump will cease to work. The pump will be able to work again if the water rises up again to the workingIrrigation value.

lowWaterLevel = 72.5 cm
workingIrrigation = 62.5 cm

Thank you!

flow chart

What about my last question?

hi again! either tank it is

const byte pumpPin = 2;
...
    if ((distanceT1 < workingIrrigation or distanceT2 < workingIrrigation) and digitalRead(pumpPin) == LOW)
    {
      Serial.println("Water pump and solenoid valves will now work");
      digitalWrite(pumpPin, HIGH);
      // once the distance is less than workingIrrigation value,
      // the pump and solenoid valves will start to work until
      // the water drops down again to the lowWaterLevel value.
    }
    else if (distanceT1 > lowWaterLevel and distanceT2 > lowWaterLevel and digitalRead(pumpPin) == HIGH)  
    {
      Serial.println("Water pump and solenoid valves will not work");
      digitalWrite(pumpPin, LOW);
      // once the distance is greater than lowWaterLevel value,
      // the pump and solenoid valves will cease to work until
      // the water rises up again to the workingIrrigation value.
    }  
1 Like

@ivanr1 I will look closer, but the "flow" chart I'd like to see is a simple drawing of where water comes from and goes to and by what means the coming or going is effected.

I'm almost certain such a diagram could be gleaned from your words, but you know the old saying…

a7

Post a simple handdrawn system overview showing sensors and actuators per tank.

1 Like

That's the upper and lower thresholds. Besides how you need and do not need to deal with two tanks and two sensors, it's exactly the pseudocode I posted and is implemented by @PaulRB in #10 abkve.

The extra condition checking whether the pump is on (or off) already is mostly uselful to keep the printing down to one message per switching.

The simpler logic I posted just turns it on or off without regard to whether it may already be. On or off.

Somethings that don't like being turned on when they are already on must exist… LEDs and motors on MOSFETs don't know the difference.

How many pumps are there? How many valves?

a7

1 Like

Hello, everyone! After many 'mini' revisions of PaulRB's shared arduino code, I have partially achieved what our device intended to do in terms of the water level sensoring. This code that I will share does what the device is intended to do, but it treats the two tanks as ONE.

Here's the part of the code:

#include <NewPing.h>

#define MAX_DISTANCE 400  // Maximum distance (in cm) to ping.
float durationT1, distanceT1, durationT2, distanceT2;
int iterations = 5;
const float lowWaterLevel = 72.5;
const float workingIrrigation = 62.5;

const int PUMPrelayPin = 7;

char *state[] = {"Water pump and solenoid valves will now work", "Water pump and solenoid valves will not work"};
int pumpState = HIGH;

unsigned long currentMillis = 0;

unsigned long PreviousMillis = 0;
unsigned long sonarPreviousMillis = 0;
unsigned long sonarPreviousMillis2 = 0;
unsigned long pumpPreviousMillis = 0;

const unsigned long Period = 1000;
const unsigned long sonarPeriod = 29;
const unsigned long sonarPeriod2 = 29;

NewPing sonar[2] = {              // Sensor object array.
  NewPing(49, 48, MAX_DISTANCE),  // Each sensor's trigger pin, echo pin, and max distance to ping.
  NewPing(47, 46, MAX_DISTANCE)
};

void setup() {
  Serial.begin(9600);
  Serial.println("test");

  pinMode(PUMPrelayPin, OUTPUT);
  digitalWrite(PUMPrelayPin, HIGH);
  pinMode(relayPin1, OUTPUT);
  digitalWrite(relayPin1, HIGH);
  pinMode(relayPin2, OUTPUT);
  digitalWrite(relayPin2, HIGH);
  pinMode(relayPin3, OUTPUT);
  digitalWrite(relayPin3, HIGH);
}

void loop() {
  currentMillis = millis();

  if ((currentMillis - sonarPreviousMillis) > sonarPeriod) {
      sonarPreviousMillis = currentMillis;

      durationT1 = sonar[0].ping_median(iterations);
      distanceT1 = (durationT1 / 2) * 0.0343;
  }

  if ((currentMillis - sonarPreviousMillis2) > sonarPeriod2) {
    sonarPreviousMillis2 = currentMillis;

    durationT2 = sonar[1].ping_median(iterations);
    distanceT2 = (durationT2 / 2) * 0.0343;
  }

  if ((currentMillis - pumpPreviousMillis) > 20) {
    pumpPreviousMillis = currentMillis;

    if (((distanceT1 < workingIrrigation) and (distanceT2 < workingIrrigation)) and (pumpState == HIGH))
    {
      pumpState = LOW;
    }
    else if (((distanceT1 > lowWaterLevel) and (distanceT2 > lowWaterLevel)) and (pumpState == LOW))  
    {
      pumpState = HIGH;
    }
    digitalWrite(PUMPrelayPin, pumpState);
  }

  if ((currentMillis - PreviousMillis) > Period) {
    PreviousMillis = currentMillis;
    
    Serial.print("TANK 1");
    Serial.print(" = ");
    Serial.print(distanceT1);
    Serial.print("cm ");

    Serial.print("TANK 2");
    Serial.print(" = ");
    Serial.print(distanceT2);
    Serial.println("cm");

    if (((distanceT1 < workingIrrigation) and (distanceT2 < workingIrrigation)) and (pumpState == LOW))
    {
      Serial.println("Water pump and solenoid valves will now work");
    }
    else if (((distanceT1 > lowWaterLevel) and (distanceT2 > lowWaterLevel)) and (pumpState == HIGH))  
    {
      Serial.println("Water pump and solenoid valves will not work");
    }
    else
    {
      Serial.println(state[pumpState]);
    }

    Serial.println();
  }
}

I've been happy with the results as there is progress. The next step is for the device to treat the two tanks as separate and not as one. I think, I'll just need to separate those conditions. Hoping for you another insightful comments, thank you!

In terms of the flow chart and drawing, I'm still in the phase of doing it.

Haha, there goes the spam reduction!

Also, I don't know about ppl with more functioning brain cells than I seem to be able to scare up just now, but I am having lotsa trouble envisioning this because you talk about distances rather than levels.

So saying when the distance is greater than X I would be saying when the water is below X Y.

The distance could be transformed into a level, just sayin'.

a7

1 Like

One pump and three valves. The pump will let water flow to the irrigation pipes and out to the plants, while those three valves will keep the water from going out. The valves and pumps are also dependent to the soil moisture content of the plants' soil.

Yes, haha. I made that last part to serial print every second to not bomb me with too much unreadable outputs. It helped me a lot knowing and solving what the problem is.

About the values, the ultrasonic sensors will be placed on top of the lid of the tanks facing down. So, the values of the distances will decrease as the water level rises. Indirectly proportional.

That thought of transforming them into levels has already crossed my mind, but I prioritized first fixing the problem.

Thank you very much for the patience you allotted for envisioning the code!

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