I would like help with coming up with some logic for making a method more dynamic
I have these two objects that start when their respective cogs start, and after that they are static. I have a third object that monitors the 2 frequencies generated by each one and compares them to each other. Right now they run and do not change once they are started (as far as how far one is offset from the other), staying at a constant frequency. I would like a way to vary the second method in reference to the first method, which will simulate real world conditions much more accurately. I do not need to vary the frequency, but I do need to shift the start time of each loop in the second code block back and forth, in reference to the the loop (tooth) count of the first code block.
Does anyone have any ideas on how to go about this? These methods work perfect as static spin methods, but I will try and rewrite them in PASM if I need to. I can't seem to envision a way to do this very well, so any help with that would be very appreciated. Thanks for reading.
Does anyone have any ideas on how to go about this? These methods work perfect as static spin methods, but I will try and rewrite them in PASM if I need to. I can't seem to envision a way to do this very well, so any help with that would be very appreciated. Thanks for reading.
PUB simulateCrankWheel(simCrankWheelPinNum, crankTeethSimToothCnt, crankTeethSimMissingToothCnt, crankTeethSimRPM, autoRangeRPM) | 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, for 600rpm = 111111, 5555 for 12000rpm
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]~~ ' high
waitcnt(startCnt += logicHighWaitTime) ' on for 1 tooth
outa[simCrankWheelPinNum]~ 'low
waitcnt(startCnt += logicLowWaitTime) ' off for 1 tooth
outa[simCrankWheelPinNum]~ ' low
waitcnt(startCnt += logicLowGapWaitTime) ' off for 57% of 2 teeth
outa[simCrankWheelPinNum]~~ ' high
waitcnt(startCnt += logicHighGapWaitTime) ' on for 43% of 2 teeth
PUB simulateCamWheel(simCamWheelPinNum, engineRPM, crankRotsToCamRots, degreeOfTrigger1, degreeOfTrigger2, degreeOfTrigger3, camTriggerDegreeWidth, autoRangeVVTI, degreeChangesPerSecond) | localIndex, crankRpmPerSecond, camRpmPerSecond, localCnt, trigger1Wait, trigger2Wait, trigger3Wait, emtpySpace1Wait, emtpySpace2Wait, emtpySpace3Wait, cyclesPerDegOfRot, toothWaitDelay, startTooth, autoRangeChangesPerSecond, advancing, retarding, degreesShifted, updateCnt
dira[simCamWheelPinNum]~~
outa[simCamWheelPinNum]~
localIndex := 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
toothWaitDelay := (clkfreq/(crankRpmPerSecond*36))
autoRangeChangesPerSecond := (clkfreq/degreeChangesPerSecond)
trigger1Wait := (camTriggerDegreeWidth*cyclesPerDegOfRot) ' 19 degrees
trigger2Wait := (camTriggerDegreeWidth*cyclesPerDegOfRot) ' 19 degrees
trigger3Wait := (camTriggerDegreeWidth*cyclesPerDegOfRot) ' 19 degrees
emtpySpace1Wait := (degreeOfTrigger1*cyclesPerDegOfRot) ' 72 degrees
emtpySpace2Wait := (degreeOfTrigger2*cyclesPerDegOfRot) ' 72 degrees
emtpySpace3Wait := (degreeOfTrigger3*cyclesPerDegOfRot) ' 159 degrees
startTooth := 26
localCnt := cnt
repeat
outa[simCamWheelPinNum]~~ ' pin high
waitcnt(localCnt += trigger1Wait) ' wait cnt time stamp plus trigger degree width in cycles
outa[simCamWheelPinNum]~ ' pin low
waitcnt(localCnt += emtpySpace1Wait) ' wait cnt time stamp plus first empty space degree width in cycles
outa[simCamWheelPinNum]~~ ' pin high
waitcnt(localCnt += trigger2Wait) ' wait cnt time stamp plus trigger degree width in cycles
outa[simCamWheelPinNum]~ ' pin low
waitcnt(localCnt += emtpySpace2Wait) ' wait cnt time stamp plus second empty space degree width in cycles
outa[simCamWheelPinNum]~~ ' pin high
waitcnt(localCnt += trigger3Wait) ' wait cnt time stamp plus trigger degree width in cycles
outa[simCamWheelPinNum]~ ' pin low
waitcnt(localCnt += emtpySpace3Wait) ' wait cnt time stamp plus third empty space degree width in cycles

