• AVR Freaks

Hot!Frequency Counter PIC16F877A

Page: 12 > Showing page 1 of 2
Author
delfindelfin
Super Member
  • Total Posts : 387
  • Reward points : 0
  • Joined: 2017/01/19 12:32:58
  • Location: Mexico
  • Status: offline
2019/09/08 18:03:15 (permalink)
0

Frequency Counter PIC16F877A

I am trying to make a frequency counter using a pic16f877a and a Schmitt Trigger 74LS14
This is my code:

 
// Including C Standard Libraries
#include <stdint.h>
// Including XC8 Compiler Library
#include <xc.h>
// Including User's Libraries
#include "lcd.h"
 
 
 
// Defining Oscillator Frequency
#define _XTAL_FREQ 8000000
 
 
 
// CONFIGURATION BITS
#pragma config FOSC = HS // Oscillator Selection bits (HS oscillator)
#pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT enabled)
#pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT disabled)
#pragma config BOREN = ON // Brown-out Reset Enable bit (BOR enabled)
#pragma config LVP = OFF // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3 is digital I/O, HV on MCLR must be used for programming)
#pragma config CPD = OFF // Data EEPROM Memory Code Protection bit (Data EEPROM code protection off)
#pragma config WRT = OFF // Flash Program Memory Write Enable bits (Write protection off; all program memory may be written to by EECON control)
#pragma config CP = OFF // Flash Program Memory Code Protection bit (Code protection off)
 
 
 
void double_dabble_32_bit(char *NBCD_Ones, char *NBCD_Tens, char *NBCD_Hundreds, char *NBCD_Thousands, char *NBCD_Tens_Thousands, char *NBCD_Hundreds_Thousands, char *NBCD_Millions, char *NBCD_Tens_Millions, char *NBCD_Hundreds_Millions, char *NBCD_Billions, uint32_t binary ) // Range: 0-4,294,967,295
{

uint8_t Ones = 0;
uint8_t Tens = 0;
uint8_t Hundreds = 0;
uint8_t Thousands = 0;
uint8_t Tens_Thousands = 0;
uint8_t Hundreds_Thousands = 0;
uint8_t Millions = 0;
uint8_t Tens_Millions = 0;
uint8_t Hundreds_Millions = 0;
uint8_t Billions = 0;

uint8_t i;

for(i=0; i<32; i++) { // Dabble Double Algorithm to Convert Binary into BCD
Ones <<= 1;
Tens <<= 1;
Hundreds <<= 1;
Thousands <<= 1;
Tens_Thousands <<= 1;
Hundreds_Thousands <<= 1;
Millions <<= 1;
Tens_Millions <<= 1;
Hundreds_Millions <<= 1;
Billions <<= 1;

if (binary & 0x80000000) { // xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx & 1000 0000 0000 0000 0000 0000 0000 0000 = x000 0000 0000 0000 0000 0000 0000 0000
Ones++;
}
if (Ones >= 10) {
Ones -= 10;
Tens++;
}
if (Tens >= 10) {
Tens -= 10;
Hundreds++;
}
if (Hundreds >= 10) {
Hundreds -= 10;
Thousands++;
}
if (Thousands >= 10) {
Thousands -= 10;
Tens_Thousands++;
}
if (Tens_Thousands >= 10){
Tens_Thousands -= 10;
Hundreds_Thousands++;
}
if (Hundreds_Thousands >= 10){
Hundreds_Thousands -= 10;
Millions++;
}
if (Millions >= 10){
Millions -= 10;
Tens_Millions++;
}
if (Tens_Millions >= 10){
Tens_Millions -= 10;
Hundreds_Millions++;
}
if (Hundreds_Millions >= 10){
Hundreds_Millions -= 10;
Billions++;
}
binary <<= 1;
}

*NBCD_Ones = Ones; // Assigning BCD Values to Sensor Reading Values
*NBCD_Tens = Tens;
*NBCD_Hundreds = Hundreds;
*NBCD_Thousands = Thousands; // Assigning BCD Values to Sensor Reading Values
*NBCD_Tens_Thousands = Tens_Thousands;
*NBCD_Hundreds_Thousands = Hundreds_Thousands;
*NBCD_Millions = Millions;
*NBCD_Tens_Millions = Tens_Millions;
*NBCD_Hundreds_Millions = Hundreds_Millions;
*NBCD_Billions = Billions;

*NBCD_Ones += '0'; // Convert to ASCII
*NBCD_Tens += '0';
*NBCD_Hundreds += '0';
*NBCD_Thousands += '0'; // Assigning BCD Values to Sensor Reading Values
*NBCD_Tens_Thousands += '0';
*NBCD_Hundreds_Thousands += '0';
*NBCD_Millions += '0';
*NBCD_Tens_Millions += '0';
*NBCD_Hundreds_Millions += '0';
*NBCD_Billions += '0';
 
 
 
}
 
 
 
