View previous topic :: View next topic |
Author |
Message |
Salenko
Joined: 08 Sep 2008 Posts: 84
|
|
Posted: Fri Jun 12, 2009 3:32 am |
|
|
Dear PCM Programmer,
you solved my problem , thank you.
now I'm getting 1 Hz into my Terminal. this is a progress but the display remains imprecise, in fact, the frequency of the received signal is around 1.42hz, while I'm getting 1 Hz ,then I made the flowing changes (in bold):
Quote: | float frequency;
frequency = (float) ((2500000L + (current_ccp_delta >> 1)) / current_ccp_delta);
printf("------%f Hz\n\r", frequency); |
I got 1.00 Hz , is there anything else to change to get the correct decimal.
Salenko. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Jun 12, 2009 1:00 pm |
|
|
You are doing integer math which has no decimal fraction result, and
then casting the integer as float. It will always have .00 on end.
You need to force it to do floating point math inside the equation.
The equation consists of a division of two terms. The top term
is an addition, within parentheses. Solution: Cast either the top
term or the bottom term to a float. This forces the division to be
done in floating point. It's easiest just to stick it in front of the
bottom term:
Quote: |
frequency = ((2500000L + (current_ccp_delta >> 1)) / (float)current_ccp_delta); |
Also, be aware that some versions of the CCS compiler (not sure which
ones) need Width and Precision numbers to be specified in the "%f"
field, in order for printf to work properly. The first number must be
higher than the 2nd number. Example: "%7.2f" |
|
|
Salenko
Joined: 08 Sep 2008 Posts: 84
|
|
Posted: Fri Jun 12, 2009 1:48 pm |
|
|
Dear PCM,
for the nth time, thank you.
you are doing a great job in this forum. |
|
|
Macas
Joined: 09 Jun 2009 Posts: 13
|
|
Posted: Wed Sep 30, 2009 8:05 am |
|
|
Dear PCM,
I just tried your code and it doesnt worked for me. Im using pic 18f2580 with external oscillator 20MHz.
In rs232 not even print "Non signal". What is wrong with this?
Code: | #include <18F2580.H>
#fuses 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;
// 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()
{
int16 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)
{
disable_interrupts(GLOBAL);
current_ccp_delta = g32_ccp_delta;;
enable_interrupts(GLOBAL);
if(gc_capture_flag == TRUE)
{
frequency = (int16)((5000000L + (current_ccp_delta >> 1)) / current_ccp_delta);
printf("%lu Hz\n\r", frequency);
// printf("%lu Hz, delta = %lx \n\r", frequency, current_ccp_delta);
gc_capture_flag = FALSE;
}
else
{
printf("No signal\n\r");
}
delay_ms(500);
}
}
|
|
|
|
Macas
Joined: 09 Jun 2009 Posts: 13
|
|
Posted: Wed Sep 30, 2009 8:32 am |
|
|
I just change the fuses to and its working now
but only at 1Hz im getting on terminal:
1 Hz
no signal
1 hz
no signal
no signal
1Hz
and so on...
why ? |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Sep 30, 2009 11:37 am |
|
|
The problem is probably because:
1. The voltage levels of your input signal are too low. They need
to be at least 0v to 4v levels. (For a PIC running at 5v).
2. Your input frequency may not be in the correct range to work
with the Timer1 prescaler and the frequency divisor in the posted code.
3. Your input signal may not be a normal, continuous squarewave.
What is the frequency of your input signal ?
What are the voltage levels of your input signal ?
Is it a normal continuous squarewave ? |
|
|
Macas
Joined: 09 Jun 2009 Posts: 13
|
|
Posted: Wed Sep 30, 2009 2:07 pm |
|
|
PCM programmer wrote: | The problem is probably because:
1. The voltage levels of your input signal are too low. They need
to be at least 0v to 4v levels. (For a PIC running at 5v).
2. Your input frequency may not be in the correct range to work
with the Timer1 prescaler and the frequency divisor in the posted code.
3. Your input signal may not be a normal, continuous squarewave.
What is the frequency of your input signal ?
What are the voltage levels of your input signal ?
Is it a normal continuous squarewave ? |
the input signal is a normal continuous squarewave with 1Hz, 0v-5v. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Sep 30, 2009 4:02 pm |
|
|
For low frequency operation, change these things:
1. Change the declaration of the 'frequency' variable to a float:
Code: |
void main()
{
float frequency;
|
2. Change the while(1) loop to this:
Code: | 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;
}
}
|
I did those changes, and put in signal from my B&K Function Generator
that was the lowest possible frequency (0.4 Hz). Then I turned the
frequency adjust knob slowly so it went up to 2 Hz. Here is the output:
Quote: |
0.41
0.41
0.41
0.40
0.41
0.47
0.62
0.75
0.89
0.96
0.99
1.02
1.06
1.14
1.24
1.36
1.46
1.60
1.62
1.76
1.93
2.02
2.08
2.09
2.08
2.09
|
|
|
|
Macas
Joined: 09 Jun 2009 Posts: 13
|
|
Posted: Fri Oct 16, 2009 8:23 am |
|
|
I recently switch from external 20MHz xtal to the internal osc 4Mhz...and now i dont know why, the program just stop.
Im debugging via rs232 and around 100Hz+ to 300Hz input, it stops sending data to rs232. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Oct 16, 2009 2:51 pm |
|
|
If you lower the oscillator from 20 MHz down to 4 MHz, then you need
to also change the numerator in the frequency equation from 5 million
down to 1 million, as shown below in bold:
Quote: | frequency = (1000000L / (float)current_ccp_delta); |
I don't know why it would stop doing output. You probably changed
something else. The input levels might be incorrect, or the cable
connection is bad. |
|
|
Macas
Joined: 09 Jun 2009 Posts: 13
|
|
Posted: Tue Dec 15, 2009 10:58 am |
|
|
I return to 20Mhz Xtal because that problem.
In tests, while i change the frequency sometimes the output pull to a different value.
Example:
I increase the frequency from 10Hz to 100Hz, while the output is increasing sometimes im getting weird values. Like getting 10Hz output when the frequency is reaching 80Hz.
Another thing, what is the best way to use watchdog without corrupt the output.
Because i add WTD2048 Fuse to my program and Setup_WDT(WDT_ON) to main code, but when the PIC reset per example with a 20Hz input, the next output immediately after the reset is weird.
thks |
|
|
Macas
Joined: 09 Jun 2009 Posts: 13
|
|
Posted: Fri Dec 18, 2009 9:06 am |
|
|
anyone ? |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Dec 18, 2009 10:42 am |
|
|
Quote: |
I increase the frequency from 10Hz to 100Hz, while the output is
increasing sometimes im getting weird values. Like getting 10Hz
output when the frequency is reaching 80Hz.
|
You could use a Median Filter to fix the problem. If you get an
occasional bad output from the tachometer code, this filter will remove it:
http://www.ccsinfo.com/forum/viewtopic.php?t=3462 |
|
|
Macas
Joined: 09 Jun 2009 Posts: 13
|
|
Posted: Wed Jan 06, 2010 9:10 am |
|
|
PCM programmer wrote: | Quote: |
I increase the frequency from 10Hz to 100Hz, while the output is
increasing sometimes im getting weird values. Like getting 10Hz
output when the frequency is reaching 80Hz.
|
You could use a Median Filter to fix the problem. If you get an
occasional bad output from the tachometer code, this filter will remove it:
http://www.ccsinfo.com/forum/viewtopic.php?t=3462 |
Thanks, it is much better now |
|
|
Macas
Joined: 09 Jun 2009 Posts: 13
|
|
Posted: Fri Jan 22, 2010 7:54 am |
|
|
New question eheh!
I'm getting problems on WDT and the output.
Example:
Output: 32
Output: 32
Output: 32
Output: 32
Output: 32
Output: 32
WDT
Output: weird value
Output: 32
Output: 32
Output: 32
and so on...
How can I avoid that weird value next to WDT?
Thanks in advance |
|
|
|