Prev: ANNOUNCE: Jeszra ZERO-ONE
Next: PureTkGUI v0.9.0 is out
From: CKL on 8 Dec 2009 18:47 Hi tcl gurus There is now 2 weeks that I try to find a solution to my problem The problem is relative simple to understand. My PC have to control a serial device. But The PC has to be the Master and the device a Slave. So there is a Handshaking mechanism I use, to simulate the serial port, the free "Virtual Serial Ports Emulator" : http://www.eterlogic.com/Products.VSPE.html I virtually connect com1 and com2, to simulate a loopback Run the below tcl code, and use "Tera Term" terminal emulator, to enter characters, and to read it on my shell In the example below, to allow to enter chars in the terminal the delay and timeout are long enough to play manually with the program So in the example Every 5 seconds Check to see is something is available on the serial port: For this * Enter in FreeRunningRead Mode * write "RTR" (Request To Read message) on serial port * Read the answer message from the device. if message is Acknowledged by AKR (Acknowledge Read) message, exit mode, and enter in "Waiting" mode or * Wait maximum 2s for an answer. If delay passed, issue by displaying "Timeout message", exit mode, and enter in "Waiting" mode FreeRunningRead Mode PC Device ---------------- RTR ---------------> o <-------------- Message ------------- <-------------- AKR ---------------- This is easy. The problem is now, that during all this time, there can be an asynchronous event, which could interfere. This event will try to write a data message to the serial port, and must be acknowledged by AKW ForcedWrite Mode PC Device --------------- Message -------------> <--------------- AKW ---------------- And here is the issue. Before to write the message, I must be sure that I'm outside: FreeRunningRead Mode Trying to play with after, vwait in all the direction, I pass now more then 2 weeks to find a solution, but Without success :-(( It seems that my approach seems not to be good. Please, if someone have a little bit time to analyse my program. Thanks in advance set chid [open com1: r+] fconfigure $chid -mode "9600,n,8,1" -blocking 0 -buffering none - translation binary fileevent $chid readable [list serial_receiver $chid] set mode Waiting set MessageRead "" set LoopTime 5000 set Timeout 2000 set cnt 0 proc serial_receiver { chan } { global mode global MessageRead global FreeRunningRead_Result global ForcedWrite_Result set data [read $chan] append MessageRead $data if {$mode == "ForcedWrite"} { if { [string range $MessageRead end-2 end] == "AKW"} { set ForcedWrite_Result AKW } } elseif {$mode == "FreeRunningRead"} { if { [string range $MessageRead end-2 end] == "AKR"} { set FreeRunningRead_Result AKR } } } proc FreeRunningRead { chid } { global mode global MessageRead global Timeout global FreeRunningRead_Result global ForcedWrite_Result set mode "FreeRunningRead" puts "Start FreeRunningRead" puts -nonewline $chid "RTR" puts -nonewline $chid \x0D puts -nonewline $chid \x0A set MessageRead "" after $Timeout { set FreeRunningRead_Result TimeOut } vwait FreeRunningRead_Result switch $FreeRunningRead_Result { "TimeOut" { puts " FreeRunningRead TimeOut" } "AKR" { puts " FreeRunningRead = $MessageRead" } } puts "Stop FreeRunningRead" set mode "Waiting" } proc ForcedWrite { chid } { global mode global MessageRead global Timeout global FreeRunningRead_Result global ForcedWrite_Result global cnt if {$mode == "FreeRunningRead"} { vwait $FreeRunningRead_Result } set mode "ForcedWrite" puts "Start ForcedWrite" set cnt [expr $cnt + 1] puts -nonewline $chid "Message Write $cnt" puts -nonewline $chid \x0D puts -nonewline $chid \x0A set MessageRead "" after $Timeout { set ForcedWrite_Result TimeOut } vwait ForcedWrite_Result switch $ForcedWrite_Result { "TimeOut" { puts " ForcedWrite TimeOut" } "AKW" { puts " ForcedWrite = $MessageRead" } } puts "Stop ForcedWrite" set mode "Waiting" } wm protocol . WM_DELETE_WINDOW { exit } button .b1 -text Quit -command {exit} button .b2 -text Write -command {ForcedWrite $chid } pack .b1 pack .b2 set HS_Loop 0 while {1} { if {$mode == "Waiting" } { after $LoopTime { set HS_Loop 1 } vwait HS_Loop FreeRunningRead $chid } else { after $LoopTime { set HS_Loop 1 } vwait HS_Loop } }
From: dave.joubert on 9 Dec 2009 04:46 On Dec 8, 11:47 pm, CKL <christian.klugesh...(a)gmail.com> wrote: > Hi tcl gurus > > There is now 2 weeks that I try to find a solution to my problem > > Trying to play with after, vwait in all the direction, I pass now more > then 2 weeks to find a solution, but Without success :-(( > It seems that my approach seems not to be good. > Looking at your code, I think a re-design is called for. There are 2 design criteria that your code does not meet, that are characteristic of a working design: 1) Instead of waiting on multiple different variables, you should wait on the fewest number of possible variables, preferably only one. That way every routine can (a) check what the current state is (b) you can never end up in 'two states at once' (c) any routine that changes the state can do so globally 2) Since you have expected events and unexpected events, you should: a) always only 'block' on expected events, never on unexpected events. b) buffer all your un-expected events (while waiting for expected events) by putting them in a queue. Only then handle the unexpected events queue when you are no longer waiting for expected events. Provided you follow (1) religiously, (2) can be made more complicated by pushing and popping state on a stack. Dave
From: CKL on 9 Dec 2009 13:00 On 9 déc, 10:46, "dave.joub...(a)googlemail.com" <dave.joub...(a)googlemail.com> wrote: > On Dec 8, 11:47 pm, CKL <christian.klugesh...(a)gmail.com> wrote: > > > Hi tcl gurus > > > There is now 2 weeks that I try to find a solution to my problem > > > Trying to play with after, vwait in all the direction, I pass now more > > then 2 weeks to find a solution, but Without success :-(( > > It seems that my approach seems not to be good. > > Looking at your code, I think a re-design is called for. > > There are 2 design criteria that your code does not meet, that are > characteristic of a working design: > > 1) Instead of waiting on multiple different variables, you should wait > on the fewest number of possible variables, preferably only one. That > way every routine can (a) check what the current state is (b) you can > never end up in 'two states at once' (c) any routine that changes the > state can do so globally > > 2) Since you have expected events and unexpected events, you should: > a) always only 'block' on expected events, never on unexpected events. > b) buffer all your un-expected events (while waiting for expected > events) by putting them in a queue. > Only then handle the unexpected events queue when you are no longer > waiting for expected events. > > Provided you follow (1) religiously, (2) can be made more complicated > by pushing and popping state on a stack. > > Dave Hi Dave Thanks for the proposed criteria I will try to follow your rules, and remodel completely the program. Nevertheless, I think that the second point: "buffer all your un- expected events" will not be easy. I have no idea for the moment, how to store these events ?? Will be a hard think and not evident, and will see what I will propose in the next 2 weeks :-) In all the case, I suspected, when I wrote the message, that I would have to take the problem in an different way. Ok Lets go ..... Thanks for now Dave Regards Christian
From: dave.joubert on 9 Dec 2009 13:41 Hi Christian, On Dec 9, 6:00 pm, CKL <christian.klugesh...(a)gmail.com> wrote: > > Nevertheless, I think that the second point: "buffer all your un- > expected events" will not be easy. > I have no idea for the moment, how to store these events ?? > > > Christian The obvious way may be the easiest: set todoBuffCount 0 .. .. .. While if {$mustBuffer} {
From: Uwe Klein on 9 Dec 2009 13:44
CKL wrote: > On 9 d�c, 10:46, "dave.joub...(a)googlemail.com" > <dave.joub...(a)googlemail.com> wrote: > >>On Dec 8, 11:47 pm, CKL <christian.klugesh...(a)gmail.com> wrote: >> >> >>>Hi tcl gurus >> >>>There is now 2 weeks that I try to find a solution to my problem >> >>>Trying to play with after, vwait in all the direction, I pass now more >>>then 2 weeks to find a solution, but Without success :-(( >>>It seems that my approach seems not to be good. >> >>Looking at your code, I think a re-design is called for. >> >>There are 2 design criteria that your code does not meet, that are >>characteristic of a working design: >> >>1) Instead of waiting on multiple different variables, you should wait >>on the fewest number of possible variables, preferably only one. That >>way every routine can (a) check what the current state is (b) you can >>never end up in 'two states at once' (c) any routine that changes the >>state can do so globally >> >>2) Since you have expected events and unexpected events, you should: >>a) always only 'block' on expected events, never on unexpected events. >>b) buffer all your un-expected events (while waiting for expected >>events) by putting them in a queue. >>Only then handle the unexpected events queue when you are no longer >>waiting for expected events. >> >>Provided you follow (1) religiously, (2) can be made more complicated >>by pushing and popping state on a stack. >> >>Dave > > > Hi Dave > > Thanks for the proposed criteria > I will try to follow your rules, and remodel completely the program. > Nevertheless, I think that the second point: "buffer all your un- > expected events" will not be easy. > I have no idea for the moment, how to store these events ?? > > Will be a hard think and not evident, and will see what I will propose > in the next 2 weeks :-) > > In all the case, I suspected, when I wrote the message, that I would > have to take the problem in an different way. Have you looked into expect? look into the exp_background command. Couple of years ago I had to "connect" to lab scales that could be commanded but also emmited loadcell values in second intervals ( actually programmable ) I matched all input from the scales in the background evaluating incoming messages ( value or cmd reply ) setting state information in elements of an array variable. All outgoing messages were queued and "timed" via state info in the same array. uwe |