Line before 'for loop' is running until 'for loop' ends

I'm having trouble with some code running until my for loop is done. I have a buzzer that signals the start of the light change, and I'm using a For Loop to intialize the lights on a NeoPixel Ring.

The problem is that the buzzer keeps on ringing until the for loop has completed lighting all the LEDs on the NeoPixel ring.

I don't physically have a NeoPixel Ring, I'm using Circuits on Tinkercad | Tinkercad to test this with.

What I've tried to rectify the problem is:

  • Create a for loop for the buzzer. (still gets stuck)
  • Move the for loop outside the if statement (still gets stuck)
  • Remove the delay (buzzer doesn't sound)

Without the for loop, lighting a single RGB LED works fine.. but adding this into their seems to have messed it up. I've tried to use strip.fill from the NeoPixel library but for some reason tinkercad doesn't recognize it so I'm stuck using this for loop to accomplish my goal.

I'm including the full code, a snippet where the problem is happening, and an image of the setup.

Here is the full code:

#include <Adafruit_NeoPixel.h>
#define PIN 5
#define NUMPIXELS 24
Adafruit_NeoPixel ring(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);

int powerInd=13;
int button=7;
int buzzer=6;
int buzzTone1=880;
int buzzTone2=1046.5;
int buzzTone3=1318.52;
byte ringState=0;
boolean oldButtonState = LOW;
boolean buttonState1 = LOW;
boolean buttonState2 = LOW;
boolean buttonState3 = LOW;
int j;

void setup() {
  pinMode(powerInd,OUTPUT);
  digitalWrite(powerInd,HIGH); //Indicate Power is On
  pinMode(button,INPUT);
  pinMode(buzzer,OUTPUT);
//  tone(buzzer,2800);   --------REMOVED BUZZER FOR TESTING---------
//  delay(500);
//  noTone(buzzer);   
}

void loop() {

   buttonState1 = digitalRead(button);
   buttonState2 = digitalRead(button);
   buttonState3 = digitalRead(button);
 
    if (  (buttonState1==buttonState2) && (buttonState1==buttonState3) )
    {
 
        if ( buttonState1 != oldButtonState ) 
        {
 
           if ( buttonState1 == HIGH )
           {
                ringState++;
                
                 if (ringState > 3) { ringState = 0;}
                          
                   ring.clear();
                   ring.show();
                
                    if (ringState==1) {
                      tone(buzzer,buzzTone1,100);
                      delay(100);
                      for(int j=0;j<NUMPIXELS;j++) {
                        ring.setPixelColor(j, ring.Color(0, 255, 0));
                        ring.show();}
                    }
    
                    if (ringState==2) {
                      tone(buzzer,buzzTone2,200);
                      delay(200);
                      tone(buzzer,buzzTone1,100);
                      delay(100);                                      
                      for(int j=0;j<NUMPIXELS;j++) {
                        ring.setPixelColor(j, ring.Color(255, 255, 0));
                        ring.show();}
                     }   
             
                    if (ringState==3) {
                      tone(buzzer,buzzTone2,200);
                      delay(200);
                      tone(buzzer,buzzTone1,100);
                      delay(100);
                      tone(buzzer,buzzTone3,200);
                      delay(200);                      
                      for(int j=0; j<NUMPIXELS; j++) {
                        ring.setPixelColor(j, ring.Color(255, 0, 0));
                        ring.show();}
                    }
              delay(1000);
          }
         oldButtonState == buttonState1;
      }
  }
}

Here is where the problem is:

                    if (ringState==1) {
                      tone(buzzer,buzzTone1,100);
                      delay(100);
                      for(int j=0;j<NUMPIXELS;j++) {
                        ring.setPixelColor(j, ring.Color(0, 255, 0));
                        ring.show();}
                    }

Since your never seem to "parallelize" any actions with the buzzer a better idea might be to adopt tone/noTone approach, instead of specifying duration in tone and then repeating it in delay.

For example

tone(buzzer, buzzTone2);
delay(200);
noTone();

Did you try to use an explicit call to noTone before the LED cycle? Does it stop the buzzer?

I just tried to add noTone(buzzer) and it doesn't stop the buzzing from running until the for loop ends.

Thanks for the suggestion on that though!

EDIT:
Sorry.. I didn't catch the part where you said to match the delay.

It's working fine now with:

                    if (ringState==1) {
                      tone(buzzer,buzzTone1);
                      delay(100);
                      noTone(buzzer);
                      delay(100);
                      for(int j=0;j<NUMPIXELS;j++) {
                        ring.setPixelColor(j, ring.Color(0, 255, 0));
                        ring.show();}
                    }

Thanks!

ONE MORE EDIT: I just realized you didn't specifically say to do this, but it works.. I'd still like to understand why it does this though.

Something that might be causing problems, by letting the code run constantly while the button is HIGH instead of just once:

 oldButtonState == buttonState1;