Program causing Piezo to buzz?

Hello all. Noob here.

I am trying to make the project 8 (digital hourglass) from the Starter Kit, and I'm adding a piezo to sound when the final led lights up.

And it works, except that after a few seconds, the piezo starts buzzing constantly, then wobbles a bit and turns off randomly.

My code is below. I've tried everything. Turning the pin it's connected to low, changing lots of other sections of the code, etc.

So when this runs, each led lights up one at a time, when the 7th is about to light up the piezo buzzes for a second, then stops..... Then if you leave it alone for a few more seconds the piezo starts buzzing again without stopping. This happens even when I set that pin output to LOW. At first I thought maybe there was a tiny bit of voltage slipping through and sort of 'building up' in the piezo, but that doesn't appear to be the case because if you leave the piezo unplugged for the whole time, then plug it in later it buzzes constantly.

So it's like the pin (pin 12 in this case) just decides to turn to HIGH after awhile. Even though nothing in the program is telling it to.

I used a multimeter on that pin, and it is basically 0 until the piezo would start buzzing, at which point it jumps to just under 5v and stays there. Why?

UPDATE!!: I removed the "led++" portion of the code, and replaced it with a series of write2, delay, write 3, delay, etc... This stopped the buzzing. Why? What is the led++ doing to make it turn the pins on?

Would appreciate any help!

const int piezoPin = 12;
unsigned long previousTime =0;
int led = 2;
long interval = 1000;

void setup() {
pinMode(2, OUTPUT);
pinMode(3, OUTPUT);
pinMode(4, OUTPUT);
pinMode(5, OUTPUT);
pinMode(6, OUTPUT);
pinMode(7, OUTPUT);

pinMode(piezoPin, OUTPUT);
}

void loop(){
unsigned long currentTime = millis();
if(currentTime - previousTime > interval){
previousTime=currentTime;

digitalWrite(led,HIGH);
led++;

if(led == 7){
pinMode(piezoPin, HIGH);
tone(piezoPin,200,1000);
}
else if (led <=6){
pinMode(piezoPin,LOW);
}

}
}

First up, you should place your code within [code]code tags[/code], rather than [quote]quote tags[/quote]:-

const int piezoPin = 12;
unsigned long previousTime = 0;
int led = 2;
long interval = 1000;

void setup()
{
    pinMode(2, OUTPUT);
    pinMode(3, OUTPUT);
    pinMode(4, OUTPUT);
    pinMode(5, OUTPUT);
    pinMode(6, OUTPUT);
    pinMode(7, OUTPUT);
    pinMode(piezoPin, OUTPUT);
}

void loop()
{
    unsigned long currentTime = millis();
    if (currentTime - previousTime > interval)
    {
        previousTime = currentTime;

        digitalWrite(led, HIGH);
        led++;

        if (led == 7)
        {
            pinMode(piezoPin, HIGH);
            tone(piezoPin, 200, 1000);
        }
        else if (led <= 6)
        {
            pinMode(piezoPin, LOW);
        }
    }
}

You regularly increment the value stored in 'led' without ever resetting it, so after 10 seconds have elapsed, led=12, then when you do a 'digitalWrite(led,HIGH)', you turn the piezo buzzer on. (I guess it's a buzzer with a built-in driver, since it sounds when the pin is HIGH? If that's the case, you don't need to call 'tone()'.)
You need to re-think the logic of your program.

OldSteve:
You regularly increment the value stored in 'led' without ever resetting it, so after 10 seconds have elapsed, led=12...
You need to re-think the logic of your program.

That makes sense. The 'logic' was decided on by the authors of the Arduino book :slight_smile: I think they do weird things with the code so we can learn different things (instead of using delay all the time in this case).

Can you point me to where I can learn about 'resetting' the value incrementation? Or stop it? I tried something along the lines of "led <8" at one point during my troubleshooting.

Your calls to pinMode() with HIGH and LOW are incorrect, pinMode() should only be used to configure pins as inputs or outputs. Calling tone() with a duration is all you need to accomplish what you want.

You're correct - they're not necessary, but they are making the pin output then input. (I only looked quickly, and somehow saw the 'pinMode()' calls as 'digitalWrite()' calls. I was going to point out that they weren't needed either, but first wanted to double-check what sort of buzzer it is.)

From the original description of the fault, though, it sounds like 'tone()' isn't necessary either. If the buzzer turns on when the 'led' variable equals 12 and 'digitalWrite(led)' is called, then the buzzer is the type with a built-in driver, and 'digitalWrite()' is all that's needed. Otherwise, if the buzzer wasn't that type, it shouldn't sound when 'led' = 12 and that pin is made high. 'tone()' isn't being called when the buzzer sounds but isn't supposed to.

@therfws, to double-check what sort of buzzer it is, connect it to a pin and make that pin high. If it sounds, you don't need 'tone()'. You don't need anything else connected for that test.
You could load and run this:-

const byte piezoPin = 12;

void setup()
{
    pinMode(piezoPin, OUTPUT);
    digitalWrite(piezoPin, HIGH);
}

void loop(){}

Do this test first, then we can go from there, after we know for sure exactly which type of buzzer it is.

I've tried everything.

Please describe "everything" more detailed, I don't know what "everything" might be.

Did you check whether you have an active or a passive piezo?

That's how to do:

Connect the black piezo connector to GND and the red one to 5V, no program needed. If the piezo starts sounding, you have an active piezo that generates his own frequency. This type of piezo will always play his own native frequency, you just can control the sound on and off.

Passive piezos stay quiet in that test, they need to be driven in audio frequency, i.e. by the Arduino tone() function. They are like passive speakers.

Please check out http://www.arduino.cc/en/Tutorial/ToneMelody?from=Tutorial.Tone for a passive piezo test.

jurs:
Connect the black piezo connector to GND and the red one to 5V, no program needed. If the piezo starts sounding, you have an active piezo that generates his own frequency.

I was going to suggest simply connecting the piezo wires to +5V and GND, but figured that since the piezo was already connected to the Arduino, it would be just as easy to upload a simple program to test it. (No disconnecting/re-connecting the piezo needed. :slight_smile: )
We should know for sure what type it is soon.