How to get certain period Buzzer beep?

Hi everyone.
The code below can't get what I excepted a certain period Buzzer beep like 10 conseds need help please?
Thanks
Adam

const int buzzer = 12;
const long onDuration = 5;// OFF time for LED
const long offDuration = 2000;// ON time for LED
int BUZState = HIGH; // initial state of LED

long rememberTime = 0; // this is used by the code

int PIRread = 0;
int PIRpin = 13;
int  PIRreadBJ = 0;
int maxNum = 6;
int i = 0;


int ledPin =  12;      // the number of the LED pin
int ledState = LOW;             // ledState used to set the LED
unsigned long previousMillis = 0;        // will store last time LED was updated
long OnTime = 5;           // milliseconds of on-time
long OffTime = 2000;          // milliseconds of off-time

void setup() {

  Serial.begin(9600);
  Serial.println("xxx_setup!");

  Serial.print("File   : "), Serial.println(__FILE__);
  const char compile_date[] = __DATE__ " " __TIME__;
  Serial.print("Compile timestamp: ");
  Serial.println(compile_date);

  // put your setup code here, to run once:
  pinMode(buzzer, OUTPUT); // define buzzer as output
  pinMode(PIRpin, INPUT); // define buzzer as output
  digitalWrite(buzzer, BUZState); // set initial state
}

void loop() {
  // put your main code here, to run repeatedly:
  PIRread = digitalRead(PIRpin);

  Serial.print("PIR =");
  Serial.println(digitalRead(PIRpin));

  if (PIRread == HIGH)
  {
    PIRreadBJ = 1;
  }

  if (PIRreadBJ == 1)
  {
    for (int i = 0; i <= maxNum; i++)
    {
      BUZloopO(); //
    }
    if (i == maxNum)
    {
      digitalWrite(ledPin, LOW);
    }
  }
}

void BUZloopO()
{
  // check to see if it's time to change the state of the LED
  unsigned long currentMillis = millis();

  if ((BUZState == HIGH) && (currentMillis - previousMillis >= OnTime))
  {
    BUZState = LOW;  // Turn it off
    previousMillis = currentMillis;  // Remember the time
    digitalWrite(ledPin, BUZState);  // Update the actual LED
  }
  else if ((BUZState == LOW) && (currentMillis - previousMillis >= OffTime))
  {
    BUZState = HIGH;  // turn it on
    previousMillis = currentMillis;   // Remember the time
    digitalWrite(ledPin, BUZState);   // Update the actual LED
  }
  PIRreadBJ = 0;
}

You have 2 different variables called i in your code.
I guess you need to get rid of the global i.
You do not need to test for i==maxNum, because the for loop will end when maxNum is reached.

1 Like

Thank you build_1971.

I removed one 'i', same situation, the buzzer can't beep as expected, just 2 short, and a few long sound.

added the test for i==maxNum is trying to eliminate the 'noise' , cause of the buzzer beep some time without PIR touched.

Always look for a change in state rather than the actual state of the sensor.

1 Like

Your buzzer will be on for 5 milli seconds. That is maybe a bit short?
Do you have an active buzzer?
Can you post your updated code?
What is PIRpin?

1 Like

Why do you have non blocking code for your buzzer and then call it from a for loop 8 times?

1 Like

Thanks.
the PIR motion sensors hooked to 13.
the 5 milli beep is ok to be heard, because it works well when put the 'BUZloopO()'s content into loop instead of a sub.

const int buzzer = 12;
const long onDuration = 5;// OFF time for LED
const long offDuration = 2000;// ON time for LED
int BUZState = HIGH; // initial state of LED

long rememberTime = 0; // this is used by the code

int PIRread = 0;
int PIRpin = 13;
int  PIRreadBJ = 0;
int maxNum = 6;
int i = 0;


int ledPin =  12;      // the number of the LED pin
int ledState = LOW;             // ledState used to set the LED
unsigned long previousMillis = 0;        // will store last time LED was updated
long OnTime = 5;           // milliseconds of on-time
long OffTime = 2000;          // milliseconds of off-time

void setup() {

  Serial.begin(9600);
  Serial.println("xxx_setup!");

  Serial.print("File   : "), Serial.println(__FILE__);
  const char compile_date[] = __DATE__ " " __TIME__;
  Serial.print("Compile timestamp: ");
  Serial.println(compile_date);

  // put your setup code here, to run once:
  pinMode(buzzer, OUTPUT); // define buzzer as output
  pinMode(PIRpin, INPUT); // define buzzer as output
  digitalWrite(buzzer, BUZState); // set initial state
}

void loop() {
  // put your main code here, to run repeatedly:
  PIRread = digitalRead(PIRpin);

  Serial.print("PIR =");
  Serial.println(digitalRead(PIRpin));

  if (PIRread == HIGH)
  {
    PIRreadBJ = 1;
  }

  if (PIRreadBJ == 1)
  {
    for ( i = 0; i <= maxNum; i++)
    {
      BUZloopO(); //
    }
    if (i == maxNum)
    {
      digitalWrite(ledPin, LOW);
    }
  }
}