uint8_t old_RB4 = 0;
 
 
 
uint8_t frequency = 0;
uint32_t delay_total;
uint8_t computation_cycle = 0;

void __interrupt() ISR()
{

uint8_t delay_high;
uint8_t delay_low;

uint8_t new_RB4 = PORTBbits.RB4;

if(old_RB4 != new_RB4){
PORTCbits.RC4 = 1;

if(new_RB4 == 1){
delay_low = TMR0;

INTCONbits.TMR0IF = 0; // Clearing Timer 0 interrupt flag
TMR0 = 0; // Load the time value for 1ms delay: TMR0_RegValue = 256-((1ms*8MHz)/(32*4)) = 256 - 62.5 = 193.5
INTCONbits.TMR0IE = 1; // Enabling Timer 0 interrupt

computation_cycle = 1;
}else{
delay_high = TMR0;

INTCONbits.TMR0IF = 0; // Clearing Timer 0 interrupt flag
TMR0 = 0; // Load the time value for 1ms delay: TMR0_RegValue = 256-((1ms*8MHz)/(32*4)) = 256 - 62.5 = 193.5
INTCONbits.TMR0IE = 1; // Enabling Timer 0 interrupt
}

}


if(computation_cycle == 1)
{
delay_total = ( ((256-delay_low)*((uint32_t)128)*4) + (256-delay_high)*((uint32_t)128)*4 ) ;
//delay_total = delay_high;
//delay_total = (256-delay_low) + (256-delay_high) ;
//delay_total = (((256-delay_low)*(128)*4) + ((256-delay_high)*(128)*4));
delay_total = delay_total;
//delay_total = ( (((256-delay_low)*(128)*4) + ((256-delay_high)*(128)*4)) * 1000) /8000000 ;

}


//__delay_ms(1);
INTCONbits.RBIF = 0; // Resetting the RB port change interrupt flag
}

void main(void)
{
// Initiating General Configurations ///////////////////////////////////////////
TRISCbits.TRISC4 = 0; // RD4 as a Output
PORTCbits.RC4 = 0; // RD4 set Off

// LCD Initiation ////////////////////////////////////////////////////////////
TRISD = 0x00;
//TRISC = 0x00;

//Lcd_Initiation();
Lcd_Four_Bit_Init();

Lcd_Set_Cursor(1,1);
Lcd_Display_String("Counter0");

Lcd_Set_Cursor(1,2);
Lcd_Display_String("Hello World");

//Lcd_Eight_Bit_Init();
//Lcd_Init_CG();

//__delay_ms(2000);

Lcd_Clear();

char ones = '0';
char tens = '0';
char hundreds = '0';
char thousands = '0';
char tens_thousands = '0';
char hundreds_thousands = '0';
char millions = '0';
char tens_millions = '0';
char hundreds_millions = '0';
char billions = '0';

// Initiating Interrupt Configurations ///////////////////////////////////////////
TRISBbits.TRISB4 = 1; // RB4 as a Input
//OPTION_REG = 0x00;
OPTION_REGbits.nRBPU = 0; // Enables PULL UPs

INTCONbits.GIE = 1; // Enable Global Interrupt
//INTCONbits.PEIE = 1; // Enable the Peripheral Interrupt
//INTCONbits.INTE = 1; // Enable RB0 as external Interrupt pin
INTCONbits.RBIE = 1; // Enables the RB port change interrupt

// Timer 0 Configuration ///////////////////////////////////////////////////
OPTION_REGbits.T0CS = 0; // TMR0 with internal Clock

OPTION_REGbits.PSA = 1; // Prescalar assigned to TMR0 Module

OPTION_REGbits.PS2 = 1;
OPTION_REGbits.PS1 = 1;
OPTION_REGbits.PS0 = 0; // TMR0 Prescaler Rate as 1:128

// Main Function ///////////////////////////////////////////////////////////
while(1) {

Lcd_Set_Cursor(1,1);
Lcd_Display_String("TMR0:");

if(computation_cycle ==1)
{
double_dabble_32_bit(&ones, &tens, &hundreds, &thousands, &tens_thousands, &hundreds_thousands, &millions, &tens_millions, &hundreds_millions, &billions, delay_total);

Lcd_Display_Char(billions);
Lcd_Display_Char(hundreds_millions);
Lcd_Display_Char(tens_millions);
Lcd_Display_Char(millions);
Lcd_Display_Char(hundreds_thousands);
Lcd_Display_Char(tens_thousands);
Lcd_Display_Char(thousands);
Lcd_Display_Char(hundreds);
Lcd_Display_Char(tens);
Lcd_Display_Char(ones);

}
 
 
 


old_RB4 = PORTBbits.RB4; // Storing Original PORTB value

PORTCbits.RC4 = 0; // LED Off
//PORTD = 0x00; // LEDs Off
}
}
 
 
 
 
 
 
 

