looping question

Hello
I'm relatively new to programming.
I'm using an UNO with a relay shield to develop a simple automatic watering system to turn on 24vdc water valves for the garden.

I'm using Ardublock to program and have an UNO programmed and running using a breadboard to test.
The idea is to have 4 inputs triggered by 4 moisture sensors to trigger the 4 shield relays to power 24vdc water valves.
When I go to test it works wonderfully when testing an individual random input all by itself. However, when I go to test more than one input (say I press an input and then press another input shortly after) the second input does nothing.

My question is how do I separate the four loops (if possible) so that each input is not waiting on another to restart the loop?

I have a delay for each loop of 30 seconds and another for 5 minutes. The 30 seconds is to run the water and the 5 minutes delay is for the water to soak into the soil before taking a moisture reading which will send a low to the input and shut the process down until the sensor kicks a high.

Do I subroutine the delays in each loop or can I separate the 4 loops?

Take a look at the blink without delay example in the IDE.

My question is how do I separate the four loops (if possible) so that each input is not waiting on another to restart the loop?

You don't. You write a single loop that does all four things.

I have a delay for each loop of 30 seconds and another for 5 minutes. The 30 seconds is to run the water and the 5 minutes delay is for the water to soak into the soil before taking a moisture reading which will send a low to the input and shut the process down until the sensor kicks a high.

Time to study up on Blink Without Delay and any of the myriad examples and tutorials about that concept. You can't have the delays. You have to handle timing a different way if you want to have more than one thing happening.

A bit advanced, but it may ring the bell.

I need the delays to allow time for the soil to soak up the water. I cant have soil saturation that drowns the plants.
Is it possible to put the delay times for each loop in a subroutine?

You need a passage of time.
You do not need delays

OP, have a look at this code. It compiles on a Mega2560 and hopefully wouldn't need a great deal to work on your setup. I've only tested #1 in DEBUG (see define) but not the other channels.

See if you can trace what I'm doing to time these events "simultaneously" without using "delay()" and without having any of the plants suffer while waiting for the others to be watered.

(Part 1 of 2)

//watering and soaking time constants
//because we use millis, these are expressed in
//unsigned longs and are in milliseconds
const unsigned long culWateringTime = 30000;
const unsigned long culSoakingTime = 300000;

//sensor and water valve control pins
const int pinMoistureSensor1 = A0;
const int pinMoistureSensor2 = A1;
const int pinMoistureSensor3 = A2;
const int pinMoistureSensor4 = A3;

const int pinWaterValve1 = 9;
const int pinWaterValve2 = 10;
const int pinWaterValve3 = 11;
const int pinWaterValve4 = 12;

//i don't know how your sensor works. assume it's just
//an analog voltage with a count that ranges from
//0 to 1023. 850 is an arbitrary "dryness" value below
//which water is needed. Adjust as needed
const int cnSoilDrynessThrehold = 850;          //whatever value you deem as being too dry

//these are the state names. all four state machines can use them
//all that's needed is they have unique numbers to differentiate
//them from one another
#define CHECK_SENSOR        0
#define APPLY_WATER         1
#define ALLOW_SOAK          2

//depending on how your solenoids are wired, a high or
//a low might be needed to turn them on. I guessed...
#define WATER_ON            HIGH
#define WATER_OFF           LOW


#define DEBUG               1       //for testing timing function on #1 (comment out for normal operation)

void setup() 
{
    pinMode( pinMoistureSensor1, INPUT );
    pinMode( pinMoistureSensor2, INPUT );
    pinMode( pinMoistureSensor3, INPUT );
    pinMode( pinMoistureSensor4, INPUT );

    pinMode( pinWaterValve1, OUTPUT );
    digitalWrite( pinWaterValve1, WATER_OFF );
    pinMode( pinWaterValve2, OUTPUT );
    digitalWrite( pinWaterValve2, WATER_OFF );
    pinMode( pinWaterValve3, OUTPUT );
    digitalWrite( pinWaterValve3, WATER_OFF );
    pinMode( pinWaterValve4, OUTPUT );
    digitalWrite( pinWaterValve4, WATER_OFF );

    //if you want to add some debug messages
    Serial.begin(9600);
    
}//setup

void loop() 
{
    //loop just calls each of the four state machines
    //because millis timing is used, the time spent in each
    //function is very small so no stations suffer from
    //being "delayed" by the others
    WaterOne();
    WaterTwo();
    WaterThree();
    WaterFour();
    
}//loop

Part 2 of 2 (copy and paste to the 1st…)

