Shop OBEX P1 Docs P2 Docs Learn Events
Pulse width measurement? — Parallax Forums

Pulse width measurement?

Jim BarnesJim Barnes Posts: 9
edited 2008-08-20 19:05 in General Discussion
Hello,

I want to measure a ~ 3 msec low-high-low pulse that repeats every ~ 30 msec.· Then I need to compare the ratio of 10:1 for calibrating the device.·

I'd like·to do an event-count of the resonator clock cycles (or some other·oscillator that I could provide if the microcontroller likes this better cool.gif).· I would count 1] while the pulse is high, and 2] count from the first high pulse until the next high pulse, then compare the two counts.··

Can the SX family handle that?· Is there a better parallax product for this project?·

Thanks very much for your help.

Jim Barnes

Comments

  • JonnyMacJonnyMac Posts: 9,215
    edited 2008-08-06 17:25
    The SX can EASILY handle this chore -- and there have been several threads in recent days on this topic.
  • Jim BarnesJim Barnes Posts: 9
    edited 2008-08-06 17:31
    Thanks J-Mac,

    Sorry if this is a redundant post--I searched on pulse width and on counter and didn't see anything that looked like this.· Will look further....any hints on search keywords appreciated.......·tail between legs.....

    Jim
  • JonnyMacJonnyMac Posts: 9,215
    edited 2008-08-06 17:53
    PULSIN is built into SX/B's vocabulary, though it may not have enough resolution (10 microseconds). Look for recent threads having to do with measuring servo pulses; a couple of us demonstrated replacing PULSIN with interrupt driven code; code that can easily be modified for any resolution you like.
  • Jim BarnesJim Barnes Posts: 9
    edited 2008-08-19 20:39
    JonnyMac,

    Thanks, been reading posts and documentation. ·I need resolution of 1 microsec or better.· Again, measuring two time intervals simultaenously, starting from the same high edge:· ·t1 (~3msec) is the interval until the the high pulse goes back low......t2 (~30 msec) is·the·interval until the·next high edge on the same·pin.·· Ideally the same high edge·initiates both measurements.·· I only need to·compare the ratio of the·two times,·make an adjustment in the hardware, and repeat until the ratio is correct.· Time measurement is critical, the rest can take "forever."·

    In the example Measure_Pulses.SXB, I think what is going on is the ISR starts every 10 microsec and increments a count if the given bit is high, then over and over again.· Please, have I got it right?· If so, I need to keep the ISR shorter than the resolution I want to achieve, right?· ·How do I figure that practical limit?· Don't be afraid to dumb it down for me.·

    Clearly I need a book and a quiet place as well as your help.· Is Gunther's book a good place to start?· Should I be looking at the·SX-28 or the -48?· SX/B or ASM?·Any recommendation/help is grealy appreciated.

    Jim
  • JonnyMacJonnyMac Posts: 9,215
    edited 2008-08-19 21:13
    Have a look at the attached program -- should get you close. There is a function that will wait on the 0->1 edge, measure the high portion, the low portion, then return those values to the caller (the program shows how to retrieve more than two bytes from a single function call). If you are certain that your pulses are less than 65 milliseconds wide then you can remove the check that aborts the timing loop on a rollover.
  • pjvpjv Posts: 1,903
    edited 2008-08-20 19:01
    Hello Jim;

    Just foir fun I wanted to see how tight one could create some assembler code to do what I think you are looking to accomplish. The code must use ra.1 as the high/low input, and will count the duration (2 bytes) that a continuous high or low is detected. When that input pin transitions to the opposite state (say low), the accumulated count is output on ports e/d, and the counter is zroed. The accumulation starts again, and when the input again transitions (now high), the accumulated count is put on ports c/b. This way you can separately see the high and low results in real time via leds connected to those 32 port pins.
    Although fairly short, the program is quite intricate -even tricky in spots- and ANY alteration will cause it to fail unless certain timing/code length principles are upheld. As it stands, it will (just) work up to minimum durations of 440 nano seconds, and that's its resolution.
    Sixteen bit accumulators permit 65355 counts to be captured, so at the programmed speed of 440 nanoseconds, permits a slowest duration of .44 x 65535 = 28.8 milliseconds... perhaps just outside your range. If that is the case, one could safely slow the interrupt period down from minus 22 cycles to minus 25 cycles (as in the commented out "INTVAL·EQU -25·" line, and that would yield a 500 nano second resolution. Then the slowest you could capture (that is per high OR per low duration) would be .5 x 65535 = 32.7 milliseconds.

    device SX48,oscHS3    ; new assembler
    id'Ratio1'
    freq 50_000_000       ; default run speed = 50MHz
    reset reset_entry     ; JUMP to start label on reset
     
    IntVal  equ -22     ;440 nsec resolution at 50 MHz (can be made slower, but not faster for this EXACT code)
    ;IntVal  equ -25     ;500 nsec resolution at 50 MHz (can be made slower)
    
    Low   equ rb
    High  equ rd
    
      org $0A
    IntCtrLo           ds 1
    IntCtrHi           ds 1
     
    watch Low,16,uhex
    watch High,16,uhex
    watch IntCtrLo,16,uhex
     
      org 0
    Intsvc incsz IntCtrLo   ;keep track of interrupt events
           skip
           inc  IntCtrHi
           rl  ra           ;input on ra.1
           mov  w,<<ra
           and  w,#%0001_1000
           add  pc,w
     
    Add00  mov  w,#IntVal   ;aligned on plus 0 boundary 
           retiw      
      
           nop       ;these nops
           nop       ;must be located
           nop       ;precisely here to
           nop       ;park the "ADD TO PC"
           nop       ;state code at
           nop       ;the proper spots
     
    Add01  mov  w,IntCtrLo   ;aligned on plus 8 boundary 
           mov  rb,w
           mov  w,IntCtrHi
           mov  rc,w
           clr  IntCtrLo
           clr  IntCtrHi
           mov  w,#IntVal    ;
           retiw      ;
     
    Add10  mov  w,IntCtrLo   ;aligned on plus 16 boundary 
           mov  rd,w
           mov  w,IntCtrHi
           mov  re,w
           clr  IntCtrLo
           clr  IntCtrHi
           mov  w,#IntVal    ;
           retiw      ;
     
    Add11  mov  w,#IntVal   ;aligned on plus 24 boundary 
           retiw      
    
    Reset_entry             ;Program starts here on power-up and on reset.
    Init   mov  m,#$0d     ;Set 0 for CMOS levels
           mov  !ra,#%0000_0000  
           mov  !rb,#%0000_0000  
           mov  !rc,#%0000_0000  
           mov  !rd,#%0000_0000  
           mov  !re,#%0000_0000  
           mov  m,#$0e     ;Set 0 for pullups
           mov  !ra,#%0000_0000  
           clr  ra
           clr  rb
           clr  rc
           clr  rd
           clr  re
           mov  m,#$0f     ;Set 0 for output
           mov  !ra,#%0000_0010   ;ra.1 is the high/low transition input
           mov  !rb,#%0000_0000  
           mov  !rc,#%0000_0000  
           mov  !rd,#%0000_0000  
           mov  !re,#%0000_0000  
           clr  rtcc
           mov  !option,#%1000_1000  ;0 = w, 0 = interrupt, 0 = internal, 0 = lo to hi, 0 = scale rtcc, xxx divide
           clr  IntCtrLo
           clr  IntCtrHi
    
    Main   jmp  Main     ;
           nop        ;dummy required because IDE will not "BREAK" at last program instruction
     
    

    Have fun with this.

    Cheers,

    Peter (pjv)
  • JonnyMacJonnyMac Posts: 9,215
    edited 2008-08-20 19:05
    Tricky? That's an understatement, my friend! smile.gif
Sign In or Register to comment.