Arduino_Buzzer_Millis question

Hi,
I'd like to have the buzzer on 20, and off 1000.
The code just can't get there, buzzer keep on.
why?
Thanks
Adam

// constants won't change. Used here to set a pin number:
const int buzzerPin =  A2;// the number of the LED pin WAS LEDPin that is 13 for UNO

// Variables will change:
int buzzerState = LOW;             // ledState used to set the LED

// Generally, you should use "unsigned long" for variables that hold time
// The value will quickly become too large for an int to store
unsigned long previousMillis_1 = 0;        // will store last time LED was updated
unsigned long previousMillis_2 = 0;        // will store last time LED was updated

// constants won't change:
const long interval_1 = 20;           // interval at which to blink (milliseconds)
const long interval_2 = 1000;

void setup() {
  // set the digital pin as output:
  pinMode(buzzerPin, OUTPUT);
  digitalWrite(buzzerPin, LOW);
}

void loop() {
  // here is where you'd put code that needs to be running all the time.

  // check to see if it's time to blink the LED; that is, if the difference
  // between the current time and last time you blinked the LED is bigger than
  // the interval at which you want to blink the LED.
  unsigned long currentMillis = millis();

   if (currentMillis - previousMillis_1 >= interval_1) {
    // save the last time you blinked the LED
   previousMillis_1 = currentMillis;
   
   digitalWrite(buzzerPin, LOW);
  }


  if (currentMillis - previousMillis_2 >= interval_2) {
    // save the last time you blinked the LED
  /////  previousMillis_2 = currentMillis;

    digitalWrite(buzzerPin, HIGH);
  }
}

Where did you get the code you working with? Link, please thank you.

   /////  previousMillis_2 = currentMillis;

Why did you comment out this line?

a7

1 Like

Great!
It was a mistake, works fine now, thank you.
Sorry I just see this:

The code I modified from BlinkWithoutDelay.

doesn't "prevoiusMillis_1" need to be set to 20 msec after previousMillis_2 expires?

what about

#undef MyHW
#ifdef MyHW
const int buzzerPin =  10;
#else
const int buzzerPin =  A2;// the number of the LED pin WAS LEDPin that is 13 for UNO
#endif

// Variables will change:
int buzzerState = LOW;             // ledState used to set the LED
// Generally, you should use "unsigned long" for variables that hold time
// The value will quickly become too large for an int to store
unsigned long previousMillis_1 = 0;        // will store last time LED was updated
// constants won't change:
const long interval_1 = 20;           // interval at which to blink (milliseconds)
const long interval_2 = 1000;

void setup() {
    // set the digital pin as output:
    pinMode(buzzerPin, OUTPUT);
    digitalWrite(buzzerPin, LOW);
}
void loop() {
    unsigned long currentMillis = millis();
    if (currentMillis - previousMillis_1 >= interval_2) {
        // save the last time you blinked the LED
        previousMillis_1 = currentMillis;

        digitalWrite(buzzerPin, LOW);
        delay (interval_1);
        digitalWrite(buzzerPin, HIGH);
    }
}
1 Like

Thanks.

Agree @gcjr there is something not quite right about the code with only the small change I suggested.

It does blink (LED) or beep, that is, but it is oddly flawed and seems to need the on and off times to be related, I got a headache trying to figure out or fix it. Life too short. Mine anyway.

And the code in #4 above works perfectly, but uses delay() to time the ON interval, which kinda defeats half the purpose. You might as well go back to timing both the ON and OFF periods using delay.

So take your finger for a stroll through this and see it it lights up either half or even both halves of your brain - this tracks the state of the controlled device, I used a variable that was in your first post.

const int buzzerPin =  A2;

int buzzerState = LOW;                     // ledState used to set the LED

unsigned long previousMillis_1 = 0;        // will store last time LED was updated
unsigned long previousMillis_2 = 0;        // will store last time LED was updated

const long interval_1 = 337;               // ON time
const long interval_2 = 1000 - 337;        // OFF time

