Shop OBEX P1 Docs P2 Docs Learn Events
Is there a way to count pulses (a steady 120hz) for a changing length of a butt — Parallax Forums

Is there a way to count pulses (a steady 120hz) for a changing length of a butt

Clock LoopClock Loop Posts: 2,069
edited 2005-06-30 23:31 in BASIC Stamp
Is there a way to count pulses (a steady 120hz) for a changing length of a button.

Im trying to count pulses that are a steady 120hz, for a length of time, that time is variable upon the amount of time that passes between each button push. pulsin wont work because its max pulse width is too small.

so basically I want to

COUNT pin, (duration is time between button presses), variable

Is it possible for me to count a signal AND monitor a button press for a desired state?
«13

Comments

  • Chris SavageChris Savage Parallax Engineering Posts: 14,406
    edited 2005-06-26 19:34
    Hello,

    ·· That's not going to work the way you plan.· The COUNT command requires a specific duration to be used.· You can't COUNT until another event, at least not using the command that way.· You may need to implement an external RTC or other clock/counter source, reset the counter, initiate the clock, and when the button is pressed, read the counter.· This could even be done using simple/common chips, depending on your part count requirements.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Chris Savage
    Parallax Tech Support
    csavage@parallax.com
  • Clock LoopClock Loop Posts: 2,069
    edited 2005-06-26 20:16
    Hmm, more and more I am beginning to realize that the stamp is mostly a calculator, and logic machine. For clocking and counting, its not so good. (for multitasking reasons)

    But thats not bad, (try to do major math operations with external logic chips heh)
    I have got a ton of mil-spec logic chips. So somehow I will be able to do this.
    As far as my part count? Dosen't matter. Room, and chips aren't a design consideration.
    But counting with say a 74HC393 (dual binary counter) (to count to 120 i would need 3 chips, 0011 0001 0011 0010 0011 0000 = 120
    But the problem comes trying to load the binary number into the stamp. I guess I would need another chip that takes parallel in serial out?

    Again, I think I am reminded to stick to One / Two wire chip systems. DAMN MIL CHIPS! (thats what I get for using 60's technology)

    (runs away screaming)
  • Chris SavageChris Savage Parallax Engineering Posts: 14,406
    edited 2005-06-26 20:29
    Hello,

    ·· I didn't have a specific arrangement in mind.· I can think of two main ways to do this.· One would involve a serial clock chip, such as the DS1302, although you would probably need one that counts tenths of seconds, so you might have to do a little looking.

    ·· In any event you would reset the clock (minutes/seconds, tenths) then start checking for your button input.· Once you get it, read the clock value for the elapsed time.· I didn't read back to see if you specified the resolution you wanted for it.

    ·· The other way would be using discrete chips, and would depend on your level of experience, but it's how we did things in the old days (80's and early 90's).· You could have a TTL Oscillator clocking a counter (16-bit?· Would depend on resolution, etc.).· You would most likely need a divide-by-n counter between the two.· The main counter chip would need a parallel output.· This output could be tied to 74LS165's to be read into the BS2 via SHIFTIN (Using 3 lines).· Now you would need one output from the Stamp to reset the counter (Many chips have a reset line on them).



    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Chris Savage
    Parallax Tech Support
    csavage@parallax.com
  • Beau SchwabeBeau Schwabe Posts: 6,545
    edited 2005-06-26 20:46
    What kind of time are you talking about between button presses? There may be a way to do it using an external SCR "latch" to
    enable or disable the incoming 120Hz pulses within a "time window" and still use the COUNT command.

    Also, what kind of resolution between presses do you need? What is the source of the 120Hz in relation to your circuit?

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Beau Schwabe

    IC Layout Engineer
    Parallax, Inc.
  • Clock LoopClock Loop Posts: 2,069
    edited 2005-06-26 20:56
    Source is a 120hz crystal. Resolution? I need to be able to count every pulse coming from the 120hz crystal at the start of each button press to the next time the button is pressed.

    So in a sence Im counting EVERY 120hz pulse, but noting how many pulses happen from the instant the button is pressed, all the way to the next time the instant the button is pressed again. So I need to monitor two inputs heh. Which isn't possible at the same time.

    The button is pressed by a human not faster than mabee once every 100ms MAX. And can be as long as once every 1000ms between button presses.
  • Clock LoopClock Loop Posts: 2,069
    edited 2005-06-26 21:01
    So every 8.3 ms, I have a pulse that I must count. Wait, I can do this can't I ?

    I could monitor the 120hz input for a pulse, then at pulse, add 1 to my total pulse count. (every 5 ms?) then after that keep monitoring the button for a desired state, then desired state is reached, reset total pulse count?

    Something like that? Is the BS2 fast enough to do this?
  • Jon WilliamsJon Williams Posts: 6,491
    edited 2005-06-26 21:08
    Since a 120 Hz signal has a 8.3 ms period, you may be able to use the following subroutine.· It waits for a button press, waits for the release, starts counting, and stops when the button is pressed again.· I tested this on my PDB using the signal generator setting at 100 Hz.· That's a little slower than your signal, but it·worked, so I tested at 120 Hz using a 555.

    Count_Pulses:
      DO : LOOP UNTIL (StartBtn = Pressed)
      DO : LOOP UNTIL (StartBtn = Released)
      DO
        IF (PulsesIn = 0) THEN
          pCount = pCount + 1
          DO : LOOP UNTIL (PulsesIn = 1)
        ENDIF
      LOOP UNTIL (StartBtn = Pressed)
      RETURN
    


    I've attached the full program that is currently running on my PDB with a 120 Hz signal from a 555 circuit that I happened to have built-up for another project (StampWorks update).· Here's how I tested: I pressed the button and then counted out loud: "One thousand on, one thousand two..." up to five seconds.· The result: 597.· Since 120 x 6 = 600 and my button timing may not have been exactly five seconds I'd say it's working.

    Now ... if you have to do a bunch of other things while the inputs are being counted, then you will need an enternal circuit.· An easy solution could be an RTC (real time clock chip) set to counter mode.· Have a look at the PCF8483.· It's an I2C device, but has an event counter mode and I2C routines can be synthesized with the stock BS2.· If you're using any of the "p" family members, I2C is built in.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Jon Williams
    Applications Engineer, Parallax

    Post Edited (Jon Williams (Parallax)) : 6/26/2005 9:10:49 PM GMT
    798 x 597 - 184K
    450 x 369 - 52K
  • Clock LoopClock Loop Posts: 2,069
    edited 2005-06-26 22:01
    The BS2 isn't fast enough to make this work, is it?

    ' {$STAMP BS2}
    ' {$PBASIC 2.5}
    
    hz        PIN   0       '120hz input on pin 0
    bttn      PIN   1       'Button input on pin 1
    prev      VAR   Bit     'Previous button state
    prevhz    VAR   Bit     'Previous 120hz state
    counthz   VAR   Byte    'hertz count
    
    onn       CON   1       'Active High
    off       CON   0
    
    
    Main:
    
      DO
        DEBUG ? counthz
    
        IF bttn = off THEN
        prev = off                              'button isn't pressed set prev state to 0
        ENDIF
    
        IF bttn = onn AND prev = off THEN       'button is pressed and prev state was 0
        counthz = off                           'reset 120hz pulse counter
        prev = onn                              'set previous state to 1
        ENDIF
    
        IF hz = off THEN
        prevhz = off                            '120hz line is in low mode, set prevhz state to 0
        ENDIF
    
        IF hz = onn AND prevhz = off THEN       '120hz is in pulse state, and previous state was 0
        counthz = counthz + 1                   'counthz adds 1 because cycle is complete.
        prevhz = onn                            'set prevhz state to 1
        ENDIF
    
      LOOP
    
    
    
  • Jon WilliamsJon Williams Posts: 6,491
    edited 2005-06-26 22:13
    You're doing things the hard way and adding a lot of overhead that is killing the ability to count pulses.· For example, you have pulses coming every 8.3 milliseconds yet you're sending a DEBUG message while attempting to count.· At 9600 baud, each byte transmitted takes one millisecond, so doing this:

    · DEBUG ? countHz

    Will consume at least 11 milliseconds (when countHz is one digit; add another ms for each additional digit)·-- no good.·

    Is there some problem with the program I wrote for you?· It proves that the BS2 if fast plenty enough to do what you want.· The key is efficient programming; something I have a bit of practice with in 12 years of BASIC Stamp programming.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Jon Williams
    Applications Engineer, Parallax

    Post Edited (Jon Williams (Parallax)) : 6/26/2005 10:19:58 PM GMT
  • Clock LoopClock Loop Posts: 2,069
    edited 2005-06-26 22:16
    No, for somereason I was not able to get it to work right. I connected my 120hz pulse to pin1.
    And then connected my button, to pin2, with the other pin of the button to low (vss). I also connected pin2 to Vdd thru a 1k resistor to make the button active low.

    Is this right?
  • Clock LoopClock Loop Posts: 2,069
    edited 2005-06-26 22:22
    oops, i reversed button with 120hz in pins.

    But after switching them, it still doesn't work. heh
  • Jon WilliamsJon Williams Posts: 6,491
    edited 2005-06-26 22:22
    No.· If you look in the declarations you'll see that my button was connected to P0.· If you want it on P2, update the declaration like this:

    StartBtn······· PIN·····2······················ ' active-low button input

    And I can assure you that the program does work ... when connected properly.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Jon Williams
    Applications Engineer, Parallax
  • Clock LoopClock Loop Posts: 2,069
    edited 2005-06-26 22:25
    LOL.. ok ok

    Let me SAY this right.

    I DO have pin 1 connected to my freq.

    AND I DO have pin0 connected to my button.

    and it doesn't work heh.
  • Chris SavageChris Savage Parallax Engineering Posts: 14,406
    edited 2005-06-26 22:27
    ·· I should've waited because I knew Jon would come up with something simpler to do this.· Even I learn something new, as I didn't realize that chip (PCF8483) had an event counter mode.· I'll have to file that info away...


    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Chris Savage
    Parallax Tech Support
    csavage@parallax.com


    Post Edited (Chris Savage (Parallax)) : 6/26/2005 10:34:46 PM GMT
  • Jon WilliamsJon Williams Posts: 6,491
    edited 2005-06-26 22:30
    If you're running my program without changes and you've got the connections correct, then the problem may be with you 120 Hz input. Is it TTL level (you mentioned a cyrstal earlier, so I'm suspicious). You should probably put a 'scope on your circuit and check the levels. If the 120 Hz input is not going higher than 1.4 volts then the BASIC Stamp will never see it.

    If you don't have a scope,· do this:

    · COUNT 1, 1000, countHz
    · DEBUG ? countHz

    If it doesn't show

    · countHz = 120

    ... then you know the BASIC Stamp is not seeing the 120 Hz input and you need to fix that.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Jon Williams
    Applications Engineer, Parallax

    Post Edited (Jon Williams (Parallax)) : 6/26/2005 10:35:32 PM GMT
  • Clock LoopClock Loop Posts: 2,069
    edited 2005-06-26 22:43
    I got it to work.

    You were active low on BOTH(not just button). I use a different power regulator for my 555(setup on another breadboard). So I use common ground. (not common 5) Since you were active low on both button and 120hz, the 120hz wasn't being seen.
    (due to common low) I just modified your code to make active high.

    [noparse]:)[/noparse]
    Thank you
  • Chris SavageChris Savage Parallax Engineering Posts: 14,406
    edited 2005-06-26 22:48
    BPM,

    ·· Just remember, before you think the Stamp can't do something, ask someone with experience like Jon Williams and it's probably either been done, or can be done with the right code and/or minimal hardware.· Also, clear details about your circuit and what you're trying to do can save a lot of back and forth posting to get all the information.· But at least you have it working now.


    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Chris Savage
    Parallax Tech Support
    csavage@parallax.com
  • Jon WilliamsJon Williams Posts: 6,491
    edited 2005-06-26 22:52
    I'm glad it's finally working.· Now take back every mean thing you ever said about the BASIC Stamp! tongue.gif

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Jon Williams
    Applications Engineer, Parallax
  • Clock LoopClock Loop Posts: 2,069
    edited 2005-06-26 23:12
    I have NEVER said anything mean! I ALWAYS assume it is human error. (because even if I fried it, it would be my fault)

    Stamps rawk!

    Im just thinking I may need to get a BS2P24 or BS2P40. I2C, and other commands are nice. so might more speed. convincing my wife that I need another 100$ item is the problem... [noparse]:)[/noparse]

    Got a program to help me with that one?

    Ok, heres what im REALLY trying to do with this stamp.

    Count a button click and calculate the Beats Per Minute the button clicks at. Then take the result and display it on a 3 digit display.
    Also, based on some pin inputs(switches), flash two pin outputs at the same BPM speed.
    I do have alot of work to do.
    [noparse]:)[/noparse]
  • Jon WilliamsJon Williams Posts: 6,491
    edited 2005-06-26 23:46
    Sure...

    Main:
    · DEBUG· "Honey, I love you ... can I spend $100?· Please..."
    · END


    As far as the rest of your program, calculating BPM from your 120 Hz input is easy:

    · bpm =·7200 / countHz

    Displaying on three 7-segment LEDs will take a bit of hardware, and you have choices: you could use a multiplexer like the MAX7219 or the MC14489 (cheaper), or -- if the display cathodes are not common -- you can go really cheap and use a 74HC595 for each digit.· These can be daisy-chained so you'll only need three IO pins to display the BPM (that goes for the muliplexers as well).

    Calculating the blink rate for the LEDs is no big mystery either.· Assuming a 50% duty-cycle you could do this:

    · blinkRate = 30000 / bpm
    · DO
    ··· TOGGLE BpmLed
    ··· PAUSE blinkRate
    · LOOP UNTIL (StartBtn = Pressed)

    See my attachment for a more advanced version that turns the LED on for a fixed period; the off time is dependent on the bpm value.


    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Jon Williams
    Applications Engineer, Parallax
  • Clock LoopClock Loop Posts: 2,069
    edited 2005-06-27 00:17
    Will I have a hard time using the BS2 for talking to 2-wire, 1-wire, or I2C devices? I have a few samples on the way from maxim, and one of them is the display driver MAX6959 (which is a 2-wire)
  • Jon WilliamsJon Williams Posts: 6,491
    edited 2005-06-27 01:04
    You cannot use 1-Wire devices unless you have a serial-to-1-wire convertor -- unless you get a BS2p model. All BS2 models have SHIFTOUT and SHIFTIN instructions that can be used with devices like shift registers, etc., and can also be used to synthesize I2C communications. If you get a BS2p you can skip the I2C synthesis since those models (BS2p, BS2pe, BS2px) have I2COUT and I2CIN instructions.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Jon Williams
    Applications Engineer, Parallax
  • Clock LoopClock Loop Posts: 2,069
    edited 2005-06-27 06:36
    In this code,

    Count_Pulses:
      DO : LOOP UNTIL (StartBtn = Pressed)
      DO : LOOP UNTIL (StartBtn = Released)
      DO
        IF (PulsesIn = 0) THEN
          pCount = pCount + 1
          DO : LOOP UNTIL (PulsesIn = 1)
        ENDIF
      LOOP UNTIL (StartBtn = Pressed)
      RETURN
    
    



    What does the " : " in "DO : LOOP UNTIL" do?
    Ive searched the help and didn't find any example code that shows use of " : " like this.
  • Bruce BatesBruce Bates Posts: 3,045
    edited 2005-06-27 10:05
    BPM -

    The colon just permits you to stack more than one PBASIC command on one physical line
    like this -

    A = 1 : B = 2 : C = 3

    DO : LOOP UNTIL etc

    I suppose another way of saying it is that the PBASIC Stamp Editor views it as an artifical
    LF + CR.

    Regards,

    Bruce Bates
  • Tracy AllenTracy Allen Posts: 6,656
    edited 2005-06-27 14:44
    newPulsesIn VAR bit
    oldPulsesIn VAR bit
    Count_Pulses:
      DO : LOOP UNTIL (StartBtn = Pressed)
      DO : LOOP UNTIL (StartBtn = Released)
      DO
        newPulsesIn=PulsesIn
          pCount = pCount + (newPulsesIn ^ oldPulsesIn & oldPulsesIn)
        oldPulsesIn=newPulsesIn
      LOOP UNTIL StartBtn
      RETURN 
    
    

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Tracy Allen
    www.emesystems.com
  • George SuttonGeorge Sutton Posts: 180
    edited 2005-06-27 16:08
    In just a matter of MINUTES, the first of several very useful and informative replies were provided.· And in a matter of a few hours, circuits were breadboarded and software code was written, tested, and provided.· If this is not customer service, then such does not exist.· Jon, Beau, Chris, Tracy, and Bruce are to be commended for yet again coming to the aid of a Stamp user.
    ·
  • Jon WilliamsJon Williams Posts: 6,491
    edited 2005-06-27 17:36
    I actually tried that technique on a different project and while it works, it is much slower than IF-THEN-ENDIF (probably due to all the bit level variable access and manipulation).· I love the trick though, and have included it in the StampWorks update in the multi-button input and debouncing project.
    Tracy Allen said...
    newPulsesIn VAR bit
    oldPulsesIn VAR bit
    Count_Pulses:
      DO : LOOP UNTIL (StartBtn = Pressed)
      DO : LOOP UNTIL (StartBtn = Released)
      DO
        newPulsesIn=PulsesIn
          pCount = pCount + (newPulsesIn ^ oldPulsesIn & oldPulsesIn)
        oldPulsesIn=newPulsesIn
      LOOP UNTIL StartBtn
      RETURN 
    
    

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Jon Williams
    Applications Engineer, Parallax
  • Clock LoopClock Loop Posts: 2,069
    edited 2005-06-27 19:26
    To make sure I understand this code correctly,
    
    Count_Pulses:                               'Sub Count_pulses.
      DO : LOOP UNTIL (StartBtn = Pressed)      'this loops this one line of code untill I press the button
      DO : LOOP UNTIL (StartBtn = Released)     'this loops this one line of code untill I release the button
      DO
        IF (PulsesIn = 0) THEN                  'this makes sure every active low part of 120hz is counted, not every high swing.
          pCount = pCount + 1                   'this adds 1 to the count for every active low part of 120hz
          DO : LOOP UNTIL (PulsesIn = 1)        'This loops this one line of code untill 120hz swings high.
        ENDIF
      LOOP UNTIL (StartBtn = Pressed)           'this loops the entire 120hz pulse counter until the button is pressed again.
      RETURN                                    'this returns me to main to display count results.
    
    
    
  • Clock LoopClock Loop Posts: 2,069
    edited 2005-06-27 19:45
    I hope Im not annoying you guys with all my questions. heh.. Ive got another.
    Heres my results from counts. I added some code to repeat the counts, without resetting the chip, and added code to calculate the bpm and display it.

    My question is, if I use the command BUTTON to debounce the button, will it smooth out my BPM results? Or is there another reason I am getting a very WIDE range of results. The button was pressed at a constant rate, timed by a metranome. obviously humans aren't perfect, but i know the results should be within +/-10 bpm of eachother... Obviously I will use averaging over a time frame, but I would like to improve the data I am sending to my averager.

    example:
    Press button. Wait. Press again.
    bpm = 57
    bpm = 240
    bpm = 86
    bpm = 86
    bpm = 10
    bpm = 167
    bpm = 122
    bpm = 167
    bpm = 144
    bpm = 194
    bpm = 167
    bpm = 194
    bpm = 144
    bpm = 20
    bpm = 144
    bpm = 240
    bpm = 104
    bpm = 1
    bpm = 144
    bpm = 104
    bpm = 225
    bpm = 224
    bpm = 104
    bpm = 194
    bpm = 144
    bpm = 144
    bpm = 144
    bpm = 167
    bpm = 122
    bpm = 1
    bpm = 86
    bpm = 1
    bpm = 194
    bpm = 232
    bpm = 144
    bpm = 104
    bpm = 86

    heres the code
    ' -----[noparse][[/noparse] I/O Definitions ]-------------------------------------------------
    
    Bttn            PIN     0                       ' active-high button input
    Hz              PIN     1                       ' 120 Hz input
    
    
    ' -----[noparse][[/noparse] Constants ]-------------------------------------------------------
    
    Pressed         CON     1                       ' for active high button
    Released        CON     0
    
    
    ' -----[noparse][[/noparse] Variables ]-------------------------------------------------------
    
    pCount          VAR     Word                    ' count of pulses
    bpm             VAR     Byte
    
    ' -----[noparse][[/noparse] EEPROM Data ]-----------------------------------------------------
    
    
    ' -----[noparse][[/noparse] Initialization ]--------------------------------------------------
    
    Reset:
      DEBUG CLS,
            "Press button.  Wait. Press again.", CR
    
    
    ' -----[noparse][[/noparse] Program Code ]----------------------------------------------------
    
    Main:
    
     DO
      pCount = 0
      GOSUB Count_Pulses
    '  DEBUG ? pCount
       bpm = 7200 / pCount
       DEBUG ? bpm
    
     LOOP
    
    
    ' -----[noparse][[/noparse] Subroutines ]-----------------------------------------------------
    
    Count_Pulses:
      DO : LOOP UNTIL (Bttn = Pressed)
      DO : LOOP UNTIL (Bttn = Released)
      DO
        IF (Hz = 1) THEN
          pCount = pCount + 1
          DO : LOOP UNTIL (Hz = 0)
        ENDIF
      LOOP UNTIL (Bttn = Pressed)
      RETURN
    
    
  • allanlane5allanlane5 Posts: 3,815
    edited 2005-06-27 20:11
    1. No, you should not use 'Button' to debounce, or you'll lose the time between presses.

    2. A human being had kind of limited resolution. +- 10 mSec might be a better metric.

    3. You may need to de-bounce your readings -- not with "Button" though.
    That would explain your '1' and perhaps '86' readings. Note that a switch will 'bounce' for 1 to 3 mSec, depending on the spring tension.
Sign In or Register to comment.