| 
	
	|  |  |  
	
		| View previous topic :: View next topic |  
		| Author | Message |  
		| John Guest
 
 
 
 
 
 
 
			
			
			
			
			
			
			
			
			
 
 | 
			
				| Frequency measurements in a good way? |  
				|  Posted: Fri Feb 28, 2003 3:08 pm |   |  
				| 
 |  
				| I am planning to make a data logger (16F870) which should store 2 independent frequencies in an external memory but I am uncertain how I should implement it in an intelligent way... 
 Both frequencies varies between 0-200Hz and the accuracy of measurement does not need to be 100\% perfect. The problem is that I would like to store the values at certain time intervals, say every 100ms, or perhaps with some form of timestamp in order to be able to calculate the total measurement time when analysing the stored data.
 First I was thinking of have a free running timer which at interrupt saves the latest measured values but ran into problems since this interrupt may occur at the same time as the interrupts used for frequency measurements. Hence the measured frequency got corrupt.
 
 Does anyone have a theory on how to tackle the problem?
 
 Regards,
 /John
 ___________________________
 This message was ported from CCS's old forum
 Original Post ID: 12238
 |  |  
		|  |  
		| PCM programmer 
 
 
 Joined: 06 Sep 2003
 Posts: 21708
 
 
 
			    
 
 | 
			
				| Re: Frequency measurements in a good way? |  
				|  Posted: Fri Feb 28, 2003 3:26 pm |   |  
				| 
 |  
				| :=I am planning to make a data logger (16F870) which should store 2 independent frequencies in an external memory but I am uncertain how I should implement it in an intelligent way... :=
 :=Both frequencies varies between 0-200Hz and the accuracy of measurement does not need to be 100\% perfect. The problem is that I would like to store the values at certain time intervals, say every 100ms, or perhaps with some form of timestamp in order to be able to calculate the total measurement time when analysing the stored data.
 :=First I was thinking of have a free running timer which at interrupt saves the latest measured values but ran into problems since this interrupt may occur at the same time as the interrupts used for frequency measurements. Hence the measured frequency got corrupt.
 :=
 :=Does anyone have a theory on how to tackle the problem?
 :=
 :=Regards,
 :=/John
 ------------------------------------------------------------
 I'm not sure how the timer isr would corrupt the frequency
 values, because the PIC (and CCS) does not support nested
 interrupts.
 
 Maybe you're reading the freq variable outside of the
 isr, and it's a word variable (2 bytes) ?  In that case,
 just disable interrupts and copy the freq variable to
 another variable.  Then re-enable interrupts.  That way,
 you can't ever read a partially updated word value.
 You'll always read the correct value.
 
 ---------
 
 You didn't ask this, but the standard way to measure frequency
 with a PIC is to use the CCP module.
 
 If you want to extend the Timer1 to 24 bits, and avoid the
 "gotcha's" involved with interrupt latency, you can see my
 sample code here:
 http://www.ccsinfo.com/forum/viewtopic.php?t=906
 Using a 24-bit timer allows you to measure low values
 of the frequency without having to switch between different
 CCP pre-scalers.
 
 --------
 
 Edited on Jan. 31, 2005 to update the link so it actually points to
 the correct thread.   When the old forum was ported over to this
 new forum, the embedded links didn't work anymore.   Now at
 least this one is fixed.
 ___________________________
 This message was ported from CCS's old forum
 Original Post ID: 12239
 
 Last edited by PCM programmer on Mon Jan 31, 2005 1:01 pm; edited 1 time in total
 |  |  
		|  |  
		| John Guest
 
 
 
 
 
 
 
			
			
			
			
			
			
			
			
			
 
 | 
			
				| Re: Frequency measurements in a good way? |  
				|  Posted: Sat Mar 01, 2003 1:15 pm |   |  
				| 
 |  
				| :=I'm not sure how the timer isr would corrupt the frequency :=values, because the PIC (and CCS) does not support nested
 :=interrupts.
 :=
 :=Maybe you're reading the freq variable outside of the
 :=isr, and it's a word variable (2 bytes) ?  In that case,
 :=just disable interrupts and copy the freq variable to
 :=another variable.  Then re-enable interrupts.  That way,
 :=you can't ever read a partially updated word value.
 :=You'll always read the correct value.
 :=
 :=---------
 :=
 :=You didn't ask this, but the standard way to measure frequency
 :=with a PIC is to use the CCP module.
 :=
 :=If you want to extend the Timer1 to 24 bits, and avoid the
 :="gotcha's" involved with interrupt latency, you can see my
 :=sample code here:
 := <a href="http://www.pic-c.com/forum/general/posts/10833.html" TARGET="_blank"> <a href="http://www.pic-c.com/forum/general/posts/10833.html" TARGET="_blank">http://www.pic-c.com/forum/general/posts/10833.html</a></a>
 :=Using a 24-bit timer allows you to measure low values
 :=of the frequency without having to switch between different
 :=CCP pre-scalers.
 
 Thanks for your reply.
 Since I am using a F870 I only have one CCP so I thought I'd test using int_rb as the interrupt for measuring both frequencies. The idea was to use RTCC as a free running timer which value is captured when an int_rb occurs. I used timer 2 to create "constant" intervals for saving the data. As I tested the code below I found that it works ok at higher frequencies but at lower it gives errors (signal period higher than the period between data save).
 In the test code below I only measure one frequency and don't really save it, only print it on screen. I feel that it could be done much more effective but I don't know how... (the great newbie feel :-)  )
 Is it possible to get it to work or should I do it completely differently?
 
 #include <16f870m.h>
 #fuses HS, NOPROTECT, NOWDT, PUT, NOLVP
 #use DELAY(clock=4000000)
 #use fast_io ( A )
 #use fast_io ( B )
 #use fast_io ( C )
 #use rs232(baud=19200, xmit=PIN_C6, rcv=PIN_C7)
 #bit speed = 0x06.4	//RB4
 
 //GLOBAL VARIABLES
 int speedcount=0;	//timer_0 value
 short speed_on=0;	//speed timing period?
 int speed_r_over=0;	//increases at every timer0 roll over
 
 #int_timer2
 timer_2_isr(){
 disable_interrupts(GLOBAL);
 printf("\r \%3U \%2U", speedcount, speed_r_over);	//"save" data
 enable_interrupts(GLOBAL);
 }
 
 #int_rb
 rb_isr() {
 if (speed && !speed_on){	//trig L->H measure start
 set_timer0(0);
 speed_r_over=0;
 speed_on=1;
 }
 else if (speed && speed_on){	//trig L->H measure stop
 speedcount=get_timer0();
 speed_on=0;
 }
 }
 
 #int_rtcc
 timer0_isr() {
 speed_r_over += 1;
 }
 
 void main( void )
 {
 set_tris_a ( 0b11110000 );
 set_tris_b ( 0b11111100 );    	//RB4 speedtrigger
 set_tris_c ( 0b10000000 );    	//RC6,7 RS232
 
 setup_timer_2(T2_DIV_BY_16, 250, 8);
 setup_counters(RTCC_INTERNAL,RTCC_DIV_256);
 enable_interrupts(int_rb);
 enable_interrupts(INT_TIMER2);
 enable_interrupts(int_rtcc);
 enable_interrupts(GLOBAL);
 
 while(1);	//just wait for the interrupts...
 }
 
 /John
 ___________________________
 This message was ported from CCS's old forum
 Original Post ID: 12257
 |  |  
		|  |  
		| John Guest
 
 
 
 
 
 
 
			
			
			
			
			
			
			
			
			
 
 | 
			
				| Maybe not in a good way, but it works... |  
				|  Posted: Sat Mar 01, 2003 4:15 pm |   |  
				| 
 |  
				| Don't know why I wrote the rb isr as I did... Changing it to the following made it work at least  (with some other minor code changes). #int_rb
 rb_isr() {
 if (speed) {
 speedcount=get_timer0();
 set_timer0(0);
 }
 }
 /John
 ___________________________
 This message was ported from CCS's old forum
 Original Post ID: 12260
 |  |  
		|  |  
		|  |  
  
	| 
 
 | 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
 
 |