Optimizing this serial communication code

Hi everyone,

I’m currently working on a code for the arduino pro mini that allows it to communicate and receive input from another device. Depending on the input of the other device, the arduino will beep. Sounds simple right? I thought so too, but the code belong is giving me troubles in its slow response speed and unreliability. Would someone mind helping?

int speakerPin = 6;
//BEGIN Exact copy of the melody.pde sample code
int length = 15; // the number of notes
char notes[] = "ccggaagffeeddc "; // a space represents a rest
int beats[] = { 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 2, 4 };
int tempo = 300;

void playTone(int tone, int duration) {
  for (long i = 0; i < duration * 1000L; i += tone * 2) {
    digitalWrite(speakerPin, HIGH);
    delayMicroseconds(tone);
    digitalWrite(speakerPin, LOW);
    delayMicroseconds(tone);
  }
}

void playNote(char note, int duration) {
  char names[] = { 'c', 'd', 'e', 'f', 'g', 'a', 'b', 'C' };
  int tones[] = { 1915, 1700, 1519, 1432, 1275, 1136, 1014, 956 };
  
  // play the tone corresponding to the note name
  for (int i = 0; i < 8; i++) {
    if (names[i] == note) {
      playTone(tones[i], duration);
    }
  }
}
//END copying
void setup() {
  Serial.begin(9600);
  pinMode(speakerPin, OUTPUT);

}

int in[50]; //creates an array to hold each byte of serial.read individually
int num=0; 
void loop() {
  Serial.println("<COMMAND>"); //command sent to the other device. Once received, the device takes about 5 seconds to finish its task and returns an output

   delay(5500);//waits for the other device to finish its processing
//in the 5 second period, the other device sends in data to the arduino multiple times. a few bytes are sent instantly, the rest are sent later

    while (Serial.available()>0) { //reads all incoming bytes
   in[num]= Serial.read(); //saves each byte individually
   num+=1;
  }
  //find the int value of a couple particular read values
   int s=int(in[36]); 
   int p=int(in[37]);
   int o=int(in[38]);


    if(int('N')==s && int('O')==p){   //if the characters N and O match the variables respectively
 
      //Start beeping
  for (int i = 0; i < length; i++) {
    if (notes[i] == ' ') {
      delay(beats[i] * tempo); // rest
    } else {
      playNote(notes[i], beats[i] * tempo);
    }
    
    // pause between notes
    delay(tempo / 2); 
  }
    }
    num=0;
      Serial.flush(); //clears all data so the loop can start anew
 
}

This code seemed to work fine initially, but later on seemed to beep even if s and p aren’t even N and O. Also there is a significant delay from one beep to another. If the output of the other device maintains the chars N and O for the variable s and p, I want the beep to be continuous. However because the processing for the other device takes time, this is difficult to achieve. Can you guys give me some pointers to make this code as efficient as possible?

I also know that the entire melody code can be optimized as I am not looking to play a melody but just a droning buzzing sound. I’m just not sure how…

Thank you for any help!
lzhang

I did some editing of the code, how does it look now?

int speakerPin = 6;
//BEGIN Exact copy of the melody.pde sample code
int length = 15; // the number of notes
char notes[] = "ccggaagffeeddc "; // a space represents a rest
int beats[] = { 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 2, 4 };
int tempo = 300;

void playTone(int tone, int duration) {
  for (long i = 0; i < duration * 1000L; i += tone * 2) {
    digitalWrite(speakerPin, HIGH);
    delayMicroseconds(tone);
    digitalWrite(speakerPin, LOW);
    delayMicroseconds(tone);
  }
}

void playNote(char note, int duration) {
  char names[] = { 'c', 'd', 'e', 'f', 'g', 'a', 'b', 'C' };
  int tones[] = { 1915, 1700, 1519, 1432, 1275, 1136, 1014, 956 };
  
  // play the tone corresponding to the note name
  for (int i = 0; i < 8; i++) {
    if (names[i] == note) {
      playTone(tones[i], duration);
    }
  }
}
//END copying
void setup() {
  Serial.begin(9600);
  pinMode(speakerPin, OUTPUT);

}

int in[50]; //creates an array to hold each byte of serial.read individually
int num=0;
void loop() {
  Serial.println("<COMMAND>"); //command sent to the other device. Once received, the device takes about 5 seconds to finish its task and returns an output

 for(int i=0; i<17; ++i) {
   while (!Serial.available()){
   playNote(notes[i], beats[i] * tempo);
    delay(tempo / 2);
   }
 Serial.read();} 
//in the 5 second period, the other device sends in data to the arduino multiple times. a few bytes are sent instantly, the rest are sent later

    while (Serial.available()>0) { //reads all incoming bytes
   in[num]= Serial.read(); //saves each byte individually
   num+=1;
  }
  //find the int value of a couple particular read values
   int s=int(in[10]);
   int p=int(in[11]);
   int o=int(in[12]);


    if(int('N')==s && int('O')==p){   //if the characters N and O match the variables respectively

      //Start beeping
  for (int i = 0; i < length; i++) {
   
      playNote(notes[i], beats[i] * tempo);
    
    
    // pause between notes
    delay(tempo / 2);
  }
    }
    num=0;
      Serial.flush(); //clears all data so the loop can start anew

}
for(int i=0; i<30; ++i) {
   while(Serial.available()==0){}
   if(i>23){
      in[num]= Serial.read();
      Serial.print(char(in[num]));
   num+=1;
   }else{
// ta=Serial.read();
 //Serial.print(char(ta));
 //delay(100);
   }
 } 
 Serial.print("done");
 delay(100);