Comments
You may not want this adjustment to be added to all the WAITCNTs, maybe just to a few of them depending on where you want to adjust the simulation. There'll always be a discontinuity somewhere that will take a few cycles to smooth out.
I've noticed at the slower frequencies (less than 3600hz for crank object/150hz for cam object) , the 2 objects don't clock exactly synced. What would you suggest to set this, or is this probably a code error, since they do clock exactly at higher speeds?
You're right, it is the values in waitcnt, at a certain speed the one loop (x2) takes 13709184, and the other 13791600 and they should both match. I did however get the values to jump back and forth as I want them to dynamically. I just now how to figure out a correction algorithm, it doesn't look like there is a rhyme or reason to the differences
PUB simulateCamWheel(simCamWheelPinNum, engineRPM, crankRotsToCamRots, degreeOfTrigger1, degreeOfTrigger2, degreeOfTrigger3, camTriggerDegreeWidth, autoRangeVVTI, degreeChangesPerSecond) | localIndex, crankRpmPerSecond, camRpmPerSecond, localCnt, trigger1Wait, trigger2Wait, trigger3Wait, emtpySpace1Wait, emtpySpace2Wait, emtpySpace3Wait, cyclesPerDegOfRot, toothWaitDelay, startTooth, autoRangeChangesPerSecond, advancing, retarding, degreesShifted, updateCnt, tenDeg, fiftyDeg, emtpySpace3WaitSansDelay, variableDelay, loopCnt, prevLoopCnt dira[simCamWheelPinNum]~~ outa[simCamWheelPinNum]~ localIndex := 0 camRpmPerSecond := (((engineRPM*100)/60)/2) ' 83.333 cam rots per second at 10k rpm cyclesPerDegOfRot := ((((clkfreq/camRpmPerSecond))*10/36))'0)*10) ' 960000/360 at 10k or 2660 autoRangeChangesPerSecond := (clkfreq/degreeChangesPerSecond) trigger1Wait := (camTriggerDegreeWidth*cyclesPerDegOfRot) ' 19 degrees trigger2Wait := (camTriggerDegreeWidth*cyclesPerDegOfRot) ' 19 degrees trigger3Wait := (camTriggerDegreeWidth*cyclesPerDegOfRot) ' 19 degrees emtpySpace1Wait := (degreeOfTrigger1*cyclesPerDegOfRot) ' 72 degrees emtpySpace2Wait := (degreeOfTrigger2*cyclesPerDegOfRot) ' 72 degrees emtpySpace3Wait := (degreeOfTrigger3*cyclesPerDegOfRot) ' 159 degrees tenDeg := (10*cyclesPerDegOfRot) 'emtpySpace3WaitSansDelay := (emtpySpace3Wait-tenDeg) fiftyDeg := (50*cyclesPerDegOfRot) emtpySpace3WaitSansDelay := (emtpySpace3Wait-fiftyDeg) l_pst1 := trigger1Wait l_pst2 := trigger2Wait l_pst3 := trigger3Wait l_pst4 := emtpySpace1Wait l_pst5 := emtpySpace2Wait l_pst6 := emtpySpace3Wait l_pst9 := tenDeg l_pst15 := camRpmPerSecond l_pst16 := cyclesPerDegOfRot l_pst12 := fiftyDeg startTooth := 26 localCnt := cnt repeat prevLoopCnt := loopCnt loopCnt := cnt l_pst7 := (loopCnt - prevLoopCnt) if (l_variableDegreeDelay <> 0) variableDelay := (l_variableDegreeDelay * cyclesPerDegOfRot) l_variableDegreeDelay := 0 waitcnt(localCnt += (variableDelay + fiftyDeg)) variableDelay := 0 outa[simCamWheelPinNum]~~ ' pin high waitcnt(localCnt += trigger1Wait) ' wait cnt time stamp plus trigger degree width in cycles outa[simCamWheelPinNum]~ ' pin low waitcnt(localCnt += emtpySpace1Wait) ' wait cnt time stamp plus first empty space degree width in cycles outa[simCamWheelPinNum]~~ ' pin high waitcnt(localCnt += trigger2Wait) ' wait cnt time stamp plus trigger degree width in cycles outa[simCamWheelPinNum]~ ' pin low waitcnt(localCnt += emtpySpace2Wait) ' wait cnt time stamp plus second empty space degree width in cycles outa[simCamWheelPinNum]~~ ' pin high waitcnt(localCnt += trigger3Wait) ' wait cnt time stamp plus trigger degree width in cycles outa[simCamWheelPinNum]~ ' pin low 'waitcnt(localCnt += emtpySpace3Wait) ' wait cnt time stamp plus third empty space degree width in cycles waitcnt(localCnt += emtpySpace3WaitSansDelay)PUB simulateCrankWheel(simCrankWheelPinNum, crankTeethSimToothCnt, crankTeethSimMissingToothCnt, crankTeethSimRPM, autoRangeRPM) | localIndex, waitTime, logicHighWaitTime, logicLowWaitTime, logicHighGapWaitTime, logicLowGapWaitTime, startCnt, existingTeeth, loopCnt, prevLoopCnt ' Initialize variables here dira[simCrankWheelPinNum]~~ outa[simCrankWheelPinNum]~ localIndex := 0 waitTime := (clkfreq/((crankTeethSimRPM*(crankTeethSimToothCnt*2))/60)) ' for 1500rpm = 44444, for 600rpm = 111111, 5555 for 12000rpm , 95238 for 700rpm 'logicHighWaitTime := ((waitTime/50)*45) ' 85770 for 700rpm 'logicLowWaitTime := ((waitTime/50)*55) ' 104860 for 700rpm 'logicHighGapWaitTime := ((((waitTime*6)/100)*43)-logicHighWaitTime) ' 245917 for 700rpm this percentage can be measured by a prop scope and a signal capture 'logicLowGapWaitTime := ((((waitTime*6)/100)*57)-logicLowWaitTime) ' 325983 logicHighWaitTime := ((waitTime*45)/50) ' 85714 for 700rpm logicLowWaitTime := ((waitTime*55)/50) ' 104761 for 700rpm logicHighGapWaitTime := ((((waitTime*4)*43)/100))'-logicHighWaitTime) logicLowGapWaitTime := ((((waitTime*4)*57)/100))'-logicLowWaitTime) existingTeeth := (crankTeethSimToothCnt - crankTeethSimMissingToothCnt) { 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) } l_pst9 := logicHighWaitTime l_pst10 := logicLowWaitTime l_pst11 := logicHighGapWaitTime l_pst12 := logicLowGapWaitTime l_pst13 := existingTeeth l_pst14 := waitTime startCnt := cnt repeat prevLoopCnt := loopCnt loopCnt := cnt l_pst8 := (loopCnt - prevLoopCnt) repeat localIndex from 1 to (existingTeeth) ' loop number of physical teeth on and off outa[simCrankWheelPinNum]~~ ' high waitcnt(startCnt += logicHighWaitTime) ' on for 1 tooth outa[simCrankWheelPinNum]~ 'low waitcnt(startCnt += logicLowWaitTime) ' off for 1 tooth outa[simCrankWheelPinNum]~ ' low waitcnt(startCnt += logicLowGapWaitTime) ' off for 57% of 2 teeth outa[simCrankWheelPinNum]~~ ' high waitcnt(startCnt += logicHighGapWaitTime) ' on for 43% of 2 teethCan you tell me what you mean by base 2 or explain the concept a little better? I thought that I was already using base 2 with the prop
We could say 1 degree equals 1024 (0x400)
0.5 degrees = 512 (0x200)
0.25 degrees = 256 (0x100)
0.125 degrees = 128 (0x80)
0.1 degree ~ 102 = (0x66)
Therefore, 2.2 degrees = 2*1024 + 2*102 = 2252 or 0x8CC. That's pretty good resolution.
Basically, remove decimal math from the calculations. The only time you have to worry about the number is when displaying the results.
I think I'm going to have to rewrite the object in PASM, so that I can sync it properly. I don't think spin is fast enough unfortunately