void BUZloopO()
{
  // check to see if it's time to change the state of the LED
  unsigned long currentMillis = millis();

  if ((BUZState == HIGH) && (currentMillis - previousMillis >= OnTime))
  {
    BUZState = LOW;  // Turn it off
    previousMillis = currentMillis;  // Remember the time
    digitalWrite(ledPin, BUZState);  // Update the actual LED
  }
  else if ((BUZState == LOW) && (currentMillis - previousMillis >= OffTime))
  {
    BUZState = HIGH;  // turn it on
    previousMillis = currentMillis;   // Remember the time
    digitalWrite(ledPin, BUZState);   // Update the actual LED
  }
  PIRreadBJ = 0;
}

Yes, as suggested the for loop is not correct. You run six calls to a function before any of the timing can occur.

Instead of the for loop, You can use an if conditional based on the number of cycles completed.

Thanks.
I was thinking, let it run 8 times to get total run time about 10 seconds? Didn't get it at all. How to get a period of 10 seconds, please?
actually I need to a led on for about 10 seconds.

First, only start the buzzer (set a flag) when PIRread transitions from LOW to HIGH. Second you need an additional timer to time the 10 seconds. You do not need the for loop at all.

Call BUZloopO() every time loop() executes. In BUZloopO() if the buzzer is enabled check to see if the 10 second timer has expired. If not then perform the buzzer on/off timing. When the 10 second timer expires turn off the buzzer and reset the buzzer flag.

@shanren,

I have followed a part of your questions. From that part of your questions that I have read I got the impression that you are to a certain extent unwilling to learn the basics. Of course you are learning with each new question. Very clear. But to me you do it in a somehow unsystematic way.

There is always some detail question you want to have answered - please.

Of course you are free to ask in almost any way you want. Though I want to give a friendly tap "how about learning it systematically?" Which of course you can answer to with "no".
Just a friendly tap to try it.

Not too systematic but showing an important concept of non-blocking timing
Below is a code that attempts to make visible how non-blocking timing works

unsigned long MyTestTimer = 0;                   // Timer-variables MUST be of type unsigned long
unsigned long myBlink_XO_Timer;
unsigned long myBlink_AZ_Timer;

char X_or_O = 'X';
char A_or_Z = 'A';

long myCounter = 0;

void setup() {
  Serial.begin(115200);
  Serial.println("Setup-Start");
}

void loop() {
  blink_AZ(); // change character every  500 milliseconds between 'A' and 'Z'
  blink_XO(); // change character every  2000 milliseconds between 'X' and 'O'
  countUpPrintEach100ms(); // once every 100 milliseconds count up and print
}


// easy to use helper-function for non-blocking timing
boolean TimePeriodIsOver (unsigned long &startOfPeriod, unsigned long TimePeriod) {
  unsigned long currentMillis  = millis();
  if ( currentMillis - startOfPeriod >= TimePeriod ) {
    // more time than TimePeriod has elapsed since last time if-condition was true
    startOfPeriod = currentMillis; // a new period starts right here so set new starttime
    return true;
  }
  else return false;            // actual TimePeriod is NOT yet over
}

void blink_AZ() {
  if ( TimePeriodIsOver(myBlink_AZ_Timer, 500) ) { // check if 500 milliseconds have passed by
    // if 500 milliseconds HAVE passed by
    if (A_or_Z == 'A') { // check if character is an 'A'
      A_or_Z = 'Z';      // change to 'Z'
    }
    else {
      A_or_Z = 'A';      // change to 'A'
    }
  }
}

void blink_XO() {
  if ( TimePeriodIsOver(myBlink_XO_Timer, 2000) ) { // check if 2000 milliseconds have passed by
    // if 2000 milliseconds HAVE passed by
    if (X_or_O == 'X') { // check if character is an 'X'
      X_or_O = 'O';      // change to 'O'
    }
    else {
      X_or_O = 'X';      // change to 'X'
    }
  }
}

void clearSerialMonitor() {
  for (int i = 0; i < 30; i++) { // print 50 empty lines to clear screen
    Serial.println();
  }
}


void countUpPrintEach100ms() {
  if ( TimePeriodIsOver(MyTestTimer, 100) ) { // check if 50 milliseconds have passed by
    // if 50 milliseconds HAVE passed by
    myCounter++;
    clearSerialMonitor();
    Serial.println("left  Z/A changes every 0,5 seconds");
    Serial.println("right X/O changes every 2,0 seconds");
    Serial.print(A_or_Z);
    Serial.print(":");
    Serial.print(myCounter);
    Serial.println(X_or_O);
  }
}

best regards Stefan

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