Buzzing piezo and refreshing lcd at the same time

Hello, I’m displaying co2 measurements from a sensor on a lcd (the measurements are just an float value right now because I dont have acces to the sensor yet). My problem is that, if the value is above 1000, I want to buzz 2 times every 3 seconds, like this would do if it was just that piece of code:

 void loop() {
     tone(piezo, 500);
      delay(200);
      noTone (piezo);
      delay(200);
      tone(piezo, 500);
      delay(200);
      noTone(piezo);
      delay(3000);
}

But I also want to update the info on the lcd every 0.5 seconds. Is there a way I can update the lcd while also buzzing the piezo at the same time? I found this as a possible solution: https://www.arduino.cc/en/Tutorial/BuiltInExamples/BlinkWithoutDelay, but I don’t know how to implement it properly. This is my code: (please read the remarks as well)

#include <LiquidCrystal.h>

LiquidCrystal lcd(2,3,4,5,6,7);

float Co2 = 1001; //these are just values 'simulating' the sensor
float temp = 20;
float hum = 70.6;
int r = 10;
int g = 9;
int b = 8;
int piezo = 13;
int buzzing = 0;
int x;

void setup()
{
  Serial.begin(9600);
  pinMode(r, OUTPUT);
  pinMode(g, OUTPUT);
  pinMode(b, OUTPUT);
  lcd.begin(16,2);
  lcd.clear();
  for (int x = 0; x < 40; x++) {
    lcd.print("Warming up");
    delay(250);
    lcd.clear();
    lcd.print("Warming up.");
    delay(250);
    lcd.clear();
    lcd.print("Warming up..");
    delay(250);
    lcd.clear();
    lcd.print("Warming up...");
    delay(250);
    lcd.clear();
  }
}

void buzz (int x) {
  if (buzzing == 0) {
    buzzing = 1;
    if (x == 0) {
      tone(piezo, 500); //This part takes time which causes the entire loop to wait until it is over. The lcd 
      delay(200);       // won't refresh every 0.5 seconds because of this.
      noTone(piezo);
      delay(3000);
      buzzing = 0;
    }
    else if (x == 1) {
      tone(piezo, 500);
      delay(200);
      noTone (piezo);
      delay(200);
      tone(piezo, 500);
      delay(200);
      noTone(piezo);
      delay(3000);
      buzzing = 0;
    }
  }
}
void loop()
{
  lcd.print("Co2: ");
  lcd.print(Co2, 0);
  lcd.print("PPM");
  lcd.setCursor(8, 1);
  lcd.print("H: ");
  lcd.print(hum,1);
  lcd.print("%");
  lcd.setCursor(0,1);
  lcd.print("T: ");
  lcd.print(temp, 0);
  lcd.print("C");
  if (Co2 > 800 && Co2 < 1001){
    analogWrite(r, 255);
    analogWrite(g, 69);
    x = 0;
    buzz(x);             //I call the function above here.
  }
  else if (Co2 > 1000) {
    analogWrite(r, 255);
    analogWrite(g, 0);
    x = 1;
    buzz(x);
  }

Thanks!

It's simple really, you can't make Blink without Delay (i.e. more than one thing at a time) while also using delay(). You have to also code the tone delay using millis().

this was quite a challange to wrap my head around it. The code compiles but is only “tested” inside my brain
so give it a try if it works as intended in the real world

#include <LiquidCrystal.h>

LiquidCrystal lcd(2, 3, 4, 5, 6, 7);

float Co2 = 1001; //these are just values 'simulating' the sensor
float temp = 20;
float hum = 70.6;
int r = 10;
int g = 9;
int b = 8;
int piezo = 13;
int buzzing = 0;


const byte BeepOnce  = 0;
const byte BeepTwice = 1;

const byte StartBeepCycle = 1;
const byte Beep           = 2;
const byte ShortPausing   = 3;
const byte LongPausing    = 4;

int buzzStates = StartBeepCycle;

unsigned long currentMillis;
unsigned long previousMillis;

unsigned long ShortInterval   =  200;
unsigned long LongInterval    = 3000;


void setup()
{
  Serial.begin(9600);
  pinMode(r, OUTPUT);
  pinMode(g, OUTPUT);
  pinMode(b, OUTPUT);
  lcd.begin(16, 2);
  lcd.clear();

  for (int x = 0; x < 40; x++) {
    lcd.print("Warming up");
    delay(250);
    lcd.clear();
    lcd.print("Warming up.");
    delay(250);
    lcd.clear();
    lcd.print("Warming up..");
    delay(250);
    lcd.clear();
    lcd.print("Warming up...");
    delay(250);
    lcd.clear();
  }
}


void buzzNew(byte NumberOfBeeps) {

  static byte BeepCounter;
  
  currentMillis = millis();
  switch (buzzStates) {

    case StartBeepCycle:
      if (NumberOfBeeps == BeepOnce) {
        BeepCounter = 1;
      }
      else if (NumberOfBeeps == BeepTwice) {
        BeepCounter = 2;
      }
      buzzStates = Beep;        
      break;

    case Beep:
      tone(piezo, 500);
      if (currentMillis - previousMillis >= ShortInterval) {
         previousMillis = currentMillis;
         BeepCounter--;

        if (BeepCounter == 0) {
          buzzStates = LongPausing;
        }
        else if (BeepCounter == 1) {  
          buzzStates = ShortPausing;
        }
      }        
      break;

    case ShortPausing:
      noTone (piezo);
      
      if (currentMillis - previousMillis >= ShortInterval) {
        previousMillis = currentMillis;
        
        if (BeepCounter == 1) {  
          buzzStates = Beep;
        }
        else if (BeepCounter == 0)
          buzzStates = StartBeepCycle;
      }
      break;
      
    case LongPausing:
      noTone(piezo);
      if (currentMillis - previousMillis >= LongInterval) {
         previousMillis = currentMillis;
         buzzStates = StartBeepCycle;
      }
      break;
  }    
}



void loop() {
  lcd.print("Co2: ");
  lcd.print(Co2, 0);
  lcd.print("PPM");
  lcd.setCursor(8, 1);
  lcd.print("H: ");
  lcd.print(hum, 1);
  lcd.print("%");
  lcd.setCursor(0, 1);
  lcd.print("T: ");
  lcd.print(temp, 0);
  lcd.print("C");

  if (Co2 > 800 && Co2 < 1001) {
    analogWrite(r, 255);
    analogWrite(g, 69);
    buzzNew(BeepOnce);             //I call the function above here.
  }
  else if (Co2 > 1000) {
    analogWrite(r, 255);
    analogWrite(g, 0);
    buzzNew(BeepTwice);
  }
}

best regards Stefan