Switch of pump before closing valves

Hi, Can you please help me with my code. I googled for a solution but could not find it. I do not have enough experience to solve this on my own.
I am writing a sketch to control a solar hot water system. The sketch is based on the Differduino sketch from Nateful. I am using an Arduino Uno. The sketch is to long to attach in full. I will attach the sections I think are relevant for you to be able to understand the issue and help.

Solar heating system overview:

the system has 30m2 of solar water collectors, a 4000l hot water storage tank, 3 water pumps, 5 solenoid on/off water valves and 7 temperature sensors. Based on the value of the temperature sensors the sketch has to start/stop the relevant pump/s and open and close the required valves.
There is a total of 9 different water circulation options possible such as (heating storage tank, heating pool, heating boiler etc.)

Problem with the sketch:

The sketch is working except that the solenoid valves are closing while the water is still flowing in the pipes causing a terrible loud bang I can hear throughout the house. I have to include a pump stop of about 5 seconds before triggering the valves to close in the code. I have tried various ways to do this but nothing has worked so far.

Existing sketch:

declaring Booleans to store circulation options (above void setup):

//variables used for control logic

static bool collectortanktoppossible;
static bool collectorgeyser1possible;
static bool collectorgeyser2possible;
static bool collectorpoolpossible;
static bool fireplacetanktoppossible;
static bool fireplacegeyser1possible;
static bool fireplacegeyser2possible;
static bool fireplacepoolpossible;
static bool tanktopgeyser1possible;
static bool tanktopgeyser2possible;

If else test to determine which circulating option is possible (in void loop). There is a total of 9 of these in the sketch:

// collector pump switching logic for collector/tanktop heating
     
      if (tankbottomcollectorMaxed)
           
      {       
        if  (tankbottom < (tankbottomMax - tankbottomCooldown ) ) 
        { 
          tankbottomcollectorMaxed =false;
        }
      }
           
      else
      {
        if ( tankbottom > tankbottomMax )
        {
          
          tankbottomcollectorMaxed = true;
          collectortanktoppossible = false;
         
        
        }
      }

      if (!tankbottomcollectorMaxed)
      
      {
        if (collectortanktoppossible)
        {

          if ( (differentialcollectortankbottom < minDifferentialcollectortankbottom ) )
          {
            
            collectortanktoppossible = false;        
            
          }
        }
        else
        {
          if ( (differentialcollectortankbottom > setDifferentialcollectortankbottom ) )       
          {
            
            collectortanktoppossible = true;
           
          }
        } 
      }

Pump and valve switching logic (in void loop). there is a total of 9 of these in the sketch:

  // pump and valve switching logic for collector/tanktop heating             
     
         if (!collectorgeyser1possible && !collectorgeyser2possible && collectortanktoppossible && !(collectortanktoppossible && fireplacetanktoppossible))

            {
            digitalWrite (pumpfireplace, LOW);
            digitalWrite (pumptank, LOW);
            digitalWrite (pumpcollector, HIGH);
            
            digitalWrite (valvegeyser1, LOW);
            digitalWrite (valvegeyser2, LOW);
            digitalWrite (valvetank, HIGH);
            digitalWrite (valvepool, LOW);
            digitalWrite (valvedrain, LOW);        
            }

My attempt of coding pump to stop 5 seconds before valve closes. I think there should be 9 of these. code does not work. Pump just switches on and of every 5 seconds:

//variables used for control logic pump slow down

static bool collectortanktoppossiblestate;
static bool lastcollectortanktoppossiblestate;


// pump and valve switching logic for pump slow down if collectortanktoppossible changes    
 // read collectortanktoppossible state     
     collectortanktoppossiblestate = collectortanktoppossible;
     

    // compare the collectortanktoppossiblestate to its previous state
     if (collectortanktoppossiblestate != lastcollectortanktoppossiblestate)

           {

           digitalWrite (pumpcollector, LOW);  
           digitalWrite (pumpfireplace, LOW);
           digitalWrite (pumptank, LOW); 
           delay(5000);
            
           }

     // save the current collectortanktoppossiblestate as the last state for the next time through the loop
      collectortanktoppossiblestate = lastcollectortanktoppossiblestate;

Thanks for your help
Fuenkli

Fuenkli:
The sketch is to long to attach in full.

You can post it as an attachment.

thank you for the tip. I have attached the sketch.

solar_control_program_version_20.10.2017.ino (57.4 KB)

Fuenkli:
thank you for the tip. I have attached the sketch.

no offense meant, sincerely, but your code is quite the kludge.

You really should learn about creating arrays and objects (a struct or a class) to make it a lot easier to make changes.

also, look at the method of reading the sensors by their address directly rather than doing the address search method, it is very inefficient.

and use the F Macro to put those string literals into flash memory, you are wasting a lot of SRAM in your code.

instead of this:

Serial.println ("starting lcd");

like this

Serial.println (F("starting lcd"));

There is also an easy plumbing change that will limit or eliminate the problem. Google for "water hammer". The remedy is quite simple.

Paul

thanks for the input. Based on your advice I will rewrite my code. I do however still not know how to run a section of a loop only once after a variable has changed. I can not eliminate the "water hammer" with a change to the plumbing. There is just no space upstream of the valves to install dampers. I can also not reduce the velocity in the pipes without compromising the efficiency of the system.

Fuenkli:
thanks for the input. Based on your advice I will rewrite my code. I do however still not know how to run a section of a loop only once after a variable has changed. I can not eliminate the "water hammer" with a change to the plumbing. There is just no space upstream of the valves to install dampers. I can also not reduce the velocity in the pipes without compromising the efficiency of the system.

it is OK, stopping the flow by shutting off the pump, waiting, and then closing the valves is the way to go, even if you had a mechanical way to prevent the water hammering.

My advice... make a program that works for one water circuit, then come back to learn how to do the rest with objects and arrays

thanks for the advice. I will give it a go.