Shop OBEX P1 Docs P2 Docs Learn Events
Piezo speaker Coding Problem — Parallax Forums

Piezo speaker Coding Problem

ChrispysimChrispysim Posts: 10
edited 2008-08-11 00:24 in BASIC Stamp
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.

Comments

  • Mike GreenMike Green Posts: 23,101
    edited 2008-07-10 00:57
    I haven't looked at your code, but this is a typical problem due to the fact that a Stamp can only do one thing at a time.
    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.
  • ChrispysimChrispysim Posts: 10
    edited 2008-07-10 02:31
    Thank you Mike. I'll try that and let you know. I have a couple right here.
  • Mike GreenMike Green Posts: 23,101
    edited 2008-07-10 02:42
    Here's one circuit (electronicidea.blogspot.com/2008/01/beeper-using-1c-555.html). Read the note near the end for how to use a logic level input (Stamp I/O pin) to turn it on and off.
  • ChrispysimChrispysim Posts: 10
    edited 2008-07-11 00:19
    Terrific. I've been playing around with a few ICs. Thanks for the link Mike.
  • Steph LindsaySteph Lindsay Posts: 767
    edited 2008-07-11 23:00
    It sounds like you have this figured out and the extra IC will be nice.·

    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
  • ChrispysimChrispysim Posts: 10
    edited 2008-07-13 18:14
    Hi Steph,
    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?
  • Steph LindsaySteph Lindsay Posts: 767
    edited 2008-07-14 18:40
    Hi Chrispysim,

    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.
  • ChrispysimChrispysim Posts: 10
    edited 2008-07-29 12:43
    Hi Steph,
    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
  • Steph LindsaySteph Lindsay Posts: 767
    edited 2008-07-29 17:01
    Hi 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
  • metron9metron9 Posts: 1,100
    edited 2008-07-30 15:54
    Another idea for you. If you set up a latching pushbutton your code can check to see if the button was pressed even when it is not specifically polling an input.

    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!
  • Steph LindsaySteph Lindsay Posts: 767
    edited 2008-07-30 16:59
    Ooh, neat idea Metron9. But, as long as either long FREQOUT durations or PAUSE commands are used to make 1 second spacing between alarm beeps, the pushbutton state won't be acted upon during that time regardless of how it is sensed.

    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.
  • ChrispysimChrispysim Posts: 10
    edited 2008-07-31 13:06
    Thanks for the idea Metron9, that may come in handy. Reminds me of an old physics problem when we studied RC circuits.
    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.
  • metron9metron9 Posts: 1,100
    edited 2008-07-31 17:29
    Your code gosubs ALARM, from ALARM it uses a GOTO for two other routines that end with "GOTO MAIN" those routines should use a RETURN to get back to the main loop.

    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!
  • ChrispysimChrispysim Posts: 10
    edited 2008-07-31 19:43
    Cool. I'll give that a try.
  • ChrispysimChrispysim Posts: 10
    edited 2008-08-09 17:33
    Metron9-
    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?
  • SRLMSRLM Posts: 5,045
    edited 2008-08-10 19:09
    Might I ask which pin the button is on. The most likely choices that I've noticed are soap or deact. I'm assuming that it is deact. I'm looking at your most recent file (Chris7-29-08 kforspeaker.bs2) One thing I noticed is that in your alarm method you have a couple of things that can be improved. The most obvious is the two lines

    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.
  • ChrispysimChrispysim Posts: 10
    edited 2008-08-11 00:24
    Thanks for the tip, I'll give that a try and let you know.
Sign In or Register to comment.