PDA

View Full Version : Timer SubRoutine



pescador
- 11th September 2016, 22:53
I'm using a 16f616 - but can be changed. I need to do 2 things at same time. I need a timer that has 2 stages - 1 minute on, 5 minutes off (controlling a relay). At the same time I need to monitor an analog voltage and be able to react to it while its timing.

Right now I'm trying a rather crude method by going to a sub routine that pauses 250 ms, adds a count to a variable, and returns. I keep track of 1 minute and 5 minutes that way by comparing to te variable. In same main, I'm doing the analog voltage monitoring.

Whats a better way to keep track of time? It does not have to be that accurate - 5% is ok..

towlerg
- 12th September 2016, 16:20
set up a one minute timer, a very simple state machine and a one byte counter. From init your in 1min state, do your 1min task, then go to 5 min state which adds on to the one byte counter until it equals 5, then do your 5 min task, repeat .............

What an odd sig you have.

mark_s
- 12th September 2016, 20:18
If you don't want to create your own timer. You could use DT's "Elapsed Timer" include . Then monitor the minutes like towlerg suggested.

http://www.picbasic.co.uk/forum/showthread.php?t=190&highlight=dt+timer

Maybe like this?


Include "Elapsed.pbp"
Ticks var byte ' 1/100th of a second
Seconds var byte ' 0-59
Minutes var byte ' 0-59
Hours var byte ' 0-23
Days var word ' 0-65535


Gosub ResetTime ' Reset Time to 0d-00:00:00.00
Gosub StartTimer ' Start the Elapsed Timer


MainLoop:

Read ADC

If minutes =0 then
Relay on
endif
If minutes =1 then
Relay off
endif
If minutes = 6 then
Gosub ResetTime 'Reset to 0 minutes
endif

MainLoop

amgen
- 12th September 2016, 23:49
I had similar circuit for a battery charger setup. I used 2 main loops, 1 for off and 1 for on. you can use for-next or while loops. set the counts based on how often you want to check the a/d values and then pause in loop....... for the 1 minute loop, pause 100, check the a/d (10 times a second) and the loop count would be 600, then either exit loop because of a/d or at end of loop, turn off relay and jump into 5 minute loop. The instructions in the looping take little time but you can adjust the pause or loop count to make the timing more correct.

keithv
- 13th September 2016, 21:10
Maybe try using the TMR0 interrupt. You'll need to configure the TRIS and ANSEL registers to your specific peripherals. It's basically a clock that runs in the background. Every 60th of a second it goes to the dualcounter subroutine (or whatever subroutine you tell it to go to) without you having to call it so that you're free to write code to do other things. The last three bits of the OPTION_REG set up the prescaler which is what tells it how often to interrupt. I'm not exactly sure, but I think 1:64 is about 1/60th of a second. You may need to tweak that a bit though.



#config
__CONFIG _CP_OFF & _WDTE_OFF & _BOREN_OFF & _PWRTE_ON & _INTRC_OSC_NOCLKOUT & _MCLRE_OFF & _IOSCFS_8MHZ
#endconfig

ADCON0 = %00000000
ADCON1 = %00110000
ANSEL = %00000110
define ADC_SAMPLEUS 50
define ADC_BITS 8
DEFINE ADC_CLOCK 3
CM1CON0 = %00000000
CM2CON0 = %00000000
TRISA = %00001111
TRISC = %00000000


' Set TMR0 interrupt prescaler to 1:64
OPTION_REG = %10000101 ' Set TMR0 configuration and enable PORTB pullups
INTCON = %10100000 ' Enable TMR0 interrupts
On Interrupt Goto dualcounter

1minutecounter var word
5minutecounter var word

MAIN:

' insert main code here

if 1minutecounter > 3600 then
' insert code to handle 1 minute timer here
1minutecounter = 0 ' clear counter
endif

if 5minutecounter > 18000 then
' insert code to hand 5 minute time here
5minutecounter = 0 'clear counter
endif

goto MAIN

'''''''''''''''''''''''''''''''''''''''''''''''''' ''''''INTERRUPT''''''''''''''''''''''''''''''''''' '''''''''''''''''''''''''''''''''''''''''''''''''' ''''

Disable ' Disable interrupts during interrupt handler
dualcounter: ' Interrupt routine to handle each timer tick
1minutecounter = 1minutecounter + 1 ' add 1 on every interrupt
5minutecounter = 5minutecounter + 1
tiexit:
INTCON.2 = 0 ' Reset timer interrupt flag
Resume
enable
end

towlerg
- 13th September 2016, 22:39
what speed is the PIC clock? (thats what drives the timers in most cases)

keithv
- 13th September 2016, 23:03
what speed is the PIC clock? (thats what drives the timers in most cases)

I believe the 16F616 has options for either 4MHz or 8MHz internal clock.

towlerg
- 14th September 2016, 02:21
Using the Mikro timer calculator @ 8MHz


'Timer1
'Prescaler 1:4; TMR1 Preload = 15536; Actual Interrupt Time : 100 ms

'Place/Copy this part in declaration section
sub procedure InitTimer1()
T1CON = 0x21
TMR1IF_bit = 0
TMR1H = 0x3C
TMR1L = 0xB0
TMR1IE_bit = 1
INTCON = 0xC0
end sub

sub procedure Interrupt()
if (TMR1IF_bit) then
TMR1IF_bit = 0
TMR1H = 0x3C
TMR1L = 0xB0
'Enter your code here
end if
end sub


Of course the syntax is wrong but the values are correct. I couldn't get 1 second so I did 0.1 second. Same principle count to 10 for one sec and 50 for five sec.