CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

CCP - Problem with capture mode
Goto page 1, 2, 3  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
hemnath



Joined: 03 Oct 2012
Posts: 242
Location: chennai

View user's profile Send private message

CCP - Problem with capture mode
PostPosted: Fri Apr 12, 2013 4:26 am     Reply with quote

I'm trying to measure and display the frequency value in LCD. I'm using PIC18F2520. Internal oscillator 4Mhz. Frequency from function generator. I have connected output of function generator to pin C2(CCP1) of uC. Using capture mode, I'm trying to capture the signal and displaying. But in the display it shows fixed value and value is not changing in the LCD when i change the frequency in function generator.

Please help.

Code:
#include "18f2520.h"
#fuses INTRC
#use delay(clock=4000000)

#define RS PIN_A2
#define EN PIN_A1

void lcd_init();
void lcd_cmd(unsigned char);
void lcd_data(unsigned char);

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;

lcd_init();

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)((1000000) / current_ccp_delta);
   lcd_cmd(0x01);
   lcd_cmd(0x80);
   printf(lcd_data,"%lu Hz", frequency);

   delay_ms(500);
  }

}

void lcd_init()
{
lcd_cmd(0x30);      // Configure the LCD in 8-bit mode, 1 line and 5x7 font
//lcd_cmd(0x28);
lcd_cmd(0x0c);      // display on and cursor off
lcd_cmd(0x01);      // clear display screen
lcd_cmd(0x06);      // increment cursor
lcd_cmd(0x80);      // set cursor to 1st line
}

void lcd_cmd(unsigned char c)
{
output_b(c);
output_low(RS);
output_high(EN);
delay_ms(15);
output_low(EN);
}

void lcd_data(unsigned char z)
{
output_b(z);
output_high(RS);
output_high(EN);
delay_ms(15);
output_low(EN);
}
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Apr 12, 2013 12:23 pm     Reply with quote

Regarding the signal on Pin C2:

Look at the signal with an oscilloscope and post the answers to
these questions:

1. Is the signal a squarewave or a rectangular waveform ?
Or, is it a sinewave or some other shape ?

2. What is the frequency of the input signal ?

3. What are the low and high level voltages of the input signal ?
For example, does the signal go from 0v to 3.3v, or 0 to 5v ?


Quote:
the display it shows fixed value and value is not changing in the LCD

Post what you see displayed on the LCD.
hemnath



Joined: 03 Oct 2012
Posts: 242
Location: chennai

View user's profile Send private message

PostPosted: Sat Apr 13, 2013 1:48 am     Reply with quote

Sorry. I noticed now only, that output level from function generator was about 1V. I increased to +4.5V. Now the code works good. Thanks for the valuable information. But now I faced another problem, when i give input frequency from function generator say about 5Khz. LCD display value keeps changing. So i thought to use PLL.
I declared in the fuses line as H4 and used external crystal 4Mhz.

Now the LCD fluctuates from 5Khz to 5.025Khz.
Can i control with any methods?

code changes
Code:
#include "18f2520.h"
#fuses H4
#use delay(clock=16000000)  // crystal used 4Mhz . So 4*4 = 16Mhz is this right?



Code:
 frequency = (int16)((4000000) / current_ccp_delta);


If the error is 1Hz, that doesn't matter. But error increases as frequency increases. Please help me how to control it.
Ttelmah



Joined: 11 Mar 2010
Posts: 19549

View user's profile Send private message

PostPosted: Sat Apr 13, 2013 3:41 am     Reply with quote

You need to start by looking at your input signal.

Now, unless this is a TTL source, you have a waveform (possibly programmable in shape), which will almost certainly be going +ve and -ve of it's ground. You are then feeding this into a logic input, with clamp diodes, which stop the -ve excursions going more than about 0.6v below ground, and the remainder of the waveform then goes +ve of ground. The logic input detects 'high' at a particular voltage about ground. So unless everything is very stable indeed, there will be variation with this point, and the signal coming in.

To feed an AC signal like this into the processor, you really need to probably clamp the incoming to half the supply rail, and process it with something like a zero crossing detector and comparator to give a a nice logic square wave to feed the PIC.

You need to get this done first.

Then look at smoothing the count result.

Best Wishes
Mike Walne



Joined: 19 Feb 2004
Posts: 1785
Location: Boston Spa UK

View user's profile Send private message

PostPosted: Sat Apr 13, 2013 4:41 am     Reply with quote

