Shop OBEX P1 Docs P2 Docs Learn Events
Would this be accurate timeing??? — Parallax Forums

Would this be accurate timeing???

krazyideaskrazyideas Posts: 119
edited 2008-10-16 09:00 in Propeller 1
Hello,

Assuming that degree is equal to one degree of rotation,
and fire1 is how many degrees past zero I want pin 0 to turn on,
and win1 is how many degrees I want pin 0 to stay on before turning off,
and then I want pin 0 to stay off for the rest of the rotation (360) and then do the same thing indefinatly turning on and off at the same degrees every rotation.

Would this work and would it be accurate?? If not how could I make it more accurate and fast?? I know that doing all this in assembly code would make it faster, but I want to know if the idea or prencible would work??
I'm trying to get to a speed where this could be done accurately at a RPM of 1500 to 4000

Thanks so much


Pub Ffire1 | time
· time := cnt
· repeat
··· waitcnt(time += (degree * fire1))
··· !outa[noparse][[/noparse]0]··
··· waitcnt(time += (degree * win1))
··· !outa[noparse][[/noparse]0]
··· waitcnt(time += (degree * (360 - (fire1 + win1))))

Comments

  • JasonDorieJasonDorie Posts: 1,930
    edited 2008-10-16 06:42
    4000rpm = 66.6.. revolutions per second. If you wanted single-degree accuracy, that's only 24,000 'time comparisons' per second. Since the internals of the waitcnt instruction ARE in asm, after the overhead of issuing the instruction is done, it'll do the compare basically per-clock. Issuing the wait is in spin, so that's the only slow bit, and by slow, I mean roughly 400,000 'instructions' per second. In order, the multiply is one, the += is one,·the wait is another, and there's a couple just to pull the numbers in.

    Short version - Yeah, dead easy.

    Jason
  • StefanL38StefanL38 Posts: 2,292
    edited 2008-10-16 07:14
    the command !outa[noparse][[/noparse]0] INVERTS the state of the IO-PIN

    here an example how you can analyze what is going on by code instead of thinking
    I added debug-output to your code. the debuglines are more indented that it is easy to
    recognize your original code

    CON    
      _clkmode = xtal1 + pll16x
      _xinfreq = 5_000_000
    
    OBJ
      heart : "heartbeat"   'object from the obex that makes an LED blink for showing propeller-chip is alive and working
      Debug : "Extended_FDSerial" 'serial connection to PC       
    
    VAR
      long degree
      long fire1
      long win1
      
    Pub Ffire1 | time
      heart.Start(27,250) 'blinking LED on P27 with 2 Hz as Lifesignal of PropellerChip
      
      Debug.Start(31,30,0,115200) 'start(rxpin, txpin, mode, baudrate) :
      Debug.Str(string("START",13))
    
      degree := 1_000_000
      fire1 :=  60
      win1  := 120
      
      time := cnt
      repeat
            Debug.Str(string("outa[noparse][[/noparse]0]="))
            Debug.Dec(outa[noparse][[/noparse]0])
            Debug.Tx(13)
            Debug.Str(string("Start waitcnt(time += (degree * fire1))",13))
        waitcnt(time += (degree * fire1))
            Debug.Str(string("finished waitcnt(time += (degree * fire1))",13))
        !outa[noparse][[/noparse]0]  
            Debug.Str(string("new state outa[noparse][[/noparse]0]="))
            Debug.Dec(outa[noparse][[/noparse]0])
            Debug.Tx(13)
            Debug.Str(string("Start waitcnt(time += (degree * win1))",13))
        waitcnt(time += (degree * win1))
            Debug.Str(string("finished waitcnt(time += (degree * win1))",13))
        !outa[noparse][[/noparse]0]
            Debug.Str(string("new state outa[noparse][[/noparse]0]="))
            Debug.Dec(outa[noparse][[/noparse]0])
            Debug.Tx(13)
            Debug.Str(string("Start waitcnt(time += (degree * (360 - (fire1 + win1))))",13))
        waitcnt(time += (degree * (360 - (fire1 + win1))))
            Debug.Str(string("finished waitcnt(time += (degree * (360 - (fire1 + win1))))",13))
    
    



    from this you will get the output

    START
    outa[noparse][[/noparse]0]=0
    Start waitcnt(time += (degree * fire1))
    finished waitcnt(time += (degree * fire1))
    new state outa[noparse][[/noparse]0]=1
    Start waitcnt(time += (degree * win1))
    finished waitcnt(time += (degree * win1))
    new state outa[noparse][[/noparse]0]=0
    Start waitcnt(time += (degree * (360 - (fire1 + win1))))
    finished waitcnt(time += (degree * (360 - (fire1 + win1))))
    outa[noparse][[/noparse]0]=0
    Start waitcnt(time += (degree * fire1))
    finished waitcnt(time += (degree * fire1))
    new state outa[noparse][[/noparse]0]=1
    Start waitcnt(time += (degree * win1))
    finished waitcnt(time += (degree * win1))
    new state outa[noparse][[/noparse]0]=0
    Start waitcnt(time += (degree * (360 - (fire1 + win1))))
    
    



    outa[noparse][[/noparse]0] is low at the beginning and with this startpoint the logic levels are wrong inside the loop
    and the state is changed at the wrong times

    just switch it on BEFORE waiting fire1
    and off AFTER waiting fire1
    for switching ON/OFF use

      outa[noparse][[/noparse]0] := 1
      outa[noparse][[/noparse]0] := 0
    
    



    as this kind does an DEFINITE ON/OFF

      !outa[noparse][[/noparse]0] 
    
    



    INVERTS EVERY state whatever it is and therefore it might be the wrong state that is switched
    as long as you just want to blink on/off with the same time on/off this is OK otherwise it becomes unsecure

    as long as you don't have to do something special after turning off after fire1 and time win1
    it is not nescessary to wait for win1 as an extra command just wait for 360 - fire1 for the rest of the cycle

    then the code would look like this
    CON    
      _clkmode = xtal1 + pll16x
      _xinfreq = 5_000_000
    
    OBJ
      heart : "heartbeat"   'object from the obex that makes an LED blink for showing propeller-chip is alive and working
      Debug : "Extended_FDSerial" 'serial connection to PC       
    
    VAR
      long degree
      long fire1
      long win1
      
    Pub Ffire1 | time
      heart.Start(27,250) 'blinking LED on P27 with 2 Hz as Lifesignal of PropellerChip
      
      Debug.Start(31,30,0,115200) 'start(rxpin, txpin, mode, baudrate) :
      Debug.Str(string("START",13))
    
      degree := 1_000_000
      fire1 :=  60
      win1  := 120
      
      time := cnt
      repeat
        outa[noparse][[/noparse]0] := 1
            Debug.Str(string("outa[noparse][[/noparse]0]="))
            Debug.Dec(outa[noparse][[/noparse]0])
            Debug.Tx(13)
            Debug.Str(string("Start waitcnt(time += (degree * fire1))",13))
        waitcnt(time += (degree * fire1))
            Debug.Str(string("finished waitcnt(time += (degree * fire1))",13))
        outa[noparse][[/noparse]0] := 0  
            Debug.Str(string("new state outa[noparse][[/noparse]0]="))
            Debug.Dec(outa[noparse][[/noparse]0])
            Debug.Tx(13)
            Debug.Str(string("Start waitcnt(time += (degree * (360 - fire1)))",13))
        waitcnt(time += (degree * (360 - fire1)))
            Debug.Str(string("finished waitcnt(time += (degree * (360 - fire1)))",13))
    
    
    



    if this is accurate enough depends on the requirements of your application
    a SPIN waitcnt has a minimum of 385 microseconds if you want to wait shorter
    the systemcounter cnt will have run over the matchpoint before the SPIN-overhead-time
    and then you wait 53 seconds until the counter matches the value again AFTER a ROLLOVER to zero

    example with easy numbers

    waitcnt(200 + cnt)

    when cnt is "snapshotted" let's say the value is 1.000.000
    so your new value to match is 1.000.200
    before the REAL waitcnt command STARTS to wait the systemcounter will already be
    on 1.000.385 and then the counter goes on 2.000.000 and on 3.000.000 and on 4.000.000
    until 4.294.967.295 (four BILLIONS) wrap around to zero count up again to 1.000.200 which will take aprox 53 seconds at 80 MHz

    You can tweak the waitcnt commands by substracting a constant value which represents the execution time of the spin-commands
    there will stay a little jitter (time-varying) through the fact that the cog gets access to the hub only every 7-22 clockticks
    depending on the HUB-position when the cog WANTS to access HUB-RAM but has to wait until he gets access


    here I have a question too:

    if somebody can quickly write down how the overhead can be CALCULATED instead of measuring with an oscilloscope


    best regards

    Stefan
  • Cluso99Cluso99 Posts: 18,069
    edited 2008-10-16 07:20
    Download my debugger with the RamInterpreter option. Then run the code and it will give you the spin intruction count and the pasm instruction count. Add a small amount for the rd/wr to hub overhead.
  • StefanL38StefanL38 Posts: 2,292
    edited 2008-10-16 09:00
    Hello Cluso,

    thank you very much for pointing to your debugger.

    I made a search in the threads with the http://search.parallax.com searchengine
    there were a lot of hits and different versions

    Which one is the actual and best suited for this question?

    best regards

    Stefan
Sign In or Register to comment.