my button debounce code in SPIN using CTRA
iammegatron
Posts: 40
I used posedge detection of the counter, according to "AN001", to debounce a switch. I didn't see it mentioned anywhere. So here it is
Please help improve this for other debounce applications.
{{ assuming positive edge trigger; add some pull-down on the input pin switch ───────┳─ P0 (Propeller) │ 100K │ pull down to GND }} CON _clkmode = xtal1 + pll16x 'Standard clock mode * crystal frequency = 80 MHz _xinfreq = 5_000_000 VAR long current_phsa_cnt OBJ serial : "FullDuplexSerial" PUB main serial.Start(31, 30, %0000, 115200) CTRA := constant(%01010 << 26) 'use PIN0 as input; posedge trigger FRQA := 1 'set FRQA to add 1 current_phsa_cnt := PHSA repeat waitcnt(cnt + (1 * clkfreq)) serial.Str(STRING("phsa count:")) serial.Tx($0D) serial.Hex(PHSA, 4) serial.Tx($0D) if (PHSA - current_phsa_cnt) > 0 serial.Str(STRING("triggered")) serial.Tx($0D) 'perform your task once here waitcnt(cnt + clkfreq/1000 ) 'for example: takes 1ms 'end task 'then update current_phsa_cnt := PHSA
Please help improve this for other debounce applications.
Comments
Whereas the timer is just persisting that the signal changed at least once.
If your code were to run inside a fast event loop it would trigger on every bounce that wasn't shorter
in duration than the event loop period.
Or have I misunderstood?
All the switch bounces that produce a positive edge will increment PHSA by one count (because of FRQA=1).
However because "current_phsa_cnt" doesn't get updated until your_one_time_triggered_task finishes. So the "inactive" period is the time to finish the task.
Does that sound right?
I have always just used a few IF statements with a delay between, this is great for most cases.
would you translate that into simple Texan?
in0timer := 0 #> ++in0timer <# posx
the #> and <# part?
#> and <# are clamping the value that it is in between both given values
in long form this does the following:
in0timer := in0timer + 1
if in0timer<0 then in0timer := 0
if in0timer>posx then in0timer := posx
Mike
Looks like:
Pull-up resistor switched to ground for buttons?
negx and posx look like constants.
Limits of how long the button is pressed, or released.
Jon? What are those limits - normally?
Debounce and auto-repeat, short press - long press?
The problem is that in0timer can never be advanced past posx or negx because the value will roll over. Is this a problem in the application? No. This code gets called every millisecond. The value of posx is 2147483648 (2^31). That's a lot of milliseconds.
2147483648 milliseconds =
2147483. 648 seconds =
35791.394 minutes =
596.523 hours =
21.304 days
This code lives in a Halloween prop that will be powered down every day. Still, I will fix it and send it to my friend (who is installing it in Russia this week). This is the fix: By right-shifting the limits by one bit I cut them in half -- still WAY more range than will ever be seen in operation
In simple terms, in0timer will be positive when the button is pressed (it's an active-high input), or negative when the button is released. In the program we want a 25ms debounce for the trigger; we know we have this when in0timer is 25 or higher -- this triggers the event. We also want to force the user to release the trigger for 500ms before being able to run again. The code watches for -500 or less in in0timer before allowing another activation. This code works here because there is no auto-repeat desired; that takes different code (yes, I've done it).
Mike
It would generally be called from a "foreground" loop like this: Note that the button input code will advance the timer is the timer value is negative (hold-off/repeat delay) or the button is pressed. If the button is released and the value is positive, the timer will be cleared. The key is to detect a press and then set the timer to a negative value that is the desired delay between repeats. No, this code doesn't allow the user to release to button when the repeat delay is active -- though that would be very easy to code.
Thanks, Jon.
That is sort of like Jon's in that it uses a timer.
Jon, The limits in your code could be constant(posx-1) and constant(negx+1) instead of the shifts, if it ever matters. The code I just posted will do weird things too if the button is stuck high.