Pages: [1]   Go Down
Author Topic: Play melody without delay()  (Read 2367 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 40
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi guys, I have a little script that controls a servo, blinks an LED and plays a tone. The problem is that because the beep1 function is not asynchronous and uses delay(), it needs to run the melody first then the rest of the script continues. Is there a way to avoid this? As in play the melody at the same time as the rest of the action happening?

Here's the code...


Code:

#include <Servo.h>

Servo myservo; 
int pos = 0;   
const int outputPinA = 8;
const int speaker = 12;
long previousMillis = 0;



void setup()
{
  pinMode(outputPinA, OUTPUT);
  Serial.begin(9600);
  myservo.attach(9);

}


void loop()
{
  if (Serial.available() > 0) {
    int incomingByte = Serial.read();
    if (incomingByte == 0x01) {
      beep1();
      for(pos = 70; pos < 180; pos += 1) 
        myservo.write(pos);     
      digitalWrite(outputPinA, HIGH);
      delay(3);     
    }
    for(pos = 180; pos>=70; pos-=1)     
    {                               
      myservo.write(pos);             
      delay(3);                       
    }
    digitalWrite(outputPinA, LOW);
  }

}

void beep1(){ 
  tone(speaker,1500,100);
  delay(20); 
  tone(speaker,1600,100);
  delay(20);
  tone(speaker,1700,100);
  delay(20);
  tone(speaker,1800,100);
  delay(20);
  tone(speaker,1900,100);
  delay(20); 
  tone(speaker,2000,100);
  delay(20); 
  tone(speaker,2100,100);
  delay(20);
  tone(speaker,2000,100);
  delay(20); 
  tone(speaker,1900,100);
  delay(20); 
  tone(speaker,1800,100);
  delay(20); 
  tone(speaker,1700,100);
  delay(20);
  tone(speaker,1600,100);
  delay(20);
  tone(speaker,1500,100);
  noTone(speaker); 




Logged

Offline Offline
Edison Member
*
Karma: 19
Posts: 1041
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

1. take BlinkWithoutDelay example
2. Add a "counter" so you know which note you're currently playing and another variable to hold how long you're supposed to be playing it for.
3. Change digitalWrite() to tone()
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 40
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Would you put the tones in an associative array? the time is constant
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 40
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

it actually appears that this won't work within a running loop because it still needs to complete whatever is called
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 40
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Updated code with millis

Code:
#include <Servo.h>

Servo myservo; 
int pos = 0;   
const int outputPinA = 8;
const int speaker = 12;
long previousMillis = 0;       
long interval = 20; 
int melody[] = {
 1900, 2000, 2100, 2000, 1900 };
const int max = 5;

void setup()
{
  pinMode(outputPinA, OUTPUT);
  Serial.begin(9600);
  myservo.attach(9);

}


void loop()
{
  if (Serial.available() > 0) {
    int incomingByte = Serial.read();
    if (incomingByte == 0x01) {
      for(pos = 70; pos < 180; pos += 1){ 
        myservo.write(pos);     
        digitalWrite(outputPinA, HIGH);
        delay(3);     
      }
      beep1();
      for(pos = 180; pos>=70; pos-=1)     
      {                               
        myservo.write(pos);             
        delay(3);                       
      }
      digitalWrite(outputPinA, LOW);
    }

  }
}

void beep1(){ 
  int i = 0;
  while (i<max) {
    unsigned long currentMillis = millis();
    if(currentMillis - previousMillis > interval) {
      // save the last time you blinked the LED
      previousMillis = currentMillis;   
      // set the LED with the ledState of the variable:
      tone(speaker,melody[i],100);
      i++;
    }
  }
Logged

Offline Offline
Edison Member
*
Karma: 19
Posts: 1041
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

i needs to be declared static so it won't get reset after every call of the function.

You need to get rid of the delay() in the servo movement
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 5
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

So what is the advantage of declaring speaker and writing speaker in the code rather than just writing

Code:
tone(12,1500,100);

?
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 601
Posts: 48543
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
So what is the advantage of declaring speaker and writing speaker in the code rather than just writing
Suppose you decide to add an Ethernet shield, and can no longer use pin 12. How many changes do you need to make to your code, if you hardcode 12 everywhere? Can you be confident that you got them all?

How many lines need to change if you use a name, instead?
Logged

Offline Offline
Edison Member
*
Karma: 19
Posts: 1041
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Shouldn't interval be 120? Because of how tone() works, the tone will automatically stop after duration time (100ms in your case), so you want to trigger the next tone 120ms after the previous tone started.
Logged

Pages: [1]   Go Up
Jump to: