Searching \ for '24 hour timer' in subject line. ()
Make payments with PayPal - it's fast, free and secure! Help us get a faster server
FAQ page: techref.massmind.org/techref/timers.htm?key=time
Search entire site for: '24 hour timer'.

Truncated match.
PICList Thread
'24 hour timer'
1999\10\04@144626 by David Williams

flavicon
face
Hello,

I've got to set a pin every 24 hours plus or minus 10 minutes.  I need the
timer to work while I'm doing a bunch of other things (I guess this means
I've got to use interrupts).  Anyway, anyone have any ideas how to set up
a 24 hour count?  C code is preferred.

Thanks,
Dave

1999\10\04@164428 by Barry King

flavicon
face
> I've got to set a pin every 24 hours plus or minus 10 minutes.  I need the
> timer to work while I'm doing a bunch of other things (I guess this means
> I've got to use interrupts).
Or you have to have a main loop that always takes the same amount
of time, that is, the same amount of instructions, no matter what
"else" it is doing.  Sometimes that's practical, usually not.

> Anyway, anyone have any ideas how to set up
> a 24 hour count?  C code is preferred.

That depends on which part you are targeting, and which timer
hardware you have available.

Certainly you cannot set up the hardware to interrupt you only every
24 hours (except with ridiculously low clock rates).

So you are going to have to set up an interrupt to occur every so
often (Say every second or so).  Your ISR usually just counts, (with
a counter of more than one byte), and returns.  When the magic
number of interrupts has occured, the ISR sets a flag to tell you its
time to do the "daily" thing.

That's the general idea.  If you need more specific help, tell us what
the hardware config. is, and which timers you can spare.
------------
Barry King, KA1NLH
Engineering Manager
NRG Systems "Measuring the Wind's Energy"
Hinesburg, Vermont, USA
http://www.nrgsystems.com

1999\10\04@175407 by bill

flavicon
face
> > I've got to set a pin every 24 hours plus or minus 10 minutes.  I need the
> > timer to work while I'm doing a bunch of other things (I guess this means
> > I've got to use interrupts).
> Or you have to have a main loop that always takes the same amount
> of time, that is, the same amount of instructions, no matter what
> "else" it is doing.  Sometimes that's practical, usually not.

Make a subroutine that adds the contents of the RTCC to several registers
then resets the RTCC. The subroutine has to be called often enough to
keep the RTCC from overflowing. This means including a call to it inside all
loops. The tricky part is accounting for the time it takes for the subroutine
to execute.

Here's an example that creates a 24 bit timer:

TIMER
; add RTCC contents to 24 bit value (RTIMEL, RTIMEM, RTIMEH)
; This strange looking addition is designed to execute in exactly
; the same number of cycles regardless of the number of carries.
       movfw   RTCC        ;
       addwf   RTIMEL,F    ;
       btfss   STATUS,C    ;
       goto    $+2         ;
       incfsz  RTIMEM,F    ;
       goto    $+2         ;
       incf    RTIMEH,F    ;
;*  reinitialize RTCC
       movlw   $+3-TIMER   ; this the number of instruction cycles between
                           ; the time that the RTCC is read and the time when
                           ; it is written, plus 2 more to adjust for the
                           ; time that is required for the RTCC to restart
                           ; after being written
       movwf   RTCC        ;
;*  return
       retlw   0           ;

This routine will always take exactly the same time to execute.

Unfortunately, using a prescaler with this technique will introduce error
because subroutine can be called at varying times relative to the
prescaler's interval.

I've used this with great success to generate long and accurate timers on
PICS without interrupts. It can also be used to get very high resolution (as
fine as 0.2 microsecond with a 20mhz pic) measurement of external events
on PICS that do have interrupts, while still maintaining long counts.

It is also sometimes convenient to generate slow, non-critical timings by
monitoring single bits within this 24 bit timer.  For example, you might
blink an LED by finding a bit that changes at a frequency close enough to
what you want (like maybe every 1/2 second) and writing it to an IO pin
whenever convenient (like maybe once in each iteration of your main loop,
or maybe attach this to the TIMER routine itself).  The timing won't be
perfectly consistent, but the inconsistency will be too small for human
perception.

You can modify this technique to create longer times.  The 24 bits in this
example won't be enough for your 24 hour timer, unless you run your pic
extremely slow.

This timer routine can also be a convenient place to put routine tasks like
resetting the WDT (may or may not be a good idea, depending on your
application), or re-writing your tris registers in case they get corrupted.


---
                                       Peace,
                                       William Kitchen
                                       spam_OUTbillTakeThisOuTspamiglobal.net

The future is ours to create.

1999\10\04@193738 by Wagner Lipnharski

picon face
David Williams wrote:
>
> Hello,
>
> I've got to set a pin every 24 hours plus or minus 10 minutes.  I need the
> timer to work while I'm doing a bunch of other things (I guess this means
> I've got to use interrupts).  Anyway, anyone have any ideas how to set up
> a 24 hour count?  C code is preferred.
>
> Thanks,
> Dave

It remembers me about a device I did long ago, when 60Hz AC was not
available (to synch the unit), and no RTC chip available at that time,
so we needed to track time basically by software, *with* several
interrupts sharing the same microprocessor, it was a Z80.

We had two ideas, the first one was to implement a top priority
interrupt (NMI - Non Maskable Interrupt) each second, so it would be our
3600 counts per hour.  The idea was simple and nice, if some of the
secondary interrupts were not also top priorities... :)

The second idea (that worked), had the processor main routine just
counting Z80 processing cycles.  It just counted certain number or
instructions per second. We accounted how many processing cycles were
used in each one of the 6 possible interrupts. At the end of each one,
the routine just subtracted its particular cycles quantity from the main
timer decrementing counters. It means that the main routine always
decremented its counters to zero at the right time.

There was a tricky thing;  Each interrupt routine should take care of
possible missing "seconds counter" update. This situation only happens
if an interrupt was being handled during the time when the "non
interrupted main clock routine" should reach its counters to zero and
update the seconds counter, but it was not done because the interrupt
routine.

Then we changed this job to the main timer routine. If the decrementing
counters were negative, the routine immediately updated the "seconds
counter" and calculated the misplaced negative value for a new (smaller)
reload, so the next seconds update would be right on time.

Of course, at that time we had no software to take care of how many
machine cycles each routine would take, so we needed to do it manually.
Many pages of paper and lots of handwriting later, we got the right
code.  Ahh, by the way, we had no assembler compiler either, it was
everything done by hand... can you imagine how long it takes to write a
1000 bytes of code?  2708 was the Eprom chip, programmed by hand in a
byte by byte fashion, first to a couple of 2114 (1k sram) and then the
continuous programming cycles... :)

It took 3 weeks to do what we can do today in just 5 minutes or less.

Wagner

1999\10\04@195018 by Scott Dattalo

face
flavicon
face
On Mon, 4 Oct 1999, William J. Kitchen wrote:

{Quote hidden}

A slightly easier to read (IMO) and slightly faster, yet still isochronous
is:

   movfw  RTCC
   addwf  RTIMEL,F
   rlf    known_zero,W
   addwf  RTIMEM,F
   rlf    known_zero,W
   addwf  RTIMEH,F

  ;followed by the RTCC fix-up code

where known_zero is a variable that has been initialized to zero.

A slighty more obscure version that doesn't require the known_zero:

   incf    RTIMEH,F
   movfw   RTCC
   addwf   RTIMEL,F
   skpnc
    incfsz RTIMEM,F
     decf  RTIMEH,F

I'm not sure if this one is more obscure or not:

   movfw   RTCC
   addwf   RTIMEL,F
   skpnc
    incf   RTIMEM,F
   skpz
    incf   RTIMEH,F

On the 18cxxx you could do this:

   movf    RTCC,w     ;or whatever the tmr register is called...
   addwf   RTIMEL,F
   clrf    wreg
   addwfc  RTIMEM,F
   addwfc  RTIMEH,F

But on the 18cxxx parts, tmr0 can be 16bits wide. So there maybe other
tricks to try there...


{Quote hidden}

OTOH, you can easily add more stages to the counter. And since only +/-
10 minute (and not +/- 10 microsecond) resolution out of 24 hours is
needed, then you could use the prescaler and simply count the tmr0
rollovers (either by polling or within an interrupt routine). Then you
could do something like (I believe Dmitry first wrote this):

   incf   timel,f
   skpnz
    incf  timem,f
   skpnz
    incf  timeh,f

or on the 18cxxx parts:

   incf     timeh,f
   infsnz   timel,f
    incfsz  timem,f
     decf   timeh,f

Scott

1999\10\04@200514 by Sean H. Breheny

face picon face
Scott,

Did you ever find out the real answers from mchip on exactly how all of the
18Cxxx instructions work? I remember you bringing up several examples of
ambiguous instructions,but don't recall any final conclusions.

Sean

|
| Sean Breheny
| Amateur Radio Callsign: KA3YXM
| Electrical Engineering Student
\--------------=----------------
Save lives, please look at http://www.all.org
Personal page: http://www.people.cornell.edu/pages/shb7
.....shb7KILLspamspam@spam@cornell.edu ICQ #: 3329174

1999\10\05@064223 by anbarsystem

flavicon
face
Hello  David.
I think can help you in some thing. The best way to do a long timer is
really using INT of TMR0.
Place the prescaler 1/256 . I used a 4 mhz clock.
Enable INT of TMR0, then use some Regs. to get the time.
See the codes that you get an time aprox. 2:00hs. For 24hs it places more
some other Regs.
;Make a macro
t_2hs:   macro
             movlw d'15 '
             movwf cont_1sec       ;Its will give aprox 1sec
             movlw D'60 '
             movwf cont_1min       ;its will give aprox 1min.
             movlw d'180 '              ;thats is the min. here is 180min.
= 2hs
             movwf cont_h_min
             endm

             org 0x004
             btfss INTCON,T0IF     ;Int tmr0 ok
             retfie
             bcf INTCON,T0IF         ;clr the flag
;Here it begins the time of approximately 2:00hs
             decfsz cont_1sec,1
             retfie
             movlw d'15 '
             movwf cont_1sec         ;carry the values of 1sec again
             decfsz cont_1min,1
             retfie
             movlw d'60 '                  ;carry the values of 1min again
             movwf cont_1min
             movlw d'15 '
             movwf cont_1sec
             decfsz cont_h_min,1     ;Dec.the min.
             retfie
             ; here, do what you want

Excuse my English and I do not the C codes.
Regards
Lu’s F.

-----Mensagem Original-----
De: David Williams <davidw2spamKILLspamMORGAN.UCS.MUN.CA>
Para: <PICLIST>
Enviada em: Segunda-feira, 4 de Outubro de 1999 15:45
Assunto: 24 hour timer


> Hello,
>
> I've got to set a pin every 24 hours plus or minus 10 minutes.  I need the
> timer to work while I'm doing a bunch of other things (I guess this means
> I've got to use interrupts).  Anyway, anyone have any ideas how to set up
> a 24 hour count?  C code is preferred.
>
> Thanks,
> Dave

1999\10\05@093147 by anbarsystem

flavicon
face
   Hello  David.
I think can help you in some thing. The best way to do a long timer is
really using INT of TMR0.
Place the prescaler 1/256 . I used a 4 mhz clock.
Enable INT of TMR0, then use some Regs. to get the time.
See the codes that you get an time aprox. 2:00hs. For 24hs it places more
some other Regs.
;Make a macro
t_2hs:   macro
             movlw d'15 '
             movwf cont_1sec       ;Its will give aprox 1sec
             movlw D'60 '
             movwf cont_1min       ;its will give aprox 1min.
             movlw d'180 '              ;thats is the min. here is 180min.
= 2hs
             movwf cont_h_min
             endm

             org 0x004
             btfss INTCON,T0IF     ;Int tmr0 ok
             retfie
             bcf INTCON,T0IF         ;clr the flag

;Here it begins the time of approximately 2:00hs
             decfsz cont_1sec,1
             retfie
             movlw d'15 '
             movwf cont_1sec         ;carry the values of 1sec again
             decfsz cont_1min,1
             retfie
             movlw d'60 '                  ;carry the values of 1min again
             movwf cont_1min
             movlw d'15 '
             movwf cont_1sec
             decfsz cont_h_min,1     ;Dec.the min.
             retfie
             ; here, do what you want

Excuse my English and I do not the C codes.
Regards
Lu’s F.


-----Mensagem Original-----
De: David Williams <.....davidw2KILLspamspam.....MORGAN.UCS.MUN.CA>
Para: <PICLIST>
Enviada em: Segunda-feira, 4 de Outubro de 1999 15:45
Assunto: 24 hour timer


> Hello,
>
> I've got to set a pin every 24 hours plus or minus 10 minutes.  I need the
> timer to work while I'm doing a bunch of other things (I guess this means
> I've got to use interrupts).  Anyway, anyone have any ideas how to set up
> a 24 hour count?  C code is preferred.
>
> Thanks,
> Dave

1999\10\05@105141 by Scott Dattalo

face
flavicon
face
On Mon, 4 Oct 1999, Sean H. Breheny wrote:

>
> Scott,
>
> Did you ever find out the real answers from mchip on exactly how all of the
> 18Cxxx instructions work? I remember you bringing up several examples of
> ambiguous instructions,but don't recall any final conclusions.
>

Yes.

The ambiguities were:

1) Do the rotate instructions really affect the Z bit? Yes they do. This
is different than the 12 and 14 bit cores. So be careful when you port
your c74 code over.

2) What happens if an indirect register is the object of indirect? For
example:

   lfsr indf0,0     ;Load fsr0 with the address of indf0
   movf indf0,w     ;double indirection? Nah..

Like the 14-bit core, this will load W with zero regardless where indf is
pointing. This is not too unexpected. But what about this:

   lfsr  indf1,0           ;load fsr0 with the address of indf1
   lfsr  indf0,2           ;load fsr2 with the address of indf0
   movff preinc0,postinc2  ;?

As I understand it, the first fetch will read zero because fsr0 is
pointing to an indirect register (indf1). This zero is then written to the
address that is contained fsr2. However, fsr2 points to an indirect
register (indf0). Consequently the write is ignored.

3) I also had a question about whether the program memory addresses were
always even. The answer is yes - even though all instructions are 16 bits
wide. The reason is that the table reads and writes to program memory can
occur on byte boundaries. Now if you look at the instruction set closely
you'll notice that the least significant bit of the program counter is
never used EXCEPT for the table reads and writes. Examine the offsets for
the branch instructions for example.

Scott

1999\10\05@181044 by paulb

flavicon
face
David Williams wrote:

> I've got to set a pin every 24 hours plus or minus 10 minutes.  I need
> the timer to work while I'm doing a bunch of other things

 Care to explain the "other things"?  It makes it far easier to suggest
code.

> (I guess this means I've got to use interrupts).

 This appears to be a common misconception.  There are *THREE* ways to
achieve this functionality on a PIC with timer and interrupts, *two* on
one with timer and no interrupts (16C5xx, 12c5xx).

 The three ways are:
1} Isosynchronous code - loops performing all functions take a measured
time to cycle.  Very tedious, virtually impossible in "C".

2} Interrupt-driven.  On interrupt, counters are incremented/
decremented and overflow to other counters.  The main routine can "peek"
at these counters and determine when to perform the necessary task which
it does outside of "interrupt time", thus avoiding problems with
interrupts overlapping.

 To resolve whether the task has been performed at each required
interval however, the interrupt routine can set a (series of) flag(s) on
certain overflows e.g., each hour.  The mainline code then checks if the
flag is set *and* the hour is right, if so clears the flag (so it
doesn't perform the task twice) and performs the action.

 Hint:  These flags are all bit flags within a byte; the interrupt
routine sets the whole byte. Easier if worked the other way - it clears
all the bits at once.

 Along this line, it simplifies things a bit if the interrupt routine
only deals with say, seconds, setting a flag each second which the main
routine uses to advance the second count and count minutes, hours, days
etc.  But this does lead to the next proposal:

3} Timer-polling.  This is the simplest and easiest to code, and can be
done on the 12-bit core devices without interrupt hardware.  That makes
it a very *mature* approach!

 The basis is to set up the timer and prescaler so that the timer
overflows every so many thousand clock cycles, more than enough to
perform either the whole of the "other" functions, or a substantial
module of those functions.  After performing a function group known to
take such a time, you wait polling for the overflow, perform the timing
count when it happens and go on to the next function group.  Thus for
one function:

 While TRUE Do
   main_function
   wait_for_rollover
   timer_count
 Loop

and for multiple parts of code each taking less *on average* than the
overflow time:

 While TRUE Do
   main_function1
   wait_for_rollover
   timer_count

   main_function2
   wait_for_rollover
   timer_count

   main_function3
   wait_for_rollover
   timer_count

   main_function4
   wait_for_rollover
   timer_count
 Loop

 For example, function 1 can take 1¸ times the overflow time while
function 2 is very short, the first overflow is serviced before another
overflow occurs, and the short second function brings the next overflow
in on time.  You can even cut it slightly finer than that.

 The "rollover" code (should be a subroutine) on the devices with an
interrupt flag (T0IF) consists of polling for that flag *and clearing it
when found*, but note: no interrupt, specific or global is enabled.
(Other interrupts can however be enabled as long as they will not make
the mainline code modules run significantly over-time as above.)

 The timing cycles are each of the form:

timer   macro   unit,unit_max,end_time
       decfsz  unit
       goto    end_time
       movlw   unit_max
       movwf   unit
       endm

e.g., for seconds, minutes
       decfsz  seconds
       goto    done_time
       movlw   60
       movwf   seconds

       decfsz  minutes
       goto    done_time
       movlw   60
       movwf   minutes

could be macro coded as:
       timer   seconds,60,done_time
       timer   minutes,60,done_time
 ..more timers..
 ..payload; i.e. what you do at the end..
done_time

>  Anyway, anyone have any ideas how to set up a 24 hour count?  C code
> is preferred.

 Sorry, I'm not good on "C", and don't think it suits timing
applications.

 Further hint on using interrupts and timer in general:  IMNSHO don't
even *think* of setting/ re-setting/ altering the timer value within the
interrupt or poll routine.  Always let it count un-impeded, use "nice"
numbers.  *Far* less heartache that way.  KISS!
--
 Cheers,
       Paul B.

More... (looser matching)
- Last day of these posts
- In 1999 , 2000 only
- Today
- New search...