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>

Reply via email to