Beep a numeric code with a buzzer without delay

Hi, i’m trying to make a buzzer transmit a 3-digit numeric code using beeps (sort of pseudo morse). I’m using the delay function for this but the pausing is getting in the way of the rest of the program. I’ve been trying to transform this into code using millis for three nights in a row but seem to be getting lost in the proces every time. Below is the code with delay that works fine, except for the delay. :wink:

Anybody out there that can show me the way?

#define buzzer 13 

int code[] = {4, 6, 2}; // array with 3 digit code to transmit

void setup() {
pinMode(buzzer, OUTPUT);
} 

void loop() {
  for (int m1 = 0; m1 < 3; m1++) {        // loop through the array three times 
    for (int m2 = 0; m2 < code [m1]; m2++) {  // as long as the number of beeps played is smaller than de value of the digit play a beep and then pause
      tone(buzzer, 3000, 100); // beep for 100 ms
      delay(200);   // pause 200 ms between two beeps 
    }              
  delay(1000);  // longer pause of 1000ms between digits
  }               
}

Your final code will have NO for loops - it doesn't need them. The loop() function already loops.

It will have NO delay()s.

On any given pass through loop(), it may, or may not be time to do something. The first step is to determine that.

If it IS time to do something, the next thing to do is to define WHAT to do. Increment m1 (a global variable), maybe. Make a noise, maybe. YOU define what it is you want to do when it is time to do something.

The blink without delay example shows how to do things periodically without using delay().

What do you intend to do when the required number of beeps has happened?

Thx PaulS for your guidance, i will try to write it tonight and post the result here. One question. If i decide later to transform this into a function, will that change anything. ie. do i then have to use loops?

Thx again PaulS. With your advice a was able to come up with this bit of code. There is still a delay in there but it doesn’t bother. I you have any tips on optimizing the code i would love to here it. For example i tried to use

if (n < sizeof code) {

to replace

if (n < 3) {

but after 1,5 loop of the function it goes haywire.

Also if you know of a more elegant ways of doing the same job i would love to hear about it.

#define buzzer 13
int code[] = {1, 2, 3}; // array with 3 digit code to transmit
int n = 0;
int beeps = 0; // remember the number of beeps played for this digit
unsigned long prevMillis = 0;

void setup() {
  pinMode(buzzer, OUTPUT);
}

void loop() {
  morse ();
}

void morse() {
  if (n < 3) { // if not all digits are played
    if (beeps < code[n]) { // if number of beeps is not equal to # digit, play a beep
      if (millis() - prevMillis >= 200 ) { // if 200 ms passed
        tone(buzzer, 3000, 100); // beep for 100 ms
        prevMillis = millis(); // reset the timer
        beeps++; // remember you played a beep
      }
    } else {
      delay(1000); // wait 1 second
      beeps = 0;
      n++; // go to next digit
    }
  } else {
    n = 0; // reset
  }
}

Hello
Sizeof return the size in bytes of an array, not the elements inside it. I guess that you won t have number >255 so you should declare the array code as "byte" not int

Than, i would use a different approach

If i were you i would create a new function
For example:
void beepNumber (byte num) {
Put here your for loop
}

In this way it would be cleaner and more debugging friendly

Looking at this another way, you are always beeping but the delay between beeps is either short or long depending on whether you are in the middle of a code.

Using the code as a counter you know how many beeps to make with the short delay. When the count gets to zero the long delay should be used and the counter needs to be reset based on the next code.

I'll offer alternative code that does away with the call to delay().

#define buzzer 13
int code[] = {1, 2, 3}; // array with 3 digit code to transmit
int n = 0;
int beeps = 0; // remember the number of beeps played for this digit
unsigned long prevMillis = 0;

unsigned long beepDelay = 0UL;    // how long to delay between beeps
byte codeIdx = 0;                 // index into code
byte beepCount;                   // # of beeps in current code

void setup() {

  pinMode(buzzer, OUTPUT);

  // initialize count for first code
  beepCount = code[0];

}


void loop() {

  // if it's time to beep
  if (millis() - prevMillis >= beepDelay)
  {
    tone(buzzer, 3000, 100);

    // if no more beeps for this code
    if ( !--beepCount )
    {

      // delay between codes
      beepDelay = 1000;

      // increment index, wrap to first code
      codeIdx = codeIdx == 2 ? 0 : codeIdx + 1;

      // set # of beeps for this code
      beepCount = code[codeIdx];

    } else {

      // delay between beeps in code
      beepDelay = 200;

    } // else

    // mark time of this beep
    prevMillis = millis();

  } // if

}