PDA

View Full Version : Looking to translate spin to PASM



turbosupra
04-07-2012, 06:08 PM
Hi,

I have a method (actually two) that are written in spin, they works well but they are too slow for what I need. Unfortunately they involve a lot of math and I'd like to add even more math, and from what I've read in the manual, PASM math/comparisons are pretty difficult for a PASM beginner.

Also I'm about to start trying to translate them to PASM and I'm used to troubleshooting with the PST, how do you debug PASM?





PUB calculateCrankRpm(localCrankPeriod) | elapsed

elapsed := -cnt

l_previousNum8 := l_previousNum7
l_previousNum7 := l_previousNum6
l_previousNum6 := l_previousNum5
l_previousNum5 := l_previousNum4
l_previousNum4 := l_previousNum3
l_previousNum3 := l_previousNum2
l_previousNum2 := l_current
l_current := localCrankPeriod


if (l_timeStampCrank == 0)
l_timeStampCrank := (cnt + clkfreq)

if (l_previousNum8 <> 0 and l_previousNum7 <> 0 and l_previousNum6 <> 0 and l_previousNum5 <> 0 and l_previousNum4 <> 0 and l_previousNum3 <> 0 and l_previousNum2 <> 0)
l_previous7average := ((l_previousNum8 + l_previousNum7 + l_previousNum6 + l_previousNum5 + l_previousNum4 + l_previousNum3 + l_previousNum2)/7)

if (((l_current/10)*100) > ((l_previous7average/10)* 110)) or (((l_current/10)*100) < ((l_previous7average/10)*90))
' GAP exists if current greater than 110% of average or current less than 90% of average

l_gapTimePrevious := l_gapTime
l_gapTime := cnt
l_current := l_previous7average

else



if (((clkfreq/l_current)*60)/36) < 200
pst.str(string("crap2"))
pst.char(13)

else

l_toothRpm := (((clkfreq/l_previous7average)*60)/36)

elapsed += cnt - 544





PUB calculateCamRpm(localCamPeriod)



if(localCamPeriod) <> 0 and l_pstReadCamWheel == 1
l_previousCam6 := l_previousCam5
l_previousCam5 := l_previousCam4
l_previousCam4 := l_previousCam3
l_previousCam3 := l_previousCam2
l_previousCam2 := l_currentCam
l_currentCam := localCamPeriod

{pst.dec(l_previousCam6) ' 2324128 ' 2323968 ' 4546304 ' 2324128
pst.char(13)
pst.dec(l_previousCam5) ' 2323968 ' 4546304 ' 2324128 ' 2323968
pst.char(13)
pst.dec(l_previousCam4) ' 4546304 ' 2324128 ' 2323968 ' 4546304
pst.char(13)
pst.dec(l_previousCam3) ' 2324128 ' 2323968 ' 4546304 ' 2324128
pst.char(13)
pst.dec(l_previousCam2) ' 2323968 ' 4546304 ' 2324128 ' 2323968
pst.char(13)
pst.dec(l_currentCam) ' 4546304 ' 2324128 ' 2323968 ' 4546304
pst.char(13)
pst.char(13)} '(average) ' 2768499 ' 3212934 ' 3212966

' 4546304 is 1.65% of 2768499 and 2323968 is 83% of 2768499
' 4546304 is 1.42% of 3212934 and 2323968 is 72% of 3212934
' 4546304 is 1.42% of 3212966 and 2323968 is 72% of 3212966

if l_previousCam6 <> 0 and l_previousCam5 <> 0 and l_previousCam4 <> 0 and l_previousCam3 <> 0 and l_previousCam2 <> 0

l_CamToothAverage := ((l_previousCam6+l_previousCam5+l_previousCam4+l_p reviousCam3+l_previousCam2/5))
'if (((l_currentCam/10)*100) =< ((l_CamToothAverage/10)*105)) and (((l_currentCam/10)*100) => ((l_CamToothAverage/10)*95))
if (((l_currentCam/10)*100) =< ((l_CamToothAverage/10)*170)) or (((l_currentCam/10)*100) => ((l_CamToothAverage/10)*70))
'(768/10)*100 [7600] =< (3812614/10)*170 [40032405] or (768/10)*100 [7600] => (3812614/10)*95 [36219795]
' less than 105% of average or greater than 70% of average
' trigger1/(cba)
' c > b*1.1 and c > a*1.1
if((l_currentCam*100) > (l_previousCam2*110)) and ((l_currentCam*100) > (l_previousCam3*110)) and (l_trigger1 <> true)
if((l_previousCam2*100) < (l_previousCam3*105)) and ((l_previousCam2*100) > (l_previousCam3*95)) ' b < a*1.1 and b > a*.95
l_trigger1 := true
l_trigger2 := false
l_trigger3 := false


' trigger2/(acb)
' a*1.1 < c
if((l_currentCam*110) < (l_previousCam2*100)) and (l_trigger2 <> true)
if(((l_currentCam*100) < (l_previousCam3*105)) and ((l_currentCam*100) > (l_previousCam3*95))) ' a < b*1.05 and a > b*.95
if((l_previousCam2*100) > (l_previousCam3*110)) 'c > b*1.1
l_trigger2 := true
l_trigger3 := false
l_trigger1 := false


' trigger3/(bac)
' b < a*1.05 and b > a*.95 b*1.1 < c
if(((l_currentCam*100) < (l_previousCam2*105)) and ((l_currentCam*100) > (l_previousCam2*95))) and ((l_currentCam*110) < (l_previousCam3*100)) and (l_trigger3 <> true)
if((l_previousCam2*110) < (l_previousCam3*100)) ' a*1.1 < c
l_trigger3 := true
l_trigger1 := false
l_trigger2 := false


if(l_trigger3 == true)and(l_trigger1 == false)and(l_trigger2 == false)
l_calculatedCamRpm := (((clkfreq/((l_currentCam+l_previousCam2+l_previousCam3)/10))*120)/10) ' or ((((clkfreq/1+2+3)*10)*120)/10)
l_trigger3 := false

else

l_currentCam := l_CamToothAverage

JonnyMac
04-07-2012, 06:50 PM
I doubt it's the calculations that are the problem; the real timing crunch is coming from sending serial data from that method. What I tend to do is create a debugging cog that runs serial output autonomously, picking up values from the global space to output. This way the methods I'm running are just doing math, not waiting on serial output.

turbosupra
04-07-2012, 07:30 PM
Ok, over the last hour I've tried to translate the first method into PASM

I'm not sure how to do the math, so my code does not compile because the compiler tells me my compare math is exceeding the registers 9 bits (511) storage location . Are you able to use operators in PASM like you can in spin?

I also do not see a way to have clkfreq in PASM, although I'm sure there is a way, I used 80000000 temporarily instead.

How bad does this PASM code look? *hides behind rock* :)



DAT


org 0

frcntr mov tmp1, par ' * start of structure, passes an address to the value par represents and copies that address to tmp1
rdlong tmp2, tmp1 ' * get beginning variable address location, copy into tmp2


start

mov previousNum8, previousNum7 ' l_previousNum8 := l_previousNum7
mov previousNum7, previousNum6 ' l_previousNum7 := l_previousNum6
mov previousNum6, previousNum5 ' l_previousNum6 := l_previousNum5
mov previousNum5, previousNum4 ' l_previousNum5 := l_previousNum4
mov previousNum4, previousNum3 ' l_previousNum4 := l_previousNum3
mov previousNum3, previousNum2 ' l_previousNum3 := l_previousNum2
mov previousNum2, current ' l_previousNum2 := l_current
mov current, jmfreqperiod ' l_current := localCrankPeriod

cmp previousNum8, #0 WZ, WC ' z=0, c=0 l_previousNum8 <> 0
IF_NC_AND_NZ jmp #seven
IF_C_OR_Z jmp #start

seven
cmp previousNum7, #0 WZ, WC ' z=0, c=0 l_previousNum7 <> 0
IF_NC_AND_NZ jmp #six
IF_C_OR_Z jmp #start

six
cmp previousNum6, #0 WZ, WC ' z=0, c=0 l_previousNum6 <> 0
IF_NC_AND_NZ jmp #five
IF_C_OR_Z jmp #start

