|
|
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
|