Issue w/ Timing Events

Hi. I want to preface this by letting you know that I am a novice at this, so please be patient with me.

I have been working on a program to make two piezo elements play music together. I have used the millis() function to make the two rapidly loop to give the illusion that they are playing simultaneously. I have made that part work, but I am unable to figure out how to make a short pause in between the music notes so they can be heard. My comments in the code show where the pause needs to be.

#include "pitches.h"
#define pz1 8
#define pz2 9

unsigned long previousMillis = 0;  //some global variables available anywhere in the program
unsigned long currentMillis;
unsigned long startMillis;

int melody[] = {

  NOTE_C4, NOTE_G3, NOTE_G3, NOTE_A3, NOTE_G3, 0, NOTE_B3, NOTE_C4
};

// note durations: 4 = quarter note, 8 = eighth note, etc.:
int mnoteDurations[] = {

  4, 8, 8, 4, 4, 4, 4, 4
};



int bass[] = {

  NOTE_C4, NOTE_G3, NOTE_G3, NOTE_A3, NOTE_G3, 0, NOTE_B3, NOTE_C4
};

// note durations: 4 = quarter note, 8 = eighth note, etc.:
int bnoteDurations[] = {

  4, 8, 8, 4, 4, 4, 4, 4
};

void taskMelody () {
  static unsigned long chrono = millis();
  
 if (currentMillis - chrono < 5000) return;
 chrono = millis();
 // iterate over the notes of the melody:
for (int mthisNote = 0; mthisNote < 8; mthisNote++) {

  int mnoteDuration = 1000 / mnoteDurations[mthisNote];
  int mpauseBetweenNotes = mnoteDuration * 1.30;
    
   tone(pz1, melody[mthisNote], mnoteDuration);
    
    //I need to make a pause here equal to mpauseBetweenNotes

    noTone(pz1);
  }

}

void taskBass (/* put arguments here */) {
   static unsigned long chrono = millis();
 if (millis() - chrono < 5000) return;
 chrono = millis();
 for (int bthisNote = 0; bthisNote < 8; bthisNote++) {
    
    int bnoteDuration = 1000 / bnoteDurations[bthisNote];


    tone(pz2, bass[bthisNote], bnoteDuration);

    int bpauseBetweenNotes = bnoteDuration * 1.30;
    
    //I need to make a pause here equal to bpauseBetweenNotes
  

    noTone(pz2);
 }
}

void setup(){
startMillis = millis();  //initial start time


}

void loop () {
  currentMillis = millis();  //get the current "time" (actually the number of milliseconds since the program started)
  taskMelody (/* arguments for task 1 */);
  taskBass (/* arguments for task 2 */);

}

Think of the pause as just another note. You can't stop and block to make the pause. Just do it the same way you handle the note. Just don't make any sound this time.

First of all, thank you so much for your quick reply.
Unfortunately, I cannot do what you are suggesting. I need to make a pause between each note so it can be heard. If I were to make a pause in the note, it wouldn't make a difference because the notes cannot be heard in the first place.
Also see that in my comment in the code I say that the pause needs to be equal to the variables **mpauseBetweenNotes and bpauseBetweenNotes**. This is because the pause needs to be proportional to the durations of the notes.

Are you wanting a space between the notes with no sound? If you can time a note then you time that no sound the same way.

Looking at your code I don't think it works the way you think it does. If you're going to use a for loop for the 8 tones, then you might as well use delay. You can't make them play at the same time. You're stuck there in one function going around a for loop. You need to let that function start one note, and then each time it is called see if it is time to change to another note. You already have the millis code there timing off 5 seconds. Replace the 5 seconds with the note duration, get rid of the for loop, and add a variable to keep up with what note you're on.

You do know though that you can't use tone to play two tones at once right? From the reference on tone:

Only one tone can be generated at a time. If a tone is already playing on a different pin, the call to tone() will have no effect. If the tone is playing on the same pin, the call will set its frequency.

Yes, I do want a brief space between the notes with no sound. The 8 notes are placeholders to see if it works. I cannot use the delay function because it stops the other tasks from running during that time. To clarify, my goal is not to play notes at the exact same time, but rather to make it seem that way. I know how to make music with one line already, but I really want to be able to make a melody and a base. Any ideas to make that happen would be very appreciated, even if it means I have to rework a lot of my code.

You also cannot use that for loop for the same reason. Your function has to work like a checklist. Is a tone playing? If so then stop. If no tone is playing then is it time to start one? If so then do it.

You mean you want it to warble back and forth between the two? That's going to take a lot more thought about coding. And it's going to sound like crap.

Not really something you can do with the Tone library. Maybe with a Mega you could make a copy of Tone that used the other 16 bit timer, then you could have two at once.

Thank you so much for telling me this! I understand know that my ambitions were disproportionate to my skill level.

Hello @lakebedtempleenjoyer -

I understand you want the two buzzers to play your array of tones at the timing array. Your code compiles, but all I hear from your original code is a beep every five seconds. Simulated here:

I tried the Arduino example on the same setup and it worked in your setup. Simulated here:

I read that you want your rests to be proportional to your notes. I thought they do that... so I do not understand this part.

Further; I think your desire to play two notes (somewhat) simultaneously might need deep knowledge of low-level timers used on the mpu... BUT... why not try without them? The worst that can happen is; it does not work, but you will have learned more about the Arduino.

If you do a search on Arduino Melody Library, you might find others who have written a library that is just what you need to "simultaneously" play notes.

Of interest to you...

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