| 
	
	|  |  |  
	
		| View previous topic :: View next topic |  
		| Author | Message |  
		| theasus 
 
 
 Joined: 31 May 2009
 Posts: 79
 
 
 
			    
 
 | 
			
				| Frequency meter with Pic 16F877 |  
				|  Posted: Tue Jan 05, 2010 11:00 am |   |  
				| 
 |  
				| I want to design a frequency meter. Actually I will count pulses for one minute? Could you propose any method for this operation please? I think RB0 can be usefull but I couldn't determine yet. |  |  
		|  |  
		| PCM programmer 
 
 
 Joined: 06 Sep 2003
 Posts: 21708
 
 
 
			    
 
 |  |  
		|  |  
		| theasus 
 
 
 Joined: 31 May 2009
 Posts: 79
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Sun Jan 10, 2010 3:56 am |   |  
				| 
 |  
				| Ok I found a code for this operation but I couldn't understand some codes as shown below; 
 
  	  | Code: |  	  | 1-#define BytePtr(var, offset) (char *)((char*)&var + offset)
 ------------------------------------------------------------------
 2-*BytePtr(current_ccp, 2) = timer_ext_copy;
 ----------------------------------------------------------------------
 3-g32_ccp_delta = (current_ccp > old_ccp) ? current_ccp - old_ccp : current_ccp + (0x1000000 - old_ccp);
 
 | 
 ---------------------------------------------------------------------------
 -----------------------------------------------------------------------------
 Here is my program;
 
  	  | Code: |  	  | #include <16F877.H>
 #fuses HS,NOWDT, PUT, BROWNOUT, NOLVP // 20 MHz xtal
 #use delay(clock=20000000)
 #use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
 #priority CCP1, TIMER1
 #define BytePtr(var, offset) (char *)((char*)&var + offset)
 #byte PIR1 = 0xF9E
 #bit  TMR1IF = PIR1.0
 int8  gc_timer1_extension = 0;
 int8  gc_capture_flag = FALSE;
 int32 g32_ccp_delta;
 //------------------------------------------------------
 #int_timer1
 void timer1_isr(void)
 {
 gc_timer1_extension++;
 }
 //------------------------------------------------------
 #int_ccp1
 void ccp1_isr(void)
 {
 char timer_ext_copy;
 int32 current_ccp;
 static int32 old_ccp = 0;
 gc_capture_flag = TRUE;
 current_ccp = (int32)CCP_1;
 timer_ext_copy = gc_timer1_extension;
 if(TMR1IF)
 {
 if(*BytePtr(current_ccp, 1) < 2)
 timer_ext_copy++;
 gc_timer1_extension++;
 TMR1IF = 0;
 }
 
 *BytePtr(current_ccp, 2) = timer_ext_copy;
 g32_ccp_delta = (current_ccp > old_ccp) ? current_ccp - old_ccp : current_ccp + (0x1000000 - old_ccp);
 old_ccp = current_ccp;
 }
 //=======================
 void main()
 {
 float frequency;
 int32 current_ccp_delta;
 
 set_timer1(0);
 setup_timer_1(T1_INTERNAL | T1_DIV_BY_1);
 setup_ccp1(CCP_CAPTURE_RE);
 clear_interrupt(INT_TIMER1);
 enable_interrupts(INT_TIMER1);
 clear_interrupt(INT_CCP1);
 enable_interrupts(INT_CCP1);
 enable_interrupts(GLOBAL);
 
 while(1)
 {
 if(gc_capture_flag == TRUE)
 {
 disable_interrupts(GLOBAL);
 current_ccp_delta = g32_ccp_delta;;
 enable_interrupts(GLOBAL);
 frequency =  (5000000L / (float)current_ccp_delta);
 printf("%4.2f\n\r", frequency);
 gc_capture_flag = FALSE;
 }
 }
 }
 
 | 
 Thanks for considering...
 |  |  
		|  |  
		| lopb 
 
 
 Joined: 09 Dec 2010
 Posts: 6
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Thu Dec 09, 2010 9:26 am |   |  
				| 
 |  
				| Hi, I'm using this code in a 18f452 and measures 30hz instead the real which is 50hz, can you help me? |  |  
		|  |  
		| PCM programmer 
 
 
 Joined: 06 Sep 2003
 Posts: 21708
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Thu Dec 09, 2010 2:09 pm |   |  
				| 
 |  
				| The code by Theasus is weird, because he's using a 16F877 but the register address of PIR1 is for an 18F PIC.   That won't work.
 
 Then in your code, you claim to be using an 18F452, but you still quote
 code with a 16F877 in the #include line.
 
 Post the true, actual code that you are testing.   Also post your compiler
 version.  Post the high and low voltage levels of your input signal.
 Look at the signal with an oscilloscope to see this.
 |  |  
		|  |  
		| lopb 
 
 
 Joined: 09 Dec 2010
 Posts: 6
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Mon Dec 13, 2010 9:33 am |   |  
				| 
 |  
				|  	  | PCM programmer wrote: |  	  | The code by Theasus is weird, because he's using a 16F877 but the register address of PIR1 is for an 18F PIC.   That won't work.
 
 Then in your code, you claim to be using an 18F452, but you still quote
 code with a 16F877 in the #include line.
 
 Post the true, actual code that you are testing.   Also post your compiler
 version.  Post the high and low voltage levels of your input signal.
 Look at the signal with an oscilloscope to see this.
 | 
 Sorry, there is my code:
 
  	  | Code: |  	  | #if defined(__PCH__) #include <18F452.h>
 //////// Fuses: LP,XT,HS,RC,EC,EC_IO,H4,RC_IO,PROTECT,NOPROTECT,OSCSEN
 //////// Fuses: NOOSCSEN,NOBROWNOUT,BROWNOUT,WDT1,WDT2,WDT4,WDT8,WDT16,WDT32
 //////// Fuses: WDT64,WDT128,WDT,NOWDT,BORV20,BORV27,BORV42,BORV45,PUT,NOPUT
 //////// Fuses: CCP2C1,CCP2B3,NOSTVREN,STVREN,NODEBUG,DEBUG,NOLVP,LVP,WRT
 //////// Fuses: NOWRT,NOWRTD,WRTD,NOWRTB,WRTB,WRTC,NOWRTC,CPD,NOCPD,CPB
 //////// Fuses: NOCPB,EBTR,NOEBTR,EBTRB,NOEBTRB
 #FUSES NOWDT                    //No Watch Dog Timer
 #FUSES HS                       //High speed Osc (> 4mhz for PCM/PCH) (>10mhz for PCD)
 #FUSES NOPUT                    //No Power Up Timer
 #FUSES NOPROTECT                //Code not protected from reading
 #FUSES NODEBUG                  //No Debug mode for ICD
 #FUSES NOBROWNOUT               //No brownout reset
 #FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
 #FUSES NOCPD                    //No EE protection
 #FUSES NOWRT                    //Program memory not write protected
 #FUSES NOOSCSEN
 #FUSES NOPUT
 #FUSES CCP2C1
 #FUSES NOSTVREN
 #FUSES NODEBUG
 #FUSES NOWRTD
 #FUSES NOWRTB
 #FUSES NOWRTC
 #FUSES NOCPB
 #FUSES NOEBTR
 #FUSES NOEBTRB
 
 #use delay(clock = 20000000)
 #use rs232 (baud=9600,parity=N,xmit=PIN_B2,rcv=PIN_B1,bits=8)
 
 #priority CCP1, TIMER1
 
 #define BytePtr(var, offset) (char *)((char*)&var + offset)
 
 #byte PIR1 = 0x0C
 #bit  TMR1IF = PIR1.0
 
 int8  gc_timer1_extension = 0;
 int8  gc_capture_flag = FALSE;
 int32 g32_ccp_delta;
 
 //------------------------------------------------------
 #int_timer1
 void timer1_isr(void)
 {
 gc_timer1_extension++;
 }
 
 //------------------------------------------------------
 
 #int_ccp1
 void ccp1_isr(void)
 {
 char timer_ext_copy;
 int32 current_ccp;
 static int32 old_ccp = 0;
 
 gc_capture_flag = TRUE;
 
 current_ccp = (int32)CCP_1;
 
 // Get local copy of the timer ext.
 timer_ext_copy = gc_timer1_extension;
 
 
 if(TMR1IF)
 {
 if(*BytePtr(current_ccp, 1) < 2)  // Was CCP captured after Timer1 wrapped?
 timer_ext_copy++;  // If so, inc the copy of the timer ext.
 
 // Since we know a timer interrupt is pending, let's just
 // handle it here and now.  That saves a little load off
 // the processor.
 gc_timer1_extension++;  // Increment the real timer extension
 TMR1IF = 0;     // Then clear the Timer1 interrupt
 }
 
 // Insert the timer extension into the proper place in the 32-bit
 // CCP value.
 // ie.,  Insert it into location "EE" as follows: 0x00EEnnnn
 // (nnnn = the CCP).
 *BytePtr(current_ccp, 2) = timer_ext_copy;
 
 g32_ccp_delta = (current_ccp > old_ccp) ? current_ccp - old_ccp : current_ccp + (0x1000000 - old_ccp);
 
 // Save the current ccp value for next time.
 old_ccp = current_ccp;
 
 }
 
 //=======================
 void main()
 {
 float frequency;
 
 int32 current_ccp_delta;
 
 set_timer1(0);
 setup_timer_1(T1_INTERNAL | T1_DIV_BY_1);
 
 setup_ccp1(CCP_CAPTURE_RE);
 
 // Enable interrupts.
 clear_interrupt(INT_TIMER1);
 enable_interrupts(INT_TIMER1);
 
 clear_interrupt(INT_CCP1);
 enable_interrupts(INT_CCP1);
 
 enable_interrupts(GLOBAL);
 
 
 while(1)
 {
 if(gc_capture_flag == TRUE)
 {
 disable_interrupts(GLOBAL);
 current_ccp_delta = g32_ccp_delta;;
 enable_interrupts(GLOBAL);
 
 frequency =  (5000000L / (float)current_ccp_delta);
 printf("%4.2f\n\r", frequency);
 
 gc_capture_flag = FALSE;
 }
 else
 {
 printf("No signal\n\r");
 }
 
 delay_ms(500);
 }
 
 }
 | 
 I'm relatively new on this, can you tell me what should I change in this code written for 16f877 on 18f452?
 Right now only says no frequency, and the loop is not working, it says none signal only once.
 
 Thanks
 |  |  
		|  |  
		| PCM programmer 
 
 
 Joined: 06 Sep 2003
 Posts: 21708
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Mon Dec 13, 2010 2:15 pm |   |  
				| 
 |  
				| Right, but I also asked for your compiler version.  If you want me to test it, I need to install your exact version.
 |  |  
		|  |  
		| lopb 
 
 
 Joined: 09 Dec 2010
 Posts: 6
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Tue Dec 14, 2010 2:55 pm |   |  
				| 
 |  
				|  	  | PCM programmer wrote: |  	  | Right, but I also asked for your compiler version.  If you want me to test it, I need to install your exact version.
 | 
 OK, thank you.
 My compiler version is 4.104
 |  |  
		|  |  
		| PCM programmer 
 
 
 Joined: 06 Sep 2003
 Posts: 21708
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Tue Dec 14, 2010 3:25 pm |   |  
				| 
 |  
				| That code seems to have problems.  I don't want to trouble-shoot it. Use the following code instead.   I ran it just now on a 18F452 on a
 PicDem2-Plus board, with a B&K Function Generator putting out a 239 Hz
 0v to 5v square wave (50% duty cycle), and I got this output in a
 TeraTerm window:
 
  	  | Quote: |  	  | 239 Hz
 239 Hz
 239 Hz
 239 Hz
 239 Hz
 239 Hz
 239 Hz
 239 Hz
 239 Hz
 239 Hz
 
 | 
 I tested it with CCS versions 4.104 and 4.114 and it works with both.
 
  	  | Code: |  	  | #include <18F452.h>
 #fuses HS,NOWDT,PUT,BROWNOUT,NOLVP
 #use delay(clock = 20000000)
 #use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
 
 int16 isr_ccp_delta;
 
 #int_ccp1
 void ccp1_isr(void)
 {
 int16 current_ccp;
 static int16 old_ccp = 0;
 
 current_ccp = CCP_1;
 
 isr_ccp_delta = current_ccp - old_ccp;
 
 old_ccp = current_ccp;
 }
 
 
 //=======================
 void main()
 {
 int16 current_ccp_delta;
 int16 frequency;
 
 set_timer1(0);
 setup_timer_1(T1_INTERNAL | T1_DIV_BY_1);
 setup_ccp1(CCP_CAPTURE_RE);
 
 clear_interrupt(INT_CCP1);
 enable_interrupts(INT_CCP1);
 enable_interrupts(GLOBAL);
 
 while(1)
 {
 disable_interrupts(GLOBAL);
 current_ccp_delta = isr_ccp_delta;
 enable_interrupts(GLOBAL);
 
 frequency = (int16)(5000000L / current_ccp_delta);
 
 printf("%lu Hz\n\r", frequency);
 
 delay_ms(500);
 }
 
 }
 | 
 |  |  
		|  |  
		| lopb 
 
 
 Joined: 09 Dec 2010
 Posts: 6
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Wed Dec 15, 2010 7:22 am |   |  
				| 
 |  
				| Is not working PCM Your code is more clean than the other.
 
 i have a rectified signal from the 50hz of my line (just the positive cycle) with a diode and a zener, this singal is very clear i believe.
 
 The signal must be right, because it was showing 50hz in the 16f877.
 
 i'm getting a constant of 3528hz
 Any idea?
 
 thanks again
 |  |  
		|  |  
		| PCM programmer 
 
 
 Joined: 06 Sep 2003
 Posts: 21708
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Wed Dec 15, 2010 1:03 pm |   |  
				| 
 |  
				| To reduce the lower limit on the frequency range, for the tachometer program, you can increase the pre-scaler on Timer1.  Edit the line in
 bold below, and change it to a divisor of 8:
 
  	  | Quote: |  	  | void main()
 {
 int16 current_ccp_delta;
 int16 frequency;
 
 set_timer1(0);
 setup_timer_1(T1_INTERNAL | T1_DIV_BY_8);
 setup_ccp1(CCP_CAPTURE_RE);
 
 | 
 
 Then adjust the frequency equation.  Also divide it by 8, as shown in
 bold below:
 
  	  | Quote: |  	  | while(1) {
 disable_interrupts(GLOBAL);
 current_ccp_delta = isr_ccp_delta;
 enable_interrupts(GLOBAL);
 
 frequency = (int16)((5000000L/8) / current_ccp_delta);
 
 | 
 Then the program should work down to approximately 9 Hz.
 |  |  
		|  |  
		| lopb 
 
 
 Joined: 09 Dec 2010
 Posts: 6
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Thu Dec 16, 2010 8:43 am |   |  
				| 
 |  
				| Thank you PCM, it is working now. |  |  
		|  |  
		| lopb 
 
 
 Joined: 09 Dec 2010
 Posts: 6
 
 
 
			    
 
 | 
			
				| PCM i was wondering if u have time to check this. |  
				|  Posted: Thu Dec 16, 2010 3:16 pm |   |  
				| 
 |  
				| PCM, I should solve this problem. But, I think you are faster than me. If you can, take a look to this: http://dpaste.org/LHoZ/ I am using your code inside a more large program. The problem is that I'm not getting the frequency. Anyway, if you can, otherwise I will keep working on it.
 Thanks again man.
 |  |  
		|  |  
		| PCM programmer 
 
 
 Joined: 06 Sep 2003
 Posts: 21708
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Thu Dec 16, 2010 3:34 pm |   |  
				| 
 |  
				| You have too much code.  I don't really want to look at a lot of code. 
 However, here is a suggestion.  Give the INT_CCP1 interrupt the highest
 priority.   It may help.  Add the statement shown in bold below:
 
  	  | Quote: |  	  | #include <18F452.h> #fuses HS,NOWDT,PUT,BROWNOUT,NOLVP
 #use delay(clock=20000000)
 
 #priority CCP1, TIMER2, RB   // Set interrupt priority
 
 | 
 |  |  
		|  |  
		| MAKInnovation 
 
 
 Joined: 16 Nov 2010
 Posts: 61
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Thu Dec 30, 2010 1:12 am |   |  
				| 
 |  
				| how can we print int32 with printf command & can we get frequency upto 1MHz with this code
 |  |  
		|  |  
		|  |  
  
	| 
 
 | You cannot post new topics in this forum You cannot reply to topics in this forum
 You cannot edit your posts in this forum
 You cannot delete your posts in this forum
 You cannot vote in polls in this forum
 
 |  
 Powered by phpBB © 2001, 2005 phpBB Group
 
 |