Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Pausing a TCL script

79 views
Skip to first unread message

Bob Liesen

unread,
Apr 16, 2021, 7:02:19 PM4/16/21
to
Hello,
I have a script that talks to a serial port (actually a USB to RS232 converter) and toggles the RTS line to control a transmitter. It is currently hard coded for com5.
Depending on what is currently plugged into the computer, when plugging in the converter, it does not always end up on com5. I then go in and re-code the script for the port in question. This is a pain. I have figured out how to populate a listbox with several com port values and can get the selected one into a variable to open said com port.
However, I need a way to pause the script until after a port is selected in the list box, otherwise the script runs to the point where it tries to open the com port and it crashes because the port number variable is empty.
Clearly, the GUI will need to allow clicking on a listbox member as it is paused.
Any ideas on how to do this?

Thanks and stay well
Bob L

Rich

unread,
Apr 17, 2021, 12:29:17 AM4/17/21
to
Bob Liesen <wb0...@gmail.com> wrote:
> I have a script that talks to a serial port (actually a USB to RS232
> converter) and toggles the RTS line to control a transmitter. It is
> currently hard coded for com5.

> ...

> However, I need a way to pause the script until after a port is
> selected in the list box, otherwise the script runs to the point
> where it tries to open the com port and it crashes because the port
> number variable is empty.

> Clearly, the GUI will need to allow clicking on a listbox member as
> it is paused.

Yes, indeed, it does, but 'paused' is not the right term here.

> Any ideas on how to do this?

There are several ways, but all involve redoing the script to work
differently than how it sounds like you have coded the script so far.

You need to redo the script to generate the GUI, and to wait for a GUI
event (i.e., a click) to occur before it attempts to open the serial
port and continue doing whatever it does after it opens the port.
Which means your "serial port opening and handling" is best put into a
proc, and that proc is not run during the GUI creation phase.

Then, you create the GUI, and setup the widgets such that when one of
them is selected, it calls the proc for serial port handling, passing
the proc the serial port name. Then the proc can go about opening the
port and doing whatever it is that it does after that.

I.e., you need to make the proc that is handling the serial port "event
driven" (as in it reacts to an event happening in the GUI).

Here is a really simple, very minimal example:

---cut---cut---cut---
#!/usr/bin/wish

proc serial-port {port} {
puts stderr "proc serial-port: port='$port'"
# ... do whatever else is normally done
}

button .b1 -text COM1 -command [list serial-port COM1]
button .b2 -text COM2 -command [list serial-port COM2]
button .b3 -text COM3 -command [list serial-port COM3]

pack .b1 .b2 .b3 -side top
---cut---cut---cut---

You'd put the serial port opening inside the "serial-port" proc. When
the script first executes, the proc will be created, but not executed.

Then the script simply creates a stack of button widgets, one per com
port (note, in a real script, I'd create these buttons in a loop, I
simply typed them all out here separately to illustrate). Then the
buttons are packed and the script goes idle, waiting for a button to be
clicked.

Each button has a slightly different proc call attached to it's
-command option. If the mouse cursor clicks on .b2, then .b2's command
that is executed is "serial-port COM2", and if you try this script,
you'll see the puts from the proc showing that the proc was called when
the button was pushed.

There are also several other widgets you can use, menubutton's,
listboxes (as you are already using), you could even use a text widget
or a canvas (although doing so would be excessive just for a "list" of
clickable items). A stack of buttons, a menubutton with an
appropriately configured menu attached, or a listbox with a binding
attached to the <<ListboxSelect>> event would all work. In order of
complexity, a stack of plain buttons is likely simplest, a menu button
is next, and a listbox with a binding to <<ListboxSelect>> is yet a bit
more complicated.


Uwe Klein

unread,
Apr 17, 2021, 4:46:25 AM4/17/21
to
Am 17.04.21 um 01:02 schrieb Bob Liesen:
Rich gave an example.

Assuming that your script
builds some gui elements and
then progresses into its core activity:

Another way is to use vwait:

build the gui and selector.

the selector activated by the user
will assign a serial device
to a toplevel variable

set ::MYDEV = COM5

insert ahead of the productive code
where you open the com port and use it

vwait ::MYDEV

the script will now wait for a write to ::MYDEV
while continuing to process events from the GUI.

Uwe



Alan Grunwald

unread,
Apr 17, 2021, 8:14:25 AM4/17/21
to
Could you only start the connection process after the user has specified
a COM port?

Alan

Emiliano

unread,
Apr 18, 2021, 12:09:02 PM4/18/21
to
Adding to the answers other people already gave, here are a sketch of how I manage
serial ports selection. This code is taken and stripped down for your case from a more generic, cross platform code I wrote:

proc listports {} {
# windows specific
package require registry
set serial_base [join {
HKEY_LOCAL_MACHINE
HARDWARE
DEVICEMAP
SERIALCOMM} \\]
if {[catch {registry values $serial_base} values]} {
# this machine never had any serial port
return {}
}
foreach value $values {
lappend result \\\\.\\[registry get $serial_base $value]
}
lsort $result
}

proc connect {} {
# toggle connection
global connected fd port
if {$connected} {
chan close $fd
set connected 0
.port state !disabled
.conn configure -text Connect
} else {
set fd [open $port r+]
# configure -mode
set connected 1
.port state disabled
.conn configure -text Disconnect
}
}

ttk::combobox .port -textvariable port -postcommand listports
.port state readonly
ttk::button .conn -text Connect -command connect
set connected 0
set port [lindex [listports] 0]
0 new messages