Generating a RTC-based interrupt

Started by arhodes19044 March 26, 2005

I need to have the BX-24 generate its own interrupt. I already am
using the WaitForInterrupt() on pin 11, so I need to have the BX-24
generate its own interrupt.

Essentially I want to update a display every second. I want it to
coincide with the RTC full second (not at a fractional second).

Probably I need to have a loop check the a RTC register and when it
comes back to zero, then execute the display action. But....

It would be nice to have this interrupt driven by the hardware every
second (on the full second), so I would not have to be checking the
RTC manually in a loop.

How do I create a RTC-based hardware interrupt?

What happens if my Pin 11 WaitForInterrupt exactly coincides with the
RTC-based interrupt? Does one get dropped?

-Tony



--- In basicx@basi..., "arhodes19044" <spamiam@c...> wrote:
> I need to have the BX-24 generate its own interrupt. I already am
> using the WaitForInterrupt() on pin 11, so I need to have the BX-24
> generate its own interrupt.
> [...]
> It would be nice to have this interrupt driven by the hardware every
> second (on the full second), so I would not have to be checking the
> RTC manually in a loop.
>
> How do I create a RTC-based hardware interrupt?
>
> What happens if my Pin 11 WaitForInterrupt exactly coincides with the
> RTC-based interrupt? Does one get dropped?

The only direct access that BasicX programs have to any type of
interrupt is using WaitForInterrupt().

Much depends on what other capabilities of the BX-24 you're already
using. For example, if you don't use any functions that use Timer1,
you could program it to generate an "output compare" signal every
second. This signal could be tied in with your existing external
interrupt so that either would activate your task that is awaiting
Int1. You'd have to arrange your circuitry so that you could
distinguish between the two interrupt sources and respond accordingly.



> ... How do I create an RTC-based hardware interrupt?

If you need to guarantee that your per-second code runs within a few
hundred microseconds, like a true hardware interrupt, of the start of a
new second, you can't, as Don says, but you can get close.

The BX-24 RTC is a firmware device so determining the new second must be
a software function; new second detection by software is always late.
If you can tolerate the second event being late, and a little jittery, a
small BX-24 task can do that for you, within one tick, ~1.95mS, of the
new second. The machine can be running other tasks, of course, and they
can affect the per-second task execution, just as they can affect any
other task. Tom
Tom Becker
--... ...--
GTBecker@GTBe... www.RighTime.com
The RighTime Clock Company, Inc., Cape Coral, Florida USA
+1239 540 5700



Don, I was afraid that there was no built-in technique to generate a
timed interrupt.

See my reply to Tom's message two messages later than yours for a
follow-up question Thanks!

-Tony

--- In basicx@basi..., "Don Kinzer" <dkinzer@e...> wrote:
>
> --- In basicx@basi..., "arhodes19044" <spamiam@c...> wrote:
> > I need to have the BX-24 generate its own interrupt. I already
am
> > using the WaitForInterrupt() on pin 11, so I need to have the BX-
24
> > generate its own interrupt.
> > [...]
> > It would be nice to have this interrupt driven by the hardware
every
> > second (on the full second), so I would not have to be checking
the
> > RTC manually in a loop.
> >
> > How do I create a RTC-based hardware interrupt?
> >
> > What happens if my Pin 11 WaitForInterrupt exactly coincides
with the
> > RTC-based interrupt? Does one get dropped?
>
> The only direct access that BasicX programs have to any type of
> interrupt is using WaitForInterrupt().
>
> Much depends on what other capabilities of the BX-24 you're
already
> using. For example, if you don't use any functions that use
Timer1,
> you could program it to generate an "output compare" signal every
> second. This signal could be tied in with your existing external
> interrupt so that either would activate your task that is awaiting
> Int1. You'd have to arrange your circuitry so that you could
> distinguish between the two interrupt sources and respond
accordingly.




A little late is not big deal. I just do not it running late in the
second one time and early in the second the next. Timing is
important down to the second, but less than 1/2 second would not be
a problem.

I have to look at Don's suggestion to use timer-1 to create
an "output compare" I have no idea how to do that, but I will look
in the Netmedia manuals. I am not using the Timer-1, so this might
be feasible. I could use other chips to toggle other pins when the
external interrupt occurs, then use yet another pin to reset the
toggle (XOR or something like that)

I suppose that the simple work-around is to loop and check the RTC
tick counter and decide when it has come bacl past zero. What
register has the RTC tick value? I can read it, right? I did not
see anything listed in the register listing for the BX family. I
will check the back messages now.

The device I am currently designing is a "rally computer". It uses
a hall effect transudcer mounted on the drive shaft or the axle to
record rotation information. This will (I think) be creating the
pulses that WaitForInterrupt will be waiting for. Based on a
calibration we will know the number of wheel-ticks per mile.
THerefore we have a really good odometer reading, to a fraction of a
tiree rotation. Even at 60 mph, the wheel-ticks will only occur a
few times a second.

Then once a second, at the beginning of the second, the display will
update, the driving info. There will be a Real time clock, a
calculated time clock based on distance travelled and the INTENDED
speed. [If the Calculated time is behind the real time, then you
are going too slow.] and vice versa. There will also be a speed
reading. Those are the really essential functions in a nutshell.
Ther are all sorts of fancy bells and whistles, but those are after
I get it doing the basics.

-Tony

--- In basicx@basi..., "Tom Becker" <gtbecker@r...> wrote:
> > ... How do I create an RTC-based hardware interrupt?
>
> If you need to guarantee that your per-second code runs within a
few
> hundred microseconds, like a true hardware interrupt, of the start
of a
> new second, you can't, as Don says, but you can get close.
>
> The BX-24 RTC is a firmware device so determining the new second
must be
> a software function; new second detection by software is always
late.
> If you can tolerate the second event being late, and a little
jittery, a
> small BX-24 task can do that for you, within one tick, ~1.95mS, of
the
> new second. The machine can be running other tasks, of course,
and they
> can affect the per-second task execution, just as they can affect
any
> other task. > Tom >
> Tom Becker
> --... ...--
> GTBecker@R... www.RighTime.com
> The RighTime Clock Company, Inc., Cape Coral, Florida USA
> +1239 540 5700




--- In basicx@basi..., "arhodes19044" <spamiam@c...> wrote:
> I have to look at Don's suggestion to use timer-1 to create
> an "output compare" I have no idea how to do that, but I will look
> in the Netmedia manuals. I am not using the Timer-1, so this might
> be feasible. I could use other chips to toggle other pins when the
> external interrupt occurs, then use yet another pin to reset the
> toggle (XOR or something like that)

You'll have to read the datasheet for the AT90S8535 (available from
the Atmel site) to figure out how to program any of the timers. This
topic is too low-level to be included in the BasicX manuals.

You may be Timer1 and not be aware of it? Several of the
timing-related I/O functions in the System Library use Timer1. For
example, PulseIn(), PulseOut(), InputCapture(), OutputCapture(), etc.
It's not clear to me whether Com3 uses Timer1 or Timer2. I
originally thought it used the latter but my recollection is that when
I looked at the control register (with Com3 open) it wasn't
programmed. On the other hand, I find it hard to believe that it
could use Timer1 since so many other I/O functions do as well.

> What register has the RTC tick value? I can read it, right?
> I did not see anything listed in the register listing for the
> BX family.

It's Register.RTCTick, not listed with the AVR-related registers.
It's on page 11 of the BX-24 Hardware Reference.

Don


> ... the simple work-around is to loop and check the RTC tick counter
and decide when it has come back past zero.

A simple way to do this is to use GetTime() to parse the tick count (512
ticks per second) into a seconds byte and watch for its change, or you
can divide Register.RTCtick by 512 and watch for change in the quotient.

It sounds to me like you'll have plenty of processor time to do a rally
computer, Tony, even if you don't use a hardware interrupt for the
odometer pulse. When you get around to writing code, though, my guess
is you'll need to do some window averaging to get stable display values.

By rough calculation you'll get about 32pps on a 2.5x driveshaft from a
30" tire at 60mph. One pulse count error in a one second measurement
period is about 3% error, so a displayed speed might flop between 58 and
62 or so. A one-tick measurement period error, though, is only about
0.2%, so your driveshaft error dominates. More pulses per rotation will
help, as will a longer measurement period, as will a moving window
average.

Incidentally, magnetic business card stock has about eight poles per
inch; wrapped around a shaft, it can generate many pulses per rotation,
yielding far better resolution.
http://groups.yahoo.com/group/basicx/message/12836 Tom
Tom Becker
--... ...--
GTBecker@GTBe... www.RighTime.com
The RighTime Clock Company, Inc., Cape Coral, Florida USA
+1239 540 5700



--- In basicx@basi..., "Tom Becker" <gtbecker@r...> wrote:
> A simple way to do this is to use GetTime() to parse the tick
> count (512 ticks per second) into a seconds byte and watch for
> its change, or you can divide Register.RTCtick by 512 and watch
> for change in the quotient.

If minimum execution time is an issue, you can use the code below to
read the second LSB of the RTC tick (which counts half-seconds) and
then zero the least significant bit of that value. The Byte result
will change every second. By comparing this with a previously saved
"second number" you'll know that it's now a different second but you
won't know which second of the day it is.

Dim sec as Byte

sec = RamPeek(MemAddress(Register.RTCTick) + 1) And &Hfe

This generates only 6 fairly simple pcode isntructions, one of which
assigns the result to the 'sec' variable.

To make it ever-so-slightly faster, you could hard-code the address of
the second LSB of the tick counter:

sec = RamPeek(99) And &Hfe



Wow, you really know this stuff! My tires have about 800 turns per
mile, and I have the sensor on the axle with 2 magnets. I get about
1600 pulses per mile. Of course more pulses would be more accurate,
but this accuracy is OK.

I posted a problem with my waitforinterrupt. When I compiled the
pulse counting demo, it worked FINE. So I need to start there and
work up to my code.

If the interrupt is set to do so with a "rising edge" then why does
the pulse counter trigger on BOTH switch depression and release?

-Tony

I have a rally computer right now, but I want to program it
differently, and I think I can do it better. Cheaper too.

--- In basicx@basi..., "Tom Becker" <gtbecker@r...> wrote:
> > ... the simple work-around is to loop and check the RTC tick
counter
> and decide when it has come back past zero.
>
> A simple way to do this is to use GetTime() to parse the tick
count (512
> ticks per second) into a seconds byte and watch for its change, or
you
> can divide Register.RTCtick by 512 and watch for change in the
quotient.
>
> It sounds to me like you'll have plenty of processor time to do a
rally
> computer, Tony, even if you don't use a hardware interrupt for the
> odometer pulse. When you get around to writing code, though, my
guess
> is you'll need to do some window averaging to get stable display
values.
>
> By rough calculation you'll get about 32pps on a 2.5x driveshaft
from a
> 30" tire at 60mph. One pulse count error in a one second
measurement
> period is about 3% error, so a displayed speed might flop between
58 and
> 62 or so. A one-tick measurement period error, though, is only
about
> 0.2%, so your driveshaft error dominates. More pulses per
rotation will
> help, as will a longer measurement period, as will a moving window
> average.
>
> Incidentally, magnetic business card stock has about eight poles
per
> inch; wrapped around a shaft, it can generate many pulses per
rotation,
> yielding far better resolution.
> http://groups.yahoo.com/group/basicx/message/12836 > Tom >
> Tom Becker
> --... ...--
> GTBecker@R... www.RighTime.com
> The RighTime Clock Company, Inc., Cape Coral, Florida USA
> +1239 540 5700




Don, that is great! Thanks so much. I found a reference to
register.RTCTick here in the messages, but I never did find it in
the Netmedia documents. I am sure it is ther, Ijust never found it.

It is a long value and I then did a modulo 512. Your technique
should be faster. Quite a bit faster, I'd guess. I will use your
technique. And hard code the address.

My waitforinterrupt did not work, but I have the demo program
working... I will have to see what the difference is.

-Tony --- In basicx@basi..., "Don Kinzer" <dkinzer@e...> wrote:
>
> --- In basicx@basi..., "Tom Becker" <gtbecker@r...> wrote:
> > A simple way to do this is to use GetTime() to parse the tick
> > count (512 ticks per second) into a seconds byte and watch for
> > its change, or you can divide Register.RTCtick by 512 and watch
> > for change in the quotient.
>
> If minimum execution time is an issue, you can use the code below
to
> read the second LSB of the RTC tick (which counts half-seconds) and
> then zero the least significant bit of that value. The Byte result
> will change every second. By comparing this with a previously
saved
> "second number" you'll know that it's now a different second but
you
> won't know which second of the day it is.
>
> Dim sec as Byte
>
> sec = RamPeek(MemAddress(Register.RTCTick) + 1) And &Hfe
>
> This generates only 6 fairly simple pcode isntructions, one of
which
> assigns the result to the 'sec' variable.
>
> To make it ever-so-slightly faster, you could hard-code the
address of
> the second LSB of the tick counter:
>
> sec = RamPeek(99) And &Hfe