Question about delays within a function and the main loop

Hi all,

I have what I'm assuming is a very basic question. I'm new to arduinos though and unfortunately due to covid and holiday break I'm unable to test this out myself for a couple of weeks, so was hoping the forums could help me.

I have the following code (copied below), the idea is that I have a sensor and a solenoid pump (so it works as a valve) hooked up to one arduino. I would like to read from the sensor as quickly as possible (i.e. at the shortest loop time), while also being able to trigger the solenoid without it holding up the loop.

My question is, because solenoid() contains a delay, will the loop get held up until solenoid() is completed, meaning I will only read from the sensor once every ~3 seconds? In C# I'd typically resolve this problem using a coroutine or multithreading depending on circumstance, but as I'm still new to arduino I am not sure what is possible with this device and how I'd go about it, if I even need to.

Here is the code. At the moment, it is meant to just read from the sensor continuously, and also send a signal to the solenoid every 3s to pump fluid through it.

int sensorPin = A0; 

int sensorValue = 0;
// int counter = 0;

void setup() {
  pinMode(5, OUTPUT); // output for solenoid
  Serial.begin(57600);
}

void loop() {
  sensorValue = analogRead(sensorPin); // reads sensor
  Serial.println(sensorValue);
    
  solenoid();    
}

void solenoid(){
    digitalWrite(5, HIGH);
    delay(250);
    digitalWrite(5, LOW);
    delay(2750);
}

Yes delay() locks everything up.

-jim lee

Take a look at Using millis() for timing. A beginners guide, Several things at the same time and the BlinkWithoutDelay example in the IDE

You can make it easy by using ezOutput library

it will be simple as below without using delay:

solenoid.blink(250, 2750); // 250 milliseconds ON, 2750 milliseconds OFF

You can take a look to this example

Or implement by yourself by using millis() instead of [delay()[/iurl]. See how to use millis() instead of multiple delay()
](https://arduinogetstarted.com/reference/arduino-delay)

UKHeliBob:
Take a look at Using millis() for timing. A beginners guide, Several things at the same time and the BlinkWithoutDelay example in the IDE

IoT_hobbyist:
You can make it easy by using ezOutput library

it will be simple as below without using delay:

solenoid.blink(250, 2750); // 250 milliseconds ON, 2750 milliseconds OFF

You can take a look to this example

Or implement by yourself by using millis() instead of [delay()[/iurl]. See how to use millis() instead of multiple delay()

[/quote]
Thanks so much for the replies, super informative. Managed to get a hold of an Uno to test it out (using print statements, I don't have the actual equipment handy), using millis() instead of delay as in this example makes a lot of sense and has put me on the right track I think.

I read through the page I linked above (How to use millis() instead of delay()), as well as the several things at the same time and the beginners guide to millis() pages, and I think I understand it conceptually. However, I tried to implement my own code based on these and I'm sure I've made some silly mistake but cannot figure out for the life of me what I've done wrong.

I've copied the new code below - I realized that I can just move the print statement into the if statement and it would run exactly as I want it (and considering I will swap the print statement to digitalWrite this is probably better anyway) but I'm still curious about what I did wrong. The timings are correct, but when the case is HIGH for some reason I am printing both "on" and "off" to the monitor when I only want to be printing "on".

Thanks again for the help

#define SOLENOID_ON 2000

#define SOLENOID_OFF 3000

int sensorPin = A0;

// solenoid needs digital output and gnd
int sensorValue = 0;
int counter = 0;

unsigned long lastMillis = 0;
// unsigned long lastMillis_2 = 0;
byte solenoidState = HIGH;

void setup() {
  pinMode(5, OUTPUT); // output for solenoid
  Serial.begin(9600);
}

void loop() {
  sensorValue = analogRead(sensorPin); // reads sensor
  //Serial.println(sensorValue); 
  solenoid();
}

void solenoid(){
 
  unsigned long currentMillis = millis();
 
  switch( solenoidState ){
   
    case HIGH:
      Serial.println("on");
      if (currentMillis - lastMillis >= SOLENOID_ON) {
        lastMillis = currentMillis;
        solenoidState = LOW;
      }
     
    case LOW:
      Serial.println("off");
      if (currentMillis - lastMillis >= SOLENOID_OFF) {
        lastMillis = currentMillis;
        solenoidState = HIGH;
      }
  }
}





](https://arduinogetstarted.com/reference/arduino-delay)

latchh:
The timings are correct, but when the case is HIGH for some reason I am printing both "on" and "off" to the monitor when I only want to be printing "on".

I didn't follow the action line by line but, I notice you've no break;* statements to conclude the cases. Without a break; execution flows right into the next statement - although sometimes this is the intent. If you set the warning level to max in IDE - file/preferences you'll see messages to this effect.

IDE reference page