Arduino_Buzzer_Millis question

@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