Frequency counter - Page 2


Yesterday 19:45
Forum: Proton Plus Compiler v3
Starter: glenlivet
Views: 0
Replies: 14
+ Reply to Thread
Page 2 of 2 FirstFirst 12
Results 11 to 20 of 20

Thread: Frequency counter135 days old

  1. #11
    Member teo's Avatar
    Join Date
    Sep 2010
    Posts
    266
    Thumbs Up
    Received: 9
    Given: 1
    Total Downloaded
    3.76 GB

    0 Not allowed!

    Default Re: Frequency counter

    Hello John,
    You can look a little over your code because CaptureFlag is permanently "0".
    Thanks in advance,
    Teo

  2. #12
    Administrator John Drew's Avatar
    Join Date
    Feb 2002
    Posts
    2,555
    Thumbs Up
    Received: 108
    Given: 29
    Total Downloaded
    2.69 GB

    0 Not allowed!

    Default Re: Frequency counter

    Hello Teo,
    Here is the complete program. It was used to read an encoder that provided a PWM output. I needed to convert the PWM to a period and then to a value in degrees which is sent out via serial to another PIC for interpretation and control functions.
    It definitely works in a 16F628A. Many examples of the project being used worldwide.
    John

    Code:
    '****************************************************************
    '*  Name    : PWMunit.BAS                                       *
    '*  Author  : John F Drew                                       *
    '*  Notice  : Copyright (c) 2007 [John F Drew]                  *
    '*          : All Rights Reserved                               *
    '*  Date    : 12/10/07                                          *
    '*  Version : 1.0                                               *
    '*  Notes   : Takes data from PWM on RB3 and puts AZ            *
    '*          : out a serial port if handshaking set              *
    '*            : data format A + word + check                           *
    '*            : check is a byte arithmetic sum of 3 data bytes    *
    '*            : if SW1 low make 180 degree offset to readings     *
    '*            : if SW2 low terminal mode sends data to term prog  *
    '*            : if SW3 low reverses count for alternate mounting  *
    '*          : style variable to allow ASCII elevation unit      *
    '*          : two data bytes in eedata 1 and 2 for finetuning   *
    '****************************************************************
    
    Device 16F628A
    Config WDT_OFF,PWRTE_ON,HS_OSC,CP_OFF,BODEN_OFF,LVP_OFF,MCLRE_ON     'set fuses 
    Declare Xtal=10
    'set up the serial port
    Hserial_Baud = 9600                        ' Set baud rate to 9600
    Hserial_RCSTA = 000000                  ' Enable serial port
    Hserial_TXSTA = 100000                  ' Enable transmit and asynchronous mode 
    
    'setup Timer1
    
    T1CON = 000001                       'set the divider to produce a 1:1 and timer1 enabled                                      
    CCP1CON = 0                             'PWM module off initially
    TRISB=001010                              '(outputs)    RB0, RB2, RB4, RB5, RB7
                                              '(inputs)     RB1,RB3,RB6
    TRISA=111101                           ' Configure A (PortA.0,A2-7) as inputs
                                              ' and A.1 as output
    Dim Azimuth                As Word            'the azimuth word
    Dim Azimuth1            As Dword        'used in inversion of direction
    Dim Check                As Word            'checksum out
    Dim Style               As Byte         'determines if a special elevation unit  0=normal
                                            'reads value in edata 0
    
    'following variables used in calculations converting binary to decimal
    Dim Degrees                As Word            'used in calculating angle
    Dim Step1                As Dword        'temp in calculations
    Dim PartDeg                As Word            'used in calculating part degrees
    Dim Tenths                As Word            'used in calculations part degrees
    
    'following variables used in developing total count for azimuth
    Dim CountDword          As Dword        'count referred to 4096
    Dim Loopcount           As Byte         'loop counter  
    Dim FirstCapture        As Word         'the timer count for first capture
    Dim SecondCapture       As Word         'the timer count for second capture
    Dim ThirdCapture        As Word         'timer count for third capture
    Dim PulseWidth          As Word         'pulse width in timer counts
    Dim Period              As Word         'the period of the wave
    Dim MultiplierAdd       As Byte         'added to multiplier to gain correct spread
    Dim OffsetSubtract      As Byte         'subtracted from pulse width to set zero
    Dim Multiplier          As Word         'the multiplier to convert to degrees
    
    'RB1,2 will be usart comms port
    
    Symbol SW1=PORTA.2                         'pin 1   SW1 unused in this mode
    Symbol DegreesOrWord=PORTA.3            'pin 2   SW2 if low sends Azimuth+degrees and no check
    Symbol SW3=PORTB.1                        'pin 7     SW3 invert the direction of count depending on mounting
    Symbol SerialOut=PORTB.2                'pin 8   RS232 out to shack
    Symbol PWMin=PORTB.3                    'pin 9   interrupt occurs on this pin from PWM
    Symbol Handshake=PORTB.6                'pin 12     handshaking pin, low=send data
    Symbol CaptureFlag = PIR1.2             'define the Capture flag 0=cleared, 1 = a TMR1 capture occurred
    Symbol L1LED = PORTB.4                  'indicates SW1 active - rotate by 180 deg
    Symbol L2LED = PORTB.5                  'indicates SW3 active - reverse rotation
    
    EData    $00                             'zero for normal use including azimuth, >0 for elevation unit 
                                            'note if using shack unit then this MUST be zero
    EData   $0D                             'added to 4096 multiplier 
    EData   $0B                             'subtracted from base reading of pulsewidth                                       
    All_Digital=true
    
    GoTo INITIALISE
    
    '********************** this section is the bringing in of the data from the PWM device ************************     
    
    GetData:    
            'set capture to every rising waveform
            TMR1L = 0                               'reset the timer to 0
            TMR1H = 0               
            CCP1CON = 000101                     'set ccp interrupt
            PIE1.2 = 0                              'clear the ccp1 interrupt bit
            CaptureFlag = 0                         'reset the flag after setting mode
            'configure time prescaler so that timer will run Tmax without overflow - done in general setup    
            'enable the CCP interrupt
            
            PIE1.2=1                                'set the interrupt on port B3 (CCP)         
    
            'save the captured timer value thus providing the zero count 
            While CaptureFlag=0:Wend                'wait for the flag to go high
            FirstCapture.LowByte=CCPR1L
            FirstCapture.HighByte=CCPR1H            'firstcapture now has value of timer         
            'set capture to every falling waveform
            CCP1CON = 000100                     'interrupt on falling waveform
            CaptureFlag=0                           'prepare for next interrupt must be reset after changing mode   
    
            'when CCP interrupt occurs again subtract saved value (T2) from previous captured value - pulse width
            While CaptureFlag=0:Wend                'wait for the flag to go high
            SecondCapture.LowByte=CCPR1L
            SecondCapture.HighByte=CCPR1H           'firstcapture now has value of timer 
            PulseWidth=SecondCapture - FirstCapture 'now we have the pulse width
            'set capture to every rising waveform
            CCP1CON = 000101 
            CaptureFlag=0                           'capture flag must be reset after change in mode to avoid false trigger
    
            'when CCP interrupt occurs again subtract saved value (T1) from this new value to give T, period of waveform
            While CaptureFlag=0:Wend                'wait for the flag to go high
            ThirdCapture.LowByte=CCPR1L
            ThirdCapture.HighByte=CCPR1H             'firstcapture now has value of timer 
            CaptureFlag=0                           'prepare for next interrupt 
            Period = ThirdCapture - FirstCapture    'now we have the period
            PIE1.2=0                                'disable the interrupt on port B3 (CCP)
            CCP1CON = 000000                     'turn off module
            If PulseWidth<=Period Then              'just in case of funnies at 0 degrees
                'Duty cycle=pulsewidth/period       'straight conversion would be 4096*pulsewidth
                PulseWidth = PulseWidth - OffsetSubtract  'adjust offset
                Multiplier = 4096 + MultiplierAdd         'adjust multiplier
                CountDword=Multiplier * PulseWidth        'modified numbers to get 360 spread and 0.1 minimum
                CountDword=CountDword/Period              'this is a value referred to 4096 and Duty cycle
            Else
                CountDword=0
            EndIf
            If CountDword > 4096 Then CountDword = 4096   'bring back to accepted limits
            If CountDword < 0 Then CountDword = 0         'probably needed only around 359 and 0 degrees
    Return
              
    '********************** end of PWM in section ***********************************
              
    CONVERT10BITS:                                                     
             'convert 12 bits to decimal degrees for ASCII to a terminal
              Step1=Azimuth * 45
              Degrees=Step1/512
              PartDeg=Step1 // 512           
              PartDeg=PartDeg * 10
              Tenths=PartDeg/512
              Step1=PartDeg // 512
              If Step1>255 Then 
                 If Tenths=9 Then
                             Inc Degrees
                             Tenths=0
                 Else
                               Inc Tenths
                 EndIf
              EndIf                 
              Return
                        
    INITIALISE:          
              DelayMS 100
              Loopcount=1                                               'set loop counter - not used
              Style = ERead 0                                           'o=normal, 1=elevation unit
              MultiplierAdd = ERead 1                                   'adjustments for pwm devices
              OffsetSubtract = ERead 2
    MAIN:
              GoSub GetData                                               'get the data in countdword
              
              Azimuth  = CountDword
              
              If SW3=0 Then                                             'invert the numbers
                    L2LED=1                                                'light led if switch on
                 Azimuth1 = Azimuth - 4096                              'to allow for reverse rotation
                    Azimuth = Abs Azimuth1
                 Else L2LED =0   
                 EndIf
                 
              If SW1=0 Then                                             'rotate degrees by 180
                    L1LED=1                                                'light led if switch on
                 Azimuth= Azimuth + 2048
                    If Azimuth >4096 Then
                       Azimuth=azimuth-4096
                    EndIf 
              Else L1LED=0        
                 EndIf
              
              If Handshake=0  Then                                      'shack wants data
                 If DegreesOrWord=0 Then                                'if SW2 high raw data else send to a terminal prog
                          GoSub CONVERT10BITS
                       If Style=0 Then 
                            HRSOut "AZIMUTH = ",Dec Degrees,".",Dec Tenths," ",13  'baud in declare, 8 data, no par, 1 stop
                       Else
                            HRSOut "ELEVATION = ",Dec Degrees,".",Dec Tenths," ",13  'baud in declare, 8 data, no par, 1 stop
                       EndIf     
                    Else 
                       If Style=0 Then
                        Loopcount=1
                        Check=65+ Azimuth + Loopcount                   'calculate checksum
                        HRSOut "A",Azimuth,Loopcount,Check                'send azimuth shackunit data out
                       Else
                        Check=69+ Azimuth + Loopcount                   'calculate checksum
                        HRSOut "E",Azimuth,Loopcount,Check                'send elevation shackunit data out
                       EndIf 
                 EndIf
              While Handshake=0: Wend   
              EndIf   
          
              GoTo MAIN
    End
    The code I posted previously was the GetData subroutine. The formatting has been messed up but I think it is still clear enough to follow. The whole program makes it a little clearer as to how it works. The code for determining the period of the PWM is just a conversion of the MicroChip guide.

  3. #13
    Member teo's Avatar
    Join Date
    Sep 2010
    Posts
    266
    Thumbs Up
    Received: 9
    Given: 1
    Total Downloaded
    3.76 GB

    0 Not allowed!

    Default Re: Frequency counter

    Hi John,
    Thousands of thanks
    Teo

  4. #14
    Prolific Poster See_Mos's Avatar
    Join Date
    Feb 2004
    Posts
    1,214
    Thumbs Up
    Received: 18
    Given: 0
    Total Downloaded
    614.99 MB

    0 Not allowed!

    Default Re: Frequency counter

    Hi Teo, did you get it working?
    My RAM is failing

  5. #15
    Member teo's Avatar
    Join Date
    Sep 2010
    Posts
    266
    Thumbs Up
    Received: 9
    Given: 1
    Total Downloaded
    3.76 GB

    0 Not allowed!

    Default Re: Frequency counter

    Hi See_Mos,
    Yes it works.
    For me it's not exactly what I need.
    I have to measure each period and transmit on the serial port.
    With this program I will transmit a period and the next will not be transmitted.
    I'm thinking of doing a thing with SN74LV8154 and a PIC18F26K22.
    All the best,
    Teo

  6. #16
    Prolific Poster See_Mos's Avatar
    Join Date
    Feb 2004
    Posts
    1,214
    Thumbs Up
    Received: 18
    Given: 0
    Total Downloaded
    614.99 MB

    0 Not allowed!

    Default Re: Frequency counter

    If it helps I have a low frequency DFM that was part of a bigger project. It would need some more work doing on it. At the moment it measures a full cycle then calculates and prints the frequency, not period, to an LCD display then waits for the next valid rising edge.

    It uses CCP1 on an 18F25K22. The lower the frequency the more stable the readings, up at 160Hz there is a bit of jitter but I only needed sub 80Hz.

    At the moment it is reading 1.045Hz with my Thurlby DDS generator set to 1.050Hz
    My RAM is failing

  7. #17
    Member teo's Avatar
    Join Date
    Sep 2010
    Posts
    266
    Thumbs Up
    Received: 9
    Given: 1
    Total Downloaded
    3.76 GB

    0 Not allowed!

    Default Re: Frequency counter

    Hi See_Mos,
    Thanks for the reply.
    Is it possible to post the program?
    Thank you in advance,
    Teo

  8. #18
    Prolific Poster See_Mos's Avatar
    Join Date
    Feb 2004
    Posts
    1,214
    Thumbs Up
    Received: 18
    Given: 0
    Total Downloaded
    614.99 MB

    0 Not allowed!

    Default Re: Frequency counter

    This is the main part, the .inc is just a setup file. I also added printing of the period count

    Code:
    $define _LCD_PORT_ 1                    ' LCD PortA = 0, PortB = 1, PortC = 2
    Include "18F25K22 IntOsc 16.inc"        ' setup LCD etc.
    'Include "18F25K22 Intosc 64.inc"
    
    Symbol TIMER1 = TMR1L.Word              ' Create a 16-bit variable out of TMR1L
    Symbol TIMER1_ON = T1CON.0
    Symbol CCP1REG = CCPR1L.Word
    
    Dim uS_Count As Dword                   ' Value from CCP capture
    Dim Edge_Count As Byte                  ' Edge counter
    Dim Frequency As Float                  ' Calculate frequency
    Dim Update_Flag As Byte                 ' Ready to update display
    Dim Overflow_Count As Byte              ' count overflow of timer 1
       
    All_Digital = True
    'Declare Watchdog = off    
    
        On_Interrupt GoTo My_Int
        GoTo Start                            ' jump over interrupt handler
    
    My_Int:
        Context Save
        
        If CCP1IF = True Then
            CCP1IF = False                   ' Clear CCP1 capture flag
            TIMER1_ON = False              ' Stop the clock
            Inc Edge_Count                 ' Increment edge counter
            If Edge_Count = 1 Then
                Clear TIMER1
                TIMER1_ON = True           ' First edge detected
            EndIf                          ' so start counting
            If Edge_Count = 2 Then         ' Second edge so
                Update_Flag = True         ' ready to print result
                CCP1IE = False
            EndIf
            GoTo INT_End
        EndIf
                 
        If TMR1IF = 1 Then               ' Below 15Hz timer 1 has overflowed
            TMR1ON = False               ' Stop the clock        
            Clear TIMER1                 ' Clear Timer1
            CCP1IF = 0                     ' Clear CCP1 capture flag
            TMR1IF = 0                     ' Clear Timer1 overflow flag
            Inc Overflow_Count           ' or for < 15Hz use this line
            TMR1ON = True
        EndIf            
    INT_End:
        Context Restore            ' Restore the registers and exit the interrupt       
    
    Start:
        Clear                   ' Clear variables
        TRISC = 000100       ' CCP1 input is PORTC.2
        DelayMS 100             ' 
     
        T1CON = 100011       ' setup timer 1 for 16MHz clock & count at @ 1MHz
    '    T1CON = 110011       ' or count @ 500KHz
    '            ||             ' select instruction clock = Fosc / 4 = 4MHz
    '              ||           ' prescaler = 1:4 = 1MHz
    '                |          ' secondary osc = off
    '                 |         ' Txsyns not applicable
    '                  |        ' TxRead = 16
    '                   |       ' Timer = On
           
        CCP1CON = 000101        ' Enable the CCP1 capture, every rising edge    
    '              ||           ' used for PWM
    '                ||         ' used for PWM
    '                  ||||     ' Prescaler (edge select)
    '                  0100     ' every falling edge
    '                  0101     ' every rising edge
    '                  0110     ' every fourth rising edge
    '                  0111     ' every sixteenth rising edge
    
        PIE1 = 000101    
    '                |          ' CCPIE  Capture compare 1 interrupt enable
    '                 |         ' TMR2IE Timer 2 interrupt enable
    '                  |        ' TMR1IE Timer 1 interrupt enable
        Cls
        Print At 1,1,"CCP V1.5"
        DelayMS 2000                ' time to read caption
        INTCON = 000000          ' Turn interrupts on
       
    MAIN_LOOP:
    While 1 = 1    
        If Update_Flag = 1 Then
            uS_Count = CCP1REG               ' Store the captured value
                                            ' and add overflow(s)
            uS_Count = uS_Count + Overflow_Count * 65535 
            Overflow_Count = 0              ' reset overflow counter
        ' ##################################################################
        ' adjust uS_COUNT or multiplier to calibrate
        ' ##################################################################            
            Frequency = 1000000 / uS_Count         ' for TIMER1 = 1MHz
        '    Frequency = 500300 / uS_COUNT         ' for 500KHz
        '    Print at 1,1,"uS_Count ",Dec us_Count * 2,"     "   ' for 500KHz
            Print At 1,1, "uS_COUNT ",Dec uS_Count, "     "
            Print At 2,1, "FREQUENCY ",Dec Frequency, "     "
            DelayMS 50    
            Edge_Count = 0                  ' reset edge counter
            Update_Flag = False             ' reset update flag   
            CCP1IF = False
            CCP1IE = True
        EndIf
    
    Wend
    My RAM is failing

  9. #19
    Member teo's Avatar
    Join Date
    Sep 2010
    Posts
    266
    Thumbs Up
    Received: 9
    Given: 1
    Total Downloaded
    3.76 GB

    0 Not allowed!

    Default Re: Frequency counter

    Hi, See_Mos
    Thank you very much,
    Teo

  10. #20
    Member teo's Avatar
    Join Date
    Sep 2010
    Posts
    266
    Thumbs Up
    Received: 9
    Given: 1
    Total Downloaded
    3.76 GB

    0 Not allowed!

    Default Re: Frequency counter

  11. Hi, See_Mos
    Your code works perfectly.
    Please help me to use ccp2 together with timer3 or other matching version.
    Will it work if two interrupts are generated simultaneously (ccp1 and ccp2)?
    It's the first time I have to use two interruptions and ..... I do not really know how.
    Thanks in advance,
    Teo

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

     

Similar Threads

  1. A Frequency Counter with the PIC16F628A
    By towlerg in forum WIKI Discussion
    Replies: 2
    Last Post: 12th May 2016, 19:27
  2. A Frequency Counter
    By AlbertoFS in forum WIKI Discussion
    Replies: 3
    Last Post: 14th July 2015, 18:26
  3. Frequency Counter - 40Mhz
    By CharlieBrown in forum The Lounge
    Replies: 15
    Last Post: 30th December 2014, 12:32
  4. Frequency Counter - complex
    By Jessica in forum Projects discussion
    Replies: 4
    Last Post: 30th January 2014, 09:32
  5. Parsing a frequency counter output.
    By david in forum The Lounge
    Replies: 31
    Last Post: 20th September 2013, 07:26

Members who have read this thread since 25th November 2018, 09:13 : 3

Actions :  (Set Date)  (Clear Date)

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