Request for help with a linear sensor driver. Assembly code challenge?

I'm thinking this may be easy for folks who know their way around Assembly and Spin; I'm a novice at Spin and have no clue with anything Assembly. Would the experts out there kindly take a whack at this?

Problem: If no magnet is present on the sensor, the Propeller "hangs up" when it tries to use the sensor. how could this driver code be changed such that the Prop doesn't wait forever for a return pulse?

Physical device description: Magnetostrictive sensor, specifically the EP2 start/stop model from MTS Sensors, found here: http://www.mtssensors.com/fileadmin/media/pdfs/Products/Industrial/E_Series/Data_Sheet_E-Series_EP2_Start_Stop_551335_EN.pdf

Driver code (not written by me):
'
'  propeller code to return magnet position as a function of
'  MCU clock cycles for the Temposonics EP2D linear position
'  sensor.
'
'
'  LIMITATIONS:
'
'  This function returns the position of the first magnet only.
'  (Magnet nearest head of sensor)
'
'  This function assumes the reference magnet is affixed to the
'  end of the sensor.  It will time out (and fail to loop) if
'  there is no magnet on the sensor. THE CODE SHOULD BE CHANGED
'  TO WAIT A FIXED AMOUNT OF TIME THEN LOOP IF NO VALUE IS
'  RETURNED.  In practice this has not been a problem except when
'  running on a breadboard.
'

'

VAR
  long pulseWidth

PUB start

'' Start a cog with the measurement routine

  return cognew(@entry,@pulseWidth)

  
    
PUB getPosition

'' Return the elapsed time (in clock ticks) between start and stop pulses

   pulseWidth := 0                              ' Use zero to indicate no pulse seen yet
   repeat until pulseWidth                      ' Wait until this changes to non-zero
   return pulseWidth                            ' Return the new value

PUB getPositionNoWait
  return pulseWidth
PUB clearPosition
  pulseWidth := 0

    
DAT
entry   org

init    mov       t1,   #1      wz              '  configure start pin as output
        shl       t1,   startPin
        muxz      outa, t1                      '  set it LOW
        muxnz     dira, t1
        mov       t2,   #1      wz              '  configure stop pin as input
        shl       t2,   stopPin
        muxz      dira, t2
        
        mov       sampTime, cnt                 ' Set up delay
        add       sampTime, #9                  ' Add 9 clk cycles - time needed to execute this block
        waitcnt   sampTime, sampDelay
        
loop    mov       t1,   #0      wz,nr    
        mov       startTime,cnt                 ' Save the system clock value
        muxz      outa, t1                      ' Set the startPin high
        nop
        nop
        nop
        nop
        nop
        nop                                     '  series of NOP's to send 1.5 us pulse
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        muxnz     outa, t1                      ' Set startPin low
        
        nop
        nop
        nop
        nop
        nop
        nop                                     '  series of NOP's to wait for bogus STOP to go low
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop

        waitpne   zeroes,t2                     ' Wait for stopPin to go high (was #%01)
        mov       endTime,cnt                   ' Get the system clock value
        sub       endTime,startTime             ' Calculate elapsed tim
        wrlong    endTime,PAR                   ' Return the elapsed time
        'mov       tempvar, t2
        'wrlong    tempvar,PAR                   ' Return the elapsed time
        waitcnt   sampTime, sampDelay           ' Pause - sensor sampling freq is ~40Hz
        jmp       #loop                         ' Loop

zeroes        long      0                      
stopPin       long      24                      
startPin      long      25                      
sampDelay     long      2_500_000               ' delay in clock cycles between sensor samples
'trigDelay     long      110
startTime     res       1                       ' Start pulse system clock
endTime       res       1                       ' Stop pulse system clock (and calculated difference)
t1            res       1
t2            res       1
trigTime      res       1
sampTime      res       1
tempvar       res       1




