Menu

Measuring Pulse Width To Sub-Microsecond Resolution with PIC Capture & Compare

2015-05-13
2022-07-11
  • William Roth

    William Roth - 2015-05-13

    Microhip has published a "Compiled Tips 'N Tricks Guide " that tells "how" to do certain tasks with PIC 8-Bit Microcontrollers. Instead of providing code in ASM or C, this document provides the steps that need to be taken to perform the task. This makes it relatively straight forward to adapt to GREAT COW BASIC.

    In Chapter 3, Tip 3, the guide offers a tip on measuring pulse width using Timer 1 and a CCP module. I used this as the basis for the code that follows. However, I found that polling the CCP flag bit was more convenient than using an interrupt.

    In this example, I used a PIC 16F1829 operating at 32 Mhz with its internal oscillator. The GCB code uses Timer 1 and CCP4. However, any one of the four CCP modules could be used. Another PIC was used to generate the pulses to be measured. A TEK THS730A Scope was used to measure/verify pulse widths.

    The test setup uses a Cheap 4x20 LDC module with an I2C Backpack. However you could just as well use serial output to a terminal program to view the data.

    Resolution: With the Timer Prescaler at 1:8 and the Chip Frequency at 32 MHz the pulse width resolution is 1 microsecond. With the Timer Prescaler at 1:2 and the ChiP Frequency at 32MHz the resolution is 250 nanoseconds.

    Accuracy: Accuracy is dependent upon the accuracy of the system clock, but scope measurements show an accuracy of +- 1us from 3us to 1000us.

    Note: For a real application I would suggest adding a line or two of code that polls the TIMER1 overflow flag. IF the timer overflows, then either no pulse was detected or the pulse was longer than allowed by the prescaler/OSC settings. In this case, return a value of zero for pulse width.

    Here's the example code:

    =================================================

    #Chip 16F1829, 32
    #CONFIG MCLRE = OFF
    
    #define I2C_MODE Master
    #define I2C_DATA PORTA.2
    #define I2C_CLOCK PORTC.0
    #define I2C_DISABLE_INTERRUPTS ON
    '''Set up LCD
    #define LCD_IO 10
    #define LCD_SPEED FAST
    
    #define LCD_Backlight_On_State  1
    #define LCD_Backlight_Off_State 0
    
    CLS
    PRINT "Pulse Width Test"
    DIM PULSE_WIDTH AS WORD
    DIR PORTC.6 IN
    InitTimer1 OSC, PS1_8   'Change to PS1_2 for 250ns resolution 
    wait 1 s
    CLS
    
    DO  'MAIN LOOP
      PULSE_IN   'Get positive pulse width.
      Locate 0,0:  PRINT Pulse_Width: PRINT "    "
      wait 1 s
    Loop
    
    MACRO PULSE_IN  'Measure Pulse Width 
      'Configure CCP4  to Capture rising edge
       CCP4CON = 5   '00000101
       StartTimer 1
       CCP4IF = 0
    
      do while CCP4IF = 0    'Wait for rising edge
      loop
      TMR1H = 0: TMR1L = 0   'Clear timer to zero
      CCP4IF = 0             'Clear flag
      'Configure CCP4 to Capture Falling Edge
      CCP4CON = 4  '00000100'
    
      do while CCP4IF = 0   'Wait for falling edge
      loop
      StopTimer 1            'Stop the time
      Pulse_Width = TIMER1   'Save the timer value
      CCP4IF = 0             'Clear the CCP4 flag
    End MACRO
    
     
  • mkstevo

    mkstevo - 2015-05-21

    Many thanks. I was looking at porting some code from another language that measures frequency. Your example will be an enourmous help.

    Much appreciated.

     
  • mkstevo

    mkstevo - 2022-07-11

    A long belated thanks for this tip. I built a Grid Frequency Meter inspired by this suggestion and the design of that has been made the subject of an article in Elektor Magazine (July/August 2022).

    I made sure to reference this page citing it as the basis of the frequency measuring portion of the code.

    Thanks again.

     
    • Anobium

      Anobium - 2022-07-11

      Nice - well done.

      Got a copy of the article?

       

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.