On Oct 21, 2006, at 7:09 AM, Chase wrote:
given the way this control works, i'm not exactly sure how to do
that. any suggestions?
i thought xmitwait did this (or something functionally similar to
this).
the documentation for Serial control says:
"If you need your code to wait for all data to be sent to the
serial device before continuing, call the
Serial control's XmitWait method immediately following a call to
the Write method."
regardless, suggestions on how to implement wait-for-OK state would
be helpful.
Problem is that XmitWait can only tell when it has sent the command,
it has no knowledge of how long the command takes the modem to digest
and return "OK". Consider being asked to go to the store. The request
"go to the store" takes seconds, the task could take a half hour,
during which you can not accept a new request, so, when returning
home you say "OK" and can accept the next task.
My favorite tool in these situations, dealing with async processes
beyond my control, is the state machine. I am sure you can find
plenty of info on state machines and may even know how to use them,
so, forgive either the brevity or the detail, I will follow up.
Briefly, a state machine solves a number of issues, yet they can be
tricky to debug; the machine stalls and the debug fun begins.
For quick 'n easy explaining, I will use global variables and ignore
errors - your coding practices should prevail.
The ingredients of an RB state machine are: a state variable as a
property, and a timer control executing a case statement based on the
state variable.
So, for this task, define the states (gState integer); gState 0 =
Initialize; gState 1 = SendNextCommand; gState 2 = WaitForOK. Setup
the timer period to fire once per second (can be fine tuned later)
and mode = off. The data available serial event should simply
accumulate rx chars until CR into a global string "gRXMessage". The
serial error event could, among other things, set gState back to
Initialize, otherwise normal state cycling would be SendNextCommand -
> WaitForOK -> SendNextCommand, ad nauseum.
Your dial button gets hit and its Action code sets gNextCommand
string to your first command then starts the timer.
The first timer event happens. Our gState variable is 0, the
Initialize state, so we open the serial port. Finnish by setting the
"gState" variable to SendNextCommand (i.e.: "1").
The next timer event happens. State is SendNextCommand, so, transmit
the gNextCommand string. Finnish by setting the "gState" variable to
WaitForOK. You do not have to call XmitWait, the state machine
handles it naturally.
The next timer event(s) happen. State is WaitForOK, so if gRXMessage
= "OK" you set gRXMessage to "", set gNextCommand to the next command
string then set gState to SendNextCommand. The tricky part is
determining the "next command string". For that you can use another
state variable that counts commands from 0 to (last command - 1) to
select the next command string. If this was the OK for the last
command, be sure to turn off the timer. Note that gState is NOT
changed if gRXMessage <> "OK".
Thats it, simplified. You interface remains alive and no time is
burned "watching paint dry" in XmitWait or While looping. Good stuff.
You can optimize this a bit by expanding the states to cover your "N"
commands, if you have 6 commands, then you could have 8 states,
Initialize, SendFirstCommand, SendSecondCommand... SendSixthCommand,
WaitForOK.
Have fun!
Gary
_______________________________________________
Unsubscribe or switch delivery mode:
<http://www.realsoftware.com/support/listmanager/>
Search the archives of this list here:
<http://support.realsoftware.com/listarchives/lists.html>