void WaterOne( void )
{
    static byte
        stateW1 = CHECK_SENSOR;
    static unsigned long
        timeW1,
        timeW1Delay;

    switch( stateW1 )
    {
        case    CHECK_SENSOR:
            //read your sensor to determine if watering is necessary
            if( analogRead( pinMoistureSensor1 ) < cnSoilDrynessThrehold )
            {
                timeW1 = millis();                              //record the millis counter now
                digitalWrite( pinWaterValve1, WATER_ON );       //turn on the water
                timeW1Delay = culWateringTime;                  //set delay compare to 30000mS (30-seconds)
                stateW1 = APPLY_WATER;                          //next time through we go to APPLY_WATER state
                
            }//if
            
        break;

        case    APPLY_WATER:
            //timeW1 was initialized above to the then-current millis count
            //as millis increases over time, the difference between "then" and
            //"now" increases. We just keep checking for that difference
            //to exceed whatever number of milliseconds we want to delay
            if( (millis() - timeW1) >= timeW1Delay )
            {
                timeW1 = millis();                              //record the millis counter now
                digitalWrite( pinWaterValve1, WATER_OFF );      //turn off the water
                timeW1Delay = culSoakingTime;                   //set soaking in delay compare to 300000mS (5-minutes)
                stateW1 = ALLOW_SOAK;                           //next time through we go to APPLY_SOAK state
                
            }//if
        break;

        case    ALLOW_SOAK:
            //wait for the soak period to end before going back to the beginning
            //state where you can start checking the moisture sensor again
            if( (millis() - timeW1) >= timeW1Delay )
                stateW1 = CHECK_SENSOR;                         //next time through we go to APPLY_SOAK state

        break;

    }//switch
    
}//WaterOne

void WaterTwo( void )
{
    static byte
        stateW2 = CHECK_SENSOR;
    static unsigned long
        timeW2,
        timeW2Delay;

    switch( stateW2 )
    {
        case    CHECK_SENSOR:
            //read your sensor to determine if watering is necessary
            if( analogRead( pinMoistureSensor2 ) < cnSoilDrynessThrehold )
            {
                timeW2 = millis();                              //record the millis counter now
                digitalWrite( pinWaterValve2, WATER_ON );       //turn on the water
                timeW2Delay = culWateringTime;                  //set delay compare to 30000mS (30-seconds)
                stateW2 = APPLY_WATER;                          //next time through we go to APPLY_WATER state
                
            }//if
            
        break;

        case    APPLY_WATER:
            //timeW1 was initialized above to the then-current millis count
            //as millis increases over time, the difference between "then" and
            //"now" increases. We just keep checking for that difference
            //to exceed whatever number of milliseconds we want to delay
            if( (millis() - timeW2) >= timeW2Delay )
            {
                timeW2 = millis();                              //record the millis counter now
                digitalWrite( pinWaterValve2, WATER_OFF );      //turn off the water
                timeW2Delay = culSoakingTime;                   //set soaking in delay compare to 300000mS (5-minutes)
                stateW2 = ALLOW_SOAK;                           //next time through we go to APPLY_SOAK state
                
            }//if
        break;

        case    ALLOW_SOAK:
            //wait for the soak period to end before going back to the beginning
            //state where you can start checking the moisture sensor again
            if( (millis() - timeW2) >= timeW2Delay )
                stateW2 = CHECK_SENSOR;                         //next time through we go to APPLY_SOAK state

        break;

    }//switch
    
}//WaterTwo

void WaterThree( void )
{
    static byte
        stateW3 = CHECK_SENSOR;
    static unsigned long
        timeW3,
        timeW3Delay;

    switch( stateW3 )
    {
        case    CHECK_SENSOR:
            //read your sensor to determine if watering is necessary
#ifdef DEBUG
            if( 0 < 1 ) //force a condition for debug
#else
            if( analogRead( pinMoistureSensor3 ) < cnSoilDrynessThrehold )
#endif
            {
                timeW3 = millis();                              //record the millis counter now
                digitalWrite( pinWaterValve3, WATER_ON );       //turn on the water
                timeW3Delay = culWateringTime;                  //set delay compare to 30000mS (30-seconds)
                stateW3 = APPLY_WATER;                          //next time through we go to APPLY_WATER state
                
            }//if
            
        break;

        case    APPLY_WATER:
            //timeW1 was initialized above to the then-current millis count
            //as millis increases over time, the difference between "then" and
            //"now" increases. We just keep checking for that difference
            //to exceed whatever number of milliseconds we want to delay
            if( (millis() - timeW3) >= timeW3Delay )
            {
                timeW3 = millis();                              //record the millis counter now
                digitalWrite( pinWaterValve3, WATER_OFF );      //turn off the water
                timeW3Delay = culSoakingTime;                   //set soaking in delay compare to 300000mS (5-minutes)
                stateW3 = ALLOW_SOAK;                           //next time through we go to APPLY_SOAK state
                
            }//if
        break;

        case    ALLOW_SOAK:
            //wait for the soak period to end before going back to the beginning
            //state where you can start checking the moisture sensor again
            if( (millis() - timeW3) >= timeW3Delay )
                stateW3 = CHECK_SENSOR;                         //next time through we go to APPLY_SOAK state

        break;

    }//switch
    
}//WaterThree

void WaterFour( void )
{
    static byte
        stateW4 = CHECK_SENSOR;
    static unsigned long
        timeW4,
        timeW4Delay;

    switch( stateW4 )
    {
        case    CHECK_SENSOR:
            //read your sensor to determine if watering is necessary
            if( analogRead( pinMoistureSensor4 ) < cnSoilDrynessThrehold )
            {
                Serial.println( "Beginning watering..." );
                timeW4 = millis();                              //record the millis counter now
                digitalWrite( pinWaterValve4, WATER_ON );       //turn on the water
                timeW4Delay = culWateringTime;                  //set delay compare to 30000mS (30-seconds)
                stateW4 = APPLY_WATER;                          //next time through we go to APPLY_WATER state
                
            }//if
            
        break;

        case    APPLY_WATER:
            //timeW1 was initialized above to the then-current millis count
            //as millis increases over time, the difference between "then" and
            //"now" increases. We just keep checking for that difference
            //to exceed whatever number of milliseconds we want to delay
            if( (millis() - timeW4) >= timeW4Delay )
            {
                Serial.println( "Beginning soaking..." );
                timeW4 = millis();                              //record the millis counter now
                digitalWrite( pinWaterValve4, WATER_OFF );      //turn off the water
                timeW4Delay = 300000ul;                         //set soaking in delay compare to 300000mS (5-minutes)
                stateW4 = ALLOW_SOAK;                           //next time through we go to APPLY_SOAK state
                
            }//if
        break;

        case    ALLOW_SOAK:
            //wait for the soak period to end before going back to the beginning
            //state where you can start checking the moisture sensor again
            if( (millis() - timeW4) >= timeW4Delay )
            {
                Serial.println( "Returning to check sensor..." );                
                stateW4 = CHECK_SENSOR;                         //next time through we go to APPLY_SOAK state
                
            }//if
        break;

    }//switch

}//WaterFour

hippalator:
I need the delays to allow time for the soil to soak up the water.

The functions delay() and delayMicroseconds() block the Arduino until they complete.
Have a look at how millis() is used to manage timing without blocking in Several Things at a Time.

And see Using millis() for timing. A beginners guide if you need more explanation.

...R

I'm not that familiar with the millis to bypass delay.
And after some thought I decided that a delay is ok. I dont need to multitask the UNO just to water a garden tube. "Keeping it simple stupid" is my moto.

However I have another issue. I've composed another sketch utilizing the Analog pin on the sensor and UNO to kick a digital output.
Using a cup filled with damp potting soil to test the threshold I'm having trouble figuring out how to stop the bouncing as I pull the sensor out of the cup.
It worked fine with one sensor and relay sketched in but I sketched in a second sensor and relay and now I'm getting this bouncing chatter.

Any ideas?

hippalator:
Any ideas?

No idea what you did wrong. I can't see your code from here. Do you see how that might be a problem?

Never mind I figured it out.
Thanks everyone for the help

hippalator:
Never mind I figured it out.
Thanks everyone for the help

That’s what we thought the problem was.

Now we can tell other new people so they can learn too.

Is there a way to skip over a piece of loop?

hippalator:
Is there a way to skip over a piece of loop?

You’re the one who says you found your error but won’t share the problem with others who might need the help. Now you want more help?

There are ways to skip part of a loop. How you might do it depends on the code which you aren’t showing and what type of loop which you haven’t said and what you want to skip which again you are not telling us.

Be detailed.

I think it best to discontinue using the arduino and find an alternative from the look of things.

hippalator:
I think it best to discontinue using the arduino and find an alternative from the look of things.

I don't know what led you to that conclusion, but go ahead, it's your choice.

hippalator:
I think it best to discontinue using the arduino and find an alternative from the look of things.

Bye.