Shop OBEX P1 Docs P2 Docs Learn Events
I would like help with coming up with some logic for making a method more dynamic — Parallax Forums

I would like help with coming up with some logic for making a method more dynamic

turbosupraturbosupra Posts: 1,088
edited 2012-05-09 20:31 in Propeller 1
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.

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

  • Mike GMike G Posts: 2,702
    edited 2012-05-09 07:23
    Use a global (static) variable.
  • Mike GreenMike Green Posts: 23,101
    edited 2012-05-09 07:41
    In your main loop in each simulation routine, you have several WAITCNTs. All you need to do is to add "+ adjustment1~" as in "waitcnt(localCnt += trigger3Wait + adjustment1~)" to each WAITCNT. The other simulation routine would use adjustment2 and both would be declared as longs. The effect is that you can insert a few clock cycles into either cog's loop and the adjustment gets zeroed after it's used. Your main control routine just has to set either adjustment1 or adjustment2 to a non-zero value and that simulation cog gets delayed by the amount requested.

    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.
  • turbosupraturbosupra Posts: 1,088
    edited 2012-05-09 09:34
    Good ideas, thank you both. Hopefully spin is fast enough to handle said adjustments.

    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?
  • Mike GreenMike Green Posts: 23,101
    edited 2012-05-09 10:00
    It's probably a code error. I'd check the various Wait values.
  • turbosupraturbosupra Posts: 1,088
    edited 2012-05-09 12:12
    Mike,

    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

    1000rpm
    cr - 4798800 (x2 = 9597600)
    ca - 9637200
    diff - 39600



    2000rpm
    cr - 2397712 (x2 = 4795424)
    ca - 4816800
    diff - 21376



    3000rpm
    cr - 1598512 (x2 = 3197024)
    ca - 3196800
    diff - 224



    4000rpm
    cr - 1198800 (x2 = 2397600)
    ca - 2401200
    diff - 3600


    5000rpm
    cr - 957696 (x2 = 1915392)
    ca - 1922400
    diff - 7008




    Stops floating around here
    6000rpm
    cr - 799200 (x2 = 1598400)
    ca - 1598400
    diff - 0
  • turbosupraturbosupra Posts: 1,088
    edited 2012-05-09 14:32
    I have gotten them somewhat close, but I cannot get it perfect because of integer only division. After spending the last 5 hours on this, I'm just going to call it as good as it gets, otherwise if I shift the math one way, it screws up the higher values and if I shift it the other way, it screws up the lower values. My brain is killing me.


    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 teeth
    
    
  • Mike GreenMike Green Posts: 23,101
    edited 2012-05-09 14:59
    You have to be careful to maintain as much precision as possible when doing divisions. For example, instead of doing A * B / C as A * (B / C), you'd do (A * B) / C. Obviously, you'd need to know your number ranges and make sure that A * B still fits in 32 bits or use multiple precision.
  • Mike GMike G Posts: 2,702
    edited 2012-05-09 16:03
    What about using the base 2 number system? I once built a timer object accurate to 1/512 of a second (conversion factor). That gave me 0xFFFFFFFF / 0x200 = 0x7FFFFF (8388607) seconds. Which was more than enough time and darn good resolution (~2ms) for the project. You might be able use the same concept?
  • turbosupraturbosupra Posts: 1,088
    edited 2012-05-09 18:13
    Hi Mike,

    Can 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 :)
  • Mike GMike G Posts: 2,702
    edited 2012-05-09 18:56
    I could be wrong but at first glance it looks like you are using base 10. Anyway, we can use conversion factors.

    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.
  • turbosupraturbosupra Posts: 1,088
    edited 2012-05-09 20:31
    Oh I see, base2 inside of spin. You are right I am using base10 in spin, which gets converted to base2 right? Either way, I understand what you mean now and I will try and implement something like that tomorrow.

    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
Sign In or Register to comment.