five
cmp previousNum5, #0 WZ, WC ' z=0, c=0 l_previousNum5 <> 0
IF_NC_AND_NZ jmp #four
IF_C_OR_Z jmp #start

four
cmp previousNum4, #0 WZ, WC ' z=0, c=0 l_previousNum4 <> 0
IF_NC_AND_NZ jmp #three
IF_C_OR_Z jmp #start

three
cmp previousNum3, #0 WZ, WC ' z=0, c=0 l_previousNum3 <> 0
IF_NC_AND_NZ jmp #two
IF_C_OR_Z jmp #start

two
cmp previousNum2, #0 WZ, WC ' z=0, c=0 l_previousNum2 <> 0
IF_NC_AND_NZ jmp #sevenAvg
IF_C_OR_Z jmp #start


sevenAvg

add previous7Avg, previousNum8 ' l_previous7average + l_previousNum8
add previous7Avg, previousNum7 ' l_previous7average + l_previousNum7
add previous7Avg, previousNum6 ' l_previous7average + l_previousNum6
add previous7Avg, previousNum5 ' l_previous7average + l_previousNum5
add previous7Avg, previousNum4 ' l_previous7average + l_previousNum4
add previous7Avg, previousNum3 ' l_previous7average + l_previousNum3
add previous7Avg, previousNum2 ' l_previous7average + l_previousNum2
mov previous7Avg, (previous7Avg/7) ' l_previous7average := (l_previous7average/7)

'cmp ((current/10)*100), ((previous7Avg/10)*110) WZ, WC ' check for gap/to see if current is greater than 110% of average
IF_BE jmp #greaterThan90 ' jump to see if it is greater than 90% of average
IF_A jmp #gap ' gap detected, jump to gap

greaterThan90
cmp ((current/10)*100), ((previous7Avg/10)*90) ' check for gap/to see if current is greater than 110% of average
IF_AE jmp #notGap ' it is smaller than 110% of avg and greater than 90% of avg, not a gap, go to notGap
IF_B jmp #gap ' gap detected, jump to gap

gap
mov gapPreviousTime, gapTime ' this is to keep track of time
mov gapTime, cnt ' this is to keep track of time

notGap
'cmp (((80000000/current)*60)/36), #200'if (((clkfreq/l_current)*60)/36) < 200
IF_BE jmp #start ' if below 200, restart
'IF_A mov toothRpm, (((80000000/previous7Avg)*60)/36)'l_toothRpm := (((clkfreq/l_previous7average)*60)/36)



' --------------------------------------------------------------------------------------------------



current long 0
previousNum2 long 0
previousNum3 long 0
previousNum4 long 0
previousNum5 long 0
previousNum6 long 0
previousNum7 long 0
previousNum8 long 0
previous7Avg long 0
jmfreqperiod long 0 ' jmfreqperiod is a place holder for a value from another cog, I don't know how to pass that yet

gapPreviousTime long 0
gapTime long 0

toothRpm long 0



tmp1 res 1
tmp2 res 1

mask res 1 ' mask for frequency input pin



fit 492

turbosupra
04-07-2012, 07:35 PM
Hi Jon,

Although you are probably right, I only left that PST code in there because it had table data that I needed to reference, I am not using that to send debug data to the PST. I am actually using this method below (in its own cog) for that, which I believe is similar to the way you are describing that you debug.



PUB com | timeStamp