OK.

Have a play at being computer.

When your input frequency is 5kHz, the period is 200us.
With your original 4MHz clock that's 200 counts.

Suppose the real period was 199.5us:-

1) Your count would be 200 one time. Displays 1e6/200 -> 5.000kHz
2) Your count would be 199 next time. Displays 1e6/199 -> 5.025kHz

Your display is doing exactly as what you're telling it.

Your method for calculating frequency is great for low frequencies, & falls over for higher ones.

So, you need to either:-

a) Modify your present method to deal with higher frequencies
OR
b) Use a different approach for higher frequencies.

BUT first, do as Ttelmah suggests and clean up your input signal.

Mike
hemnath



Joined: 03 Oct 2012
Posts: 242
Location: chennai

View user's profile Send private message

PostPosted: Sat Apr 13, 2013 5:39 am     Reply with quote

Thanks Ttelmah for the information. Now i'm giving input to PIN C2 from Pulse generating circuit which will be clean 5V and 0V. There will no negative pulse. I did everything whatever you said.

But still the problem remains the same. Do i have to change anything in the program?

I have one doubt. Please clarify me. If i use PLL, my program instructions will be executing fast right?
say #fuses H4 . and crystal 4Mhz. So the frequency could be 16Mhz? is it right?

Also i have did in my program
Code:
 frequency = (int16)((4000000) / current_ccp_delta);

like that, instead of
Code:
frequency = (int16)((1000000) / current_ccp_delta);

Thanks in advance. Please help.
Mike Walne



Joined: 19 Feb 2004
Posts: 1785
Location: Boston Spa UK

View user's profile Send private message

PostPosted: Sat Apr 13, 2013 6:12 am     Reply with quote

Quote:
But still the problem remains the same. do i have to change anything in the program?

Please clarify, what reading(s) do you get for:-

1) 4MHz crystal, #fuses HS, formula used for frequency, 5kHz applied to pin C2.
2) 4MHz crystal, #fuses H4, formula used for frequency, 5kHz applied to pin C2.

Have you had a play at being computer?
When you do, you may then understand what the fundamental problem is.

Mike
hemnath



Joined: 03 Oct 2012
Posts: 242
Location: chennai

View user's profile Send private message

PostPosted: Tue Apr 16, 2013 2:44 am     Reply with quote

Sorry for the late reply.

I have measured the frequency.
With crystal 4Mhz and for #fuses XT and 5Khz from function generator.

LCD display 5000 Hz and sometimes 5025 Hz. When i increase the frequency little higher, say about 5002 Hz, LCD still displays 5000 Hz and 5025 Hz. It seems that LCD counts every 25 Hz as stated in below post

Quote:

1) Your count would be 200 one time. Displays 1e6/200 -> 5.000kHz
2) Your count would be 199 next time. Displays 1e6/199 -> 5.025kHz


Please help me how can i display with fine resolution? I want to display every 1 hz. If i keep the frequency 5001 Hz, LCD should display 5001 Hz. Is it possible to achieve? What changes i have to do? Please help.

Thanks in advance Smile
Mike Walne



Joined: 19 Feb 2004
Posts: 1785
Location: Boston Spa UK

View user's profile Send private message

PostPosted: Tue Apr 16, 2013 3:33 am     Reply with quote

I thought I'd explained in my previous post.

You're trying to measure ~5000Hz frequency to one part in 5000.
That's 0.02%.
You're doing it by measuring period to 1 part in 200.
That's 0.5%.

The LCD is displaying what you're telling it to do!

So like I said before either:-

a) Modify your present method to deal with higher frequencies
OR
b) Use a different approach for higher frequencies.

You can do (a) by measuring several periods, then take average.
You do (b) by measuring frequency (i.e. No of cycles in 1s) directly.

It's been done loads of times here on the forum.
Do a search.
I know I've covered it myself at least once.

Mike
hemnath



Joined: 03 Oct 2012
Posts: 242
Location: chennai

View user's profile Send private message

PostPosted: Tue Apr 16, 2013 3:53 am     Reply with quote

How can i modify or to use different approach?

I'm totally clueless. Can you please change my above code to error of 1HZ? So that i ll learn from it.

Do i have to change the crystal frequency to minimize the error?

Can you please direct me to those links?

Thank you .
Mike Walne



Joined: 19 Feb 2004
Posts: 1785
Location: Boston Spa UK

View user's profile Send private message

