|
|
View previous topic :: View next topic |
Author |
Message |
filjoa
Joined: 04 May 2008 Posts: 260
|
problem with timer configuration |
Posted: Sat Nov 22, 2008 3:03 pm |
|
|
Hi
I would like work with timers but I don't understand how this work.
For example with PIC18F452 with clock 40Mhz, I like calculate how many times I push one switch in 20 sec.
Some one can explain me what kind of calculations I need make? and after what kind of code I need write?
kind regards, Filipe |
|
|
Ttelmah Guest
|
|
Posted: Sun Nov 23, 2008 3:48 am |
|
|
This is not really anything to do with 'timers' as such. You may well use one, but only as the background 'clock' to your main work. The first thing you need to do, is work out how to detect a key 'press'. This is _not_ a simple matter of reading the input, since 'real' keys will exhibit faults, such as 'bounce', when they are made/released. Hence the detection code, will need to have a 'debounce' strategy, so that the key is only genuinely detected, when it is pressed for a few moments, and the multiple small pulses that may well appear as it is made, are ignored. This is called 'debouncing', and a search here will find examples, both using timers, and using simple delay counts.
Once you have key detection sorted, then it becomes a simple matter to increment a counter when the key is seen.
Then, you will not find any hardware timers that can give time intervals like 20 seconds, without using external hardware. Instead, the normal solution, would be to create a 'heartbeat' clock, typically at some frequency like 100 ticks per second. Again, once this is working, it becomes a simple matter to add a counter to this. If using 100Hz, you would set the counter for this to 200, set the key counter to 0, then when the heartbeat timer reaches zero, the number in the key counter, is the number of keys 'seen' in this time.
Now, the individual parts of this, have all been posted here in the past. You need to ue the search engine, and find the components, then see if you can put them together. What you describe, need not be a large program, but will probably be perhaps 100 lines in total. Nobody, is going to write it for you, you need to start to understand the program, and write it yourself. Come back, and ask individual questions, when you get stuck. This is what learning is about.
Best Wishes |
|
|
filjoa
Joined: 04 May 2008 Posts: 260
|
|
Posted: Sun Nov 23, 2008 6:20 am |
|
|
Hi
thank for your answer Ttelmah
I can use for example 555 for count time but I try use timers because I think more simple. But I don't understand timers...
for example:
Quote: |
int16 TIME; // Variavel Global de Relogio - 1mS
#int_TIMER2 // a cada 1mS incrementa TIME
void TIMER2_isr(void)
{
TIME++;
}
void main()
{
setup_timer_2(T2_DIV_BY_16,39,16);
enable_interrupts(INT_TIMER2);
while(TRUE)
{
TIME=0;
while (TIME <= 20000)
{
if (input(PIN_B7) == 1)
{
count++;
}
}
if (count==3)
{
codeok();
}else fstop();
}
}
|
This example I make with wizard of PICC and try numbers for have +-1us in timer, but it don't work and I continue understand this procedure.
In my idea where I have "while (TIME <= 20000) " it is the same with program while 20sec read how many times I press PIN_B7.
My idea stay wrong?
Regards, Filipe |
|
|
Ttelmah Guest
|
|
Posted: Sun Nov 23, 2008 2:12 pm |
|
|
OK.
Much better.
The reason this doesn't work, is you need to enable the GLOBAL interrupt flag as well as the timer interrupt.
Other problem, it won't count the key presses. It''ll count how many times it goes round the 'while' loop, while the key is pressed. You need to detect the key _changing_, not just being pressed.
The interrupt will occur 976.56 times per second. Chose values to give a more accurate time. Also, even with a 'fast' processor, it'll be spending a lot of time in the interrupt running at 1KHz. I'd suggest somewhat slower.
So, something like:
Code: |
int16 time; // Variavel Global de Relogio - 1mS
#int_TIMER2 // 2mSec interrupt
void TIMER2_isr(void) {
if (time) --time;
//This means to counter will stop when it gets to zero
}
void main(void) {
int1 oldip;
setup_timer_2(T2_DIV_BY_8,249,10);
//40000000/(4*8*250*10) = 500
enable_interrupts(INT_TIMER2);
enable_interrupts(GLOBAL);
oldip=input(PIN_B7);
while(TRUE) {
time=10000;
count=0;
while (time) {
if (input(PIN_B7) == 1)
{
if (oldip==0) {
//Here pin has _changed_ to ==1
oldip=1;
count++;
}
}
else
oldip=0;
}
if (count==3)
codeok();
else
fstop();
}
}
|
This will still potentially have problems with seeing multiple 'makes' if there is keybounce, but should get close to working.
Best Wishes |
|
|
filjoa
Joined: 04 May 2008 Posts: 260
|
|
Posted: Sun Nov 23, 2008 3:57 pm |
|
|
Hi
One more time thanks Ttelmah
This is for simulating calculation of Car ABS sensor but now I have this on prototype and have a simple switch where I press "x"times.
When you suggest
Quote: |
if (oldip==0) {
//Here pin has _changed_ to ==1
oldip=1;
count++;
}
|
This is for case I press slowly the button, correct? But if I call for example interrupts in ports RB0, RB1 or RB2 (PIC18F452) for detect this impulse you think this better?
Now about timers :P
when you configure setup timers:
Quote: |
setup_timer_2(T2_DIV_BY_8,249,10);
//40000000/(4*8*250*10) = 500 |
How you use "4", "250", "10" and result "500" what this mean? or what you don't use other values?
and after you tell
Quote: | #int_TIMER2 // 2mSec interrupt |
I don't understand where appear 2msec.
I can use for example same process for timer0 and timer1?
Sorry my stupid questions but I like know how timers work...
kind regards |
|
|
Ttelmah Guest
|
|
Posted: Sun Nov 23, 2008 4:23 pm |
|
|
The point is that your main code is looping. You test for the button being made (==1), but it'll be made all the time, when it is pressed. Remember that the loop takes only a few instructions. Even the _quickest_key press will last for thousands of processor instructions. You would never see '3' without this, since it'll shoot past this, before you can physically release the button, even if you are 'faster than a speeding bullet'.
It'd actually take a typical bullet, something over 50uSec to pass 'through' a button. Counting in the loop, without a test for the change being present, I'd expect a bullet to probably give about 10 counts. Hence this type of test is _essential_...
Now, on the timing. There is a balancing act. If the interrupt is too fast, you will spend most of your time in the interrupt. 1mSec, is possible, but probably 'pushing things', hence I suggest dropping to 2mSec. Now the timer calculation, is that you have the master clock (40000000), which is divided by four, before it goes to the timer circuit (hence the first four. Then, you are looking for a set of numbers, that multiply together to give a value close to 20000, and if the timing is to be accurate, want to give _exactly_ 20000. On your original code, which was meant to give 1mSec (requiring 10000), the numbers actually give 16*40*16 = 10240.
Using 8*250*10, givesexactly 20000. You could also use 16*125*10, but there are only a few combinations that give exact decimal results like this.
the result number, is how many times the interrupt will occur a second. 500* = 2mSec interval.
On the other timers, you don't have the interrupt 'postscaler', or the ability to automatically reset the counters at a value. Generally they will only give binary counts.
Yes, you can use an interrupt on change to detect the button, but with this, debouncing will become even more essential.
Best Wishes |
|
|
filjoa
Joined: 04 May 2008 Posts: 260
|
|
Posted: Tue Nov 25, 2008 11:07 am |
|
|
hi
I try use this code on ISIS Proteus but it don't work.
Other problem is... I change PIC18F452 for PIC18F252 and CCS give an error on "setup_timer_2(T2_DIV_BY_8,249,10);" and for correct this I change to "setup_timer_2(T2_DIV_BY_4,249,10);".
My code at this moment for test timers is:
Code: |
#include <18F252.h>
#fuses EC_IO,NOWDT,NOPROTECT,NOLVP,BROWNOUT,STVREN
#use delay(clock=40000000)
#use rs232(baud=115200,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
#build(reset=0x200)
#build(interrupt=0x208)
#org 0x0000,0x01ff
void bootloader() {
#asm
nop
#endasm
} // Reserve space for the bootloader
//###### VARIAVEIS #####
int16 time; // Variavel Global de Relogio - 1mS
//###### IN PORTS ######
#define DOOR PIN_B7
#define HBREAK PIN_B6
#define RFID PIN_B5
#define IGN PIN_B4
#define ABS PIN_B0
//###### OUT PORTS ######
#define RED PIN_B1
#define GREEN PIN_B2
#define R1 PIN_C0 //relé de falha
#define R2 PIN_C1 //relé bi-estavel de corte
#define R3 PIN_C2
#define R4 PIN_C3
#int_TIMER2 // 2mSec interrupt
void TIMER2_isr(void) {
if (time) --time;
//This means to counter will stop when it gets to zero
}
void codeok()
{
output_high(R1);
delay_ms(1000);
output_low(R1);
delay_ms(1000);
output_high(R1);
delay_ms(1000);
output_low(R1);
delay_ms(1000);
}
void fstop()
{
output_high(R2);
delay_ms(1000);
output_low(R2);
delay_ms(1000);
output_high(R2);
delay_ms(1000);
output_low(R2);
delay_ms(1000);
}
void main()
{
int1 oldip;
int8 count;
setup_timer_2(T2_DIV_BY_4,249,10); //40000000/(4*4*250*10) = 1000
enable_interrupts(INT_TIMER2);
enable_interrupts(GLOBAL);
oldip=input(DOOR);
While(TRUE)
{
time=10000;
count=0;
while (time) {
if (input(DOOR) == 1)
{
if (oldip==0) //Here pin has _changed_ to ==1
{
oldip=1;
count++;
}
}
else
oldip=0;
}
if (count==3)
codeok();
else
fstop();
}
}
|
This is the circuit on Proteus:
Someone can help me to correct them?
kind regards |
|
|
filjoa
Joined: 04 May 2008 Posts: 260
|
|
Posted: Tue Nov 25, 2008 11:48 am |
|
|
Hi
I make some tests and problem stay on timers :S
it dont jump from "while(time)" :( and I dont know why.... |
|
|
filjoa
Joined: 04 May 2008 Posts: 260
|
|
Posted: Tue Nov 25, 2008 5:54 pm |
|
|
Hi
I try make other simple program but now with timer0 but it don´t work
Code: |
#include <18F252.h>
#fuses EC_IO,NOWDT,NOPROTECT,NOLVP,BROWNOUT,STVREN
#use delay(clock=40000000)
#use rs232(baud=115200,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
#int_TIMER0
int16 time; // Variavel Global de Relogio
void TIMER0_isr(void)
{
time++;
}
void main()
{
setup_timer_0(RTCC_EXT_L_TO_H|RTCC_DIV_256); // 1seg
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
setup_timer_3(T3_DISABLED|T3_DIV_BY_1);
while(1)
{
time=0;
while (time <= 20000)
{
output_high(PIN_C0);
}
output_low(PIN_C0);
delay_ms(1000);
}
}
|
With this program PIN_C0 continue infinitely high and never return to low... one more time my timer configuration don't stay correct
For configuration I go to wizard. I make this options:
Please someone can help make this work? and if is possible explain me why this don't work. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Nov 25, 2008 6:25 pm |
|
|
'time' is a 16-bit variable that is changed in the #int_timer0 routine.
You need to disable interrupts temporarily when you read or write
the 'time' value in main(). There are two places in your program
where you access 'time'.
The reason is because it takes two ASM instructions to read or write
the two bytes in the 16-bit variable. An interrupt could occur between
these two ASM instructions and the result would be a corruption of the
'time' variable.
More info:
http://www.htsoft.com/resources/articles/techtip_interrupts.php
Also, the #int_timer0 statement should go above the isr routine. Don't
put any other lines of code between them. Example of how to do it:
Quote: | #int_TIMER0
void TIMER0_isr(void)
{
time++;
} |
|
|
|
filjoa
Joined: 04 May 2008 Posts: 260
|
|
Posted: Tue Nov 25, 2008 6:45 pm |
|
|
Hi, thanks
I put the code how you tell but continue without work...
I don't understand what stay wrong with "time" where I destroy this variable? |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
|
filjoa
Joined: 04 May 2008 Posts: 260
|
|
Posted: Wed Nov 26, 2008 1:00 pm |
|
|
Hi
sorry but I think that I only understand when I see
please, some one can correct one of this program for work, with any timer... |
|
|
filjoa
Joined: 04 May 2008 Posts: 260
|
|
Posted: Thu Nov 27, 2008 5:15 am |
|
|
hi
I will try make this and I put there some "stupid" questions, for I try understand timers procedure.
For start I have PIC18F252 at 40Mhz and I try use timer1.
I make this code:
Code: |
#include <18F252.h>
#fuses EC_IO,NOWDT,NOPROTECT,NOLVP,BROWNOUT,STVREN
#use delay(clock=40000000)
#use rs232(baud=115200,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
//###### VARIAVEIS #####
int16 time; // Variavel Global de Relogio - 1mS
//###### IN PORTS ######
#define DOOR PIN_B7
#define HBREAK PIN_B6
#define RFID PIN_B5
#define IGN PIN_B4
#define ABS PIN_B0
//###### OUT PORTS ######
#define RED PIN_B1
#define GREEN PIN_B2
#define R1 PIN_C0 //relé de falha
#define R2 PIN_C1 //relé bi-estavel de corte
#define R3 PIN_C2
#define R4 PIN_C3
#int_TIMER1
void TIMER1_isr(void) {
time++;
}
void codeok()
{
output_high(R1);
delay_ms(1000);
output_low(R1);
delay_ms(1000);
output_high(R1);
delay_ms(1000);
output_low(R1);
delay_ms(1000);
}
void fstop()
{
output_high(R2);
delay_ms(1000);
output_low(R2);
delay_ms(1000);
output_high(R2);
delay_ms(1000);
output_low(R2);
delay_ms(1000);
}
void main()
{
int1 oldip;
int8 count;
enable_interrupts(INT_TIMER1);
setup_timer_1(T1_INTERNAL|T1_DIV_BY_8);
//sets the internal clock as source
//and prescale as 8. At 20Mhz timer1 will increment
//every 1.6us in this setup and overflows every
//104.896ms (Manual Pag. 77)
enable_interrupts(GLOBAL);
oldip=input(DOOR);
While(TRUE)
{
time=0;
count=0;
while (time<10000)
{
if (input(DOOR) == 1)
{
if (oldip==0)
{
oldip=1;
count++;
}
}
else
oldip=0;
}
if (count==3)
codeok();
else
fstop();
}
}
|
1º question:
I copy this "setup_timer_1(T1_INTERNAL|T1_DIV_BY_8);" from CCS manual but example work at 20Mhz but my program work at 40Mhz, how I can make this calculations for know when have my timer1?
2º question:
in this example configuration I have one timer every 1.6us what mean have overflows every 104.896ms?
3º question:
in my program if I use this example configuration (at 20Mhz) how many time +- I have on "while (time<10000)"?
Please help me try understand this... I need start timers from zero for I understand.
kind regards, Filipe Abrantes |
|
|
filjoa
Joined: 04 May 2008 Posts: 260
|
|
Posted: Thu Nov 27, 2008 9:38 am |
|
|
Sorry but I edit last reply and this don't up the post and I comment now only for this post up |
|
|
|
|
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
|