Trouble with while delay not working

This is my first attempt at a sketch to feed hydro plants with fertilized water.
I expect there is poor programming in the code because I am new to it.

Apart from other probable programming mistakes I need to know why the while loop doesn't work?
Just advice on how to make that work would be greatly appreciated.

Here is my sketch. The notes describe what I've set out to do.

/*NOTES:
Sketch to supply treated water to a hydroponics system.

A 12V DC water level board controls 9V power to an Arduino Uno R3 through a step down converter.
When the water is low the water level board switches power on to a water supply solenoid which is connected to the Arduino Uno R3 via a Normally Closed solenoid relay.
When the treated water tank begins to fill, a float level switch (2) in the bottom of the treated water tank closes and powers up the Uno.
The Uno then switches on a solution stirrer motor and a peristaltic pump feeding solution into the treated water tank for fixed time periods.
When the peristaltic pump stops the solution stirrer then stops.
When the water tank is full (float level switch 1 in the top of the treated water tank opens) the Uno turns off the water supply solenoid via the Normally Closed solenoid relay.
It then turns on the water transfer pump to feed hydroponic trays.
When the water tank drains, causing the water level switch 2 to open. The open circuit switches off the Uno.

*/

void setup() {
  pinMode(2, OUTPUT);        // 12V NC relay to switch off solenoid connected direct to UNO
  pinMode(3, OUTPUT);        // 12V growing solution stirrer motor through 12V relay module
  pinMode(4, OUTPUT);        // 12V peristaltic solution injection pump through 12V relay module
  pinMode(5, OUTPUT);        // 12V pump treated water to trays through 12V relay module
  pinMode(6, INPUT_PULLUP);  // float switch 1 (full holding tank) connected direct to UNO
}

void loop() {
  digitalWrite(3, HIGH);  // switch on growing solution stirrer motor
  //delay(20000);           // wait 20 seconds to get solution moving

  digitalWrite(4, HIGH);  // switch on peristaltic solution injection pump
  //delay(20000);           // delay time 20 sec to measure fertilizer

  digitalWrite(4, LOW);  // switch off peristaltic solution injection pump

  digitalWrite(3, LOW);  // switch off growing solution stirrer motor

  while (digitalRead(6) == LOW)  // wait until float switch 1 shows treated water tank is full
  {
    digitalWrite(2, HIGH);  // switch off water supply solenoid

    digitalWrite(5, HIGH);  // run treated water pump to tray
  }
}

Welcome to the forum

    pinMode(6, INPUT_PULLUP); 

Pin 6 is held HIGH until it is taken LOW so until then the while loop condition will be false and the code in the while loop will not be executed

How is pin 6 wired and what takes it LOW to keep the while loop running ?

It seems to me that the notes has nothing to do with code

If the pin 2 is a switch, why it initialized as OUTPUT in the code?

There are nothing similar to managing "fixed time periods." in the code.

What causes the pump to stop?

It seems to me that the iisue is not due to poor programming, but to the complete absence of a regulation algorithm at all.

Maybe a good time to start using pin names, rather than imaginary numbers.

4 Likes

Many thanks for your time.
According to the documentation the float level switch is normally closed and opens when the tank is full.
I have one lead connected to digital pin 6 and the other connected to the 5V pin on the Uno.

If you use INPUT_PULLUP, you must connect the 'other' pin to Gnd, not to 5V.

and that's a very good idea you should follow :wink: .

Whoops - as already noted by @MicroBahner

Replies to your three queries . . .

Pin 2 is used to activate the NC relay to switch off the water supply solenoid.

I have Delays after the stirrer and peristaltic pump are switched on. I assume they work but understand millis may be needed if Delays are liable to interfere with effective running of the sketch. Not active while I sort out the while coding.

The pump is switched off by the digitalWrite(3) and (4) code in the sketch.

Hi, @hydro312
Welcome to the forum.

Can you please post a copy of your circuit, a picture of a hand drawn circuit in jpg, png?
Hand drawn and photographed is perfectly acceptable.
Please include ALL hardware, power supplies, component names and pin labels.

Can you post some images of your project?
So we can see your component layout.

Do you have a DMM? (Digital MultiMeter)

Thanks.. Tom.. :smiley: :+1: :coffee: :australia:

What are (3) and (4) connected to ?
Pump3 and Pump4 ? :frowning:

Sorry. This reply was to b707. I assumed the forum format would keep comments and replies together.

Hi @hydro312,

welcome to the arduino-forum.
well done to post your code as a code-section in your first posting.

You made a first attempt on your own. It is very good that you showed own effort.

This is a good starting-point to give further advice.
As alreay mentioned you should define constants for your IO-pins.
The names of these constants should be spot-on to describe their purpose.

There is a simulation-website called WOKWI where you can simulate quite a lot of things.

I created a WokSim for your code.
The leds represent your motors and relay
Here is a simple version that has only constants for your IO-pins instead of numbers

And here is a version of your code with additional debug-macros.
At the top of the macros is a link that explains how these macros work.
Using the serial monitor to make visible what your code is doing and what values variables do have
is a very powerful tool for debugging

If you start using the serial monitor with your real hardware I recommend to use Arduino-IDE 1.8.19 and I want to explain why:

The Arduino-IDE 2.X has a lot of new features but the functionality of the serial monitor of IDE 2.X falls back far beyond what the serial monitor of IDE version 1.8.19 can do.

IDE 2.X								| IDE 1.8.19
integrated part of the main window  | extra and resizable window 
See many lines of code and          | see many lines of code AND
a few lines of the serial monitor   | many lines of the serial monitor
or                                  | at the same time
See a few lines of code and         |
many lines of the serial monitor    |
                                    |
