How to define a value when a button is pushed 1,2,3 time in a given period on time.

pef

New Member
Hi, I ask the question in the french forum,
but I think I have more chance to have an answer in english :)

then , I want to define a different value to a variable when a button is pushed 1,2,3 time in a given period on time ( 2 sec ?)

To explain a little,
Within 2 second,
If I click 1 time on my switch, a led flashes 3 times (value of B1 = 3 )
If I click 2 times, the same led flashes 10 times, (value of B1 = 10 )
If I click 3 times, the led flashes without stopping. (value of B1 = 20 )

Thx you.
 

lbenson

Senior Member
For instance:
Code:
#picaxe08M2

do
  do while pinC.4 = 1 : loop ' wait until off
  time = 0
  b4 = 0
  bit0 = pinC.4
  do while time < 2
    if pinC.4 <> bit0 then ' detect transition
      bit0 = pinC.4
      if bit0 = 1 then ' transition was to ON
        pause 10 ' debounce if needed, increase if needed
        inc b4 ' count of ON transitions
      endif
    endif
  loop
  select b4
    case 0
    case 1
    case 2
    case 3
    else
  endselect
loop
 

AllyCat

Senior Member
Hi,

There was a recent thread on a similar problem recently.

In this case you will need to wait a defined time after the button is released, to see if it is pressed again. Increment a counter (variable) if the button is pressed again within the time limit, or act on the present count if not. The "time" variable can be a good way to do this, but beware that "time" might increment from 0 to 1 almost immediately after time = 0 is commanded (ie not a full second later).

The number of flashes might be determined from a LOOKUP command, or by other software structures such as IF ... ELSEIF or CASE ... SELECT, etc..

Cheers, Alan.
 
Last edited:

lbenson

Senior Member
.. beware that "time" might increment from 0 to 1 almost immediately after time = 0 is commanded (ie not a full second later).
Does this imply that the M2 special variable, "time" is incremented based on a background timer which is not reset or adjusted by a "time = 0" command?

If so, you might use a sequence like this:
time = 0
do while time = 0 : loop ' until time becomes 1
do while time < 3 ' two seconds have passed

But you won't know exactly when your 2-second period begins.
 

hippy

Technical Support
Staff member
Rather than start a timer running and have the user push the button during that period, it will be more responsive and more flexible to have a timeout window in which further pushes can be accepted, reset the timeout window on each push. This is what AllyCat describes in post #3.

This was written and tested on 18M2 but should work for any PICAXE ...

Code:
#Picaxe 18M2
#Terminal 4800

Symbol BTN        = pinC.1 ; Button input pin
Symbol PUSHED     = 1      ; Button pushed level

Symbol MAX_PUSHES = 10     ; Maximum pushes to count

Symbol TIMEOUT_MS = 350    ; Period between presses
Symbol LOOP_MS    = 10     ; Loop time

Symbol counter    = b0
Symbol timeout    = b1

Symbol LOOP_COUNT = TIMEOUT_MS / LOOP_MS

Pause 2000
SerTxd( "Started...", CR, LF )
Do
   counter = 0
   timeout = 1
   Do
     If BTN Is PUSHED Then
       If timeout > 0 Then
         timeout = 0
         counter = counter + 1 Max MAX_PUSHES
       End If
     Else
       If counter > 0 Then
         Pause LOOP_MS
         timeout = timeout + 1
       End If
     End If     
   Loop Until timeout > LOOP_COUNT
   SerTxd( "Pushed ", #counter, " times", CR,LF )
Loop
 

AllyCat

Senior Member
Hi,

Does this imply that the M2 special variable, "time" is incremented based on a background timer which is not reset or adjusted by a "time = 0" command?
Yes, the time variable is incremensted by "ticks" from a prescaler which divides the internal "Timer 1" by 50 (Timer 1 iteslf divides an internal 1 MHz oscillator by 20,000). Timer 1 can be pre- or re-set, but sadly not the prescaler, so if you are "unlucky" and it has reached 49 when the time=0 is executed, then the time variable will rollover within 20 ms.

In some cases the easiest solution is to use ENABLETIME and DISABLETIME: Wait for time to increment and then execute a DISABLETIME and time = 0 (or copy the latest value). To start a timing interval, use ENABLETIME and then time will indicate an "accurate" elapsed (or differential) integer time.

Probably not an issue for this thread but also beware that some "blocking" commands can upset the incrementing of the time variable considerably. Sadly, using a higher SETFREQ doesn't help (except slightly at 32 MHz) because the prescaler is adjusted to retain mainly 1 second ticks as described here.

So for this application, it may be simplest to create a "custom" timer by putting (say) a PAUSE 95 within a polling/counting program loop (for ~100ms ticks).

Cheers, Alan.
 
Top