Why does this code produce this result?

HI Folks,

I’m a newbie looking for guidance with the following code. It produces an intermittent tone (beep, beep, beep) that goes on for about 6 seconds (about 13 beeps). I’ve played with the values for playtone and duration but still receive the beeping result. The result I’m looking for is a single half-second tone (beep). Can someone help to guide me here? Thanks in advance to all who take their time! I appreciate it :slight_smile:

void playTone(long duration, int freq) {
duration *= 1000;
int period = (1.0 / freq) * 1000000;
long elapsed_time = 0;
while (elapsed_time < duration) {
digitalWrite(pinSpeaker,HIGH);
delayMicroseconds(period / 2);
digitalWrite(pinSpeaker, LOW);
delayMicroseconds(period / 2);
elapsed_time += (period);
}
}

Post all the code.

I've played with the values for playtone and duration

playtone is a function - you can't play with its value.

Can you post your code please, this time in code tags?

Here… sorry.

int ledPin = 13;                // choose the pin for the LED
int inputPin = 2;               // choose the input pin (for PIR sensor)
int pirState = LOW;             // we start, assuming no motion detected
int val = 0;                    // variable for reading the pin status
int pinSpeaker = 10;           //Set up a speaker on a PWM pin (digital 9, 10, or 11)

void setup() {
 pinMode(ledPin, OUTPUT);      // declare LED as output
 pinMode(inputPin, INPUT);     // declare sensor as input
 pinMode(pinSpeaker, OUTPUT);  // declare speaker as output
 Serial.begin(9600);
}

void loop(){
 val = digitalRead(inputPin);  // read input value
 if (val == HIGH) {            // check if the input is HIGH
   digitalWrite(ledPin, HIGH);  // turn LED ON
   playTone(300, 160);
   delay(150);

   
   if (pirState == LOW) {
     // we have just turned on
     Serial.println("Motion detected!");
     // We only want to print on the output change, not state
     pirState = HIGH;
   }
 } else {
     digitalWrite(ledPin, LOW); // turn LED OFF
     playTone(0, 0);
     delay(300);    
     if (pirState == HIGH){
     // we have just turned off
     Serial.println("Motion ended!");
     // We only want to print on the output change, not state
     // Inside Of The Serial Port
     pirState = LOW;
   }
 }
}

// Tell Arduino To Play Piezo Buzzer Tone
// duration in mSecs, frequency in hertz

void playTone(long duration, int freq) {
   duration *= 1000;
   int period = (1.0 / freq) * 1000000;
   long elapsed_time = 0;
   while (elapsed_time < duration) {
       digitalWrite(pinSpeaker,HIGH);
       delayMicroseconds(period / 2);
       digitalWrite(pinSpeaker, LOW);
       delayMicroseconds(period / 2);
       elapsed_time += (period);
   }
}

It produces an intermittent tone (beep, beep, beep) that goes on for about 6 seconds (about 13 beeps).

The Arduino is doing exactly as instructed. As long as the PIR digital input is high, it will beep.

You put in some logic to have it print only once.

Tourless:
HI Folks,

I’m a newbie looking for guidance with the following code. It produces an intermittent tone (beep, beep, beep) that goes on for about 6 seconds (about 13 beeps). I’ve played with the values for playtone and duration but still receive the beeping result. The result I’m looking for is a single half-second tone (beep). Can someone help to guide me here? Thanks in advance to all who take their time! I appreciate it :slight_smile:

void playTone(long duration, int freq) {
duration *= 1000;
int period = (1.0 / freq) * 1000000;
long elapsed_time = 0;
while (elapsed_time < duration) {
digitalWrite(pinSpeaker,HIGH);
delayMicroseconds(period / 2);
digitalWrite(pinSpeaker, LOW);
delayMicroseconds(period / 2);
elapsed_time += (period);
}
}

A very rough solution but it will give you a single beep with a length in milliseconds of first argument in playTone. Use 500 for half a second beep.
I notice period and freq are both int, and the math include 1/freq. I’m a noob, but to me it looks like a possible error.

void playTone(long duration, int freq) {
    duration *= 1000;
    //int period = (1.0 / freq) * 1000000;
    //long elapsed_time = 0;

    digitalWrite(pinSpeaker,HIGH);
    delayMicroseconds(duration);
    digitalWrite(pinSpeaker, LOW);

    //while (elapsed_time < duration) {
      //  digitalWrite(pinSpeaker,HIGH);
      //  delayMicroseconds(period / 2);
      //  digitalWrite(pinSpeaker, LOW);
      //  delayMicroseconds(period / 2);
      //  elapsed_time += (period);
    //}
}

Gabriel_swe:
Note that it is 1.0/freq. That will make the whole expression calculated in floating point, and then converted to int during the assignment. That is fine, though you are right to question it.

Post all the code.