pst.Start(115_200)
pst.Clear
pst.str(string("Start"))
pst.Str(String(pst#NL))

initScreen

l_updateRateDenominator := 2000

timeStamp := cnt

repeat

if((cnt-timeStamp) > (clkfreq/l_updateRateDenominator))

timeStamp := cnt
pst.Dec(l_toothGapRpm)
pst.char(13)
pst.str(string("crank: "))
pst.Dec(l_toothRpm)
pst.char(13)
pst.str(string("cam: "))
pst.Dec(l_calculatedCamRpm)
pst.char(13)

if (l_CntPeakRead == false)
pst.dec(l_CntPeak)
pst.char(13)
pst.dec(cnt)
pst.char(13)
l_CntPeakRead := true
l_CntPeak := 0

else
pst.str(string("read"))
pst.char(13)

pst.str(@b_waitingToBeParsed)
pst.char(13)
pst.char(13)



if (l_sendAllValuesOnce == 1)
if(cnt > (timeStamp + (clkfreq/l_updateRateDenominator)))
sendValues
l_sendAllValuesOnce := 0

if (l_sendAllValues == 1)
sendValues

l_myReceivedByte := pst.RxCheck

if l_myReceivedByte <> -1
b_waitingToBeParsed[b_byteMoveIndex++] := l_myReceivedByte

pst.str(@b_waitingToBeParsed)
pst.str(string(pst#NL))

if l_myReceivedByte == 13
DelimiterFinder(@b_waitingToBeParsed)
ByteFill(@b_waitingToBeParsed, 0, strsize(@b_waitingToBeParsed))
b_byteMoveIndex := 0





I doubt it's the calculations that are the problem; the real timing crunch is coming from sending serial data from that method. What I tend to do is create a debugging cog that runs serial output autonomously, picking up values from the global space to output. This way the methods I'm running are just doing math, not waiting on serial output.

Phil Pilgrim (PhiPi)
04-07-2012, 07:46 PM
There are some things you can do to make your Spin code more efficient. For example, this code



l_previousNum8 := l_previousNum7
l_previousNum7 := l_previousNum6
l_previousNum6 := l_previousNum5
l_previousNum5 := l_previousNum4
l_previousNum4 := l_previousNum3
l_previousNum3 := l_previousNum2
l_previousNum2 := l_current
l_current := localCrankPeriod


collapses neatly into



movelong(@l_previousNum2, @l_current, 7)
l_current := localCrankPeriod

assuming those variables are longs, are declared thus, and in this order:


VAR

long l_current, l_previousNum2, l_previousNum3, l_previousNum4, l_previousNum5, l_previousNum6, l_previousNum7, l_previousNum8

The Spin compiler makes sure that the move is done in the correct order to avoid toe-stepping when the ranges overlap.

Also, the "<> 0" in this if statement is redundant:



if l_previousCam6 <> 0 and l_previousCam5 <> 0 and l_previousCam4 <> 0 and l_previousCam3 <> 0 and l_previousCam2 <> 0

The ands take care of that for you.

Also, doing 32-bit multiplies and divides in PASM won't save you that much time, since the Spin byte-code interpreter does them in assembly anyway. However, you could save time is by hard-coding the multiplications by constants using predetermined shifts and adds.

-Phil

Mike Green
04-07-2012, 07:47 PM
CLKFREQ is the long in location zero. If you want a binary fraction of that, it's easy in assembly, just do a SHR on a copy of it. If you want a decimal fraction or something more complicated, compute it in Spin and store it into the assembly code DAT section before you do the COGNEW on it.

turbosupra
04-07-2012, 07:54 PM
Also, to give some example code of what I'm monitoring/working with, I'm able to perfectly replicate my cars cam and crank trigger sensors now on the propscope, with the code below. Worst case scenario has 9000 events per second or 1 event every 8888 clkcyles at clkfreq = 80,000,000. I have to do a fair amount of math inside of this window.


cognew(simulateCamWheel(2, 15000, 2, 72, 72, 159, 19), @simulateCamWheelstack) (pin, rpm, cam rotations:crank rotations ratio, degrees from 0 degrees, degrees from first trigger, degrees from second trigger, actual metal trigger width in degrees)
cognew(simulateCrankWheel(4, 36, 2, 15000), @simulateCrankWheelStack) (pin, total teeth, missing teeth, rpm)



PUB simulateCamWheel(simCamWheelPinNum, engineRPM, crankRotsToCamRots, degreeOfTrigger1, degreeOfTrigger2, degreeOfTrigger3, camTriggerDegreeWidth) | localIndex1, crankRpmPerSecond, camRpmPerSecond, localCnt, trigger1Wait, trigger2Wait, trigger3Wait, emtpySpace1Wait, emtpySpace2Wait, emtpySpace3Wait, cyclesPerDegOfRot


dira[simCamWheelPinNum]~~
outa[simCamWheelPinNum]~
localIndex1 := 0

crankRpmPerSecond := (engineRPM/60) ' 166.667 crank rots per second at 10k rpm
camRpmPerSecond := (((engineRPM*10)/60)/2) ' 83.333 cam rots per second at 10k rpm
cyclesPerDegOfRot := (((clkfreq/camRpmPerSecond)/360)*10) ' 960000/360 at 10k or 2660

trigger1Wait := (camTriggerDegreeWidth*cyclesPerDegOfRot) ' 13300 / 5 degrees
trigger2Wait := (camTriggerDegreeWidth*cyclesPerDegOfRot) ' 13300 / 5 degrees
trigger3Wait := (camTriggerDegreeWidth*cyclesPerDegOfRot) ' 13300 / 5 degrees
emtpySpace1Wait := (degreeOfTrigger1*cyclesPerDegOfRot) ' 266000 / 100 degrees
emtpySpace2Wait := (degreeOfTrigger2*cyclesPerDegOfRot) ' 266000 / 100 degrees
emtpySpace3Wait := (degreeOfTrigger3*cyclesPerDegOfRot) ' 385700 / 145 degrees
' + = 957600 (((clkfreq/957600) * 60sec/min) * 2rots campercrank) = 10krpm

localCnt := cnt

repeat

outa[simCamWheelPinNum]~~
waitcnt(localCnt += trigger1Wait) ' 6665
outa[simCamWheelPinNum]~
'waitcnt(localCnt += (clkfreq/521)) ' 160000-6665
waitcnt(localCnt += emtpySpace1Wait)
outa[simCamWheelPinNum]~~
waitcnt(localCnt += trigger2Wait) ' 6665
outa[simCamWheelPinNum]~
'waitcnt(localCnt += (clkfreq/521)) ' 160000-6665
waitcnt(localCnt += emtpySpace2Wait)
outa[simCamWheelPinNum]~~
waitcnt(localCnt += trigger3Wait) ' 6665
outa[simCamWheelPinNum]~
'waitcnt(localCnt += (clkfreq/521)) ' 160000-6665
waitcnt(localCnt += emtpySpace3Wait)






PUB simulateCrankWheel(simCrankWheelPinNum, crankTeethSimToothCnt, crankTeethSimMissingToothCnt, crankTeethSimRPM) | localIndex, waitTime, logicHighWaitTime, logicLowWaitTime, logicHighGapWaitTime, logicLowGapWaitTime, startCnt, existingTeeth



' Initialize variables here
dira[simCrankWheelPinNum]~~
outa[simCrankWheelPinNum]~
localIndex := 0
waitTime := (clkfreq/((crankTeethSimRPM*(crankTeethSimToothCnt*2))/60)) ' for 1500rpm = 44444
logicHighWaitTime := ((waitTime/50)*45)
logicLowWaitTime := ((waitTime/50)*55)
logicHighGapWaitTime := ((((waitTime*6)/100)*43)-logicHighWaitTime) ' this percentage can be measured by a prop scope and a signal capture
logicLowGapWaitTime := ((((waitTime*6)/100)*57)-logicLowWaitTime)
existingTeeth := (crankTeethSimToothCnt - crankTeethSimMissingToothCnt)

startCnt := cnt

{ctra := (%00100 << 26) | simCrankWheelPinNum ' setup counter for pin
frqa := 1 ' this makes the cnt screw up every 26 seconds
phsa := 0}

{
This is for a Hall effect signal/sensor simulation
For 1000rpms on a 36-2 crank trigger wheel, it'd be (1000(36*2)) = 72000, then 72000/60 = 1200 teeth on/teeth off per clkfreq. 80000000(clkfreq)/1200 =
a tooth on or tooth off every 133333.3 clk cycles. It would be on for 66666.67 clk cycles and then was off for every 66666.67 clk cycles
So you'd loop on for 66666.67 cycles and then off for 66666.67 cycles and after 34 times, you'd wait for 66666.67 cycles * 4, to simulate the 2
missing teeth on and accompanying 2 "missing" teeth off (or gaps in between each tooth) . It should account for 2 missing teeth and 3 missing toothgaps
An example to start the method would be simulateCamWheel(7, 3, 105, 100)
}


repeat

repeat localIndex from 1 to (existingTeeth) ' loop number of physical teeth on and off
outa[simCrankWheelPinNum]~~
'l_crankTeethSimOn := startCnt
waitcnt(startCnt += logicHighWaitTime) ' on for 1 tooth
outa[simCrankWheelPinNum]~
'l_crankTeethSimOff := startCnt
waitcnt(startCnt += logicLowWaitTime) ' off for 1 tooth


repeat localIndex from 1 to 1'(crankTeethSimMissingToothCnt) ' loop number of times for each missing tooth
outa[simCrankWheelPinNum]~
'l_crankTeethSimOff := startCnt
waitcnt(startCnt += logicLowGapWaitTime) ' off for 57% of 2 teeth
outa[simCrankWheelPinNum]~~
'l_crankTeethSimOff := startCnt
waitcnt(startCnt += logicHighGapWaitTime) ' on for 43% of 2 teeth

turbosupra
04-07-2012, 08:00 PM
Thanks for the replies

@Phil

Can you explain why the below saves time, and if there is a way to estimate how much time it does save? I will incorporate your time savings into my code now.


longmove(@l_previousNum2, @l_current, 7)
l_current := localCrankPeriod


Also, if I remove the <>, couldn't it run through the code if just one value wasn't equal to 0, because then the sum would not then equal 0? I need to check and make sure they are not equal to 0 individually, to make sure I have cycled through 7 times and there are 7 different values.

turbosupra
04-07-2012, 09:43 PM
Another question ... How do you fix this line of code so it does not generate the error "cannot exceed $1FF" ? Isn't there a way to do mov or cmp with more than 9 bits of data?



cmp ((current/10)*100), ((previous7Avg/10)*110) WZ, WC

Phil Pilgrim (PhiPi)
04-07-2012, 11:01 PM
Can you explain why the below saves time ...
It saves time because the Spin byte-code interpreter executes the entire move in assembly, rather than interpreting each assignment separately. You can use cnt before and after a block of code to measure how much time it takes.


Also, if I remove the <>, couldn't it run through the code if just one value wasn't equal to 0, because then the sum would not then equal 0?
No. The logical and operator does not operate bitwise like the "&" operator does. Each of and's operands is deemed to be "true" if it's non-zero.

-Phil

turbosupra
04-08-2012, 12:52 AM
Thank you, I have this as part of my code now and I believe it still isn't fast enough, my com cog should be reading ~ 320000 cycles all the time, but sometimes it reads ~ 650000 ~ 970000 or even ~ 1280000, which means it is missing events. Also thanks for the explanation about longmove, that is cool, I did not know that.

I have the loop taking 27888 to 33216 cycles from start to end (more 33216 then 25056) and I need it to happen (this is worst case of course) in less than 8888 or even 1/2 that if I use cog stopping commands like waitpeq. I'm looking for a second and third opinion though ... What do you all think?

In case you were curious, when I was using the := way of transferring variable values, method time was either 25056 or 30384, so your long move saves me 2832 cycles :)

The <> part of the code saves me an additional 1920 cycles at 23136 or 28464.

I removed one of the if statements just to time it [if (((clkfreq/l_current)*60)/36) < 200] ... should that take 3696 cycles?





longmove(@l_previousNum2, @l_current, 7)
l_current := localCrankPeriod

if (l_timeStampCrank == 0)
l_timeStampCrank := (cnt + clkfreq)

if (l_previousNum8 <> 0 and l_previousNum7 <> 0 and l_previousNum6 <> 0 and l_previousNum5 <> 0 and l_previousNum4 <> 0 and l_previousNum3 <> 0 and l_previousNum2 <> 0)
l_previous7average := ((l_previousNum8 + l_previousNum7 + l_previousNum6 + l_previousNum5 + l_previousNum4 + l_previousNum3 + l_previousNum2)/7)

Phil Pilgrim (PhiPi)
04-08-2012, 01:38 AM
Unless you really need the truncation resulting from the divide, why not change



if (((clkfreq/l_current)*60)/36) < 200


to



if (clkfreq < 120 * l_current)



or, better yet,



factor := clkfreq / 120 'Way at the beginning of your program.
...
if (factor < l_current)


clkfreq may not be evenly-divisible by 120, but it may not matter.

-Phil

turbosupra
04-08-2012, 02:04 AM
The math doesn't work out that way, for example at 15000rpm, l_current would be 8888

if (((clkfreq/l_current)*60)/36) < 200 is the same as 15000 < 200

if (clkfreq < 120 * l_current) is the same as 80000000 < 1066560

Maybe I'm missing something?




I guess more importantly though, is it normal for that operation to take 3600 cycles? And is my loop time math correct from the post quoted below?



Also, to give some example code of what I'm monitoring/working with, I'm able to perfectly replicate my cars cam and crank trigger sensors now on the propscope, with the code below. Worst case scenario has 9000 events per second or 1 event every 8888 clkcyles at clkfreq = 80,000,000. I have to do a fair amount of math inside of this window.


cognew(simulateCamWheel(2, 15000, 2, 72, 72, 159, 19), @simulateCamWheelstack) (pin, rpm, cam rotations:crank rotations ratio, degrees from 0 degrees, degrees from first trigger, degrees from second trigger, actual metal trigger width in degrees)
cognew(simulateCrankWheel(4, 36, 2, 15000), @simulateCrankWheelStack) (pin, total teeth, missing teeth, rpm)

Phil Pilgrim (PhiPi)
04-08-2012, 02:30 AM
The math doesn't work out that way, for example at 15000rpm, l_current would be 8888

if (((clkfreq/l_current)*60)/36) < 200 is the same as 15000 < 200

if (clkfreq < 120 * l_current) is the same as 80000000 < 1066560

Maybe I'm missing something?

Yes, you are. :) Both statements, given your example figures, are false, are they not? The important thing to consider is where the threshold is located. In the first case, it will be where


(((clkfreq/l_current)*60)/36) == 200

But, by working though the algebra, that's the very same thing as saying


clkfreq == 200 * 36 / 60 * i_current == 120 * l_current

-Phil

turbosupra
04-08-2012, 03:31 AM
I still don't understand :)

Ok, so if you did 180rpm, which it should be true
180rpm = 3 revolutions per second or 1 revolution every 26666666 clk cycles

if (clkfreq < 120 * l_current) or 80,000,000 < 3,199,999,920


But if you went to 240rpm, which should be false (but is true)
240rpm = 4 revolutions per second or 1 revolution every 20000000 clk cycles
if (clkfreq < 120 * l_current) or 80,000,000 < 2,400,000,000

I think it will evaluate to true until it is greater than 7200rpm or 1 revolution every 666666 clk cycles, when it should be evaluating to false at anything above 200rpm?



I am probably missing something still, so don't be insulted by the additional questions please, I'm asking again because I want to learn/understand.





Yes, you are. :) Both statements, given your example figures, are false, are they not? The important thing to consider is where the threshold is located. In the first case, it will be where


(((clkfreq/l_current)*60)/36) == 200

But, by working though the algebra, that's the very same thing as saying


clkfreq == 200 * 36 / 60 * i_current == 120 * l_current

-Phil

Phil Pilgrim (PhiPi)
04-08-2012, 04:11 AM
Well, check the math with your formula, then:


clkfreq / i_current * 60 / 36 < 200, with i_current == 20_000_000 (240 rpm)
80_000_000 / 20_000_000 * 60 / 36 == 6 (integer), which is less than 200

-Phil

turbosupra
04-08-2012, 04:51 AM
I've been at this all day and just need to sleep on it. I see my error now. Ugh!

240rpm = 1 tooth every 555555 cycles, and I originally did 4 revolutions and 26666666 which was wrong, sorry about that.
180rpm = 1 tooth every 740740 cycles

(clkfreq < 120 * l_current)
80000000 < 120 * 740740 = 80,000,000 < 88,888,800 - TRUE for 180rpm
80000000 < 120 * 555555 = 80,000,000 < 66,666,600 - FALSE for 240rpm

I appreciate your patience, thanks for sticking with me on this :D



Does spin have the speed to do calculations within 8888 clk cycles or possibly 1/2 that?