void setup() {
  pinMode(buzzerPin, OUTPUT);
  digitalWrite(buzzerPin, LOW);
}

void loop() {

// here is where you'd put code that needs to be running all the time.

//

// and this checks if it is time to change the buzzer
  unsigned long currentMillis = millis();

  if (buzzerState == HIGH) {

    if (currentMillis - previousMillis_1 >= interval_1) {
      digitalWrite(buzzerPin, LOW);
      previousMillis_2 = currentMillis;
      buzzerState = LOW;
    }

  }
  else { // buzzerState == LOW

    if (currentMillis - previousMillis_2 >= interval_2) {
      digitalWrite(buzzerPin, HIGH);
      previousMillis_1 = currentMillis;
      buzzerState = HIGH;
    }

  }
}

Or see it for yourself here:

HTH

a7

1 Like

don't you want the code to periodically turn on the relay, every second. and you want it turned off some time after it is turned on.

so interval1 should be 1000 if you want it to do something every second (why 1000 -337)?

when interval_2 expires, Millis2 should be reset.

and prevMillis1 should also be be reset to currentMillis so it expires after interval_1.

but once Millis1/interval-1 expires, you don't want it executing again until after interval1 expires.

the timers are not independent

1 Like

Would this work for you?

unsigned long timer;
const int interval = 1000, onTime = 20;
const byte buzzerPin = A2;         

void setup()
{
  pinMode(buzzerPin, OUTPUT);
}

void loop()
{
  digitalWrite(buzzerPin, millis() - timer < onTime);
  if(millis() - timer >= interval)
  {
      timer += interval;   
  }
}
2 Likes

kinda awkward

this is pretty minimal, yet clear

const int buzzerPin =  13;

enum { Off = HIGH, On = LOW };

#define Period   1000
#define OnTime   20

unsigned long msecTime = Period;

void setup  () {
    Serial.begin (9600);

    digitalWrite  (buzzerPin, Off);
    pinMode       (buzzerPin, OUTPUT);
}

void loop  () {
    unsigned long msec = millis  ();

    if (msec > msecTime)  {
        byte state = digitalRead (buzzerPin);
        digitalWrite (buzzerPin, ! state);

        if (Off == state)
            msecTime = msec + OnTime;
        else
            msecTime = msec + Period;
    }
}
1 Like

The constants in the code

const long interval_1 = 337;               // ON time
const long interval_2 = 1000 - 337;        // OFF time

determine the time the LED or buzzer is ON (interval_1) and OFF (interval_2).

To have something blink once per second, the ON time plus the OFF time should be 1000 ms.

The simulation linked in #6 keeps time with the simulation clock. Better names for the variables previousMillis_1 & 2 might make the logic clearer. interval_1 & 2 also.

Maybe like wentOnAt / wentOffAt and stayOnFor / stayOffFor.

a7

1 Like

I like @JCA34F #8, mostly because I didn’t think of it. :expressionless:

I don’t remember forgetting about that approach, but looking at it now it reminds me of figuring out some how-tos using a timer/clock resources.

So where’s hardcore? :wink:

For each schemes presented here there will be a question of how to leverage it for more complicated timing requirement.

a7

1 Like

@shanren's original code, with a key line commented back in, seemed to solve the problem right away.

But it was only because the long interval was an integral multiple of the short interval.

Essentially there are two independent processes being managed, each by the idiomatic use of the millis() mechanism.

One process turns on the LED every long interval.

The other turns the LED off every short interval.

Turning the LED off multiple times is not a problem and only wastes a tiny bit of time.

If it were necessary to do one thing once on the leading edge, and another once on the trailing edge, this code would fail.

The code also fails when the long interval is not an integral multiple of the short interval.

In this case, the turning off conditions wander in and out of phase with the turning on conditions and we get odd and cyclic changing stabs of light.

The solution, adequate in the case of multiple turnings-off being of no never mind, is to scoot forward the turn off time by resetting that mechanism's timer when the turn-on occurs.

