[vox-tech] general algorithm question for an embedded system
Jeff Newmiller
jdnewmil at dcn.davis.ca.us
Tue Mar 7 18:41:32 PST 2006
Micah J. Cowan wrote:
> On Tue, Mar 07, 2006 at 01:37:29PM -0800, Dylan Beaudette wrote:
>
>>this works out ok, for time intervals less than 24 hours, except for one
>>thing... the main loop is executed about 6 times per second, therefore the
>>test for secs(0) == 00 is evaluated as true 6 times, when i would only like
>>it to be evaluated once. Ideally, i need some sort of flag for signalling the
>>main if statement to only execute once.
>>
>>any thoughts on how this could be done with bit or nibble sized variables ?
>
> How about a bit flag named "trigger" that gets set to false whenever
> "should execute" is false. When it comes time to execute, check
> "trigger": if it's false, execute, and set trigger to true. It won't
> execute again until trigger is false again, which won't be until this
> execution window has expired.
This may seem like a novel trick to the uninitiated, but it is really
just a special case of a "finite state machine". Any time you need
to develop a sequence of behaviors, you can use the following pattern.
state = 0
DO
input = GetInput()
IF state = 0 THEN
IF State0InputTest( input ) THEN
DoState01TransitionBehavior()
state = 1
ELSE
DoState0Behavior()
ENDIF
ELSE IF state = 1 THEN
IF State1InputTest( input ) THEN
DoState10TransitionBehavior()
state = 0
ELSE
DoState1Behavior()
ENDIF
ELSE
Error()
ENDIF
LOOP
where the series of state tests can be as long as needed, and
the size of the state variable only needs to be big enough
to handle the desired number of states. In your case, a single
bit would be enough to handle Micah's "trigger" state variable.
In other cases, you can string together lots of states, and
define transitions to sequence between any states you need to.
Your code would look something like (I don't know this dialect
of Basic so you will have to repair syntax defects):
-------
trigger = 0
DO
'get the number of minutes since start from each RTC unit
minOfDay(0) = blahblah
' get motor_flag(0)
motor_flag(0) = bluhbluh
'advance a motor if:
'motor_flag(n) = 0
'secs(n) = $00
'minOfDay(n) != 0
IF trigger = 0 THEN
IF minOfDay(0) <> 0 AND secs(0) = $00 THEN
IF motor_flag(0) = 0 THEN GOSUB m0
trigger = 1
ENDIF ' do nothing otherwise
ELSE
IF minOfDay(0) <> 0 AND secs(0) <> $00 THEN trigger = 0
ENDIF
LOOP
--------
I have simplified some of the control structures here, but note that
the trigger handling is separated from the RTC handling that affects
the trigger variable, which in turn is separated from the motor flag
input information (which does not affect the trigger).
There are a lot of possible tricky ways to get around the
potentially long series of if-then-else (or switch/select/case)
statements, but this basic coding pattern can be quite powerful
for embedded applications.
(ObLinux) If you have a more complicated application in a
Unix-ish environment, then tools like "flex" can be used to write
FSMs more compactly (though the produced code may look like gibberish).
For example, the sequence of behaviors necessary to implement the
"Kermit" file transfer protocol was documented using a restricted
version of "lex". [1]
[1] http://www.columbia.edu/kermit/ckcplm.html
--
---------------------------------------------------------------------------
Jeff Newmiller The ..... ..... Go Live...
DCN:<jdnewmil at dcn.davis.ca.us> Basics: ##.#. ##.#. Live Go...
Live: OO#.. Dead: OO#.. Playing
Research Engineer (Solar/Batteries O.O#. #.O#. with
/Software/Embedded Controllers) .OO#. .OO#. rocks...1k
---------------------------------------------------------------------------
More information about the vox-tech
mailing list