Shop OBEX P1 Docs P2 Docs Learn Events
How to loop exactly 1 second? — Parallax Forums

How to loop exactly 1 second?

william chanwilliam chan Posts: 1,326
edited 2008-03-03 18:38 in Propeller 1
Hi,

I need a loop that updates the second and blinks one LED accurately.

My code

dira[noparse][[/noparse]led_pin]~~ 'Set I/O pin to output direction

repeat
rtcsecs++ ' Increment RTC time
if rtcsecs > 59
rtcsecs := 0
rtcmins++
!outa[noparse][[/noparse]led_pin] ' Toggle I/O Pin
waitcnt(clkfreq + cnt) ' Delay 1 sec cycles

I know this code will run a bit slower than real time.
How do I make it loop exactly 1 second per loop?

Thanks.

▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
www.fd.com.my
www.mercedes.com.my

Comments

  • Mike GreenMike Green Posts: 23,101
    edited 2008-03-03 03:48
    The best way to do this is to use the system clock as a reference point as described in the manual:
    time = cnt
    repeat
       rtcsecs++
       ' ...
       waitcnt(time += clkfreq)
    


    This way the WAITCNT always waits for exactly one second from the last wait regardless of what has to be done after the wait.

    Post Edited (Mike Green) : 3/3/2008 4:06:23 AM GMT
  • LawsonLawson Posts: 870
    edited 2008-03-03 03:59
    The trick for rock solid timing is in how you use Waitcnt. First, grab the value of CNT exactly once, then add a constant offset to it so that the time your code is going to wait for is still in the future once your code gets to the waitcnt. Add "mark := cnt + 2000" before the 'repeat' for example. Next, replace "waitcnt(clkfreq + cnt)" with "waitcnt(mark)". Finally add "mark += clkfreq" right after the waitcnt. With this setup Waitcnt is always waiting for a pre-calculated time to arrive and all code delays are rolled into the next wait.

    I personally like separating the pacing section of a loop from the logic sections. This makes it easier to add other functions into the scan/timing loop. (a good reason to count 1/100th of a second [noparse]:)[/noparse] )

    Marty

    p.s. Mike posted a shorter way of doing the same thing above. He must've been programming is something other than spin recently 'cause ":=" is the assignment operator in spin, "=" is a conditional only nono.giftongue.gif

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Lunch cures all problems! have you had lunch?

    Post Edited (Lawson) : 3/3/2008 4:05:17 AM GMT
  • Mike GreenMike Green Posts: 23,101
    edited 2008-03-03 04:05
    Ah, caught me! I'd been doing some work in PBasic. The conditional though is "==".
  • JavalinJavalin Posts: 892
    edited 2008-03-03 16:41
    Or if you don't want to use a cog just to blink an LED....
  • Paul BakerPaul Baker Posts: 6,351
    edited 2008-03-03 17:20
    Well technically that still uses a cog (just doesn't spawn a new one). Good to see people starting to use the template.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Paul Baker
    Propeller Applications Engineer

    Parallax, Inc.
  • JavalinJavalin Posts: 892
    edited 2008-03-03 17:35
    >Well technically that still uses a cog
    Yes - just you can do other things too.

    Perhaps I should of said "Or another option would be..." - my post sounds a bit like Mike bashing....

    J
  • Beau SchwabeBeau Schwabe Posts: 6,560
    edited 2008-03-03 17:47
    You could get "fancy" and just set one of the Counters to oscillate at 1Hz.

    That way you would have the COG free to do whatever else you wanted to do as long as you didn't use that counter for anything else.

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

    IC Layout Engineer
    Parallax, Inc.
  • deSilvadeSilva Posts: 2,967
    edited 2008-03-03 18:38
    It might also be helpful to study this example, alas posted in the wrong context some time ago:
    '' Taking two (unused) timers to make a true long term clock (some 100 years)
    '  As devised and re-devised "from time to time" by Ariba, deSilva and PhiPi 
    CON
      commPin = 0      'unused Pin ?  
    
    PUB main   | oldTimerValue
    
        setupTimer
    
        REPEAT
          IF PHSB<>oldTimerValue
             oldTimerValue  := PHSB
    
             ' do what you like here, or check the commPin for any sync needed
    
    PRI setupTimer
    ' advantage: an LED at comPin can be used to show the second (even withou a resistor) 
     ctra := %00100<<26  + commPin       ' Set NCO mode i.e. toggle per 25 sec
     frqa := POSX/CLKFREQ*2              ' one second
     ctrb := %01010<<26  + commPin       ' set ctrb to POSEDGE detect
     frqb := 1
     dira[noparse][[/noparse]commPin] := 1
    
    PRI setupAltTimer
    ' just to exercise some other modes
     ctra := %00110<<26  + commPin       ' Set duty cycle i.e. once per 50 sec
     frqa := POSX/CLKFREQ*2              ' one second
     ctrb := %01000<<26  + commPin       ' set ctrb to POS detect
     frqb := 1
     dira[noparse][[/noparse]commPin] := 1
    
Sign In or Register to comment.