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

Calculating Pulse width and Pulse Output?

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
cengizguven2002



Joined: 09 Dec 2013
Posts: 5

View user's profile Send private message

Calculating Pulse width and Pulse Output?
PostPosted: Mon Dec 09, 2013 4:16 pm     Reply with quote

Hi guys. I looked at many example and i try to make my program but it is not working good. The problem is about program or MCU? 16F628A or 16F877A is enough strong or i need 24Fxxx else?

Program: I have one signal input. The signal will be between 500hz to 10khz.
So i want to calculate period of the pulse signal for example:
1khz pulse signal period is 500us. I want to calculate and at the same time i want to use that value as a pulse output. I know that i dont expect exactly 500 every time. It can have error like 499 498 497 501 502. I only try it on Proteus.

Signal input parallel to all ( portb.1, ccp1,ccp2)
Signal output portb.0

Code:

#include <16f877a.h>             
#FUSES NOWDT                   
#FUSES HS                     
#FUSES PUT                       
#FUSES NOPROTECT                 
#FUSES NOLVP                     
#FUSES NOCPD                     

#byte PORTB = 0x06
#byte TRISB = 0xfe

#use delay(clock=20000000)       
#bit sinyal = portb.1
#bit cikis = portb.0
#include <LCD.C>               

int32 pulse;    // counting data
int32 period;  // output pulse data

 

#int_ccp2
void isrr()
{
   period=1000000/pulse;
   pulse=0;
 
}                             

#int_ccp1
void isr()
{
  while (sinyal==1) {pulse++; }   

}                               


void main()
{
   setup_ccp1(CCP_CAPTURE_RE);    // Configure CCP1 to capture rise
   setup_ccp2(CCP_CAPTURE_FE);    // Configure CCP2 to capture fall


   enable_interrupts(INT_CCP2);   // Setup interrupt on falling edge
   enable_interrupts(INT_CCP1);
   enable_interrupts(GLOBAL);

lcd_init();

cycle:
while(1){
lcd_gotoxy(1,2);
printf(lcd_putc,"%u s", period);
output_high(pin_b0);   // pulse output  port b0
delay_us(period);      // delay
output_low(pin_b0);   // pulse output port b0
delay_us(period);    // delay
}

}
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Dec 09, 2013 5:58 pm     Reply with quote

Tell us the purpose of your project. Tell us if the input signal is a
continuous waveform, or is it an occasional individual pulse that occurs
once every few seconds?

Is the output signal a continuous squarewave signal ? Or, is it just a
individual pulse that is sent every time you get an input pulse ? ie. once
every few seconds ?
cengizguven2002



Joined: 09 Dec 2013
Posts: 5

View user's profile Send private message

PostPosted: Tue Dec 10, 2013 12:55 am     Reply with quote

PCM programmer wrote:
Tell us the purpose of your project. Tell us if the input signal is a
continuous waveform, or is it an occasional individual pulse that occurs
once every few seconds?

Is the output signal a continuous squarewave signal ? Or, is it just a
individual pulse that is sent every time you get an input pulse ? ie. once
every few seconds ?



Input waveform is squarewave and continuously coming. It is encoder pulse. Output will be active when input is coming. Output will follow the input with some gear.

My program is calculating the pulse but i dont know correct or not. But pulse output is not correct i think interrupts are break the delay main program.
I think if i use pulse output with timer (32bit) because my data will be 32bit. I will not have problem about pulse output. Am i right?

For example (code is not correct. i just want to explain my idea)
output_high_port_b0
settimer( timer-mydata)

#timer_int
output_low_port_b0
settimer( timer-mydata)

but for this kind of program timer must be 32bit.


I will explain my signal again. Signal is always coming and a quite different for example 10000hz, 10001hz, 10002hz, 9999hz like this. So i must count every pulse width and every time new data will mul or div with constant and send as 50% duty pwm like this. Is it possible ?
Ttelmah



Joined: 11 Mar 2010
Posts: 19540

View user's profile Send private message

PostPosted: Tue Dec 10, 2013 4:58 am     Reply with quote

First, the old rule applies. Keep interrupt handlers short. 100000/pulse, will take about 250uSec at your processor speed.
Then you stay in the INT_CCP2 handler, while the pulse is high. Why?. Same problem - time.
Why two CCP's. All you want to do, from your description, is measure the pulse interval. One CCP can do this. However it needs to read the timer count when it triggered, which is being done in neither routine. You don't need the pulse width, just the interval. Just use the rising edge with one CCP.
Then, you are not starting, or setting up the timer for the CCP to use.....
Code:

#include <16f877a.h>             
#FUSES NOWDT                   
#FUSES HS                     
#FUSES PUT                       
#FUSES NOPROTECT                 
#FUSES NOLVP                     
#FUSES NOCPD                     

#use delay(clock=20000000)
#include <LCD.C>               

union
{
   int32 whole_number;
   int16 words[2];
} counter;
int32 period=0, old_count=0;

#int_timer1
void timer_isr(void)
{
   counter.words[1]++;
}

#int_ccp1
void ccp_isr(void)
{
   counter.words[0]=CCP_1; //read when the pulse occured
   period=counter.whole_number-old_count;
   old_count=counter.whole_number;   
}                               

