Pulse output and debouce without using pause on X2

oracacle

Senior Member
After recent posts in another thread, I got to thinking that after jumping through a few extra hoops, using a timer to allow for a sudo multi tasking situation could be achieved. It a little more granular than I am used to. Using the settimer instead of timer3 should be possible but i haven't has chance to look at that as yet.
It would be useful if maths could be done within an if statement but digress
The below code contains example running on a 20x2 flashing an LED at 1hz and PTM switch debounced without the use of the pause command.
One other thing to note is, I am not sure what will happen if call a goto within the debounce sequence, I can't remeber how the picaxe deal with leaving open ended if statements like that. I would advice trying to use gosubs instead if you need to call another piece of coe

Code:
#no_table
#terminal 9600
#picaxe 20x2
tmr3setup %10000001        'timer 3 on 20x2 enabled, no prescler
'with no prescaler timer3 will increment 32,768us or 33ms
'this mean the finest timing that can be had is 33ms plenty fast enough for debounce

symbol debounce     = 2         '2 cycles of the internal timer or 66ms, this will be the debounce time
symbol flash_time = 30         'should give around 1000ms
symbol last_flash = w2        'the time of last flash
symbol last_press = w3        'the time of the last buytton press
symbol temp_timer = w4        'temp word for calculating time difference
symbol led        = b0        'led pin
symbol sw3        = pinc.7    'button on this pin


main:
    'flash without pause
    temp_timer = timer3 - last_flash            'calculate difference between last flash and now
    if temp_timer > flash_time then            'check to see if it been longer
        toggle led
        last_flash = timer3                'update time of last flash
    end if
   
    'debounce without pause
    if sw3 = 1 then                    'check for input       
        temp_timer = timer3 - last_press        'calculate time since last press
        if temp_timer > debounce then            'check for debounce time exceeded
            'do stuff
            sertxd ("Button pressed",13,10)
        end if
        last_press = timer3                'update last press time
    end if
    goto main
you can alter the timing by changing tmr3setup prescailar or altering the debounce and flash values
I suggest reading the tmr3settup command to get a better understanding of that command, and thusly this code
tmr3setup - BASIC Commands - PICAXE

This timer can also be used to determine elapsed time privding you keep a record of when the even happend (wX = timer3) and do the obligtory maths (elapsed_time = timer3 - wX) and comparing that to the time you need.
 

PhilHornby

Senior Member
... allow for a sudo multi tasking
Pseudo? :)

Can you see any major advantages of this approach, over the use of the Button statement ?

In the past, I've used code like this :-

Rich (BB code):
            Setfreq M1                                ;;;Auto-repeat and debounce don't work well at high freq.
                                                      ;;;W0 used to time the loop.  
            For w0 = 0 To FiveSecondLoop              ;;;about 5 secs (only 256 at 1MHz)
                  Button SwitchUpPin,0,255,0,ButtonVar1,1,UpPressed ;UP Button pressed
                  Button SwitchDownPin,0,255,0,ButtonVar2,1,DownPressed ;DOWN Button pressed
                  Button SwitchOKPin,0,255,0,ButtonVar3,1,OKPressed ;OK pressed
                  ;
                  ; You could do useful work here.
                  ;
            Next w0
      
            Goto Timeout1                             ;;;5 secs without a press     
(It's part of an LCD menu-updating system)

The automatic handling of auto-repeat is great, but as you can see, I ran into problems until I lowered the clock speed. This was on a 20X2 and I didn't spend too long figuring out which speeds worked - but I know 64MHz didn't and 1MHz did.
 

oracacle

Senior Member
I'm not sure if the button command does it's own loops or runs through the entire programme, it's not something I have actually tested as yet. If doesn't execute the entire code then that could be an issue for other things that might be happening in the code.

As for clock speed the timer 3 method can be adjusted for whatever clock speed you need to work at. I'm at work ATM so don't have the numbers but I think @64mhz and no prescalar the on overflow happens every 5ms, so a difference of 10 should be used for a 50ms debounce.

The most obvious draw back the my method is the amount of variables that are used. Although some could be bytes instead of words

And yes I meant pseudo, think I might have been a little tired
 

oracacle

Senior Member
Using the same single timer to time two different events. One takes its timing from a button push, while the other takes its timing from the result of the button push. I haven't done any testing to check for accuracy and I am sure that other programme events will make a difference on how accuarte that timing is.
Overall the idea is to try and avoid using the pause command. However the probelm is, depening on what you need to achieve, is it can consume variables which there are a finite number of. The storage of the last event time should be done in a word varaible to enure compability with the timer3 variable.
I am aware that this system may use alot of variables, specialy if you have multiple events to keep track of, so use of the upper memory space should be considered.
I ahve also updated the button press sequence, it now take one less if statement.

Code:
#no_table
#terminal 9600
#picaxe 20x2
tmr3setup %10000001        'timer 3 on 20x2 enabled, no prescler
'with no prescaler timer3 will increment 32,768us or 33ms
'this mean the finest timing that can be had is 33ms plenty fast enough for debounce

symbol debounce     = 2         '2 cycles of the internal timer or 66ms, this will be the debounce time
symbol flash_time1 = 151    '~5000ms
symbol flash_time2 = 90        '~3000ms
symbol last_flash1 = w2        'the time of last flash
symbol last_flash2 = w4
symbol last_press = w3        'the time of the last buytton press
symbol temp_timer = w5        'temp word for calculating time difference
symbol led_1_bool = bit0
symbol led_2_bool = bit1
symbol led_1    = b.0        'led pin
Symbol led_2    = b.1
symbol sw3        = pinc.7    'button on this pin


main:
    'debounce without pause
    temp_timer = timer3 - last_press        'calculate time since last press
    if sw3 = 1 and temp_timer > debounce then                    'check for input        
        'do stuff
        sertxd ("Button pressed",13,10)
        High led_1
        last_flash1 = timer3
        led_1_bool = 1
        last_press = timer3                'update last press time
    end if
    
    'do useful stuff
    
    temp_timer = timer3 - last_flash1        'switch off LED 5000ms after last button press
    if temp_timer > flash_time1 and led_1_bool = 1 then
        low led_1
        last_flash2 = timer3
        led_2_bool = 1
        led_1_bool = 0
    end if
    
    'do other useful stuff
    
    temp_timer = timer3 - last_flash2        'toggle second LED 3000ms after first LED switches off
    if temp_timer > flash_time2 and led_2_bool = 1 then
        toggle led_2
        led_2_bool = 0
    end if
    
    'do other other useful stuff
    
    goto main
I think the next step is to investigate using settimer to trigger interrupt based pseudo multi tasking.
 
Top