Water level control with arduino, help

Hi, I'm working on an assignment that needs to meet the bellow requirements. This is my first time using C++ and wanted to know if the code I've written is going about this in the right way.

Scenario

a control system is used to maintain the water level in a sump between the levels high and low. Two transducers (HIGH and LOW) are used to monitor the level. The water is pumped out by two pumps, P1 and P2.

The water level in the sump is to be controlled as follows:

 If the level reaches high one pump will start to pump out.

 If the level does not reach low within about 30 seconds, the second pump will come into action. If the level does reach low before 30 second pumping should stop.

 If the level does not reach low within about 30 seconds of the second pump starting, an alarm is given. The alarm is sounded until the level reaches low.

If the level does reach low before 30 seconds the pumping should stop.
 The pumps will stop when low is detected.

 To give even loading of the pumps they are to be used alternately, e.g. if on one pump cycle P1 starts first and P2 is the ‘back up’ then on the next cycle P2 will start first and P1 is the ‘back up’.

When I've tidied the code up I'll be using it UnoArduSim, but before I start to finesse what I've got I wanted to make sure what I have so far isn't a big back of spanners.


int Pump1=8;
int Pump2=9;
int Alarm=7;
int potPin= 1
int potValue=0;


void setup() {
pinMode(Pump2,OUTPUT);
pinMode(Pump1,OUTPUT);
pinMode(Alarm,OUTPUT);}

void loop()
{

for (int potvalue <= 921; ) { digitalWrite(Pump1 , LOW);}

if(digitalRead(potValue) >= 921);
{digitalWrite(Pump1, HIGH);
delay(30000);}

if(digitalRead(potValue)<=102)
{digitalWrite(Pump1 , LOW);}

Else { digitalWrite(Pump2 , HIGH);}
Delay(30000);

if(digitalRead(potValue)<=102);
{digitalWrite(Pump1, Pump2, LOW);}

Else {digitalWrite(Pump1, Pump2, LOW);
DigitalWrite(Alarm, HIGH);}

If(digitalread(potvalue)<=102);
{DigitalWrite(Alarm, LOW);}

}

I'm using a potentiometer as the level of the sump and 90% as high and 10% as low, so took 90% and 10% of 1023

One of the conditions is that Pump1 and Pump2 need to alternate but I'm not sure how to do this, is it a case of a line at the end of the loop that renames pump1 and pump2 or do I copy the code and replace pump 1 with pump 2 and vice versa and then place that below the code above so that it runs through them both and then goes back to the start

any help notes or advice much appreciated. Thanks

closed account (48T7M4Gy)
Please use code tags by selecting your code in edit mode and pressing the <> button in the toolbox on the right.

As far as your program is concerned there don't appear to be any glaring mistakes.

However the nature of Arduino work and development is such that you should be testing it yourself with a live/real system. In that respect just testing one pump and making sure you can turn it on and off is a proper start. If you haven't got pumps and water then use LED's or dc motors and switches.

In short, test and devlop in small increments and see what happens. Since the loop will execute very rapidly, putting simple time delays in will help too.

If pumps1 and 2 have to alternate then the first step is to write down exactly what that means. pseudocode will help. If you can't expalin it then nobody else can.

However, if you mean what I can only guess at, use an array of pumps and swap the indices. So pump[0] is your Pump1 etc ... So if you swap pumps you swap indices :)
In addition to @kemort's advice, I would recommend getting rid of the hard-coded values in your if statements. Where you define your other variables, define highWaterValue and lowWaterValue, and use those variables to check against. If you ever decide that 10% and 90% are not quite right, a simple change of the variables values will be less cumbersome to change the changing all of the hard-coded values in the code. Also, the variable names will make the code easier to understand.

I do see a couple glaring errors.
1
2
if(digitalRead(potValue) >= 921);
{digitalWrite(Pump1, HIGH);


You have a stray semicolon at the end of the if statement. That is a no-op for the if statement, and the next line will always execute. You did this in at least 3 places.

I've done limited Arduino coding (I need to get back to that....), so I may be slightly misguided, but std C++ uses all lower case for "if" and "else". "If" and "Else" may be legal in Arduino coding, but if you want to transition to other C++ coding, using the standard lower-case version of these key words might be a good idea.
Unfortunately I think you need a different approach. Consider this:
1
2
3
if(digitalRead(potValue) >= 921);
{digitalWrite(Pump1, HIGH);
delay(30000);}

This starts pump1 and then waits 30 seconds. What if the water pumps out in 10 seconds? You could empty the sump and run the pump dry which will burn it out if you do it enough.

A better approach would be for loop() to do something like this:
1
2
3
4
5
6
loop()
{
    // examine the state of the system
    // make any changes necessary
    sleep(1);
}

In other words, once per second you wake up, see what's going on, and change things accordingly.

You have to read the pot pin with analogRead() instead of digitalRead()

There's another nasty gotchya: when the water level is right near the high or low mark, different readings will show different values. For example, with the high mark at 921, you're likely to see readings like 920 922 919 918 921 925 920 920 923 921 922 918... You can't assume that each transition from "below high" to "above high" is a transition that you should act upon.

To avoid this, you should a technique called hysteresis. Keep a variable that says whether you were last in a low water condition or high water. A transition below the low reading only "counts" if the current state is high water. And a transition above the high reading only counts if the current state is low. You can represent the state with a single boolean
1
2
3
// set when transitioning above high mark. Cleared when transitioning below
// low mark
bool isHigh=false;


It's handy to think about what events can cause something to happen. There are 4 of them:
- transition to high water
- transition to low water
- first timer triggers
- second timer triggers

If you think of it this way, the code is very easy to write. Here is a skeleton of the code. Just fill in the code where I have the comments.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
int HighWaterMark = 1023*0.9;
int LowWaterMark = 1023*0.1;

int Pump1=8;
int Pump2=9;
int Alarm=7;
int potPin= 1;

// The pumps. start pumps[0] first and pumps[1] second.
// swap values when you reach the low water mark.
int pumps[2] = {Pump1, Pump2};

// set when above high mark. Cleared when transitioning below
// low mark
bool isHigh=false;

// Timer 1 is set to 30 seconds after pump1 turns on.
// Timer 2 is set to 30 seconds after pump2 turns on.
time_t timer1;
time_t timer2;

void setup() {
pinMode(Pump2,OUTPUT);
pinMode(Pump1,OUTPUT);
pinMode(Alarm,OUTPUT);}

void loop()
{
    // read the water level and get the current time.
    int potValue = analogRead(potPin);
    time_t now = time(0);
    
    
    if (timer1 && timer1 < now) {
	// first timer triggered
	// start second pump
	// set timer2 to 30 seconds from now
	// disable timer1 by setting it to zero.
	
    } else if (timer2 && timer2 < now) {
	// second timer triggered
	// set alarm
	// disable timer2

    } else if (potValue < LowWaterMark && isHigh) {
        // transition to low water level
	// change isHigh to indicate low water
	// disable both timers, just to be sure
	// turn off both pumps
	// turn off alarm in case it was on
	// swap pumps[0] and pumps[1] so the next time you'll use them in the opposite order
	
    } else if (potValue > HighWaterMark && !isHigh) {
	// level reached high
	// turn on pumps[0]
	// set timer1 to 30 seconds from now;
	set isHigh to indicate you've reached high water.
    }

    // now sleep for 1 second to conserve power.
    sleep(1);
} 

Topic archived. No new replies allowed.