Shop OBEX P1 Docs P2 Docs Learn Events
Best method to Measure Pulse Width in PASM — Parallax Forums

Best method to Measure Pulse Width in PASM

SailerManSailerMan Posts: 337
edited 2009-10-29 00:27 in Propeller 1
I'm working in PASM and I am learning as much as I can on my own with some help from various users on here.

I have finally been able to write a program that sends data to a 74hc595 shift register..it was a great day for me.. [noparse]:)[/noparse]

Now I want to read data from a Maxbotix Sonar sensor... using the pulse width method.. I'm just wondering if someone can point me in the right direction.

I was playing with WaitPEQ and WaitPNE command and measuring the time difference... Is it that simple? Any Guidance would be appreciated.

Regards,
Eric

PS oh yeah.. What about dividing CNT by 1000 ? Division in PASM is well beyond me at this point in time.

Comments

  • MagIO2MagIO2 Posts: 2,243
    edited 2009-10-28 15:23
    Hmm ... did not do that before ... but my idea would be:

    Use counter A to count in case pin is low
    Use counter B to count in case pin is high

    From time to time (the time should be close to the frequency of the PWM signal) you read the counters and set them to zero again.
    The ratio of the read counter values is equal to the pulse/pause ratio.

    Of course you can do other things while the counters count or you wait with a waitcnt ...
  • Bobb FwedBobb Fwed Posts: 1,119
    edited 2009-10-28 15:43
    Yes, it is that simple. Here is a simple example (untested):
    start_again             waitpne mask, mask      ' wait for low
                            mov     start, cnt      ' start timer
                            waitpeq mask, mask      ' wait for high          
                            mov     pulse, cnt      ' end timer
    
                            sub     pulse, start    ' get duration 
                            sub     pulse, #5       ' some type of compensation will be needed, 5 or 9 cycles is likely
                            wrlong  pulse, pulseaddr ' output the value to an address
                            jmp     #start_again    ' continue to measure?
    



    As for dividing cnt by 1000, the easiest way is to have the SPIN portion of your code do the dividing (before or after the PASM is called, depending on your requirements).
    If you want to do it in PASM, I haven't used this in a while, but I don't see why I would have broke the code any time recently. Put numerator in par1, denominator in par2, and the result will be stored in ret_val. The inputs are limited to 16 bits. I know there is better dividing code out there
    '----- DIVIDE ----------------------------------
    ' par1 / par2
    divide                  SHL     par2, #15       ' get divisor into y[noparse][[/noparse]30..15]
                            MOV     midx, #16       ' ready for 16 quotient bits
    
            :loop           CMPSUB  par1, par2      WC ' if y =< x then subtract it, set C
                            RCL     par1, #1        ' rotate c into quotient, shift dividend
                            DJNZ    midx, #:loop    ' loop until done
                            MOV     ret_val, par1   ' move to return
            divide_ret      RET
    



    Spin uses this code (32-bit compatible), but it is a bit more of mess:
    mdiv                    shr     y,#1            wc,wz   'divide
                            rcr     t1,#1
            if_nz           djnz    t2,#mdiv
    mdiv2                   cmpsub  x,t1            wc
                            rcl     y,#1
                            shr     t1,#1
                            djnz    t2,#mdiv2
                            test    a,#%01000       wc
                            negc    x,x
                            test    a,#%00100       wc
                            test    a,#%00001       wz
            if_z            negc    x,y
                            jmp     #push
    

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    April, 2008: when I discovered the answers to all my micro-computational-botherations!

    Some of my objects:
    MCP3X08/4 ADC Driver - Programmable Schmitt inputs, frequency reading, and more!
    Simple Propeller-based Database - Making life easier and more readable for all your EEPROM storage needs.
    String Manipulation Library - Don't make strings the bane of the Propeller, bend them to your will!

    Post Edited (Bobb Fwed) : 10/28/2009 3:48:19 PM GMT
  • Bobb FwedBobb Fwed Posts: 1,119
    edited 2009-10-28 16:04
    Well, I just tested my divide code. It has issues, if the numerator isn't a multiple of the denominator, you get bad results. I bet it is a simple fix. I will try to figure that out.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    April, 2008: when I discovered the answers to all my micro-computational-botherations!

    Some of my objects:
    MCP3X08/4 ADC Driver - Programmable Schmitt inputs, frequency reading, and more!
    Simple Propeller-based Database - Making life easier and more readable for all your EEPROM storage needs.
    String Manipulation Library - Don't make strings the bane of the Propeller, bend them to your will!
  • LawsonLawson Posts: 870
    edited 2009-10-28 19:30
    For a minimal error you could just divide by 1024, i.e. >>10.

    Lawson

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Lunch cures all problems! have you had lunch?
  • Bobb FwedBobb Fwed Posts: 1,119
    edited 2009-10-28 20:10
    Lawson said...
    For a minimal error you could just divide by 1024, i.e. >>10.
    Or SHR val, #10 (in this case)

    Yes, that is by far the easiest, fastest method. But then you are forced into binary division. But seeing as you now using a type of "binary" division, it limits your output. I would guess you would want the dividing by 1000 to return your results as some multiple of a second (milliseconds, microseconds, etc.).

    It all really depends on your application of the dividing by 1000. Can't wait until the Prop II, it is supposed to have some type of value dividing circuitry (not single-cycle instruction). Sounds interesting, but would be very nice to have.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    April, 2008: when I discovered the answers to all my micro-computational-botherations!

    Some of my objects:
    MCP3X08/4 ADC Driver - Programmable Schmitt inputs, frequency reading, and more!
    Simple Propeller-based Database - Making life easier and more readable for all your EEPROM storage needs.
    String Manipulation Library - Don't make strings the bane of the Propeller, bend them to your will!
  • Bobb FwedBobb Fwed Posts: 1,119
    edited 2009-10-28 20:20
    Lawson said...
    For a minimal error you could just divide by 1024, i.e. >>10.
    I even have some code to "round" your answer if you are very picky about the LSB:
    round                   TJZ     shpos, #:skip           ' skip this if being shifted by 0
                            SUB     shpos, #1        
                            SHR     val, shpos              ' "divide"
                            SHR     val, #1          WC     ' put "half" bit in c
                            ADDX    val, #0                 ' if "half" bit is set, round up
    :skip
    


    shpos is bits to shift (in this case 10 is probably what you'll want to set it to)

    EDIT: fixed typo

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    April, 2008: when I discovered the answers to all my micro-computational-botherations!

    Some of my objects:
    MCP3X08/4 ADC Driver - Programmable Schmitt inputs, frequency reading, and more!
    Simple Propeller-based Database - Making life easier and more readable for all your EEPROM storage needs.
    String Manipulation Library - Don't make strings the bane of the Propeller, bend them to your will!

    Post Edited (Bobb Fwed) : 10/28/2009 8:25:51 PM GMT
  • tdlivingstdlivings Posts: 437
    edited 2009-10-29 00:27
    I will share my learning example
    I decided to follow Jeff Martin's ASM web seminar example and have the ASM code measure the High Time of a pulse from a function generator attached to pin 10.
    I am using the Pro Deveopment Board.
    The high time measurement using a cog's counter A ended up being the same as that of the BS2 Functions code.
    Looking at that was a good learning exercise, my original stab at it did not wait for the signal to be low before clearing the counter. That did not work.
    I was giving the counter function more credit for watching for that than I should have.
    The best examples of using the counters is in PELabsFunBook-v1.1.pdf.

    Next version will be to add a Command = 2 to use counter B to measure the low time. Just for leaning.

    I also attached a spin only using the BS2 Functions, at the time I typed this in my code was doing nothing and this told me
    the counter can do it I just did not have it figured out.

    Using the counter is a clean way to do it with microsecond displayed results.

    Tom
Sign In or Register to comment.