you can copy only the visible part  | you can copy THOUSANDS of lines
of the window = 5 to 20 lines       | shown in the serial monitor

This limited functionality was posted as an issue on Github on Feb 6, 2022

I tested the IDE version 2.3.2 on 21.07.2024 the limited functionality is still there.

This means this serial-monitor-issue exists since 896 Days = 2,45 years

Maybe I am too dumb to see it. But I did not find any information
when the development team will start solving this issue
nor did I find any statement why the development-team will keep the
serial monitors limited functionality forever.

Here is a tutorial how you can install a completely independant
Arduino-IDE 1.8.19 for much better debugging

You should write down in normal words a description what kind of functionality you want to have.

I beg you:
use normal words. Zero programming terms at all. You are an expert in normal language. You not yet an expert about programming. This means trying to explain your wanted functionality with code has a danger of misconceptions how the code works.

As you mentioned the function millis()
explaining non-blocking timing
I want to comment on the basic blink_without_delay example-code.

The basic basic blink_without_delay example-code makes understanding non-blocking timing
harder than it must be for multiple reasons:

It starts with postings that have sentences like "use function millis() instead of delay()"
There is a pretty high danger that this sentence creates a totally wrong picture of how non-blocking timing works.
Such a sentence initiates a wrong picture of

replace delay() with millis() and you are done.

non-blocking timing requires more than a simple replacing.

  1. the blink without delay-example does NOT mention that there is a fundamental difference
    between delay() and non-blocking timing
    Without explicitly explaining this difference newcomers are in danger to see a delay()-similar-Thing
    And trying to see a delay()-similar thing will cause extra confusion because there is NO similarity!

  2. a part of the variable-names is badly chosen.

  3. the demo-code distributes the variables to mutliple places

The variable-distribution makes it harder to understand the basic principle.

I suggest that you watch this video as the introduction to non-blocking timing
It will guide you on the right track and explain it step by step

Thank you very much StefanL38. I’ve read your feedback and can see I have some way to go to become conversant with this software. At the moment time constraints oblige me to focus on correcting the mistakes in my code noted by yourself and other respondents to my enquiry, but I will back in touch with you directly when I am more knowledgable on this subject. Regards, Hydro312

Pin (3) is connected to a relay that controls a 12v DC worm drive motor stirring a fertiliser solution that tends to settle. Pin (4) is connected to a relay that drives a peristaltic pump that feeds fertiliser solution into a treated water holding tank. I have a delay drafted in the code to measure the feed volume, but have // ‘d it until the while issue is sorted.
I will update my sketch to give clear names to the pins, as suggested by others.

I take your point but I mentioned millis because I’d read elsewhere that Delay is generally frowned upon for various reasons. I don’t know if its use in the sketch I’ve drafted is likely to affect its functionality for my purposes. I have in mind delays to make the peristaltic pump run for possibly 3mins 30 sec, less time for the stirrer. Do you think Delays are wrong to achieve that in my sketch?

won't the relay be switched off as soon as the water level rises above the "low" level?

doesn't the Arduino power relay need to remain on until the water level is "high"?

wouldn't power be supplied through the Normally Open contacts?

seems that there are 2 opertions that the Arduino needs to perform but needs both sensors for when the treated water tank is full and empty

(and it remains unclear what turns on/off power to the Arduino)

enum { On = HIGH, Off = LOW };

void loop ()
{
    digitalWrite (PinStirrer, On);
    digitalWrite (PinPump,    On);

    // wait for treated water tank to become full
    while (digitalRead (PinFloat) == HIGH)
        ;

    digitalWrite (PinStirrer, Off);
    digitalWrite (PinPump,    Off);

    digitalWrite (PinPump2,   On);

    // wait for treated water tank to be emptied
    //   ????
    digitalWrite (PinPump2,   Off);
}

The function delay() should better have this name

freeze_microcontroller_COMPLETELY_stop_ALL_code_execution_until_freezing_time_is_over()

As long as a delay() is "active" which is more a freezing of the whole microcontroller you can not detect any change of an IO-pin and you can not switch on / off any other IO-pin.

So if you want to keep your 20 seconds delay()= freezing
or a 210 seconds delay() = freezing this means your control is unable to react for 210 seconds to anything.

You would have to make sure that running your peristaltic pump for 210 seconds is always possible regardless of how much water is in your tank

You would have to make sure that opening your "fill-in"-valve for "X" seconds is always possible regardless of how much water is in your tank and without overflooding.

Once you have understood non-blocking timing you never want to use delay() again.

Your water-control is a typical application for a programming-technique called
step-sequencer².

You are doing a certain sequence of steps.
I try to describe what I think what your wanted functionality is.

You will have to correct my description if my description is wrong

  1. switch on solenoid to start to fill in pure water into the storage tank
  2. switch on stirrer-motor
  3. switch on peristaltic pump to fill in fertiliser
  4. switch off peristaltic pump , switch off stirrer-motor
  5. check if storage-tank is filled up completely
  6. if filled up completely close solenoid-valve, switch on water-pump to pump water to the plants

² for all those code-term purists: sure I mean state-machine. Though IMHO the term "state-machine" is scientific and sophisticated. Might be more practical for theoretical considerations. The term step-sequencer is much more practical and creates the right picture. After having explained what it does it will be no problem to introduce the real term the scientific term for "step-sequencer" is "state-machine" .

Here is my diagram showing how everything is connected. I could send you a photo of the whole setup but it would be pointless just now. There is a hole in the middle, left when I removed the Uno to test my sketch using leds on a breadboard. I’d already done that and thought it all worked okay, but obviously not with respect to the while loop and the bad connection of Pin 6 to 5V rather than GND.