Programming bugs with dual water level controller using 2x ultrasonics HC-SR04

This is what I want to happen and what is happening with a site test.

What I want to happen is.

I have a large gold fish tank which requires old water to be removed and replaced with fresh water.

I have a small tank (I called it Feed averaging tank (FAT)) which I want to fill with fresh tap water with a solenoid valve then leave still for 5 days to dechlorinate. If the water does not sit for this time the chlorine in the tap water will kill my fish. After this is complete I need to pump old water from the gold tank and pump the fresh water from the FAT tank into the gold tank. I then want the solenoid to open and fill up the FAT tank to repeat the cycle.
As my tanks is outside they can get filled with rainwater so it would be good to have a high high level which would turn on the pumps till a high level is reached. My ultrasonics could be submersed otherwise.

The hardware is an uno R3, 2 x HC-sr04 ultrasonic sensors, a 4 channel relay board, 2 x aquarium pumps, a solenoid valve. I tested all components with different code and they are working.

The code I have written is with levels and a short delay(not 5 days) for testing purposes.I have not written in the high high level function, help with this is welcome.

What is really happening
on startup everything switchs on briefly. (bad as chlorine will go to fish)
The gold tank pump empties to low level then the fat pump transfers across (OK)
The solenoid opens and closes at high level on the FAT tank and the FAT pump transfers across small amounts. (bad as chlorine will go to fish, the FAT should fill then have the delay)
The gold tank stays at a low level(bad as this is ugly, it should be at high level for display purposes)
The program seems to reach an equilibrium and stop instead off repeating the cycle.
Serial monitor does not always work so hard to debug.

#include "Ultrasonic.h"


Ultrasonic ultrasonicg(12,13);
Ultrasonic ultrasonicf(6,7);
long duration, distance;//fat
long duration2, distance2;//gold


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

pinMode (4, OUTPUT);//fat
pinMode (5,OUTPUT);//gold
pinMode (3, OUTPUT);//sol
}

void loop()
{
  
  
  Serial.print(ultrasonicf.Ranging(CM));
  Serial.print("cm fat  ");
  
  delay(1500);
  Serial.print(ultrasonicg.Ranging(CM));
  Serial.print("cm gold  ");
  delay(1500);

  
if ((ultrasonicg.Ranging(CM)) <= 16 )
{
digitalWrite (5,LOW);//gold on


Serial.print("cm gold pump run  ");
}
if ((ultrasonicg.Ranging(CM)) > 16 )
{
  digitalWrite (5,HIGH);//gold off
digitalWrite (4,LOW);//fat on
digitalWrite (3,HIGH);//sol off
Serial.print("gold off with fat on");
}
if (((ultrasonicf.Ranging(CM)) >= 16 ) || ((ultrasonicg.Ranging(CM)) <= 6 )) 
{
digitalWrite(4,HIGH);// turn the FAT pump off

Serial.print("fat off sol on ");
}
if ((ultrasonicf.Ranging(CM)) >= 6 )
  {
digitalWrite (3,LOW);//sol on
digitalWrite(4,HIGH);// turn the FAT pump off
digitalWrite(5,HIGH);//gold off
Serial.print("sol on");
  }
 else if ((ultrasonicf.Ranging(CM)) <6)
{ 
digitalWrite (3,HIGH);//sol off
Serial.print("sol off");


delay(40000);//dechlorinate
}


}

on startup everything switchs on briefly. (bad as chlorine will go to fish)

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

digitalWrite(4,HIGH);
digitalWrite(5,HIGH);
digitalWrite(3,HIGH);
pinMode (4, OUTPUT);//fat
pinMode (5,OUTPUT);//gold
pinMode (3, OUTPUT);//sol
}

I would suggest swapping the pinModes with the digitalWrites. You want to have high outputs, not pullups.

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

pinMode (4, OUTPUT);//fat
pinMode (5,OUTPUT);//gold
pinMode (3, OUTPUT);//sol
digitalWrite(4,HIGH);
digitalWrite(5,HIGH);
digitalWrite(3,HIGH);

}

