Trying to pause inside of a loop

Hello,

I'm in need of advice. I have a very simple project that counts bubbles through a tube. When there is not a bubble the photointerrupter reads HIGH. When a bubble passes, it reads LOW. I want to have a short delay as to not miss a bubble but I don' want it counting 1 bubble as 2 or more, which is what it does currently. Is there any way to make my loop pause until the gate goes HIGH again?

int Gate = 2;
int gateState = 0;
int led = 7;
unsigned long time;

void setup() {

  Serial.begin(9600);
  pinMode(Gate, INPUT);
  pinMode(led, OUTPUT);
}

void loop() {
    
  gateState = digitalRead(Gate);
  time = millis();
  
  if (gateState == HIGH) {
    digitalWrite(led, LOW);
   
  } else {
    digitalWrite(led, HIGH);
    Serial.print("     TIME ");
    Serial.print(time);
    Serial.print("    Bubble!        ");

    delay(gateState = LOW);  ????  Problem area.
    
  }
  
  delay(100);   
}

Record the state of gateState into another variable "prevState" and see if the current state is different from prevState. Then once you see that it has changed, you then see if that current state is HIGH.

In your loop.

static byte prevState = 0; // you can make this static and have it inside the loop or global outside the loop.
gateState  = digitalRead(2); // read the pin

if(gateState != prevState) // if the current state does not equal is last state (ie changed from HIGH to LOW or Vs., go in)
{
  if(gateState == HIGH)
  {
     //increase counter
  }
  //else ignore it

  prevState = gateState; // update prevState;
}

Rather than use a delay() you should write your code to look for a LOW after a HIGH before it considers the next HIGH to be another bubble.

If you really want to use an interval use millis() to manage timing without blocking as illustrated in Several Things at a Time

...R

Thank you both so much. I'll start working on this. Great ideas.

@hazardsmind,

This is what I have now per your suggestions.

int Gate = 2;
int gateState = 0;
int led = 7;
unsigned long time;
static byte prevState = 1;

void setup() {

  Serial.begin(9600);
  pinMode(Gate, INPUT);
  pinMode(led, OUTPUT);
  
}

void loop() {
    
  
  gateState = digitalRead(Gate);
  time = millis();
  
  if (gateState != prevState) {
    digitalWrite(led, HIGH);
    Serial.print("     TIME ");
    Serial.print(time);
    Serial.print("    Bubble!        ");
   
  } 
    
   prevState = gateState; 
  
  
  delay(100);   
}

This works much better than before. It won't do anything until the first bubble passes and then it prints the time from start and "Bubble!". The only problem is that it also prints "Bubble!" and the corresponding time to when the bubble passes; thus, giving two "bubble!" announcements/actual bubble. Is there a way to make it just read the one bubble? Going from HIGH to LOW, but now LOW to HIGH?

Well, I must admit that I'm not using the bubbles at this very moment. I'm simply placing a business card in the gate.

When I start the program and the gate is uninterrupted, nothing is printed. Once I place the business card in the gate, "Bubble!" and its time is printed. Then there is pause as long as the card remains in the gate. Once I remove the card, "Bubble!" is printed again with its time.

I had two IF statements in my example, I see only one in yours.

IF only I had paid more attention... :o

Thanks again.

I'm off to make this more usable.

Works. Thanks to your suggestions. And I've learned a lot.

int Gate = 2;
int gateState = 0;
int led = 13;
float time;

void setup() {

  Serial.begin(9600);
  pinMode(Gate, INPUT);
  pinMode(13, OUTPUT);
}

void loop() {
    
  static byte prevState = 1;
  gateState = digitalRead(Gate);
  time = millis();
  
  if(gateState != prevState) 
  {
    if(gateState == LOW)
    {
    digitalWrite(led, HIGH);
    Serial.print("Bubble! @ ");
    Serial.print(time/1000);
    Serial.print("seconds\n");
    }
    //else ignore
    prevState = gateState; 
  } 
  delay(50);
}

I'm going to work on making the time displayed the actual time/date now.

Again, I appreciate it.