PDA

View Full Version : Long Timer



Tissy
- 28th October 2005, 22:44
I have searched through numerous threads for an hour or so, but there are so many topics relating to timers and it is a little confusing.

I am using a PIC18F2550 which when when of the inputs on the PIC are triggered, a counter starts. This counter needs to be setable by a variable in the code from 5 seconds to around 60mins.

Once the timer has been triggered, if the same input or another for that matter on another two ports was triggered, it would stop the counter and go back to the beginning again. A kind of 'timer abort facility.

Can any one pint me in the right direction?

I've tried the pause command, but that only workks 65536 (65seconds)

Many thanks.

Tissy
- 29th October 2005, 01:11
OK, i have have done a bit more digging and come up with this:



Red VAR PORTB.1

Seconds var byte ' 0-59
Minutes var byte ' 0-5
Minutedelay var byte

Minutedelay = 2
counter = 0
'
For Minutes = 0 to Minutedelay
Gosub Delaymin
If Minutes = Minutedelay - 1 then gosub flash
Next Minutes

Delaymin:
For Seconds=0 to 59
Pause 1000
Toggle Red ' flashing light for reference
Next Seconds
Return

Flash:
For loop = 1 to 5
red = 1
pause 125
red = 0
pause 250
red = 1
pause 125
red = 0
pause 250
Next loop
Return

End

I have had to put the


If Minutes = Minutedelay - 1 then gosub flash

in as it would not stop at the MinuteDelay variable. ie if i wanted it to stop at 2 minutes, it would stop at 3, if i wanted to stop at 3, it would stop at 4 etc etc.

Is there any other way to tidy up this routine?

Also, this routine is activated by, for argument sake, PORTC.0 going high. How would i place the abort code in. ie if the same button (PORTC.0) goes high during this routine, it stops the counting and jumps back to the main code awaiting an input instruction.

I have a CASE SELECT routine which selects different routines, depending on which button is pressed. This is just one of the routines.

Many thanks,

ccsparky
- 29th October 2005, 15:35
I believe this is the same thing you are doing.

MinuteDelay = 2

For Minutes = 1 to MinuteDelay
For Seconds = 1 to 60
if PORTC.0 = 1 Then goto main code
Pause(1000)
Next Seconds
Next Minutes

For loop = 1 to 10
if PORTC.0 = 1 Then goto main code
red = 1
pause(125)
red = 0
pause(250)
Next loop

Goto Main Code

PORTC.0 will have to be held high for one second so that it can be picked up (will not be seen during a pause)
Changed your loop from "1 to 5" to "1 to 10" since you were flashing red on and off twice in each loop.
Your use of "If Minutes = Minutedelay - 1 then gosub flash" could have been
"If Minutes = Minutedelay then gosub flash" if
"For Minutes = 0 to Minutedelay" had been "For Minutes = 1 to Minutedelay"
Since you are using PORTC.0 to send to and escape from the timer, make sure it is low when you return to main code or you'll just be sent right back to your timer or back to your main code if you are trying to activate the timer.

I'm not sure if this is proper to do and maybe someone will explain if it is not but, if you have a PIC reset switch simply pressing it at anytime would abort the timer by means of resetting your PIC. You could then omit the
"if PORTC.0 = 1 Then goto main code" in both places.


William

Tissy
- 29th October 2005, 16:22
William, thanks very much for your reply.

Your right about the abort routine. I wonder if there is another was to stop the effect where if the button is held down for the ABORT phase, when it jumps back to the main code, it will still be HIGH and thus start the delay routine again.

With this you'll need to be quick off of the button to stop this from happening.

Any other thoughts?

ccsparky
- 29th October 2005, 16:37
Tissy,
How about a button just for abort purposes? Say PORTC.1
Or maybe a 3 second pause after seeing PORTC.0 high during abort, allowing 3 seconds to get off the button, i.e.
If PORTC.0 = 1 then
pause(3000)
goto main code
end if

I am curious to see other solutions also!!!

William

Also after reading more of your orginal post and seeing that you need to time by seconds, would this be more of what you needed:

Low PortB.1

Red VAR PORTB.1

MinuteDelay VAR BYTE
SecondDelay VAR BYTE

Main Code:

MinuteDelay = 2 '1 To 60
SecondDelay = 0 '1 To 60

If PORTC.0 = 1 Then Goto Timer

Goto Main Code

Timer:

If MinuteDelay > 0 then
For Minutes = 1 to MinuteDelay
For Seconds = 1 to 60
if PORTC.0 = 1 Then goto main code
Pause(1000)
Next Seconds
Next Minutes
EndIF

If SecondDelay > 0 then
For Seconds = 1 to SecondsDelay
if PORTC.0 = 1 Then goto main code
pause(1000)
Next Seconds
EndIF

For loop = 1 to 10
if PORTC.0 = 1 Then goto main code
HIGH red
pause(125)
LOW Red
pause(250)
Next loop

Goto Main Code

Charles Linquis
- 29th October 2005, 18:47
Another way that has no PAUSE statements, so has very quick
response to all inputs.

; Assumes 20 Mhz Oscillator

T0CON =$86


LOOP:

IF INTCON.2 = 1 THEN
INTCON.2 = 0
TMR0H = $69
TMR0L = $7A
GOSUB SecondsTimer
EndIF

'Run regular code here (check for inputs, timeouts, etc)

GOTO LOOP

SecondsTimer:
Seconds = Seconds + 1
IF Seconds >= 60 THEN
Seconds = 0
Minutes = Minutes + 1
IF Minutes >=60 THEN
Minutes = 0
Hours = Hours + 1
ENDIF
ENDIF
RETURN

END

Tissy
- 29th October 2005, 20:17
Hang-on, i think i may have it !!

Tissy
- 29th October 2005, 22:01
Right cracked it, thanks very much for everones help.

Regards,

Steve

Tissy
- 30th October 2005, 21:12
Ok, i got greedy. I have now added hours to the routine.

However, i have done a test, setting the delay at 8hrs 45min 32 seconds
and it triggered at 8hrs 44min 06 seconds.

Two things really, is the the type of result expected. I know its a small margin of error, but i thought 1000ms is a 1000ms. Alternatively is there an error in the code that someone can see?


If HoursDelay > 0 then
For Hours = 1 to HoursDelay
For Minutes = 1 to 60
For Seconds = 1 to 60
If SW2 = 1 Then Goto main
Toggle Red ' flashing light for reference
Pause(1000)
Next Seconds
Next Minutes
Next Hours
EndIF

If MinutesDelay > 0 then
For Minutes = 1 to Minutesdelay
For Seconds = 1 to 60
If SW2 = 1 Then Goto main
Toggle Red ' flashing light for reference
Pause(1000)
Next Seconds
Next Minutes
EndIF

If SecondsDelay > 0 then
For Seconds = 1 to SecondsDelay
If SW2 = 1 Then goto main
Toggle Red ' flashing light for reference
pause(1000)
Next Seconds
EndIF

I thought it would be a little more accurate than that. If i set the delay at 32seconds then it triggers at 32seconds.

There are only so many lengthy test you can do, waiting 8hrs for an event to trigger is a long time !!

Cheers,

Tissy
- 1st November 2005, 01:23
Can anyone answer the above ?

Ingvar
- 1st November 2005, 12:07
What oscillator are you using?

Your error is 0.27%, not very good if you're using a crystal. Quite possible if using a resonator, very good if you're using internal oscillator.

You should also ask yourself if minute or so matters over 8 hours.

/Ingvar

Tissy
- 1st November 2005, 12:37
Cheers for the reply.

I am using a 20MHz resonator. So you reckon if i put in a Crystal instead, that should improve matters?

I know what your saying about a minute error over 8 hours, but i just wanted it as accurate as possible. When its timing seconds only, thats fine, the error just creeps in over longer periods.

I will get myself a 20MHz crystal and see if this changes things.

I also really just wanted to make sure my code looks OK, there's only so many times you can tolerate waiting a long period to check for accuracy.

Regards,

Steve

Ingvar
- 1st November 2005, 17:24
Well ...... it's always a good start to KNOW that your oscillator is reasonable accurate. You will definatley get a more accurate source using a crystal. If it makes your timing worse, atleast you know it's in the software. Personally, i would have made this kind of application with a timer and interrupt. Not that it's absolutley necessary, i just find timers useful for timingpurposes.