That's one line added to the other millis() timer.

// https://forum.arduino.cc/t/arduino-buzzer-millis-question/903934/1

// original code had a ///// important line, but that didna fix it
// constants won't change. Used here to set a pin number:
const int buzzerPin =  A2;// the number of the LED pin WAS LEDPin that is 13 for UNO

// Variables will change:
int buzzerState = LOW;             // ledState used to set the LED

// Generally, you should use "unsigned long" for variables that hold time
// The value will quickly become too large for an int to store
unsigned long previousMillis_1 = 0;        // will store last time LED was updated
unsigned long previousMillis_2 = 0;        // will store last time LED was updated

// constants won't change:
const long interval_1 = 221;           // interval at which to blink (milliseconds)
const long interval_2 = 900;

void setup() {
  // set the digital pin as output:
  pinMode(buzzerPin, OUTPUT);
  digitalWrite(buzzerPin, LOW);
}

void loop() {
  // here is where you'd put code that needs to be running all the time.

  // check to see if it's time to blink the LED; that is, if the difference
  // between the current time and last time you blinked the LED is bigger than
  // the interval at which you want to blink the LED.
  unsigned long currentMillis = millis();

   if (currentMillis - previousMillis_1 >= interval_1) {
    // save the last time you blinked the LED
   previousMillis_1 = currentMillis;
   
   digitalWrite(buzzerPin, LOW);
  }


  if (currentMillis - previousMillis_2 >= interval_2) {
    // save the last time you blinked the LED
    previousMillis_2 = currentMillis;

//    comment out the following line to see the bad behaviour

    previousMillis_1 = currentMillis;  // reschedule the turn off time!
 
    digitalWrite(buzzerPin, HIGH);
  }
}

and here to play with

I wasn't actually losing sleep over this, but it did seem that the OP had given it a good try. I was surprised that it worked with one line commented out. My habit is to play a bit with the constants, it was then I saw some unwanted activity and started to wonder about what TF was going on.

HTH

a7

1 Like

Thank you, and how to use Wokwi? I pasta my code into that window and keep saying 'build failed', why?
and I didn't find the 'devtools console' for it.

In wokwi the builds fail for the same and various reasons something might not compile verify in the “real” IDE.

So far the error reporting is a bit sketchy.If you really get stuck, you can copy paste the code into the Arduino IDE and verify it there to get more and maybe better error warning reports.

But here you problem seems to be that they don’t have the library you wanna use. See

for the way forward. If it has been brought in, you are good. If it hasn’t, you can ask of them that they do.

Worst case, and I did it before I knew the above, is to make new tabs in the wokwi and copy paste the library code into them… which in some cases is a breeze and in others would be prohibitively stupid amount of work.

So another approach which your coding style might shoukd support anyway is to use the sim for logic and flow and some hardware, then carry success back to the real world to combine with parts where simulation was too lodge a task.

HTH

a7

1 Like

Thank you!

Thank you all.
How to use millis to replace the delays for the code below?

servo_motor.write(90);
delay(2000);
distance = readPing();
delay(100);
distance = readPing();
delay(100);
distance = readPing();
delay(100);
distance = readPing();
delay(100);

See that code someone wrote that sets the buxxerPin LOW every interval_1?

Why couldn’t it just as well time out your function calls? Add a count so it only tests the time and pings a certain number of times.

But to really answer we’d need to see how those calls are to be shared in time with the other tasks you wish to simultaneously accomplish.

If there are none, there is no shame in just using delay.

a7

1 Like

Thank you.
It is a robot car control sketch, which used lot of 'delay'。I am not sure if it's better to open a new post, please let me know.

/* https://create.arduino.cc/editor/mertarduinotech/3175b31d-8f66-44bc-a21f-1c8462768f11/preview
 *  
 *  
 */

#include <Servo.h>          //Servo motor library. This is standard library
#include <NewPing.h>        //Ultrasonic sensor function library. You must install this library