void main(void)
{
   int32 local_ticks=0;
   setup_timer_1(T1_INTERNAL| T1_DIV_BY_1); //start and configure the timer
   setup_ccp1(CCP_CAPTURE_RE);    // Configure CCP1 to capture rise

   enable_interrupts(INT_CCP1);
   enable_interrupts(INT_TIMER1);
   enable_interrupts(GLOBAL);

   lcd_init();
   
   while (TRUE)
   {
      lcd_gotoxy(1,2);
      while (local_ticks!=period)
         local_ticks=period; //ensure value updates correctly if interrupt occurs
      //Now the period is counting in 0.2uSec steps (20000000/4)
      local_ticks=local_ticks/5;
      printf(lcd_putc,"%Lu s", local_ticks);
      output_high(pin_b0);   // pulse output  port b0
      delay_us(period);      // delay
      output_low(pin_b0);   // pulse output port b0
      delay_us(period);    // delay
      //This second delay is always going to be 'long', because of the lcd
      //display, and maths in the loop.
   }
}
cengizguven2002



Joined: 09 Dec 2013
Posts: 5

View user's profile Send private message

PostPosted: Tue Dec 10, 2013 3:12 pm     Reply with quote

The program did not work. I did not see counted pulse on lcd and i did not have pulse output. Actually i work it on proteus. I want to explain you again with detail. I am sorry that maybe i made you understand wrongly.

For example Input signal is 10khz and i am catching it. And i mul that signal with 1.25 so it is 12.5 khz and i gave that to pulse output(%50 duty pwm)
The program always calculate the period of the every pulse and it will give that pulse to output with electronic gear. So;

When input 10khz output is 12.5khz
when input 9.99khz output is 12.487khz
when input 500hz output is 625hz

Input is always changing. so i must catch and make calculate with every pulse. So i must give the new data to pulse train every time.
Ttelmah



Joined: 11 Mar 2010
Posts: 19540

View user's profile Send private message

PostPosted: Tue Dec 10, 2013 3:40 pm     Reply with quote

That is never going to work. It takes several tens of uSec to do the LCD functions....

Best Wishes
jeremiah



Joined: 20 Jul 2010
Posts: 1354

View user's profile Send private message

PostPosted: Tue Dec 10, 2013 8:06 pm     Reply with quote

I noticed that his outputs were 25% higher than his expected. Is that a function of the local_ticks = local_ticks/5? I noticed the comment said /4, but since I wasn't following the algorithm completely, I wasn't sure if that was intentional or not.
Ttelmah



Joined: 11 Mar 2010
Posts: 19540

View user's profile Send private message

PostPosted: Wed Dec 11, 2013 1:37 am     Reply with quote

The only way to get a continuous output, without doing the maths/LCD interfering, is to use the PWM. There will still be a tiny lag (the _next_ pulse will reflect what happened on the last input), but this should be acceptable. Any attempt to generate software pulses while also updating an LCD, is doomed to failure at this sort of rate.

No, the /4, is the clock rate. The CCP is being clocked directly off the master clock/4 (5MHz), so counts in 0.2uSec steps. So to give the result in uSec, you have to divide the retrieved count by 5.

Looking at the timings/rates being talked about, I don't think you need anything more than the int16 available directly from the CCP, which then makes the maths lots quicker, and removes the need to handle int32's at all. Problem is we don't really 'know' what is wanted (which returns to PCM_programmers questions).

Best Wishes
cengizguven2002



Joined: 09 Dec 2013
Posts: 5

View user's profile Send private message

PostPosted: Wed Dec 11, 2013 2:04 am     Reply with quote

the program must mul the signal with data. The data will be changed with my order. I will change it to any number i want. So input is 500hz to 20khz range and the output will be in the quite same range.

Gear = ( it is changing with my order not the same)


input_signal_period * gear = output_signal_period


I will not read the counted data on the LCD. I put it just see the program working or not. My idea to use LCD is that i will increase and decrease the gear by buttons and i will see the gear value on the screen. but that program is not problem i can add it later. The really important thing is that catching and calculating the every pulse width and mul it with gear and send it to output. But output must be continiously and input is coming continously.

Can it possible to do it?
gaugeguy



Joined: 05 Apr 2011
Posts: 303

View user's profile Send private message

PostPosted: Wed Dec 11, 2013 9:31 am     Reply with quote

It definitely is possible. I have done similar projects at slightly lower frequencies taking a signal, scaling it by a correction factor, and generating a new output on a PIC16C54 with newer generations of the product migrating to PIC16C558, PIC16F622, PIC16F627, and PIC16F818. The incoming signal could vary over several orders of magnitude in frequency. These were paid projects and I cannot share the code, but if definitely is possible to do what you want, especially with the hardware modules to assist.
cengizguven2002



Joined: 09 Dec 2013
Posts: 5

View user's profile Send private message

PostPosted: Sat Dec 14, 2013 6:14 pm     Reply with quote

gaugeguy wrote:
It definitely is possible. I have done similar projects at slightly lower frequencies taking a signal, scaling it by a correction factor, and generating a new output on a PIC16C54 with newer generations of the product migrating to PIC16C558, PIC16F622, PIC16F627, and PIC16F818. The incoming signal could vary over several orders of magnitude in frequency. These were paid projects and I cannot share the code, but if definitely is possible to do what you want, especially with the hardware modules to assist.


I understand but is it possible to give me just idea or tips? What is the hardware module?
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
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