help with fractional timing issue
radialrandy
Posts: 78
in the program below im having problem with entering an rpm value that gets a fractional result of the dt := clkfreq/((rpm*100)/750). If the calculation gets a fractional result then I notice the square wave out put is not perfect. When I measure the counts between low to high transition I get some variance. but a good clean calculation has exact counts. is there a way to make the calculation round up or down?
Pub squarewave | dt, T, rpm
rpm := 1500
dira[15]~~
outa[15]~
dt := clkfreq/((rpm*100)/750)
T := cnt
repeat
T += dt
waitcnt(T)
!outa[15]
Pub squarewave | dt, T, rpm
rpm := 1500
dira[15]~~
outa[15]~
dt := clkfreq/((rpm*100)/750)
T := cnt
repeat
T += dt
waitcnt(T)
!outa[15]
Comments
Can you elaborate on the variance? Are you saying the clock cycle count is slightly different for each period or that the timing (measured externally) is not related to the frequency you want?
Also, what is your clock setup (_clkmode/_xinfreq)?
rpm1 81392
rpm2 81376
but if i enter good values in rpm that dont get a fractional result from the dt := calculation then I get perfect counts in rpm1 and rpm2
CON
_xinfreq = 5_000_000
_clkmode = xtal1 + pll16x '80MHz
tb = 1
shaft = 2
OBJ
Debug : "FullDuplexSerialPlus"
VAR
long a, b, c, rpm1, rpm2, rpmdiff
long stack[30]
PUB main
cognew(squarewave, @stack[20]) 'starts my test signal
repeat
waitpeq(|<tb,|<tb,0) 'waits for high on pin 1
waitpne(|<tb,|<tb,0) 'waits for low on pin 1
repeat
waitpne(|<shaft,|<shaft,0)
waitcnt(1000+cnt) 'debounce
waitpeq(|<shaft,|<shaft,0)
waitcnt(1000+cnt)
a := cnt 'sets a to cnt for first low to high
waitpne(|<shaft,|<shaft,0)
waitcnt(1000+cnt)
waitpeq(|<shaft,|<shaft,0)
waitcnt(1000+cnt)
b := cnt 'sets b to cnt for 2nd high to low
rpm1 := b-a 'calculates the counts between first 2 low to high transitions
a := b 'makes a = b and waits for the third count
waitpne(|<shaft,|<shaft,0)
waitcnt(1000+cnt)
waitpeq(|<shaft,|<shaft,0)
waitcnt(1000+cnt)
b := cnt 'sets b to cnt for the third low to high
c := b-a 'calculates the counts between the 2nd and 3rd low to high transitions
rpm2 := b-a 'measures the difference between the 2 count measurements
rpmdiff := rpm2 - rpm1
Dbug
Pub Dbug
Debug.start(31, 30, 0, 57600)
Waitcnt(clkfreq/4+ cnt)
Debug.tx(Debug#CLS)
Debug.str(String(13,"a= "))
debug.dec (a)
Debug.str(String(13,"b= "))
Debug.dec (b)
Debug.str(String(13,"c= "))
debug.dec (c)
Debug.str(String(13,"rpm1= "))
debug.dec (rpm1)
Debug.str(String(13,"rpm2= "))
debug.dec (rpm2)
Debug.str(String(13,"rpmdiff= "))
debug.dec (rpmdiff)
waitcnt(clkfreq/4+cnt)
Pub squarewave | dt, T, rpm
rpm := 14750 'putting values in rpm that get a fractional calculation in the dt formula
dira[15]~~ 'somehow makes the count values of the above program vary.
outa[15]~
dt := clkfreq/((rpm*10)/75)
T := cnt
repeat
T += dt
waitcnt(T)
!outa[15]
The difference/variance I see is +/-16 which looks suspiciously like hub window aliasing. All variable accesses in SPIN (e.g. a := cnt) are somehow locked to 16n system clocks (which is because variable a lives in hub RAM and is accessed from within the SPIN cog). The external pulse signal is effectively free running, waitpxx has single cycle resolution (i.e. conditions are checked every system cycle). So certain pulse widths are likely to be misaligned and over time drift into the next hub window. This doesn't necessarily mean that the pulse period varies, it's just that the edges are timed with lower granularity.
That's my observation. If you need higher accuracy you may have to get involved with PASM to remove the aliasing. Not sure how much of an issue this is for the intended purpose.
HTH
BTW, when you post code you should embed in [noparse] [/noparse] tags.
You can get timing resolutions to the resolution of the system clock in Spin by using the cog counters. Download and read the documentation in the application note on these (see AN001).
Let's put your timing errors in perspective, shall we? Your code hints that you will be measuring the RPMs of a physical shaft. The errors you're seeing are +/-0.2us. Say you've got a really high speed shaft, turning at 50,000RPM. That's 1200us per revolution. So your potential measurement error would be 0.2/1200 = .0167%. It will be even better at low speeds. Is it good enough for your application?
As Mike and Kuroneko pointed out, the 16-count bobble is due to the fact that you're using Spin, which is interpreted from the hub. Hub accesses add the timing uncertainty that you're seeing. If you were to write the code in PASM, that uncertainty would be reduced considerably. You might also be able to reduce it in Spin by measuring the period required by 16 pulses, say, and dividing the result by 16.
-Phil
Here's what I'm trying to do. I'm measureing time between every low to high pulse on a shaft. Then I'm calulating what rpm each pulse would be. from one pulse to the next im calculating the rpm per second rate on increase or decrease. So if im measuring a 15000 rpm shaft speed that has 4 magnets on the shaft and the rpm is rock solid at 15000. I should get a 0 rpm per second rate of increase or decrease. But with the +-16,32 variations then I get over 3000rpm per second increase or decrease even though the speed is 15000.
I'm fairly new at this and chose the propellor to learn. Am I wasting my time trying to learn the spin language? Should I just try to learn the assembly language?
thanks for helping me
As I've already said, you can reduce this error further by averaging over several pulse periods.
-Phil
80000 counts = 15000 rpm
79984 counts = 14997 rpm differnce of -16 counts
a difference of 3 rpm in .0009998 seconds
1/.0009998 = 1000.2 in a second scale
3rpm * 1000.2= 3000.06 rpm per second increase
the error is not as bad at lower rpms but it gets worse the higher the rpm gets. so a +-16 counts is throwing me way off.
-Phil
I've put over 20 hours into trying to make this work and everything I try still has the +-16,32 count errors. I have no idea how to use assembly language. I understand Spin but assembly language looks 1000X harder. I dont know where to start.
-Phil
Hey Phil
For the use than I'm needing this calculation I NEED to measure down to this accuracy (high pulse to high pulse). Measuring over many pulses will not work for this. To me this calculation seems like it should be simple for a microcontroller of this caliber. But its not looking that way yet. I though calculations like this would be a peice of cake for this microcontroller and thats why I chose it to try to learn. Does this count fluxuation not effect big complex programs? I'm so frusterated. I'm just begining and I already want to quit and go back to analog circuits:(
I'm on the same page with ya now! I can see how that would work perfect.
I was trying to think of how to use those counter.
Thanks alot Mike!
But try it and see what happens. We're here to help if it doesn't quite pan out the way you expect. And don't give up on the Propeller. It's more than capable of handling your app, once the mechanical limitations are determined.
-Phil
-Phil
FWIW, doing this gets you back to square one. A LOGIC:always counter shows the same side effects as using cnt. What you want - based on Mike's suggestion - is LOGIC:A (%11010) or LOGIC:!A (%10101).
Hey Phil
I tried this and set it up for the external signal. This setup is WAY worse than my original program. It has alot more cnt variance. I appreciate all your help but I think I've lost faith in this chip doing the things I want to do. Again thanks for trying.
Randy
I can't say I'm surprised by your results. Trust me on this: it's not the Propeller chip; it's your assumption that a mechanical process can possibly yield nanosecond repeatability. It just won't happen. Ever.
Now, please fill us in on your project and what your ultimate goals are. I know there's a solution that the Propeller is more than capable of abetting.
-Phil
once again thanks for all your help. I NEVER assumed a mechanical process to be that accurate or repeatable. I just wanted 100% accurate measurements that could measure how inconsistant a mechanical process is. However I did find a way to make this work that has me satisfied. I now have it setup on a sampling method that yields the results I wanted.
thanks for all your help:)