Piezo speaker Coding Problem
Chrispysim
Posts: 10
So here is my problem.· I built a PIR motion detecting alarm.· When the alarm is tripped an led blinks for about 20 seconds unless you press one of two buttons.· The code works great.·
Now when the led is finished blinking, if a button has not been pressed, a piezo speaker will beep until one of the buttons is pressed.· For some reason, once the speaker is beeping,·I can't get the·buttons to register.· They only seem to work·when I hold down the button, whereas before a single push would do the trick? ·I have played with the code until I can't see straight and own enough parallax print to warrant its own shelf.
Now when the led is finished blinking, if a button has not been pressed, a piezo speaker will beep until one of the buttons is pressed.· For some reason, once the speaker is beeping,·I can't get the·buttons to register.· They only seem to work·when I hold down the button, whereas before a single push would do the trick? ·I have played with the code until I can't see straight and own enough parallax print to warrant its own shelf.
Comments
When it's driving the piezo speaker to make a beep, it can't look at the buttons to see if they're pushed. If you hold down
the button, eventually the piezo routine will stop and your program will check the button.
One solution would be to use a separate beeper. Either get a piezo speaker with its own beep generator in it or make your
own using a 555 timer. The Stamp can turn the beep on or off with an I/O pin and doesn't have to wait around while it's
beeping. There are lots of circuits for beepers on the web. Just do a web search with "555 beeper" or something similar.
But, I'm curious if you tried a "DO WHILE...LOOP" or DO...LOOP UNTIL in your Alarm routine, so the pushbuttons could be checked between·speaker beeps, then break out·of the loop when a·button push is detected?··If you need to keep track, you can still increment your index as part of the loop and check up on its value later, or as a condition to exit the loop.·
Also, you have quite a long on/off cycle for your beeps. If your application can stand a shorter beep cycle or an almost-continuous tone,·you might get a faster response to your button push if you reduce that PAUSE argument.
Just ideas, this looks like a fun project.
-Stephanie
I did in fact try the do..loop and do...loop until. I even changed the resistors for the pushbuttons. I just couldn't get it to break the cycle as easily as it did for the blinking led phase of the alarm. That solution would have been ideal because now with an optoisolator and a 556 IC the breadboard looks like a tin of sardines. I'd be happy to show you my variations?
I am looking at your Alarm routine, at the FOR...NEXT portion that combines the FREQOUT command with the button detection.· You have two seconds of "down" time· in there for the BS2 in which it can't look for button presses, which is why you have to hold the buttons down so long to get a reaction: 1 second in the FREQOUT command itself, and the two·500 ms pauses on either side of the TOGGLE (and I'm not sure what they are for.)·
I don't know the purpose of toggling the spkr pin, you don't need to give the piezo high-time and low-time like an LED for it to function.·That is taken care of by the FREQOUT command.· Also, the duration of the tone emitted is built into the FREQOUT command syntax.· I see some LOW spkr commands elsewhere in your program, those aren't needed either.
Try changing the Freqout command to: FREQOUT spkr, 100, 4000··· ' play 4000 Hz tone on spkr pin for 100 miliseconds
...and commenting out the PAUSE and TOGGLE commands.
This should greatly reduce the amount of time you need to press and hold the pushbuttons in order to get a reaction.·Try experimenting with that·number to see what happens.·Of course, since you are using a FOR-NEXT loop, the time this subroutine is active will go by much more quickly as that number is reduced.·
If you want to stay in the "sound alarm until pusbutton is pressed" state indefinitely, go back to a DO-LOOP UNTIL.· If you want the alarm to give up after a certain amount of time, you will need to increase the last number in your FOR argument to give the subroutines more cycles, since you have made each cycle shorter.
If you try this, let me know if it helps.
-Stephanie Lindsay
Editor, Parallax Inc.
Sorry for the delay, I was out of town. What I'm trying to do is make the alarm beep once every second. I swapped the pin directive for "spkr." I have tried reducing the pause argument in conjunction with Do...Loop Until. The code looks beautiful but just won't behave. I tried Mike's suggestion about a 555 timer and I quickly ran out of room because of the optoisolator already on the board. I even tried making the audible alarm a subroutine, I still had the same problem. I'm going to play around with the code today and I'll let you know.
Thanks,
Chris
I will be out of town for the next couple of weeks myself, but I will try to check in with the forums. Please feel free to post your updated code.
-Steph
Use a small capacitor from any pin. Charge the capacitor by putting the pin in output mode and then reset it to input. Tie the button to the same pin with a 220 ohm resistor so when the button is pressed the capacitor discharges through the button.
Have fun.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Think Inside the box first and if that doesn't work..
Re-arrange what's inside the box then...
Think outside the BOX!
I am imagining that the pushbutton state could be checked in a for-next loop with enough iterations to give a 1-second delay between beeps, and an EXIT if the button is detected. The FOR-NEXT and the FREQOUT code could be placed together in a DO-LOOP UNTIL that's watching the pushbutton state. There may be an obvious reason this wouldn't work, I wish I had time to play with it now. I can tell it's going to be one of those little puzzles my mind will chew on while I'm traveling.
Steph, I'll upload a few files tonight of the different coding sequences I have tried. I'm thinking of upgrading to a stamp 2p or 2pe so I could take advantage of the PollIN and PollWait commands.
Have fun OOT.
Or as I have done using gosubs and return from within the original subroutine construct. Try to keep all the code from a subroutine between the label and Return statement. If you jump outside the subroutine it should be another subroutine call and not a goto. Gotos will make spaghetti code.
Not tested code attached but I had some free time to exercise some brain cells.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Think Inside the box first and if that doesn't work..
Re-arrange what's inside the box then...
Think outside the BOX!
sorry for the delayed response. I just moved out to the suburbs and was living in the dark ages until I got everything hooked up. The code works great, it allows the buttons to trigger the desired response almost immediatly, however after logging a button hit, the code logs another hit endlessly at about 5sec increments? I was wondering if this is because of the RETURN command, I swapped the RETURN for a GOTO and the code would rapid fire out button hits?
Here are those files and a few originals.
HIGH Led1
...
TOGGLE Led1
With the pause statements, you have to wait a little longer that 100 ms for a button press to read. A more effecient idea would be (in psuedocode):
LOW Led1
FOR i = 0 to 150
TOGGLE Led1
FOR counter = 0 to 100
Check buttons
PAUSE 1
NEXT
NEXT
LOW Led1
GOTO Speaker
Anyway, I'll contradict the advice to use GOSUB. In your case, I think most of your calls should be GOTO due to the nature that you want the system to reset at the end of an action.
In your deactived method, you have a section where you modify the value of d. You'll want to move the read statement before the increment if you want to have the system keep track after it gets turned off and back on. One more thing: you can modify the speaker method in much the same way as the example above. The essence is to have a double loop: the inner checks the buttons constantly for about 1/10 second, then it does some other stuff (TOGGLE) and back to the embeded loop.