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?