|
|
View previous topic :: View next topic |
Author |
Message |
Guest
|
slow down timer |
Posted: Tue Dec 02, 2008 8:21 am |
|
|
Hello, I would like to slow down a timer so that I can measure longer time interval.
Is the following idea feasible:
Use (for example) PWM to output divided crystal frequency, and feed this signal back to timer external input.
So my idea is:
Code: |
setup_ccp1(CCP_PWM);
setup_timer_2(T2_DIV_BY_1, 3, 1); // divide frequency by 4 ????
set_pwm1_duty(2); // __--__-- signal
|
What timer can I use for that purpose? Can it be any timer 0,1,2,3?
What does "T1_EXTERNAL_SYNC" constant mean? Shall I use it?
I use PIC18F2620.
Thank you |
|
|
kisslove Guest
|
Re: slow down timer |
Posted: Tue Dec 02, 2008 9:07 am |
|
|
Anonymous wrote: | hello, i would like to slow down a timer so that I can measure longer time interval.
Is the following idea feasible:
Use (for example) PWM to output divided crystal frequency, and feed this signal back to timer external input.
So my idea is:
Code: |
setup_ccp1(CCP_PWM);
setup_timer_2(T2_DIV_BY_1, 3, 1); // divide frequency by 4 ????
set_pwm1_duty(2); // __--__-- signal
|
|
But why don't you use T2_DIV_BY_4 constant instead?
Anyway if you need to count a large ammount of time - it's easier to implement software timer driven by any of hardware timers.
Anonymous wrote: |
What timer can I use for that purpose? Can it be any timer 0,1,2,3?
What does "T1_EXTERNAL_SYNC" constant mean? Shall I use it?
I use PIC18F2620.
Thank you |
You can use any timer that has external clock source, for this device according to datasheet it can be any timer except for T2. |
|
|
Ttelmah Guest
|
|
Posted: Tue Dec 02, 2008 9:11 am |
|
|
Obviously not timer2. This doesn't have an external input, and with what you are doing, would be the clock 'source' for the other timer(s).
Yes, this is perfectly acceptable.
The 'sync' setting, ensures that the timer actually updates _in sync_ with the internal clock. Shouldn't actually matter, since your clock is in sync already.
What you show though, could be done by using Timer0. with no extra pins.
Timer1, only supports 1,2,4 & 8 'prescalers'. Timer0, allows 2,4,8,16,32,64,128, & 256 prescalers, easily going beyond what your extra division is doing...
Best Wishes |
|
|
Guest
|
|
Posted: Tue Dec 02, 2008 5:11 pm |
|
|
Thank you guys.
@Ttelmah:
Quote: | Timer1, only supports 1,2,4 & 8 'prescalers'. Timer0, allows 2,4,8,16,32,64,128, & 256 prescalers, easily going beyond what your extra division is doing.. |
I want to run the PIC at 20 or 24MHz crystal (I can't go lower because of plenty of calculations to be done - "CPU" load), the timespan I want to measure is about 6 seconds.
Hence, I reckon (I hope I am right) that using Timer0 with 256 prescaler yields only 3,3 seconds.
So that is the reason why I want to slow down the timer.
Quote: | But why don't you use T2_DIV_BY_4 constant instead? | Will the following produce the same (will it still be __--__-- signal)?
Code: |
setup_ccp1(CCP_PWM);
setup_timer_2(T2_DIV_BY_4, 1, 1); // divide frequency by 4 ????
set_pwm1_duty(1); // __--__-- signal
|
|
|
|
kisslove Guest
|
|
Posted: Wed Dec 03, 2008 4:11 am |
|
|
[quote=:
I want to run the PIC at 20 or 24MHz crystal (I can't go lower because of plenty of calculations to be done - "CPU" load), the timespan I want to measure is about 6 seconds.
Hence, I reckon (I hope I am right) that using Timer0 with 256 prescaler yields only 3,3 seconds.
So that is the reason why I want to slow down the timer.
[/quote]
Just arter T0 overflow write 5900 to it, it will give you 3 seconds, then use flag to count periods. If you have T0 interrupt and your flag=1, then 6 seconds passed.
Quote: | Will the following produce the same (will it still be __--__-- signal)?
Code: |
setup_ccp1(CCP_PWM);
setup_timer_2(T2_DIV_BY_4, 1, 1); // divide frequency by 4 ????
set_pwm1_duty(1); // __--__-- signal
|
|
I'm afraid i don't correctly understand what exactly do you want
Do you want to keep duty cycle at 50% ? Just how much time between A and B? A__--B
And where on this graph are 6 seconds that you want?
Alexey. |
|
|
Ttelmah Guest
|
|
Posted: Wed Dec 03, 2008 5:22 am |
|
|
The slower your timer clock, the lower the resolution.
Now, it is very easy to just _count_. This is how time measurement/keeping is done in most systems. All you do is have a timer/interrupt at some fast interval, that is easy to setup, and have it count up or down, till a target is reached. Hence (for example), on the older PC's, though there is a real time clock chip, this is not actually read to generate 'time', excpet during boot up. nstead the system, just counts using an interrupt at 18mSec intervals. On modern PC's, the RTC, is checked occassionally, and the 'tick' interval is now faster, but the basic time handling is still done this way.
Now it is not clear from what you have said so far, if you want to _measure_ a time, or just have a 'trigger' at a particular interval.
The latter can be done using your hardware idea. However you won't get absolute precision. The problem is that the interval you need, is not exactly divisible by 65536, which is the basic 'count' from any of the 16bit timers. Unfortunately, though you can load a counter 'to' a value, or advance a counter (the latter is more accurate if working at any speed), doing so, _resets the counter's prescaler_, leading to cumulative errors...
There is no 'need' or point to using a 50% duty cycle. The clocks work on one _edge_ of the arriving signal, so couldn't care what the mark/space ratio actually is.
So, start wth your master clock - say 24MHz.
The 'system clock' that feeds any timer, is this /4. 6MHz.
Then for 6 seconds, you would want to count 36000000.
Divide this by 65536. 549.3. So you need a 'prescale' of 549 to get as close as you can. Biggest division available from timer2 itself, is 256, so you will need to use it's prescaler. To get below 256. Use the smallest one that mees this criterion. /4. This then gives you needing to use a division by 137, to give 548 as the nearest possible counter using this approach. A timeout (from the 24MHz oscillator) of 6000000/(4*137*65536) = 0.167 times per second. 5.985 seconds.
Downside, using two timers, two hardware pins, and still not that accurate.
One (of many) alternatives, using software.
Look for a nice 'decimal' divider of the master clock. So Timer2, has a 'postscaler' supporting /1 to /16, binary prescalers of /1, /4, and /16. Now, start again with 24Mhz, and the _largest_ available decimal multiplier possible from this timer, is: /16 /250 /16 = 64000. However 60000, is a nicer fit to the 6MHz clock, so /16, /250, /15. With this, the timer will interrupt every 1/100th second, requiring a simple count to 600, for exactly 6 seconds.
Now, the big advantage of this, is that most systems _will_ require other timekeeping functions. Things like keyboard scanning, debouncing etc., all require delays. 1/100th second, is a nice 'housekeeping' tick, to use for all these jobs, and gives you time for your required application as well.
Code: |
//Have a 'global' timer tick
int16 tick=0;
//Then a basic interrupt handler
#INT_TIMER2
void tick_counter(void) {
if (tick) --tick;
}
//Then in your main
setup_timer_2(T2_DIV_BY_16, 249, 15); // 1/100th second tick
enable_interrupts(INT_TIMER2);
enable_interrupts(GLOBAL);
tick=600;
while (tick) {
//Do any other jobs you want to do while waiting
}
//Get here after 6 seconds.
|
This is a tidy way of giving nice timing for anything.
Third alternative, run a timer off a _binary divisible_ clock. So (for example), attach a 32768Hz crystal to one of the timers. ith no prescalers or anything, this potentially gives you a '2 second' tick.
So, lots of different solutions, with advantages and disadvantages to all
Best Wishes |
|
|
krey Guest
|
|
Posted: Wed Dec 03, 2008 4:19 pm |
|
|
thanx to both of you.
Quote: | I'm afraid i don't correctly understand what exactly do you want Smile
Do you want to keep duty cycle at 50% ? Just how much time between A and B? A__--B
And where on this graph are 6 seconds that you want? |
It is not necessary to keep duty cycle at 50%. I just want to have rising edge in the signal, because I want to feed it back and you PWM as clock source for a timer, and I thought it might happen to have a signal with 0 or 100% duty cycle - that is, without any rising and falling edge. I have no clue what duty cycle the following produces:
Code: | setup_timer_2(T2_DIV_BY_4, 1, 1);
set_pwm1_duty(1); |
I think I should have written the main reason of all of that:
I want to measure duration of 4 signals which usually last from 2-5 seconds. I wanted to feed the signals to PORTB and to use PORTB interrupt-on-change to measure rising endges (the timer value when this event occurs) and falling edges.
In other words, to measure every signal separately.
Thank you again |
|
|
krey Guest
|
|
Posted: Wed Dec 03, 2008 4:22 pm |
|
|
It should also be noted that the resolution can be as bad as 1ms, and that I really need to run the PIC at at least 20Mhz since it has plenty of other things to do.
cheers |
|
|
kisslove Guest
|
|
Posted: Thu Dec 04, 2008 5:40 am |
|
|
krey wrote: | It should also be noted that the resolution can be as bad as 1ms, and that I really need to run the PIC at at least 20Mhz since it has plenty of other things to do.
cheers |
Create a task that will be run(on Timer interrupt) once in 1ms(or faster). It will increase software timer if signal is there and report a number of cycles if signal has gone. Thus you'll get int16 and that will be the duration of your impulse(in ms if you'll run it once per msecond).
But if you may have a noise in incoming signal you also should use simple software slow filter to prevent false measurements. |
|
|
|
|
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
|