-
Long Timer
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.
-
OK, i have have done a bit more digging and come up with this:
Code:
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
Code:
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,
-
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
-
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?
-
Long Timer
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
-
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
-
Hang-on, i think i may have it !!
-
Right cracked it, thanks very much for everones help.
Regards,
Steve
-
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?
Code:
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,
-
Can anyone answer the above ?
-
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
-
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
-
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.