Beep for 1 second without delay

Hi! I have a timing system that I want to have beep for 1 second every time an RFID chip is read. This would be easy to do using the delay() function, but if I do that I could miss an athlete coming in after. I've been tinkering around with millis() in a separate sketch, but can't seem to get it to work properly. Any help is appreciated!
code:

int note = 880;
int piezo = 8;
int button = 9;
int buttonState;
int prevButtonState = 0;

unsigned long currentMillis = 0;
unsigned long prevMillis = millis();
unsigned period = 1000;
void setup() {
  // put your setup code here, to run once:
  pinMode(piezo, OUTPUT);
  pinMode(button, INPUT);
}

void loop() {
  buttonState = digitalRead(button);
if (buttonState != prevButtonState){
  if(buttonState == LOW){
currentMillis = millis();
  tone(piezo, note);
  if(currentMillis - prevMillis >= period){
    noTone(piezo);
  } 
   
  }
  prevButtonState = buttonState;
}
}


The Arduino tone() allows a duration to be specified

 tone(pin, frequency, duration);

so while it is admirable that you are trying, and you shoukd figure out how to use millis() instead of dealy() one day, it appears that you don't need to in this case.

a7

Hi,

If I see this correctly, you do not set prevMillis when the tone starts. You set it, when the Arduino starts. So the value will either be undefined or very close to 0.

What you need is to store prevMillis when you start the tone.
You should also check the condition every time, when the loop runs, i.e. outside of the button conditions.

I hope this works.

Your code would then look like the following:

int note = 880;
int piezo = 8;
int button = 9;
int buttonState;
int prevButtonState = 0;

unsigned long currentMillis = 0;
unsigned long prevMillis = 0; // init with 0
unsigned period = 1000;

void setup() {
  // put your setup code here, to run once:
  pinMode(piezo, OUTPUT);
  pinMode(button, INPUT);
}

void loop() {
  currentMillis = millis();
  buttonState = digitalRead(button);
  if (buttonState != prevButtonState){
    if(buttonState == LOW){
      prevMillis = currentMillis;
      tone(piezo, note);
    }
  }
  if(currentMillis - prevMillis >= period){
    noTone(piezo);
  } 
  prevButtonState = buttonState;
}

BUT: If you press the button within this period, revMillis will the set to currentMillis and the peep counter will start again. This way, you can have an endless peep, if you periodically press the button, but it will stop period millis, after the last time you pressed it.

Cool, didn't know that either! :smiley:

Neither did I. Thank you for all your help!

Real quick, do you know if the duration is in milliseconds?

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.