Comments

  • 8 Comments sorted by Date Added Votes
  • Clock LoopClock Loop Posts: 1,443
    edited April 6 Vote Up0Vote Down
    Assuming you are calling start, and then calling getPosition which is waiting forever.

    Your driver is fine(assuming the assembly is fine), it even has a way to do a "no wait get position."

    So from your main code, which isn't attached, don't call "getPosition"



    Call "getPositionNoWait"

    But in a repeat loop. I am guessing if you don't know spin or assembly, then chances are you won't be able to do this even.

    And then you must accept that after you call getPositionNoWait you could have a return value of 0, and deal with it in that loop.

    It looks like your driver is fine, its your top level spin code that calls the driver.

    If you don't know spin, or assembly, you will need someone to help you with the main code, not the driver code you posted here.

    This is one of the problems with many people that need help, they don't, or can't, post ALL the code.
    To study the nature of randomness in a digital processor network using the same clock source, 54 prop chips were all connected to a master prop. http://forums.parallax.com/discussion/127983/55-parallax-propeller-s-parallells-processing-of-permanent-perturbations/p1
    Optic communication between homogenous and commensurable, 8-core, 635nm emitting, phase locked loop, bit salad tossing units? http://forums.parallax.com/discussion/comment/1248240/#Comment_1248240
    TheBlackBox: Release v2.0 - Propeller HSS FX/Sequencer with Digital Audio SPDIF output. http://forums.parallax.com/discussion/115258/theblackbox-release-v2-0-propeller-hss-fx-sequencer-with-digital-audio-spdif
    E-Tools - Mono555 calculator, resistor calculator, voltage divider calculator, RCtime calculator, LM317 calculator, Binary-Hex-Decimal calculator, Resistor color matrix, Series LED resistance calculator, OHMS LAW calculator.
    http://forums.parallax.com/discussion/81449/e-tools-html-java-script-electronic-design-tools-free-for-you
  • Good points Clock Loop - yes, I thought of using getPositionNoWait but thought there might be issues with regard to the rest of the higher-level code. I can do rudimentary things like make loops, but not much else.

    You've corroborated my earlier hunch, thanks - I'm going to take another whack at using the NoWait routine... thanks for taking the time to comment.
  • Clock LoopClock Loop Posts: 1,443
    edited April 6 Vote Up0Vote Down
    chris_bfs wrote: »
    I'm going to take another whack at using the NoWait routine... thanks for taking the time to comment.

    As long as the START function is still run, then the background code runs identically whether you run the getposition or getpositionnowait.

    As long as you still run the start function, and even if you never run getposition or getpositionnowait, your sensor is still being measured and stored into @pulseWidth


    If you don't check getpositionnowait fast enough, you might miss something, which is why they probably ran the wait routine.

    Really, unless you are running out of cogs (unlikely), you can just run a loop that repeately checks pulseWidth for a change
    Repeat
        If pulsewidth <> 0
           pulsewidthGood := pulsewidth 
    

    This code will loop forever only storing values into pulsewidthGood that are not 0

    Then pulsewidthGood will always have the last known value that isn't 0.

    This is all very rough code stuff...

    To study the nature of randomness in a digital processor network using the same clock source, 54 prop chips were all connected to a master prop. http://forums.parallax.com/discussion/127983/55-parallax-propeller-s-parallells-processing-of-permanent-perturbations/p1
    Optic communication between homogenous and commensurable, 8-core, 635nm emitting, phase locked loop, bit salad tossing units? http://forums.parallax.com/discussion/comment/1248240/#Comment_1248240
    TheBlackBox: Release v2.0 - Propeller HSS FX/Sequencer with Digital Audio SPDIF output. http://forums.parallax.com/discussion/115258/theblackbox-release-v2-0-propeller-hss-fx-sequencer-with-digital-audio-spdif
    E-Tools - Mono555 calculator, resistor calculator, voltage divider calculator, RCtime calculator, LM317 calculator, Binary-Hex-Decimal calculator, Resistor color matrix, Series LED resistance calculator, OHMS LAW calculator.
    http://forums.parallax.com/discussion/81449/e-tools-html-java-script-electronic-design-tools-free-for-you
  • Thank you Clock Loop!

    I can't report success (or failure) at this point, just wanted to thank you for responding.

    Will report back whether the no-wait routine works out.

    Best,
    Chris
  • jmgjmg Posts: 11,066
    chris_bfs wrote: »
    Problem: If no magnet is present on the sensor, the Propeller "hangs up" when it tries to use the sensor. how could this driver code be changed such that the Prop doesn't wait forever for a return pulse?

    That gets tricky...
    The highest precision comes from using waitpne, as here, but that does mandate a STOP pulse arriving.
    You can do a timeout loop with DJNZ & Pin-poll or similar, but the granularity of that is not as good - perhaps 12x worse.

    What precision can you tolerate ?

    It says the energise pulse is ~1.5us, is the echo pulse the same width ?

    What you might be able to do, is use a Prop CTR in gated mode L=Count, H=Pause
    eg CTRMODE = %10101 increments on !A (Pin A = low)
    You then Clr CTR, then poll pinA, and immediately after poll exit, read the counter.
    The poll loop is coarse, but the counter stops on __/==== with 1 SysCLK precision.
  • waitp(n)e waits for a mask to fill you requirement, not just a single pin. So if you have a spare pin, you can run some time out code in another cog to change that spare pin after x time.

    And on your waitpxx you simply wait for a change of any of them two pins.

    Enjoy!

    Mike
    I am just another Code Monkey.
    A determined coder can write COBOL programs in any language. -- Author unknown.
    Press any key to continue, any other key to quit

    The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this post are to be interpreted as described in RFC 2119.
  • msrobots wrote: »
    waitp(n)e waits for a mask to fill you requirement, not just a single pin. So if you have a spare pin, you can run some time out code in another cog to change that spare pin after x time.

    And on your waitpxx you simply wait for a change of any of them two pins.

    Enjoy!

    Mike

    I solved similar situation differently. I needed the precision of waitpne. I used one COG to do this. It would wait indefinitely. Another COG acted as a watchdog and killed it when it timed out.

    --
    Reinhardt
  • msrobotsmsrobots Posts: 1,879
    edited April 12 Vote Up0Vote Down
    differently? That was exactly what I was trying to describe.

    I am still fighting with that English language.

    Ahh, I get it you killed the whole COG?

    Enjoy!

    Mike
    I am just another Code Monkey.
    A determined coder can write COBOL programs in any language. -- Author unknown.
    Press any key to continue, any other key to quit

    The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this post are to be interpreted as described in RFC 2119.
Sign In or Register to comment.