PostPosted: Tue Apr 16, 2013 4:38 am     Reply with quote

hemnath wrote:
I'm totally clueless...
Yes . I have to agree.

No, seriously here are two links

http://www.ccsinfo.com/forum/viewtopic.php?t=47653&start=0
http://www.ccsinfo.com/forum/viewtopic.php?t=47375&start=15

To get good resolution @ ~5kHz with 1s update you can modify.
In other words measure the average period of ~5000 cycles.
With your 1MHz instruction rate, you'll then be measuring ~1s worth of complete cycles to within 1us.
That's 0.0001%.
Should be more than good enough.

Another way of thinking of it, is to measure the number of cycles in ~1s, taking care to start and stop on one edge of your input signal.

Mike


EDIT
Going to a higher frequency crystal will improve resolution in direct proportion to frequency
hemnath



Joined: 03 Oct 2012
Posts: 242
Location: chennai

View user's profile Send private message

PostPosted: Tue Apr 16, 2013 4:58 am     Reply with quote

Thank you. I ll look into those links.

Quote:
Going to a higher frequency crystal will improve resolution in direct proportion to frequency


I prefer to increase my crystal frequency to increase more resolution. But what frequency formula should i use?

Please help me how to calculate with 20Mhz crystal?

This is the code im using right now,
Code:
#include "18f2520.h"
#fuses XT
#use delay(clock=4000000)

#define RS PIN_A2
#define EN PIN_A1

void lcd_init();
void lcd_cmd(unsigned char);
void lcd_data(unsigned char);

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;

lcd_init();

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)((1000000) / current_ccp_delta);
   lcd_cmd(0x01);
   lcd_cmd(0x80);
   printf(lcd_data,"%lu Hz", frequency);

   delay_ms(500);
  }

}

void lcd_init()
{
lcd_cmd(0x30);      // Configure the LCD in 8-bit mode, 1 line and 5x7 font
lcd_cmd(0x0c);      // display on and cursor off
lcd_cmd(0x01);      // clear display screen
lcd_cmd(0x06);      // increment cursor
lcd_cmd(0x80);      // set cursor to 1st line
}

void lcd_cmd(unsigned char c)
{
output_b(c);
output_low(RS);
output_high(EN);
delay_ms(15);
output_low(EN);
}

void lcd_data(unsigned char z)
{
output_b(z);
output_high(RS);
output_high(EN);
delay_ms(15);
output_low(EN);
}


What changes i have to do in the program?
Mike Walne



Joined: 19 Feb 2004
Posts: 1785
Location: Boston Spa UK

View user's profile Send private message

PostPosted: Tue Apr 16, 2013 5:29 am     Reply with quote

To calculate for 20MHz crystal you simply change these lines in your code
Code:
#use delay(clock=4000000)
And
Code:
frequency = (int16)((1000000) / current_ccp_delta);

BUT. Doesn't achieve what you want!

It's simple maths. Assuming your input signal is 5kHz:-

20MHz crystal -> 5MHz instuction cycles. Thats 200ns per instruction.
You're measuring 200us period as 1000 off 200ns intervals. That's 0.1%
You claim to want 5000Hz +/-1Hz. That's 0.02%
You're still out by a factor of 5. At this rate you need 100MHz crystal!

I've already outlined how to get 0.0001% with your existing 4MHz crystal.

What more do you want?

Mike
hemnath



Joined: 03 Oct 2012
Posts: 242
Location: chennai

View user's profile Send private message

PostPosted: Wed Apr 17, 2013 6:03 am     Reply with quote

Thank you very much.

It took some time for me to understand why you have mentioned 100Mhz crystal.

If possible, Can you please explain with small example program with 0.0001% with my existing 4Mhz external crystal?

Everything is good when i work out in theoritical. But practically, it's not attaining for me.

Please bear with my ignorance. Sorry .
Mike Walne



Joined: 19 Feb 2004
Posts: 1785
Location: Boston Spa UK

View user's profile Send private message

PostPosted: Wed Apr 17, 2013 7:16 am     Reply with quote

Before we go any further please tell us:-

1) Total range over which you are trying to measure frequency.
2) Required accuracy over each range.
3) Purpose of the exercise.

What I'm trying to avoid is, showing you how to do one thing, then you coming back and saying "Oh! But I want to do this elsewhere".
i.e. moving the goal posts.

Mike
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2, 3  Next
Page 1 of 3

 
Jump to:  
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