View previous topic :: View next topic |
Author |
Message |
cengizguven2002
Joined: 09 Dec 2013 Posts: 5
|
Calculating Pulse width and Pulse Output? |
Posted: Mon Dec 09, 2013 4:16 pm |
|
|
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
|
|
Posted: Mon Dec 09, 2013 5:58 pm |
|
|
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
|
|
Posted: Tue Dec 10, 2013 12:55 am |
|
|
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: 19513
|
|
Posted: Tue Dec 10, 2013 4:58 am |
|
|
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
|
|
Posted: Tue Dec 10, 2013 3:12 pm |
|
|
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: 19513
|
|
Posted: Tue Dec 10, 2013 3:40 pm |
|
|
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: 1349
|
|
Posted: Tue Dec 10, 2013 8:06 pm |
|
|
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: 19513
|
|
Posted: Wed Dec 11, 2013 1:37 am |
|
|
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
|
|
Posted: Wed Dec 11, 2013 2:04 am |
|
|
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
|
|
Posted: Wed Dec 11, 2013 9:31 am |
|
|
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
|
|
Posted: Sat Dec 14, 2013 6:14 pm |
|
|
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? |
|
|
|