We had similar problems initial problems in Tcl. This code worked for us. Had problems reading the response from the SSC32 when querying prior to using this. This event-based program in Tcl worked. If you are using RIOS to program the robot (very easy to do) but need the ASCII strings to send down the line without RIOS, export your sequence to Basicstamp. The code there contains the pulsewidths. You dont need to work out the calibrations from XYZ that are internal to RIOS that way.
You don’t really need to use the querying to control the robot: if you use a BS2 controller (we did not), it just waits for a time longer than you tell the motion to complete in. But if you want to query this worked.
We used Tcl to strip out the relevant ascii strings from the BS2 code and write them to the input files that this program reads; i.e. the ASCII input file looks like many many lines of the form
#0 P699 #1 P893 #2 P1543 #3 P1011 #4 P1899 T1500
automatically stripped out of the bs2 code.
This version works to debug any problems you may have. All I can say is that it worked on my PC. Eventually we used the ASCII strings in the sequences and transferred them to a VMS system [yes still some around] to control the arm (with no querying, just waiting between each instruction).
Minor adaption from a program written to communicate with a modem on at website (stripped html to avoid problems with this site) wiki.tcl.tk/447
Uses event-driven programming to read the reponse from
the SSC-32 board when polling the board for the state by repeatedly
sending “Q” for query and waiting for a period to indicate motion completed
before sending next string in sequence
Original comments below
#=========================================================
simple serial port example to send AT to modem and
wait for OK response in a fixed amount of time. At the
bottom is a simple loop to do this 20x to check serial
handler reliability…
Works well on Tcl 8.0 and up on Unix (Solaris/NT), poorly on
the tclsh included with Tcl 8.1.1 on NT, but pretty well on
the wish included with same.
NOTE may need to set comPort appropriately for your
platform. Must have a modem configured to respond
with “OK” to “AT” commands.
=============================================================
Only major changes are to the MAIN body
switch $tcl_platform(os) {
{Linux} {set comPort /dev/modem}
{SunOS} {set comPort /dev/cua/a}
{Windows NT} {set comPort COM1:}
default {error “Must configure comPort”}
}
set waitSecs 2
set nTries 2000
A cheap version of expect.
Set up a event-driven I/O reader on the channel, output the
string, and wait some number of seconds for the result.
@param fh
a channel opened in non-blocking mode for I/O
with buffering turned off.
@param outstr
a string to send to the output channel – note: end-
of-line characters must be included in this string,
if desired.
@param regexp
regular expression to match in the incoming data.
@param seconds
number of seconds to wait for above match
@throws error
if eof is detected on the channel while waiting
@returns int
1 if a match is found, 0 otherwise.
proc send_expect {fh outstr regexp seconds} {
global send_exp
# make sure global vars are initialized properly
set send_exp($fh.matched) 0
if {![info exists send_exp($fh.buffer)]} {
set send_exp($fh.buffer) {}
}
# set up our Read handler before outputting the string.
if {![info exists send_exp($fh.setReader)]} {
fileevent $fh readable [list private_send_exp_reader \
$fh $regexp]
set send_exp($fh.setReader) 1
}
# output the string to send
puts -nonewline $fh $outstr
flush $fh
# set up a timer so that we wait a limited amt of seconds
set afterId [after [expr {$seconds*1000}] \
[list set send_exp($fh.matched) 0]]
vwait send_exp($fh.matched)
set matched $send_exp($fh.matched)
unset send_exp($fh.matched)
catch [list after cancel $afterId]
# If we got an eof, then throw an error
if {$matched < 0} {
error "Channel EOF while waiting for data"
return 0
}
return $matched
}
PRIVATE channel read event handler for send_expect. Should
not be called by user.
proc private_send_exp_reader {fh regexp} {
global send_exp
if {[eof $fh]} {
close $fh
set send_exp($fh.matched) -1
return
}
append send_exp($fh.buffer) [read $fh]
if {[regexp $regexp $send_exp($fh.buffer)]} {
puts stdout "buffer content $send_exp($fh.buffer)"
set send_exp($fh.matched) 1
}
}
Return the current contents of the send_expect buffer
@param fh
channel identifier that was used with send_expect
@returns string
the current contents of the buffer for the channel
proc send_exp_getbuf {fh} {
global send_exp
return $send_exp($fh.buffer)
}
Reset the send_expect buffer, returning its contents
@param fh
channel identifier that was used with send_expect
@returns string
the current contents of the buffer for the channel
proc send_exp_resetbuf {fh} {
global send_exp
set buf $send_exp($fh.buffer)
set send_exp($fh.buffer) {}
return $buf
}
Close out a send_expect session, closing I/O event handler
@param fh
channel identifier that was used with send_expect
@returns
the channel identifier passed as the fh parameter
proc send_exp_end {fh} {
global send_exp
fileevent $fh readable {}
foreach v [array names send_exp $fh.*] {
catch [list unset send_exp($v)]
}
return $fh
}
MAIN
Ugly but it works on a PC
Reads files with sequences of strings to be sent to the SSC32 of the form
Polls the SSC32 continuously until it receives a period and then sends the next
string in the sequences
fh is the RS232 channel (COM1) and is configured. Note necessary to match board speed
with jumpers on the SSC32 board with the open fconfigure stmt or it won’t work.
filechn is the channel to your file containing the ASCII strings to send to the SSC32
set fh [open $comPort RDWR]
fconfigure $fh -blocking 0 -buffering none
-mode 115200,n,8,1 -translation binary -eofchar {}
set period “.”
Loops until it reads EOF on the sequences defined in your input file
while {1} {
puts -nonewline stdout "Which file do you want to run: "
flush stdout
gets stdin filename
set filechn [open $filename r]
while {![eof $filechn] } {
gets $filechn pulsestring
puts $fh $pulsestring
puts $fh “\r”
#send a CR
puts stdout $pulsestring
#Original function comment below
#============================================================
Loop nTries times, sending AT to modem and expecting OK.
#============================================================
modified to send Q and print out what is received in the buffer
once it arrives. Once a period is received the next instruction
is read from the file and the process repeated until all drives completed.
set nMatches 0
for {set i 0} {$i < $nTries} {incr i} {
if {[send_expect $fh “Q\r” “.” $waitSecs]} {
incr nMatches
regsub -all “\r” [send_exp_getbuf $fh] {\r} buf
regsub -all “\n” $buf {\n} buf
puts “GOT MATCH: <$buf>”
if {
$buf == $period
} then {
puts "Got ."
break
}
} else {
puts "NO MATCH IN $waitSecs SECONDS"
}
send_exp_resetbuf $fh
};
};#while EOF closure
send_exp_end $fh
close $filechn
puts “Matched $nMatches/$nTries
([expr 100.0*$nMatches/$nTries]%)”
};#infinite while