Buzzer

Hi,

Im trying to make a couple of simple sounds with the piezo buzzer. I want create 3 different sounds, one that sounds quick (sound on 300 milliseconds, sound off 300 milliseconds.....)

The second sound(sound on 300 milliseconds, sound off 300 milliseconds and then a longer break of 1 second)

The 3rd sound is a slow one(1 second sound on, 1 second sound off.....)

This is my code:

const byte buzzerPin = 6;
unsigned long buzzerCurrentMillis, buzzerPreviousMillis;



void setup()
{
  buzzerPreviousMillis = 0;
}


void loop()
{
  buzzer(6,100,200,1000);
}

void buzzer( int buzzerPin,int frequency, int duration, int buzzerInterval)         
{
buzzerCurrentMillis = millis();
  if(buzzerCurrentMillis > buzzerPreviousMillis + buzzerInterval)
 {
   buzzerCurrentMillis = buzzerPreviousMillis;
   tone(buzzerPin, frequency, duration);
}
}

This is backwards:-

buzzerCurrentMillis = buzzerPreviousMillis;

(Which will cause the buzzer to sound continuously.)

Also, you shouldn't use millis() in that fashion. You should only do subtraction, to avoid problems at rollover.
Try this:-

const byte buzzerPin = 6;
unsigned long buzzerCurrentMillis, buzzerPreviousMillis;

void setup()
{
    buzzerPreviousMillis = 0;
}

void loop()
{
    buzzer(6, 100, 200, 1000);
}

void buzzer( int buzzerPin, int frequency, int duration, int buzzerInterval)
{
    buzzerCurrentMillis = millis();
    if (buzzerCurrentMillis - buzzerPreviousMillis >= buzzerInterval)
    {
        buzzerPreviousMillis =  buzzerCurrentMillis;
        tone(buzzerPin, frequency, duration);
    }
}

N.B. I didn't add the second and third tones - just fixed the problem you had with the first one.

And are you sure you want microsecond timing, or did you mean milliseconds? Yor code doesn't reflect what you said at all.

OldSteve:
This is backwards:-

buzzerCurrentMillis = buzzerPreviousMillis;

(Which will cause the buzzer to sound continuously.)

Also, you shouldn't use millis() in that fashion. You should only do subtraction, to avoid problems at rollover.
Try this:-

const byte buzzerPin = 6;

unsigned long buzzerCurrentMillis, buzzerPreviousMillis;

void setup()
{
    buzzerPreviousMillis = 0;
}

void loop()
{
    buzzer(6, 100, 200, 1000);
}

void buzzer( int buzzerPin, int frequency, int duration, int buzzerInterval)
{
    buzzerCurrentMillis = millis();
    if (buzzerCurrentMillis - buzzerPreviousMillis >= buzzerInterval)
    {
        buzzerPreviousMillis =  buzzerCurrentMillis;
        tone(buzzerPin, frequency, duration);
    }
}




N.B. I didn't add the second and third tones - just fixed the problem you had with the first one.

And are you sure you want microsecond timing, or did you mean milliseconds? Yor code doesn't reflect what you said at all.

Ty for your answer and help.

I meant milliseconds. I fixed the problem with the first and 3rd sound.

Any suggestions how I can fix the second the second sound( with the 300 millisec on, 300 millisec off and then a break of 1000 millisec) ?

arduino0o0:
Ty for your answer and help.
Any suggestions how I can fix the second the second sound( with the 300 millisec on, 300 millisec off and then a break of 1000 millisec) ?

No, I'm not that familiar with tone(). I just spotted two obvious points and mentioned them, but I now see that it only works properly with one tone.

I just tried to do what you're trying, and found unpredictable results unless delay is used after each sound rather than using millis()-based timing.
It's like a roulette wheel, and when 'buzzerInterval' expires, the next call to 'buzzer()' actually works. (Any one of the three calls.) Interesting.

It's late at night here and I don't have more time to check it out more fully, so someone else will have to explain it better and/or find a solution.
You might be stuck with 'delay()' to get it to work properly.

This works, but I know it's not what you want:-

const byte buzzerPin = 6;
unsigned long buzzerCurrentMillis, buzzerPreviousMillis;

void setup()
{
    buzzerPreviousMillis = 0;
}

void loop()
{
    buzzer(6, 100, 300, 300);
    buzzer(6, 200, 300, 1000);
    buzzer(6, 400, 1000, 1000);
}

void buzzer( int buzzerPin, int frequency, int duration, int buzzerInterval)
{
//    buzzerCurrentMillis = millis();
//    if (buzzerCurrentMillis - buzzerPreviousMillis >= buzzerInterval)
//    {
        tone(buzzerPin, frequency, duration);
//        buzzerPreviousMillis =  buzzerCurrentMillis;
    delay(buzzerInterval);
//    }
}

This might be closer to what you want. It plays a tune on pin 6 while flashing a LED on pin13 at 1Hz to show that it's non-blocking.
It's a whole different approach to what you started with though. And you'll have to play with the timings to get exactly what you want.
Currently, I have it re-starting the tune every 3 seconds, but you can handle that however you want.
I'm sure there are more elegant methods, but it's now pretty late and I'm very tired, so this was the best I could come up with.

/* TuneWithMillis.ino
*
*  Processor:- UNO
*  Notes:-
*  Plays a tune while flashing a LED at 1Hz.
*  (No delays.)
*/

// Pin allocations:-
const byte buzzerPin = 6;                       // Buzzer on pin 6.
const byte ledPin = 13;                         // LED on pin 13.

// Constants:-
const byte numNotes = 3;                        // Number of notes to play.
const int notes[] = {100, 200, 400};            // Array of notes.
const int durations[] = {300, 300, 1000};       // Array of note durations.
const int intervals[] = {300, 1000, 2000};      // Array of intervals between notes.
const int tuneInterval = 3000;                  // Period between starting to play the tune each time.


// Variables:-
unsigned long currentMillis;
unsigned long prevTuneMillis = 0;
unsigned long prevNoteMillis;
unsigned long prevLEDMillis;
byte noteIndex = 0;                             // Index to next note to play.
bool ledState = 0;                              // Current LED state.
bool playTune = true;                           // Flag for playing tune.

void setup()
{
    pinMode(ledPin, OUTPUT);
    prevNoteMillis = prevLEDMillis = millis();
}

void loop()
{
    currentMillis = millis();     // Get the current time in ms.

    // Check if it's time to start the tune:-
    if(currentMillis - prevTuneMillis >= tuneInterval)
        playTune = true;

    //Play the next note in the tune:-
    playNextNote();

    // Check if it's time to toggle the LED:-
    if(currentMillis - prevLEDMillis >= 500)
    {
        ledState ^= 1;
        digitalWrite(ledPin, ledState);
        prevLEDMillis = currentMillis;
    }
}

void playNextNote()
{
    if(currentMillis - prevNoteMillis >= intervals[noteIndex] && playTune == true)
    {
        tone(buzzerPin, notes[noteIndex], durations[noteIndex]);
        noteIndex++;
        if(noteIndex == numNotes)
        {
            noteIndex = 0;
            playTune = false;
            prevTuneMillis = currentMillis;
        }
        prevNoteMillis = currentMillis;
    }
}