//our L298N control pins
const int LeftMotorForward = 5;
const int LeftMotorBackward = 4;
const int RightMotorForward = 3;
const int RightMotorBackward = 2;

//sensor pins
#define trig_pin A1 //analog input 1
#define echo_pin A2 //analog input 2

#define maximum_distance 200
boolean goesForward = false;
int distance = 100;

NewPing sonar(trig_pin, echo_pin, maximum_distance); //sensor function
Servo servo_motor; //our servo name


void setup(){

  pinMode(RightMotorForward, OUTPUT);
  pinMode(LeftMotorForward, OUTPUT);
  pinMode(LeftMotorBackward, OUTPUT);
  pinMode(RightMotorBackward, OUTPUT);
  
  servo_motor.attach(11); //our servo pin

  servo_motor.write(90);
  delay(2000);
  distance = readPing();
  delay(100);
  distance = readPing();
  delay(100);
  distance = readPing();
  delay(100);
  distance = readPing();
  delay(100);
}

void loop(){

  int distanceRight = 0;
  int distanceLeft = 0;
  delay(50);

  if (distance <= 20){
    moveStop();
    delay(300);
    moveBackward();
    delay(400);
    moveStop();
    delay(300);
    distanceRight = lookRight();
    delay(300);
    distanceLeft = lookLeft();
    delay(300);

    if (distance >= distanceLeft){
      turnRight();
      moveStop();
    }
    else{
      turnLeft();
      moveStop();
    }
  }
  else{
    moveForward(); 
  }
    distance = readPing();
}

int lookRight(){  
  servo_motor.write(10);
  delay(500);
  int distance = readPing();
  delay(100);
  servo_motor.write(90);
  return distance;
}

int lookLeft(){
  servo_motor.write(170);
  delay(500);
  int distance = readPing();
  delay(100);
  servo_motor.write(90);
  return distance;
  delay(100);
}

int readPing(){
  delay(70);
  int cm = sonar.ping_cm();
  if (cm==0){
    cm=250;
  }
  return cm;
}

void moveStop(){
  
  digitalWrite(RightMotorForward, LOW);
  digitalWrite(LeftMotorForward, LOW);
  digitalWrite(RightMotorBackward, LOW);
  digitalWrite(LeftMotorBackward, LOW);
}

void moveForward(){

  if(!goesForward){

    goesForward=true;
    
    digitalWrite(LeftMotorForward, HIGH);
    digitalWrite(RightMotorForward, HIGH);
  
    digitalWrite(LeftMotorBackward, LOW);
    digitalWrite(RightMotorBackward, LOW); 
  }
}

void moveBackward(){

  goesForward=false;

  digitalWrite(LeftMotorBackward, HIGH);
  digitalWrite(RightMotorBackward, HIGH);
  
  digitalWrite(LeftMotorForward, LOW);
  digitalWrite(RightMotorForward, LOW);
  
}

void turnRight(){

  digitalWrite(LeftMotorForward, HIGH);
  digitalWrite(RightMotorBackward, HIGH);
  
  digitalWrite(LeftMotorBackward, LOW);
  digitalWrite(RightMotorForward, LOW);
  
  delay(500);
  
  digitalWrite(LeftMotorForward, HIGH);
  digitalWrite(RightMotorForward, HIGH);
  
  digitalWrite(LeftMotorBackward, LOW);
  digitalWrite(RightMotorBackward, LOW);
 
  
  
}

void turnLeft(){

  digitalWrite(LeftMotorBackward, HIGH);
  digitalWrite(RightMotorForward, HIGH);
  
  digitalWrite(LeftMotorForward, LOW);
  digitalWrite(RightMotorBackward, LOW);

  delay(500);
  
  digitalWrite(LeftMotorForward, HIGH);
  digitalWrite(RightMotorForward, HIGH);
  
  digitalWrite(LeftMotorBackward, LOW);
  digitalWrite(RightMotorBackward, LOW);
}

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