View previous topic :: View next topic |
Author |
Message |
nizar445
Joined: 09 Jun 2009 Posts: 23
|
Frequency reading using PIC |
Posted: Thu Jun 18, 2009 11:13 am |
|
|
Dear clever people
After browsing your wonderful forum, I found many topics that related to what I was looking for, but unfortunately didn’t work nicely for me, and I’m really looking forward for your help as I am very new to PIC programming .
I am trying to make a frequency measuring application that can find a useful frequency range for me and I have found the following code in your forum which I have modified the last part of it for the ranges that I am looking for.
The problem is that when I flash the PIC and run it for the first time it detects the right frequency range and the LED flashes the right way but when I change the frequency nothing happens i.e. the LED flashing sequence doesn’t change.
In more details, that if I set my function generator to generate 70 Hz frequency and then I flash and run the PIC I get the right LED flashing that corresponds to 70 Hz, but now if I change the frequency to 28 Hz I don’t get the right output, the LED keeps flashing just like the 70Hz case.
It looks to me that’s either the frequency variable doesn’t get updated while the program is running or the program stuck in one of the loops and it doesn’t go out of it.
Please I am really stuck and need your help and advice in this matter.
Thanks in advance for your help.
Pin 8 is connected to square-wave generator (0-5v amp)
Pin 10 is connected to LED
PIC used 16F819
Code: | #include <16F819.H>
#fuses NOWDT, NOPROTECT, NOLVP,INTRC_IO, NOPUT, NOMCLR,NOBROWNOUT, NOCPD, NOWRT, NODEBUG
#use delay(clock=4000000)
// This global variable holds the time interval
// between two consecutive rising edges of the
// input signal.
int16 isr_ccp_delta;
// When a rising edge occurs on the input signal,
// the CCP1 will 'capture' the value of Timer1
// at that moment. Shortly after that, a CCP1
// interrupt is generated and the following isr
// is called. In the isr, we read the 'captured'
// value of Timer1. We then subtract from it the
// Timer1 value that we 'captured' in the previous
// interrupt. The result is the time interval
// between two rising edges of the input signal.
// This time interval is then converted to a frequency
// value by code in main().
#int_ccp1
void ccp1_isr(void)
{
int16 current_ccp;
static int16 old_ccp = 0;
current_ccp = CCP_1; // From 16F819.H file
// Calculate the time interval between the
// previous rising edge of the input waveform
// and the current rising edge. Put the result
// in a global variable, which can be read by
// code in main().
isr_ccp_delta = current_ccp - old_ccp;
// Save the current ccp value for the next pass.
old_ccp = current_ccp;
}
//=======================
void main()
{
int16 current_ccp_delta;
int16 frequency;
setup_oscillator(OSC_4MHZ); //use internal 4MHz clock
// Setup Timer1 and CCP1 for Capture mode so that
// we can measure the input signal's frequency.
// The input signal comes from an external function
// generator, which is connected to the CCP1 pin 8 with a wire.
set_timer1(0);
setup_timer_1(T1_INTERNAL | T1_DIV_BY_8);
setup_ccp1(CCP_CAPTURE_RE);
// Clear the CCP1 interrupt flag before we enable
// CCP1 interrupts, so that we don't get an unwanted
// immediate interrupt (which might happen).
clear_interrupt(INT_CCP1);
enable_interrupts(INT_CCP1);
enable_interrupts(GLOBAL);
while(1)
{
// Get a local copy of the latest ccp delta from the isr.
// We have to disable interrupts when we read a global
// isr variable that is larger than a single byte.
disable_interrupts(GLOBAL);
current_ccp_delta = isr_ccp_delta;
enable_interrupts(GLOBAL);
// To calculate the frequency of the input signal,
// we take the number of clocks that occurred
// between two consecutive edges of the input signal,
// and divide that value into the number of Timer1
// clocks per second. Since we're using a 4 MHz
// internal clock, the Timer1 clock is 1 MHz (Timer1 runs
// at the instruction cycle rate, which is 1/4 of the
// internal clock frequency). For example, suppose the
// the input waveform has a frequency of 244 Hz.
// 244 Hz has a period of about 4098 usec.
// Timer1 is clocked at 1 MHz, so between two
// consecutive rising edges of the input signal,
// it will count up by 4098 clocks. To find the
// frequency, we divide 4098 into the number of
// clocks that occur in 1 second, which is 1000000.
// This gives 1000000 / 4098 = 244 Hz.
frequency = (int16)(125000L / current_ccp_delta);
// Display the calculated frequency.
if (frequency <= 30)
do {
output_high(PIN_B4);
delay_ms(5000);
output_low(PIN_B4);
delay_ms(5000);
}
while (TRUE);
else if (frequency >= 31 && frequency <= 59)
do {
output_high(PIN_B4);
delay_ms(700);
output_low(PIN_B4);
delay_ms(1500);
output_high(PIN_B4);
delay_ms(300);
output_low(PIN_B4);
delay_ms(600);
}
while (TRUE);
else
do {
output_high(PIN_B4);
delay_ms(500);
output_low(PIN_B4);
delay_ms(500);
}
while (TRUE);
} //end while(1)
} // end main |
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Jun 18, 2009 11:25 am |
|
|
Display the frequency numbers in a terminal window on your PC.
Then you can see where the problem is. |
|
|
nizar445
Joined: 09 Jun 2009 Posts: 23
|
|
Posted: Thu Jun 18, 2009 11:40 am |
|
|
Dear PCM programmer
Thanks a lot for your quick reply but I have no idea about what are you talking about can you please explain a bit more as I am coming from Mechanical engineering background and I'm not get used to programming talk. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Jun 18, 2009 11:42 am |
|
|
Did you build the PIC board yourself, or did you buy the board ?
If you bought it, post the manufacturer, model number, and a link
to the website for the board. |
|
|
nizar445
Joined: 09 Jun 2009 Posts: 23
|
|
Posted: Thu Jun 18, 2009 11:53 am |
|
|
Dear PCM programmer
Thanks again for your quick reply
Yes I have built the PIC board by myself and I programmed it using MPLAB ICD2 programmer made by microchip |
|
|
ECACE
Joined: 24 Jul 2006 Posts: 94
|
|
Posted: Thu Jun 18, 2009 12:24 pm |
|
|
After a quick glance, it looks like your ISR is clearing the old value every time you go into it, at the start of your ISR.
Then at the end of your ISR, you save the current value as the old value.
But when you go back into your ISR, right away you blow away the old value you had saved the last time you were there.
Maybe I'm off on that, but that is what it is looking like to me.
Code: |
#int_ccp1
void ccp1_isr(void)
{
int16 current_ccp;
static int16 old_ccp = 0; ********* Right here you are blowing away any old value
********* that you had saved the last time through.
********* Is that really what you want to do?
current_ccp = CCP_1;
isr_ccp_delta = current_ccp - old_ccp;
old_ccp = current_ccp; ********* Here you are saving your old_ccp value,
********* But the next time you come into the ISR you blow it away
}
|
_________________ A HW Engineer 'trying' to do SW !!! Run!!! |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Jun 18, 2009 12:33 pm |
|
|
No it's not clearing it every time. It's only cleared upon program start-up.
nizar445:
Please an RS-232 capability to your board. Add a Max232-type chip
and a DB-9 connector. Get a serial port cable. Then you will be
about to display debugging information on your PC. It will be much
easier to fix problems in your code. |
|
|
nizar445
Joined: 09 Jun 2009 Posts: 23
|
|
Posted: Thu Jun 18, 2009 2:02 pm |
|
|
Dear ECACE
I have tried to replace "static int16 old_ccp = 0;" with "int16 old_ccp" but no luck
Thanks a lot for your help |
|
|
nizar445
Joined: 09 Jun 2009 Posts: 23
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Jun 18, 2009 2:13 pm |
|
|
That adapter board would work. You can connect the Tx, Rx, and GND
pins to your PIC board. You also need a DB-9 serial cable to connect
the board to your PC. |
|
|
nizar445
Joined: 09 Jun 2009 Posts: 23
|
|
Posted: Thu Jun 18, 2009 2:24 pm |
|
|
Dear PCM programmer
Thanks again, I will buy this board now.
Can you please tell me to which pins on the PIC I should connect these pins (Tx, Rx, and GND) and how is the PIC will communicate with this board, please note that my programming knowledge is very poor |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Jun 18, 2009 2:35 pm |
|
|
There is no schematic of the board on that web page, so I don't know
for certain how to connect it to your PIC.
Based on the photo, I can say:
Connect the Vcc pin to +5v on your board.
Connect the GND pin to GND on your board.
The TXD and RXD pins would go to the Rx and Tx pins on your PIC
board, but I'm not certain if they go TXD to Rx, or TXD to Tx,
because there is no schematic. I can't help any more on this. |
|
|
nizar445
Joined: 09 Jun 2009 Posts: 23
|
|
Posted: Thu Jun 18, 2009 2:47 pm |
|
|
Dear PCM programmer
Thanks again and I'm so sorry for bothering you with my problem. But the PIC hasn’t got Rx and Tx pins please have a look at the following PIC pins diagram:
http://www.caveo.com.ar/images/16f819.gif
By the way; is there any other method that I can use to find the code error? |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Jun 18, 2009 3:13 pm |
|
|
Then you need to use a software UART. This can easily be done with
the #use rs232() statement in CCS. Just specify two spare i/o pins for
'rcv' and 'xmit'. |
|
|
nizar445
Joined: 09 Jun 2009 Posts: 23
|
|
Posted: Sat Jun 20, 2009 5:04 pm |
|
|
Dear PCM programmer
Thanks in advance for your help, I have got the MAX232 serial adapter now and it has 4 pins (GND, V+, TX, RX)
My question is, to which pins in the PIC, I need to connect the TX and RX pins? Can I connect them to Pin11 (RB5) and Pin12 (RB6)?
http://www.caveo.com.ar/images/16f819.gif
Also did you mean that I need to add the following code to the original programme in order to see my output? (By the way, this code has been used in previous thread in this forum and I have no idea about what its doing exactly, all what I know it allows me to use some sort of serial data!)
Code: | #use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS) |
Finally could you please tell me how I can display the frequency numbers in a terminal window on my PC??
Thanks again for your help and I am looking forward for your reply. |
|
|
|