The idea was to set the pins HIGH before enabling as OUTPUTs so the low true relays don't pick up immediately.

if ((ultrasonicf.Ranging(CM)) >= 6 )

Shouldn't this be 16?

Also is the water sloshing up and down a lot? If so, you may need to put in some deadband. Are your pumps above water level in both tanks? You may have unintended siphons when levels are different and pumps are off.

The idea was to set the pins HIGH before enabling as OUTPUTs so the low true relays don't pick up immediately.

That's a good thought but you should also include pull-up resistors so the relays don't turn on when a reset turns the outputs to inputs.

I would suggest swapping the pinModes with the digitalWrites. You want to have high outputs, not pullups. Not necessary. The PORT register (the one digitalWrite() sets) acts as both the pull-up enable for INPUT and the output value for OUTPUT. You can set it before or after the Data Direction Register (the one pinMode() sets).

Shouldn't this be 16? The high water levels are lower numbers, eg 4cm is full and 29 cm will be empty as the ultrasonics measure top down.Therefore I need a low number to keep the tank full. Also rainwater might fill the tank to say 15cm from 16cm and the program will not fill the tank. Also is the water sloshing up and down a lot? If so, you may need to put in some deadband. No sloshing as I have small pumps and big tanks. Are your pumps above water level in both tanks? You may have unintended siphons when levels are different and pumps are off. Yes this is possible.I will put the discharge hoses above water level or a pin hole in the hose above water level to break any siphon. I will add ``` digitalWrite(4,HIGH); digitalWrite(5,HIGH); digitalWrite(3,HIGH); ``` to stop the initial startup issue-thanks for this. :)

Please post to help with the other issues !!

Hi, Instead of continually doing pings all the way through your sketch. I would at the top of the loop, (1). Ping each of the ultrasonics and store the two values, (2). Then use those two values ALL the way through your sketch. (Do not ping again, "One Ping and One Ping Only") (3). Go back to top of loop (as the program will do) and do (1) again, etc etc.

The values that come from the ultrasonics are never the same over two or more pings for the same level. So when you PING once you will be taking a picture of your system, then act upon it, then take another picture etc etc.

Tom.... :)

Hi, What is the source of you Ultrasonic Library? I am trying to compile but the Ultrasonic library I have has different functions.

Tom.... :)

Your problem is here:

if ((ultrasonicf.Ranging(CM)) >= 6 )

As soon as FAT pump pulls water level below 6 cm SOL comes on and FAT pump turns off.

What is the source of you Ultrasonic Library? I am trying to compile but the Ultrasonic library I have has different functions.

I found the link on this forum post http://forum.arduino.cc/index.php?topic=37712.0 And he has a website here http://blog.iteadstudio.com/arduino-library-for-ultrasonic-ranging-module-hc-sr04/

Eureka,
this works !!! :slight_smile:

#include "Ultrasonic.h"


Ultrasonic ultrasonicg(12,13);
Ultrasonic ultrasonicf(6,7);



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

pinMode (4, OUTPUT);//fat
pinMode (5,OUTPUT);//gold
pinMode (3, OUTPUT);//sol
digitalWrite(4,HIGH);
digitalWrite(5,HIGH);
digitalWrite(3,HIGH);
}

void loop()
{
  
  
  Serial.print(ultrasonicf.Ranging(CM));
  Serial.print("  cm fat  ");
  
  delay(1500);
  Serial.print(ultrasonicg.Ranging(CM));
  Serial.print("  cm gold  ");
  delay(1500);

if ((ultrasonicf.Ranging(CM)) <= 5 )
  {
    digitalWrite (3,HIGH); //sol off
    delay(20000);//dechlorinate 20 sec
    digitalWrite(5,LOW);//gold on
   
  }
  
if ((ultrasonicg.Ranging(CM)) >=15)
{ 
digitalWrite (5,HIGH);//gold off
digitalWrite (4,LOW);//fat on

digitalWrite (3,HIGH); //sol off
} 
 
if ((ultrasonicf.Ranging(CM))>= 15 )
{
digitalWrite (4,HIGH);//fat off
digitalWrite (3,LOW); //sol on

}
}