1

everyone. I am working on learning Arduino from scratch and I am on the buzzer lesson. The tutorial I am following consists on writing a code to get an input from the user in the form of an integer number, and, if it is greater than 10 (or whatever threshold you set it to) it will buzz.

I wrote the code exactly as the tutorial said but the buzzer would not buzz, it would do a weird clicking sound instead. I searched for a reason everywhere and could not find an explanation. Most questions in forums were solved by changing the positive wire from the 5V to a regular pin on the board, and those problems were due to the fact that the people asking the questions were not aware that the buzzer was a passive one.

Anyway, I managed to get a buzz by switching from digital to analogWrite and typing a value less than 255. It seemed weird that 255 and HIGH would produce the click, but values less than 255 would buzz, so I tried several analogWrite values:

  • At 255 the buzzer does the weird clicking.
  • At 254 the buzzer does a very faint buzz.

The buzzing got louder as I wrote lower numbers until it got stable at around 250, and then got less loud as I decreased the number.

Does anyone know why that is? Is the voltage too much for the buzzer at 255/HIGH? I tried a resistor but still got nothing but clicking with the program set to 255/HIGH.

This is mostly out of curiosity, but I'd still appreciate it if you could answer it.

Here is the code ("Numero" means "number" and "Dame un número" means "Give me a number":

int Numero;

int buzz=10;

int DLY=2000;

String msg="Dame un numero.";

void setup() {

Serial.begin(9600);
pinMode(buzz,OUTPUT);

}

void loop() {
 
Serial.println(msg);
while (Serial.available()==0){
  
}

Numero=Serial.parseInt(); 

if (Numero>25){

  Serial.println(Numero);

  analogWrite(buzz,10);

  delay(DLY);

  digitalWrite(buzz,LOW);

}


}
1

3 Answers 3

2

those problems were due to the fact that the people asking the questions were not aware that the buzzer was a passive one.

You seem to know, that you have a passive buzzer, but you don't know, what that means for you.

A buzzer consists mostly of a piezo element, which vibrates and thus makes a sound, if you provide it with an alternating voltage. Here we have 2 types of buzzers:

  • The ones, that generate the alternating voltage themselves, thus only demanding a simple constant voltage from you to operate (these are the active buzzers)
  • and the ones, that only have the piezo and thus demand to be provided with an alternating voltage by you (these are the passive buzzers).

You have the second type, a passive buzzer. The following is happening:

digitalWrite(pin, HIGH) will only set the pin to HIGH. On the transition from LOW to HIGH, you get a click, because the piezo in the buzzer is reacting to that change. analogWrite() on the other hand generates a PWM signal, which is an alternating voltage (alternating between LOW and HIGH).

When changing the number for analogWrite(), you are not changing the frequency, but only the duty cycle (the ratio of HIGH and LOW times in one period of the signal).

  • analogWrite(pin, 255) means 100% duty cycle and thus a constant HIGH signal. Actually it is equivalent to digitalWrite(pin, HIGH), because analogWrite() is doing exactly that, if you provide 255 (similarily it uses digitalWrite(pin, LOW), if you provide 0). Thus you again hear the same click.
  • As the piezo in the buzzer needs to oscillate to make a sound, you need to give him time for getting back to the LOW state. With the analog value 254 the LOW time of the signal is rather small, so that the piezo cannot reach its complete LOW state again. The oscillation amplitude is rather small that way. Thus you only hear a very faint buzz.
  • With analogWrite(pin, 250) you reached the maximum, because now the piezo has enough time to get to its LOW state again. The amplitude is at its maximum here, thus it is the loudest value.
  • When going lower than 250 towards zero, you are also reducing the amount of energy, that you give to the buzzer, thus the volume will reduce (though this is certainly not a linear process and depends also on the characteristics of the buzzer).

Just as Juraj already wrote in the comments, a passive buzzer can be interfaced with the tone() function. It will generate the alternating voltage for you and you can even set the frequency to your liking, so that you get tones with different pitches. There are tons of tutorials about the tone() function on the web.

5
  • I don't agree with your "When going lower than 250 towards zero, you are also reducing the amount of energy" statement. It reduces the average voltage, but average voltage is not what gets maximum sound out of a piezo emitter. You're going to get the maximum volume out of a piezo element at 50% duty cycle (digitalWrite(pin, 128)).
    – Duncan C
    Commented Jul 2, 2020 at 20:05
  • @DuncanC You mean analogWrite(pin, 128). But as I think closer, you may have a point there. Its difficult to map the duty cycle to the volume. Can you explain more, why at 50% duty cycle you have the highest volume? The piezo is fast enough, so that changes between 5 and 250 would not matter much. When the pin is high, the piezo moves in one direction. When low into the other. In between it stands still. The amplitude is given by the voltage (for the above range), which is equal for all high or low states. Thus I now could say, that in that range the value doesn't matter for the volume.
    – chrisl
    Commented Jul 2, 2020 at 20:41
  • Or am I thinking wrong here?
    – chrisl
    Commented Jul 2, 2020 at 20:41
  • Well, to say it will be loudest at 128 is an over-simplification. It will be the closest to a pure tone at 128, and you'll get equal time with the element in the in and out positions. At values other than 128 there will be additional harmonics introduced into the tone. (There's lots of high frequency harmonics in a square wave signal anyway, but at a duty cycle other than 50% there will be even more.)
    – Duncan C
    Commented Jul 2, 2020 at 21:21
  • Hey man, thanks for the explanation. Could not have asked for a better one on passive buzzers. It was clear and concise and solved my burning question. Keep it up.
    – Coy Ote
    Commented Jul 3, 2020 at 0:58
1

A passive Piezo buzzer needs excitation to make sound, from your code you have a delay time of 2000 ms. 2000ms means a frequency of 0.5 Hz thats not enough.for my YL-44 Passive buzzer even the smallest possible number allowed by the arduino delay(ms) function wich is 1 ms isn't enough to hear a clear sound. A frequency of 2000 Khz was good with delayMicroseconds(us).

double outPin = outPin;
double freq_Hz = freq_Hz;
double period_s = 1 / m_freq_Hz;
double period_ms = m_period_s * 1000;
double period_us = m_period_ms * 1000;
void loop() {
 digitalWrite(m_outPin, HIGH);
 delayMicroseconds(period_us / 2);

 digitalWrite(m_outPin, LOW);
 delayMicroseconds(period_us / 2);
}
    
0

As chrisl explained, a passive buzzer needs a switched signal of the desired frequency in order to produce a tone of a specific pitch. It's going to produce the best/loudest output with a square wave (50% duty cycle.)

The analogWrite function outputs a PWM (pulse-width modulation) signal. That is a signal of a fixed frequency but varying duty cycle (The ratio of on time to off time.) At 50% (value 128) you should be able to get a decent tone out of it. (It looks like the PWM frequency varies by Arduino model: )

If you want to produce tones of varying frequncies, use the Arudino library's tone() function, documented here: https://www.arduino.cc/reference/en/language/functions/advanced-io/tone/

With the tone() function you provide the pin number and the desired frequency, and it does the rest. As mentioned in the docs, the tone function interferes with PWM output on boards other than Mega.

You could also get a tone with code like this:

bool state = HIGH;
int buzz=10;
unsigned long time = 0;

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

void loop() {
   if (millis() > time) {
      state = state == HIGH ? LOW: HIGH;
      time = millis() + 2;
      digitalWrite(buzz, state);
   }
}

If you loop does nothing else, that should give you a tone of roughly middle C. (250 hz, if my math is correct.)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.