I am still debugging, so it has still many problem, but the one that I am stuck right now, is this line of code:
 

 
 
 
if(computation_cycle == 1)
{
delay_total = ( ((256-delay_low)*((uint32_t)128)*4) + (256-delay_high)*((uint32_t)128)*4 ) ;
//delay_total = delay_high;
//delay_total = (256-delay_low) + (256-delay_high) ;
//delay_total = (((256-delay_low)*(128)*4) + ((256-delay_high)*(128)*4));
delay_total = delay_total;
//delay_total = ( (((256-delay_low)*(128)*4) + ((256-delay_high)*(128)*4)) * 1000) /8000000 ;

}
 
 
 
 

 
 
 
if I do this, just adding a single one:
 

 
 
 
delay_total = delay_total+1;
 
 
 

The system stops working. I attached two images of the digital analysis, one with adding one, and the other without adding one 
 
post edited by delfindelfin - 2019/09/08 18:12:13

Attached Image(s)


MPLAB X IDE v5.05
XC8 2.00
#1

29 Replies Related Threads

    PStechPaul
    Super Member
    • Total Posts : 2810
    • Reward points : 0
    • Joined: 2006/06/27 16:11:32
    • Location: Cockeysville, MD, USA
    • Status: online
    Re: Frequency Counter PIC16F877A 2019/09/08 19:09:56 (permalink)
    0
    I can't figure out what you are trying to do. Are you trying to display the frequency of the waveform presented on RB4? What range of frequency and what resolution are you looking for? I don't know the time base of your digital analysis image. And it looks like you are displaying the value of TMR0, but 0000233984 is not valid for that timer.
     
    Please explain the algorithm you are using to display the frequency (assuming that is what you want). Also, you could be having RMW issues writing to the port.

     
    #2
    delfindelfin
    Super Member
    • Total Posts : 387
    • Reward points : 0
    • Joined: 2017/01/19 12:32:58
    • Location: Mexico
    • Status: offline
    Re: Frequency Counter PIC16F877A 2019/09/08 20:12:03 (permalink)
    0
    It is a little bit long, so, that's why I didn't explain it, but here it is:
    What I am doing, is generating a sinusoidal wave, to be honest, I don't remember the exact frequency since I have tested a lot of different ones, but, let's start with a frequency of 1 hz .. What the Schmitt Trigger does is to convert the Sinusoidal wave into a 0-5 V square wave .. I am reading that signal in RB4.. I choose that because I want to use the Interrupt on Change Feature, and what my code was supposed to do is that when an Interrupt on Change happens from High lo Low, I set the Timer0 and I obtain "delay0", and when an Interrupt on Change happens from Low to High, I also set the Timer0 and I obtain "delay1" ... The idea is to add delay0 and delay1 to obtain delay_total, and the frequency should be then 1/delay_total and I display that on the LCD .. I am currently debugging, so TMR0 does not correspond with 0000233984 .. I think that is an attempt to obtain delay_total .. But I am unable to do it since, at some point, the LCD freezes when I add 1
     
    Edit.
    Oh, yes, that is an attempt to obtain delay_total ... I think the correct expression to obtain delay_total in ms is:

     
     
     
    delay_total = ( (((256-delay_low)*((uint8_t)128)*4) + ((256-delay_high)*((uint8_t)128)*4)) * 1000) /8000000
     
     
     

    But if I do that, the program freezes, so I was debugging, this line of code seems to be working:
     

     
     
     
    delay_total = ( ((256-delay_low)*((uint32_t)128)*4) + (256-delay_high)*((uint32_t)128)*4 ) ; 
     
     
     

    But when I do anything else to that line of code, the program stops
     
    Edit2
    I want to measure the frequency of the AC Power Socket .. To do that I am going to use a 127-12 Volts transformer .. So, I want to read 60 hz .. But, for the purpose of debugging in the simulation I am using a lower frequency  .. I think what the digital analysis simulation is displaying is ms
    post edited by delfindelfin - 2019/09/08 20:25:40

    MPLAB X IDE v5.05
    XC8 2.00
    #3
    pcbbc
    Super Member
    • Total Posts : 1703
    • Reward points : 0
    • Joined: 2014/03/27 07:04:41
    • Location: 0
    • Status: offline
    Re: Frequency Counter PIC16F877A 2019/09/09 00:49:34 (permalink)
    +1 (1)
    What frequency are you trying to measure?
    What clock rate is your PIC running at?

    My guess is that by adding extra code to the ISR you are pushing it over the edge and there is no longer sufficient time to service your interrupts and execute any code in main. Basically your program is stuck 100% of the time in the ISR. All that other calculation code that you have commented out in there, if you ever used that, would certainly cause you huge problems too.

    Doing 32 bit integer multiplies in the ISR probably isn’t helping, unless the compiler has been clever enough to convert them to left shifts by 9. Even then probably not hugely efficient and you have a multiply by 1000 and divide by 8000000 (which cannot be optimised to shifts as not powers of 2) in the first expression. Also a full 32 bits is not required here, since the maximum size of your delay_total result will fit in 24 bits.

    There is also a common factor of 1000, so that multiply by 1000 is pointless. You might as well just divide by 8000.

    1. Do all your expensive calculations in main. The ISR should just capture a value or values, but not do any calculations on it (Certainly no integer multiply or divide. Some shifts and additions may occasionally be appropriate to combine values).
    2. Using IOC and TMR0 to measure frequency is a very poor choice. PICs have dedicated hardware for measuring intervals far more precisely. You might get away with IOC if you are only measuring 60Hz and don’t care much about accuracy.
    3. Your confusion over casting to either uint_8 or uint32_t in your suggested expressions shows you probably haven’t thought through either or why you need them.
    #4
    pcbbc
    Super Member
    • Total Posts : 1703
    • Reward points : 0
    • Joined: 2014/03/27 07:04:41
    • Location: 0
    • Status: offline
    Re: Frequency Counter PIC16F877A 2019/09/09 00:52:43 (permalink)
    0
    Edit:
    Oh, and you can do the add of low and high parts first, and then multiply by 128*4=512 (left shift 9). That way only a single shift, rather than 2.
    #5
    delfindelfin
    Super Member
    • Total Posts : 387
    • Reward points : 0
    • Joined: 2017/01/19 12:32:58
    • Location: Mexico
    • Status: offline
    Re: Frequency Counter PIC16F877A 2019/09/09 02:15:34 (permalink)
    0
    pcbbc
    2. Using IOC and TMR0 to measure frequency is a very poor choice. PICs have dedicated hardware for measuring intervals far more precisely. You might get away with IOC if you are only measuring 60Hz and don’t care much about accuracy.

    What do I need to use then? How do I measure frequency more precisely?

    MPLAB X IDE v5.05
    XC8 2.00
    #6
    ric
    Super Member
    • Total Posts : 27972
    • Reward points : 0
    • Joined: 2003/11/07 12:41:26
    • Location: Australia, Melbourne
    • Status: offline
    Re: Frequency Counter PIC16F877A 2019/09/09 02:28:52 (permalink)
    +2 (2)
    Use the CCP in capture mode to capture the precise timer value on the signal edge.
     

    I also post at: PicForum
    Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
    NEW USERS: Posting images, links and code - workaround for restrictions.
    To get a useful answer, always state which PIC you are using!
    #7
    pcbbc
    Super Member
    • Total Posts : 1703
    • Reward points : 0
    • Joined: 2014/03/27 07:04:41
    • Location: 0
    • Status: offline
    Re: Frequency Counter PIC16F877A 2019/09/09 02:39:03 (permalink)
    +2 (2)
    delfindelfinWhat do I need to use them? How do I measure frequency more precisely?

    Have a look at section 8.0 CAPTURE/COMPARE/PWM MODULES in the datasheet.
    Use the capture mode.  See section 8.1 Capture Mode for a description.
     
    In this mode every time there is an edge on RC2/CCP1 the value of TMR1 will be automatically copied to CCPR1H:CCPR1L register pair and you will get an interrupt (if enabled).
    If you subtract the value of CCPR1 saved from the previous interrupt from the current value you will get the number of elapsed TMR1 ticks between your clock edges.
    This will be as accurate as the TMR1 clock source, because the hardware reads/saves the timer value so there is no software delay while the ISR gets called and before you access and save the timer value in your code.
     
    If you require better accuracy, or need to measure higher frequencies, set the capture mode hardware to every 4th, or every 16th, rising edge so you don't get as many interrupts, and any measurement error is split over multiple cycles.  Then multiply your calculated frequency by 4/16.  Alternatively you can just count more cycles in your code and do the required averaging there.
     
    However really you should start by deciding what accuracy are you trying to achieve, and what range of frequencies are you trying to measure.  Only then can we/you say what method is appropriate.  If you are only measuring mains, for example in order to differentiate 50Hz and 60Hz in a digital clock, then no great degree of accuracy is required.
    #8
    pcbbc
    Super Member
    • Total Posts : 1703
    • Reward points : 0
    • Joined: 2014/03/27 07:04:41
    • Location: 0
    • Status: offline
    Re: Frequency Counter PIC16F877A 2019/09/09 03:06:36 (permalink)
    +2 (2)
    Also your double dabble is getting out of hand with all those separate pointers for each digit.
    Try passing a point to an array of char instead.  Added advantage you can use the string output function, rather than outputting a character at a time.
    void double_dabble_32_bit(char *result, uint32_t binary) // Range: 0-4,294,967,295
    {
        uint8_t i,j;
        for (j=0; j<11; j++) result[j] = 0;
     
        for(i=0; i<32; i++) { // Dabble Double Algorithm to Convert Binary into BCD
            for (j=0; j<10; j++) result[j] <<= 1;
     
            if (binary & 0x80000000) { // xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx & 1000 0000 0000 0000 0000 0000 0000 0000 = x000 0000 0000 0000 0000 0000 0000 0000
                result[9]++;    //Ones
            }
            for (j=9; j>0; j--) {
                if (result[j] >= 10) {
                    result[j] -= 10;
                    result[j-1]++;
                }
            }
            binary <<= 1;
        }
        for (j=0; j<10; j++) result[j] += '0';
    }

    void main(void)
    {
        char decimal[11];
        
        while(1) {
            double_dabble_32_bit(decimal, delay_total);
            Lcd_Display_String(decimal);
     
        }
    }

    #9
    delfindelfin
    Super Member
    • Total Posts : 387
    • Reward points : 0
    • Joined: 2017/01/19 12:32:58
    • Location: Mexico
    • Status: offline
    Re: Frequency Counter PIC16F877A 2019/09/09 04:26:15 (permalink)
    0
    pcbbc
    However really you should start by deciding what accuracy are you trying to achieve, and what range of frequencies are you trying to measure.  Only then can we/you say what method is appropriate.  If you are only measuring mains, for example in order to differentiate 50Hz and 60Hz in a digital clock, then no great degree of accuracy is required.

    For the moment, I want to measure mains, I don't know how much varies .. It is supposed to be 60 Hz +- something ... I guess the accuracy depends on that "Something", but I have no idea of what value could have .. I am going to study the capture mode, I hope it is not too hard to grasp  ..
    post edited by delfindelfin - 2019/09/09 04:28:16

    MPLAB X IDE v5.05
    XC8 2.00
    #10
    pcbbc
    Super Member
    • Total Posts : 1703
    • Reward points : 0
    • Joined: 2014/03/27 07:04:41
    • Location: 0
    • Status: offline
    Re: Frequency Counter PIC16F877A 2019/09/09 04:57:48 (permalink)
    +1 (1)
    delfindelfin
    For the moment, I want to measure mains, I don't know how much varies

    Depends where you are.
     
    In Europe, short term (minutes to hours) it can vary quite a bit, depending on active load.  Long term (over days to months) it will be incredibly accurate, because steps are (usually) taken to ensure that it is kept within spec for timekeeping purposes.
     
    See this article for some background about what can happen when things go wrong (and Europe temporarily lost 6 minutes for a few months).
     
    Also you can see the live UK or French grid statuses which include frequency.  The EU/French frequency doesn't seem to be working at the moment, but in the UK we currently have 50.070Hz (presumably we making up some time).
    #11
    delfindelfin
    Super Member
    • Total Posts : 387
    • Reward points : 0
    • Joined: 2017/01/19 12:32:58
    • Location: Mexico
    • Status: offline
    Re: Frequency Counter PIC16F877A 2019/09/09 11:06:53 (permalink)
    0
    Well, that's neat .. I live in Mexico, so, I guess is going to be fun find that out .. Also I would like to use a Real Time Clock and an SD Adapter to make some kind of grid datalogger .. I have used RTCs and SD Adapters with arduino, but I don't know how to implement the SD Adapter with PICs .. It looks a little bit complex to me https://www.convict.lu/pd.ProdManualSDCardv1.9.pdf
    post edited by delfindelfin - 2019/09/09 11:10:27

    MPLAB X IDE v5.05
    XC8 2.00
    #12
    PStechPaul
    Super Member
    • Total Posts : 2810
    • Reward points : 0
    • Joined: 2006/06/27 16:11:32
    • Location: Cockeysville, MD, USA
    • Status: online
    Re: Frequency Counter PIC16F877A 2019/09/09 11:55:50 (permalink)
    +2 (2)
    Measuring low frequency is often accomplished by reading the period between two (or more) rising or falling ZC transitions, and converting to frequency by calculating the reciprocal. High frequencies are usually measured by counting ZC transitions over a certain period of time, such as one second. A 60 Hz signal would read just 59, 60, or 61. If you use 10 seconds, you get greater precision, with readings of 59.9, 60.0, 60.1, etc. If you measure the period using a timer running at 100 kHz, you will get 1667 counts at 60 Hz, and a precision of 1/1667 = 0.06%, which will be displayed as 59.964, 60.000, 60.036, etc. You can get four or 16 times better resolution by sampling every four or 16 ZC transitions.
     
    Another way to get high resolution for low frequency measurement is to use a phase lock loop, such as the 74HC4046, and a 74HC390 dual decade counter, to multiply the frequency (say, 60 Hz), to 6000 Hz. Then you can get a reading of 59.99, 60.00, or 60.01 Hz by totalizing counts over a 1 second period. It may even be possible to use an additional decade counter to obtain 60 kHz and frequency readings to 0.001 Hz resolution. This method also eliminates the need to perform the inverse function and conversion from binary to BCD. I've done this myself, but it was sometimes difficult to get the PLL locked in and stable.

     
    #13
    PStechPaul
    Super Member
    • Total Posts : 2810
    • Reward points : 0
    • Joined: 2006/06/27 16:11:32
    • Location: Cockeysville, MD, USA
    • Status: online
    delfindelfin
    Super Member
    • Total Posts : 387
    • Reward points : 0
    • Joined: 2017/01/19 12:32:58
    • Location: Mexico
    • Status: offline
    Re: Frequency Counter PIC16F877A 2019/09/09 20:59:33 (permalink)
    0
    I have never used the Capture Mode on PICs, but the code would be something like this, right?
    post edited by delfindelfin - 2019/09/09 21:04:40

    MPLAB X IDE v5.05
    XC8 2.00
    #15
    ric
    Super Member
    • Total Posts : 27972
    • Reward points : 0
    • Joined: 2003/11/07 12:41:26
    • Location: Australia, Melbourne
    • Status: offline
    Re: Frequency Counter PIC16F877A 2019/09/09 21:18:58 (permalink)
    +1 (1)
    Do NOT zero the timer in the interrupt service, just let it keep running.
    Read the CCPR1H and CCPR1L registers inside the ISR, and save them to your variables.
    On the NEXT interrupt service, subtract the previous value saved for CCPRH/L from the new value.
    That gives you precisely how many timer counts occurred between the two interrupt services.
     
    Note, so long as you use unsigned arithmetic, it does NOT matter if the timer has rolled over back to zero between the two captures (so the second value is smaller than the first).
     
    If there is any possibility of the two interrupts being further apart than one complete count of the timer register (0x10000 counts), then you need to check the timer interrupt request bit also, and track how often the timer rolls over. This then needs to be added to the calculated difference.

    I also post at: PicForum
    Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
    NEW USERS: Posting images, links and code - workaround for restrictions.
    To get a useful answer, always state which PIC you are using!
    #16
    delfindelfin
    Super Member
    • Total Posts : 387
    • Reward points : 0
    • Joined: 2017/01/19 12:32:58
    • Location: Mexico
    • Status: offline
    Re: Frequency Counter PIC16F877A 2019/09/10 10:24:44 (permalink)
    0
    ric
    If there is any possibility of the two interrupts being further apart than one complete count of the timer register (0x10000 counts), then you need to check the timer interrupt request bit also, and track how often the timer rolls over. This then needs to be added to the calculated difference.

    Well, with that you can measure any slow frequency that you want ..
     
    Here is my final code, I think it is working in the range of 0.0038.. Hz to 250 Hz, although I guess it can be improved ..
    In the simulation I am generating 60 Hz and the LCD displays a delay of 16 ms .. The correct answer is 16.6666 ... ms. I not sure of how many decimals should be correct to take .. I guess we are back to the question of how much accuracy is desirable to achieve .. 
     
    Edit.
    Yes, I think it is important to know how much accuracy it is desired, because with 16 ms you get 62 Hz, instead of 60 Hz .. So, I'm going to think how to fix that 
     
     
     
    post edited by delfindelfin - 2019/09/10 10:40:35

    Attached Image(s)


    MPLAB X IDE v5.05
    XC8 2.00
    #17
    delfindelfin
    Super Member
    • Total Posts : 387
    • Reward points : 0
    • Joined: 2017/01/19 12:32:58
    • Location: Mexico
    • Status: offline
    Re: Frequency Counter PIC16F877A 2019/09/10 11:42:37 (permalink)
    0
    What is a ZC transition?

    MPLAB X IDE v5.05
    XC8 2.00
    #18
    mbrowning
    USNA79
    • Total Posts : 1791
    • Reward points : 0
    • Joined: 2005/03/16 14:32:56
    • Location: Melbourne, FL
    • Status: online
    Re: Frequency Counter PIC16F877A 2019/09/10 11:45:13 (permalink)
    +1 (1)
    Well, Z stands for Zero
    #19
    delfindelfin
    Super Member
    • Total Posts : 387
    • Reward points : 0
    • Joined: 2017/01/19 12:32:58
    • Location: Mexico
    • Status: offline
    Re: Frequency Counter PIC16F877A 2019/09/10 14:11:28 (permalink)
    +1 (1)
    mbrowning
    Well, Z stands for Zero


    and  C stands for what? is it Zero Crossing? I think it is Zero Crossing Transitions ..
    post edited by delfindelfin - 2019/09/10 14:14:26

    MPLAB X IDE v5.05
    XC8 2.00
    #20
    Page: 12 > Showing page 1 of 2
    Jump to:
    © 2020 APG vNext Commercial Version 4.5