Time Delay in SPIN
Beavis3215
Posts: 229
in Propeller 1
If I can calculate a time delay required in milliseconds, how do I implement it. I think I have to convert it to clock ticks and use waitcnt(clockticks), but I'm not really sure. The attached code does not work but exemplifies what I'm trying to do. I'm pretty new with spin and am trying to learn from this Parallax book which doesn't have many examples. Any help would be appreciated.
Thanks
Thanks
Comments
Tom
https://parallax.com/sites/default/files/downloads/122-32305-PE-Kit-Labs-Fundamentals-Text-v1.2.pdf
This is a way to do it with one variable.
I'd start by converting ms to clock ticks to reduce the time performing calculations.
If you want the loop executed at least once.
Another way to do the same thing. (Well, almost the same thing. You could use "=>" instead of ">" to make it the same. I usually don't worry about a single clock tick.)
This sort of time comparisons only work for intervals less than half the rollover time or about 26 seconds at 80MHz.
I usually follow JonnyMac's example and use a constant for milliseconds rather than computing it at run time.
The above section of code is copied from one of Jon's programs. I don't like to use abbreviations so I changed the constant names to fit my coding style. I believe Jon used "MS_001" where I used "MILLISECONDS" and "US_001" where I used "MICROSECOND."
I copied the line "CLK_FREQ = ((_clkmode - xtal1) >> 6) * _xinfreq" from Jon's code but I've since seen this same line used in the "Clock.spin" object.
Jon wrote a Spin Zone article about keeping track of time with the Propeller. There are links to Jon's Spin Zone articles in the third post of my "index" (see my signature for a link). If my signature doesn't show up in this post, just an earlier post.
* Get rid of unnecessary inline calculations (these take time). See my post just above your for a clock-sensitive constant that you can replace clkfreq/1000 with
* Use waitpne(pinmask, pinmask, 0) instead of ina[pin] == 0; likewise with waitpeq for ina[pin] == 1
* If you're going to do an inline waitcnt, put cnt as the first element of the expression
Keep in mind that Spin instructions take a few microseconds each; it would be better to measure a short event like this:
I have used this many times. The elapsed time value is in system ticks; you can divide it by a constant to get microseconds.
Here's my idea of what your code should look like -- of course, it will still need tuning and, perhaps, conversion to PASM to be as precise as you may want it.
Correct.
Spin is too slow for single (or even a few) microsecond timing since a single spin instruction can take more than a microsecond to execute. For that you need PASM.
The 544 compensates for the cycles required for the two Spin instructions (starting and stopping the event timing. If you do this:
If you print elapsed you'll get zero; again, the - 544 compensates for the setup and conclusion of the timer.
Once you've measured something it ticks you can determine microseconds by dividing by US_001. Note that if you want to do an inline delay, the shortest you can do in Spin is about 45 microseconds.
I don't care if you're a beginner; I will treat you with the respect you deserve and give you the best possible code that I can. I try to write clean code that others can easily digest and learn from.
Does the 544 have anything to do with "doing something", or how many times you do Nothing or Something? It looks like from one of your examples the answer should be no. I think that I remember you helping me about 6 years ago in my SX days.:) When you say tuning above, what exactly do I adjust. I do have an oscilloscope that I use to monitor the cam rotational period and td.
See:
https://www.parallax.com/downloads/an001-propeller-p8x23a-counters
https://www.parallax.com/downloads/an009-code-execution-time-p8x32a
1) Wait for cam to go high
2) Wait for cam to go low, completing cam sync.
3) Wait for cam to go high, start timer during which cam goes low.
4) Wait for cam to go high, stop timer and record ms (time = time+ delay + duration)?
5) Start timer again during which cam goes low
6) Calculate delay using ms
7) Execute delay while still timing
8) Fire for duration while still timing
9) Reset coil
10) goto 4)
I think this can be solved by adding MS = MS + 7 * (waitcnt(cnt + TD * US_001)) after calculating MS. I'm doing 2 delays then starting the timer late by this much. Will delay and duration autoinitialize to zero on the first pass?
Will this approach work or is there a better way?
Also, it takes more work to deal with bytes and words as they need to be extracted from longs (Propeller's normal data size) by the interpreter. Shorter: For general vars, use longs.