Shop OBEX P1 Docs P2 Docs Learn Events
WAITCNT causing REPEAT block to only cycle twice. -also: budgeting clock cycles — Parallax Forums

WAITCNT causing REPEAT block to only cycle twice. -also: budgeting clock cycles

benben10benben10 Posts: 9
edited 2011-04-18 12:09 in Propeller 1
 
CON
   
  _clkmode = xtal1 + pll16x
  _xinfreq = 5_000_000
   

OBJ
   
  Debug: "FullDuplexSerial"
   
   
PUB TestMessages

  ''Send test messages to Parallax Serial Terminal.
 
  Debug.start(31, 30, 0, 57600)

  repeat
    waitcnt (1000)
    waitpeq (%00000000000000000000000000000000,%00000000100000000000000000000000,0)
    waitpeq (%00000000100000000000000000000000,%00000000100000000000000000000000,0)
    Debug.str(string("1", 13))

I have an infrared LED and infrared phototransistor from the PE propstick usb Kit on the proto board. When I point the LED at the phototransistor and then away, I get multiple "1"s on the terminal if i do not have the waitcnt. When I add the waitcnt to help filter some of the multiple hits, i will get two 1s at most and then no more responses. Am I missing something simple?

Comments

  • MagIO2MagIO2 Posts: 2,243
    edited 2011-04-17 22:58
    You have a missunderstanding of how waitcnt works. You don't give it a relative time for example something like waitms( 1000 ) in other programming languages would wait for one second (1000ms).
    The value you pass to waitcnt is an absolute value that the propeller internal counter named CNT has to reach until waitcnt continues. CNT is increased with each clock cycle. Depending on what the current value of CNT is when you call waitcnt 1000 you will have very different wait-times. Say CNT is 900 when calling waitcnt 1000 this waitcnt will only wait 100 clock cycles. If CNT is 1001 when calling the wait passed the exact match and will wait until CNT is back at 1000 again. This takes roundabout 50seconds.

    So, if you want to wait for a fixed time, you have to do
    waitcnt CNT + 1000

    If you want fixed periodes you need a helper variable
    timeToWaitFor = CNT
    repeat
    waitcnt timeToWaitFor+=1000
    ...
  • JasonDorieJasonDorie Posts: 1,930
    edited 2011-04-17 23:44
    It's also worth noting that in Spin, the overhead for the waitcnt function is about 400 cycles (it's very slightly less than that, but 400 is easy to remember), so it's generally a good idea to make sure you're waiting for at least that long, and you should always put the CNT parameter last, so it gets read as late as possible. For example:

    waitcnt( 1000 + cnt ) 'right way
    vs
    waitcnt( cnt + 1000 ) 'not wrong, but less safe - cnt is read first, then the 1000 is added, meaning more time will elapse before it actually starts to wait

    Welcome to the forums!
  • benben10benben10 Posts: 9
    edited 2011-04-18 09:49
    i feel like such a fool. 5 mins after posting this i finally realized what i was doing wrong.
  • benben10benben10 Posts: 9
    edited 2011-04-18 10:00
    also thanks jason for that info. that is definetly something worth knowing. im trying to build an optical rpm sensor that can handle up to about 2000 or 3000 samples per second ( so i can watch for variation within a single revolution) and was wondering if there is a table of how many cycles it takes to perform each command. i think i might be getting into the area where i will need to budget my cycles. i was thinking that maybe i need have one cog watching a pin which then tells other consecutive cogs to startup and send the value of CNT to the serial terminal.
  • JasonDorieJasonDorie Posts: 1,930
    edited 2011-04-18 12:09
    If it's important to know how long certain instructions take, just time them. You can test how long it takes to execute the code when the conditions are always met, and then use that info as a constant "offset". For example, you could write:
    StartTime := cnt
    waitpeq(0, $FFFFFFFF , 0)   'wait for all pins to be zero, but knowing they aren't, so this will fall through immediately
    EndTime := cnt
    TimeTaken := EndTime - StartTime
    

    So now you know how many cycles it takes for those instructions to execute. Whatever is left over is how long you actually spent waiting. So then, if you're waiting for a real event, like an optical trigger on an optical sensor, you can subtract the TimeTaken value from the answer you get and it'll be more accurate.

    You might also want to look at the FRQA & CNTA registers. It's possible to configure them to count pulses (rising or falling edge) from an external source (input pin). You can keep track of how much time elapsed since you last checked the counter, and how many pulses it got since then, and calculate your RPM value from that. And you won't need to dedicate a cog to it.

    For something that's rotating very slowly, counting how many cycles elapsed between pulses is going to give you a more accurate answer, so it depends on your needs. With a dedicated cog, 3000 samples per second isn't a challenge in spin. I would guess you could do 20KHz or better with no problem.
Sign In or Register to comment.