High Resolution Timer & Speed Calculator


Closed Thread
Results 1 to 5 of 5
  1. #1
    Join Date
    Jan 2010
    Location
    PHILADELPHIA, PA - USA
    Posts
    34

    Default High Resolution Timer & Speed Calculator

    This PBP project is a high precision timer and Speed Calculator.
    Its designed to be used with a 2 sensor optical gate, though it can accurately measure the time of any single pulse.

    It is mostly an experiment to carry as much precision as possible.
    But also a useful gadget in it's own right.
    It uses Darrel' Taylor's Instant Interrupts and N-Bit Math (64-Bits) throughout.

    The core program is based on an implementation of CCP1, TIMER-1 Interrupts that was originally developed by Bruce from Rentron.
    http://www.picbasic.co.uk/forum/show...01&postcount=3

    Here is the Start of the Code:
    Code:
    '******************************************************************
    '*********************[ High-Resolution Timer ]********************
    '******************************************************************
    '**  Author  : Robert Wozniak,   Robert.Wozniak -at- gmail.com   **
    '**  Notice  : This code may be freely used and distributed      **
    '**            for use in non-commercial applications            **
    '**  Version : 6.10 : Feb 06, 2010                               **
    '**  Date    : JAN 14, 2010                                      **
    '******************************************************************
    '**  Versions:                                                   **
    '**   6.0 : All 64 bit MATH, 99 min limit                        **
    '**   5.0 : Working Timer and Speed Calculator with 64 bit math  **
    '******************************************************************
    '**   Hardware Tested: PIC18F4680 @20MHz                         **
    '**   4x16 Parallel LCD Module                                   **
    '**   PBP 2.60 / MPLAB IDE 8.40.000                              **
    '**   Compiled with: [-n -ampasmwin] Build Options               **
    '**   32 BIT LONG SIGNED INTEGER                                 **
    '**                                                              **
    '** Thanks to Darrel & Bruce at MEL PB Forums for Code examples  **
    '**           Alexander for N-Bit Math...Excellent ASM code      **
    '******************************************************************
    '**  MAX OVRFLO=457763, COUNTS=44041 for 99min:59.9999998sec     **
    '**  MIN OVRFLO=0, COUNTS=261 for 9999.999MPH                    **
    '******************************************************************
    
    PRECISION CON 8 SYSTEM        ; Set 8 bytes = 64-bit Precision for N-Bit_Math.pbp
    
    INCLUDE "N-BIT_Math.pbp"    ; Include Alexander Avtanski's Multibyte Arithmetic
                    ; Assembly Library Wrapped for PBP by Darrel Taylor [Version:1.3 Beta (JAN 07,2010)]
                    ; Version:1.3 Beta (1/7/2010)
    INCLUDE "DT_INTS-18.bas"    ; Include Darrel Taylor's Base Interrupt System for PIC18F [Version:3.3 (MAR 24, 2008)]
    INCLUDE "ReEnterPBP-18.bas"   ; Include Darrel Taylor's PBP interrupts for PIC18F [Version:1.4 (MAR 24, 2008)]
    
    DEFINE OSC 20
    
    DEFINE DEBUG_REG PORTC
    DEFINE DEBUG_BIT 6 
    DEFINE DEBUG_BAUD 57600     ' 38400 BAUD N-8-1, PORT C6 
    DEFINE DEBUG_MODE 1     ' 1 = inverted, 0 = true
    
    DEFINE LCD_DREG PORTA       ' Set LCD Data port
    DEFINE LCD_DBIT 0           ' Set starting Data bit (0 or 4) if 4-bit bus
    DEFINE LCD_RSREG PORTA      ' Set LCD Register Select port
    DEFINE LCD_RSBIT 4          ' Set LCD Register Select bit
    DEFINE LCD_EREG PORTB       ' Set LCD Enable port
    DEFINE LCD_EBIT 3           ' Set LCD Enable bit
    DEFINE LCD_BITS 4           ' Set LCD bus size (4 or 8 bits)
    DEFINE LCD_LINES 4          ' Set number of lines on LCD
    DEFINE LCD_COMMANDUS 2000   ' Set command delay time in us (2000)
    DEFINE LCD_DATAUS 50        ' Set data delay time in us (50)
    
    TRISA=%00000000             ' SET to Output
    TRISC.2=1               ' SET to Input
    ADCON0=%11000000
    ADCON1=%00000111
    T1CON.7=1         ' Set Timer1 to 16 bit mode
    
    LED         VAR PORTD.1       ' Alias PORTD.0 to LED
    I       VAR BYTE 
    J       VAR BYTE 
    OVRFLO      VAR LONG        ' Timer1 Overflow total
    COUNTS      VAR WORD        ' Timer1 Counts after falling edge capture
    PRESET      VAR BYTE
    OVFLS32     VAR LONG
    COUNTS32      VAR LONG
    TSEC32        VAR LONG
    OVFLS64       VAR BYTE[PRECISION]
    OVFLS64M      VAR BYTE[PRECISION]
    COUNTS64      VAR BYTE[PRECISION]
    TSEC64        VAR BYTE[PRECISION]
    BITS16      VAR LONG
    BITS1664      VAR BYTE[PRECISION]
    TMIN64      VAR BYTE[PRECISION]
    TSECINT64     VAR BYTE[PRECISION]
    TSECDEC64     VAR BYTE[PRECISION]
    CONVSEC     VAR LONG
    CONVSEC64     VAR BYTE[PRECISION]
    AA32      VAR LONG
    AA64        VAR BYTE[PRECISION]
    BB32      VAR LONG
    BB64      VAR BYTE[PRECISION]
    CC32      VAR LONG
    CC64        VAR BYTE[PRECISION]
    TMIN        VAR LONG
    TSEC        VAR LONG
    TSECINT       VAR LONG
    TSECDEC       VAR LONG
    DISTINCH      VAR LONG
    DISTFT      VAR LONG
    DISTFT64    VAR BYTE[PRECISION]
    DISTFT64M   VAR BYTE[PRECISION]
    FPS32     VAR LONG
    FPS64         VAR BYTE[PRECISION]
    FPSINT      VAR LONG
    FPSINT64        VAR BYTE[PRECISION]
    FPSDEC      VAR LONG
    FPSDEC64      VAR BYTE[PRECISION]
    MPH64     VAR BYTE[PRECISION]
    MPHINT64    VAR BYTE[PRECISION]
    MPHDEC64    VAR BYTE[PRECISION]
    MPH32     VAR LONG
    MPHINT      VAR LONG
    MPHDEC      VAR LONG
    
    ' ****** Setup Variables with Initial Parameters and 64-BIT Constants
    I = 0
    J = 1
    PRESET = 3              '  ********** PER OVERFLOW LOOP TICS CORRECTION **********
    BITS16 = 65536 * 2          '  ********** COUNTS MAX * 200 NS PER TIC**********
    @  MOVE?LP  _BITS16, _BITS1664
    DISTINCH = 6000           ' ********** 6.000 inches  (MAX = 65.535 in) **********
    DISTFT = ((DISTINCH*10000)/12)
    @  MOVE?LP  _DISTFT, _DISTFT64      '  ********** CONVERT TO FEET **********
    AA32 = 1000000            '  ********** BUMP UP RESOLUTION
    @  MOVE?LP  _AA32, _AA64
    @  MATH_MUL  _DISTFT64, _AA64, _DISTFT64M '  ********** BUMP UP DISTANCE DIGITS
    CONVSEC = 600000000
    @  MOVE?LP  _CONVSEC, _CONVSEC64            '  ********** BUMP UP TIME DIGITS
    
    
    Pause 500
    LCDOUT $FE,1
    LCDOUT $FE,$80,"HIGH-RESOLUTION "
    LCDOUT $FE,$C0,"     TIMER      "
    LCDOUT $FE,$90,"  Version 6.10  "
    LCDOUT $FE,$D0," Robert Wozniak "
    
    DEBUG 10,13,10,13,10,13
    DEBUG "HIGH-RESOLUTION ",10,13 
    DEBUG "     TIMER      ",10,13
    DEBUG "  Version 6.10  ",10,13
    DEBUG " Robert Wozniak ",10,13,10,13,10,13
    
    For I = 1 to 5
    HIGH LED        ' Turn ON LED connected to PORTD.1
    Pause 50
    LOW LED
    PAUSE 50    ' Turn OFF LED connected to PORTD.1
    NEXT I
    I = 0
    
    ;----[High Priority Interrupts (DT_INTS_18)]----------------------------------------
    ASM
    INT_LIST  macro    ; IntSource,   Label,   Type, ResetFlag?
      INT_Handler   CCP1_INT,  _Capture,  PBP,  yes
      INT_Handler   TMR1_INT,  _Timer1,   PBP,  yes
        endm
        INT_CREATE               ; Creates the High Priority interrupt processor
    ENDASM
    
    CCP1CON = %00000101     ' Capture mode, capture on rising edge
    T1CON = 0               ' TMR1 prescale=1, clock=Fosc/4, TMR1=off (200nS per count @20MHz)
    @    INT_ENABLE  CCP1_INT    ; enable Capture interrupts
    to be concluded in next post due to length limitations.

    The timer has a 200 nS resolution and can go for 99Minutes: 99.9999999Seconds.

    Here is the Schematic of the setup

    The Full Resolution PDF file is here:
    http://www.picbasic.co.uk/forum/atta...1&d=1265519692

    Here is an photo of the actual Circuit:


    This timer was developed to use an input pulse from the 2-Beam Pulse Generator Circuit which I presented here:http://www.picbasic.co.uk/forum/showthread.php?t=12614

    While this code looks like an abomination, it's actually pretty cool that all the math is done with 64 bit precision.

    I'm pretty new at all this, so I'd really like to hear your comments or criticism.

    This is a work in progress. I have several features I'm still planning to include.

    I'll follow up with a post with some comments and limitations.

    Many thanks to Darrel, Bruce and Alexander for their excellent Code examples.
    Attached Images Attached Images   
    Attached Images Attached Images
    Attached Files Attached Files
    Wozzy-2010

  2. #2
    Join Date
    Jan 2010
    Location
    PHILADELPHIA, PA - USA
    Posts
    34


    Did you find this post helpful? Yes | No

    Default ...Continued

    Here is the rest of the Code:

    Code:
    Main:
    
    IF T1CON.0 <> 0 And I = 0 THEN
      LCDOUT $FE,1
      LCDOUT $FE,$C0,"   MEASURING"
      I = 1
      GOTO LCDEND 
    ENDIF
    
    IF T1CON.0 <> 0 THEN LCDEND
    IF T1CON.0 = 0 AND J = 0 THEN
    
    '********** CONVERT COUNTS, OVERFLOWS to SECONDS **********
    @  MOVE?LP  _OVRFLO, _OVFLS64
    @  MATH_MUL  _OVFLS64, _BITS1664, _OVFLS64M
       COUNTS32 = (COUNTS-10)*2           ' 10 TICS START CORRECTION,  200 nS PER COUNT
    @  MOVE?LP  _COUNTS32, _COUNTS64
    @  MATH_ADD  _OVFLS64M, _COUNTS64, _TSEC64
    
    ' ********** CONVERT SECONDS TO MINUTES **********
    @  MATH_DIV  _TSEC64, _CONVSEC64, _TMIN64
    @  MOVE?PL  _TMIN64, _TMIN
    
    ' ********** GET INTEGER SECONDS **********
       CC32 = 10000000
    @  MOVE?LP  _CC32, _CC64
    @  MATH_MUL  _TMIN64, _CONVSEC64, _AA64
    @  MATH_SUB  _TSEC64, _AA64, _BB64
    @  MATH_DIV  _BB64, _CC64, _TSECINT64
    @  MOVE?PL  _TSECINT64, _TSECINT
    
    ' ********** GET DECIMAL SECONDS **********
    @  MATH_MUL  _TSECINT64, _CC64, _AA64
    @  MATH_SUB  _BB64, _AA64,  _TSECDEC64
    @  MOVE?PL  _TSECDEC64, _TSECDEC
    
    ' ********** CALCULATE SPEED (FPS) **********
    @  MATH_DIV  _DISTFT64M, _TSEC64, _FPS64
    
    ' ********** GET INTEGER FPS **********
       CC32 = 1000000
    @  MOVE?LP  _CC32, _CC64
    @  MATH_DIV  _FPS64, _CC64, _FPSINT64
    @  MOVE?PL  _FPSINT64, _FPSINT
    
    ' ********** GET DECIMAL FPS **********
    @  MATH_MUL  _FPSINT64, _CC64, _BB64
    @  MATH_SUB  _FPS64, _BB64,  _FPSDEC64
    @  MOVE?PL  _FPSDEC64, _FPSDEC
    
    ' ********** CONVERT FPS to MPH **********
       AA32 = 15
    @  MOVE?LP  _AA32, _AA64
       BB32 = 22
    @  MOVE?LP  _BB32, _BB64
    @  MATH_MUL  _AA64, _FPS64, _CC64
    @  MATH_DIV  _CC64, _BB64, _MPH64
    
    ' ********** GET INTEGER MPH **********
       AA32 = 1000000
    @  MOVE?LP  _AA32, _AA64
    @  MATH_DIV  _MPH64, _AA64, _MPHINT64
    @  MOVE?PL  _MPHINT64, _MPHINT
    
    ' ********** GET DECIMAL MPH **********
    @  MATH_MUL  _MPHINT64, _AA64, _BB64
    @  MATH_SUB  _MPH64, _BB64,  _MPHDEC64
    @  MOVE?PL  _MPHDEC64, _MPHDEC
    
    ' ********** DISPLAY RESULTS **********
    LCDOUT $FE,1
    LCDOUT $FE,$80," ",DEC2 TMIN,":",DEC2 TSECINT,".",DEC7 TSECDEC
    LCDOUT $FE,$90, DEC4 FPSINT,".",DEC6 FPSDEC," FPS"
    LCDOUT $FE,$D0, DEC4 MPHINT,".",DEC6 MPHDEC," MPH"
    
    DEBUG "OVRFLO: ",DEC10 OVRFLO,13,10
    DEBUG "COUNTS: ",DEC10 COUNTS,13,10,13,10
    DEBUG "TIME: ",DEC2 TMIN,":", DEC2 TSECINT,".",DEC7 TSECDEC,13,10
    DEBUG "SPEED: ",DEC4 FPSINT,".",DEC6 FPSDEC," FPS",13,10
    DEBUG "SPEED: ",DEC4 MPHINT,".",DEC6 MPHDEC," MPH",13,10,13,10
    
    J = 1
    ENDIF
    GOTO LCDEND
    
    LCDEND: 
      PAUSE 25
        @    INT_ENABLE  CCP1_INT     ; Start new capture
    GOTO Main
    
    '---[CCP1 - interrupt handler]------------------------------------------
    Capture:
      IF CCP1CON = %00000101 THEN      ' If rising edge capture then
         HIGH LED            ' Turn on LED to Indicate Measuring
         TMR1L = PRESET                ' Clear Timer1 counts with Preset (High)
         TMR1H = 0             ' Clear Timer1 counts (LOW)
         T1CON.0 = 1                   ' Turn Timer1 on at rising edge capture
         OVRFLO = 0                   ' Zero Over flow counts
         COUNTS = 0                   ' Zero remainder
         CCP1CON = %00000100           ' Switch to falling edge capture
         PIR1.0 = 0                    ' Clear Timer1 overflow flag before enable
       I = 0 : J = 0
         @    INT_ENABLE  TMR1_INT     ; Enable Timer 1 Interrupts 
         GOTO OVER_CCP                 ' Done, exit
      ENDIF
       
      IF CCP1CON = %00000100 THEN      ' If falling edge capture then
         T1CON.0 = 0                   ' Stop Timer1
         CCP1CON = %00000101           ' Switch back to rising edge capture
         @    INT_DISABLE  TMR1_INT    ; Disable Timer 1 Interrupts
         @    INT_DISABLE  CCP1_INT    ; Disable CCP1 Interrupts
         COUNTS.LowByte = TMR1L       ' Get remaining Timer1 counts on falling edge (Low Byte)
         COUNTS.HighByte = TMR1H      ' Get remaining Timer1 counts on falling edge (High Byte)
      LOW LED             ' Turn off LED 
      ENDIF
    
    OVER_CCP:
    @ INT_RETURN
    
    '---[TMR1 - interrupt handler]---------------------------------------------
    Timer1:
    OVRFLO = OVRFLO + 1
    @ INT_RETURN
    END
    It wouldn't all fit in a single post

    --Bob
    Wozzy-2010

  3. #3
    Join Date
    Jan 2010
    Location
    PHILADELPHIA, PA - USA
    Posts
    34


    Did you find this post helpful? Yes | No

    Default Notes, Limitations and Future Features

    Features:
    1) MAXIMUM TIME: 99 MIN, 99.9999999 SEC ...Really just a display limitation
    2) MINIMUM TIME: 0.0000522 SEC also a display limit at 9999.999998 MPH
    3) Time Resolution: 200 nS = 0.0000002 SEC
    4) Input single PULSE to Pin RC2
    5) Displays Measurement and resets awaiting next pulse.
    6) Data is sent out to 57600 N-8-1 Serial terminal on Pin RC6
    7) Status LED shows when pulse is being timed.

    Comments:
    This was an experiment in precision of the code.
    No oscillator is really this accurate.
    Probably pretty close for relative measurements.
    But Not for absolute measurements

    Currently the speed is based on fixed distance of the optical sensors.
    they are fixed and hard coded at 6.000 inches.
    The circuit I use to derive the pulse is here:
    http://www.picbasic.co.uk/forum/showthread.php?t=12614

    Future Plans:
    1) Add additional speed units (M/S, KMH)
    2) Add user menu to set gate distance and displayed units
    3) Add an oscillator correction factor after comparing it to bench-top timer.
    4) Write settings to Onboard EEPROM
    5) Try a 40 MHz crystal oscillator or other High accuracy clock
    6) Build a thermal oven for crystal oscillator ...

    Enjoy,
    --Bob
    Wozzy-2010

  4. #4
    Join Date
    Jan 2010
    Location
    PHILADELPHIA, PA - USA
    Posts
    34


    Did you find this post helpful? Yes | No

    Default Include Files:

    Please note that there are three include files in the above code which are required for it to operate.

    N-BIT_Math.pbp
    At its core is the Multibyte Arithmetic Assembly Library that was written by Alexander Avtanski.
    The Assembly Library was wrapped for PBP by Darrel Taylor [Version:1.3 Beta (JAN 07,2010)]
    This library is used to assemble the 64-Bit high precision math,
    You can find reference to it in this PB Forum Thread:
    http://www.picbasic.co.uk/forum/showthread.php?t=12433

    DT_INTS-18.bas & ReEnterPBP-18.bas
    DT_INTS-18.bas is Darrel Taylor's Base Interrupt System for PIC18F [Version:3.3 (MAR 24, 2008)]
    ReEnterPBP-18.bas is Darrel Taylor's PBP interrupts for PIC18F [Version:1.4 (MAR 24, 2008)]
    Both can be referenced at this PB Forum Thread:
    http://www.picbasic.co.uk/forum/showthread.php?t=3251
    Or directly from Darrel Taylor's web page here:
    http://darreltaylor.com/DT_INTS-18/home.html
    Please note that there are different versions for (PIC12F, 14F, & 16F) and for PIC18F.

    --Bob
    Wozzy-2010

  5. #5
    Join Date
    May 2008
    Location
    Italy
    Posts
    825


    Did you find this post helpful? Yes | No

    Default

    WOZZY-2010, interesting project and well documented. Thank you for sharing it.

    Al.
    All progress began with an idea

Similar Threads

  1. SERIN MIDI out of Synch?
    By jncortes in forum mel PIC BASIC Pro
    Replies: 2
    Last Post: - 9th June 2009, 21:08
  2. Old and beyond help ?
    By DavidFMarks in forum mel PIC BASIC Pro
    Replies: 46
    Last Post: - 11th December 2008, 16:23
  3. Replies: 14
    Last Post: - 26th September 2007, 06:41
  4. sample code for M25P32
    By Pedro Santos in forum mel PIC BASIC Pro
    Replies: 1
    Last Post: - 9th January 2007, 03:37
  5. Serin and TMR0
    By capitano in forum mel PIC BASIC Pro
    Replies: 6
    Last Post: - 17th May 2006, 15:58

Members who have read this thread : 1

You do not have permission to view the list of names.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts