Scripting Languages and BS2 Serial Communication
Archiver
Posts: 46,084
For those who are interested, I wrestled with the BS2 and pyserial (a Python
serial port module) last night and discovered some wackiness regarding it's
serial capabilities. If one writes a loop like so:
InLoop:
SERIN 14, 84, 10000, InLoop, [noparse][[/noparse]BIN val]
for input, then it partially simulates a loop like so:
InLoop:
SERIN 14, 84, [noparse][[/noparse]WAIT("?"), BIN val]
(obviously without the '?' check)
Now, you may ask yourself, why would I want to do that? If you write a
program in python that communicates things to the stamp and it works
flawlessly using the first loop, then switch to the second loop (changing
the write line in python to include a '?' of course), then the Stamp will
only receive data every *other* time the data is written to the serial port.
No amount of input or output flushing or reading from the port makes any
difference. I also have no idea why. I'm sure that there are some
enlightened scripting/serial programmers here that can tell me.
Hopefully I've spared some other poor soul the irritation of wrestling with
this particular issue.
Kelley
serial port module) last night and discovered some wackiness regarding it's
serial capabilities. If one writes a loop like so:
InLoop:
SERIN 14, 84, 10000, InLoop, [noparse][[/noparse]BIN val]
for input, then it partially simulates a loop like so:
InLoop:
SERIN 14, 84, [noparse][[/noparse]WAIT("?"), BIN val]
(obviously without the '?' check)
Now, you may ask yourself, why would I want to do that? If you write a
program in python that communicates things to the stamp and it works
flawlessly using the first loop, then switch to the second loop (changing
the write line in python to include a '?' of course), then the Stamp will
only receive data every *other* time the data is written to the serial port.
No amount of input or output flushing or reading from the port makes any
difference. I also have no idea why. I'm sure that there are some
enlightened scripting/serial programmers here that can tell me.
Hopefully I've spared some other poor soul the irritation of wrestling with
this particular issue.
Kelley
Comments
SERIN 14, 84, [noparse][[/noparse]WAIT("?"]
SERIN 14, 84, [noparse][[/noparse]BIN val]
--- In basicstamps@yahoogroups.com, "Kelley Reynolds"
<schnozzy@v...> wrote:
> For those who are interested, I wrestled with the BS2 and pyserial
(a Python
> serial port module) last night and discovered some wackiness
regarding it's
> serial capabilities. If one writes a loop like so:
>
> InLoop:
> SERIN 14, 84, 10000, InLoop, [noparse][[/noparse]BIN val]
>
> for input, then it partially simulates a loop like so:
>
> InLoop:
> SERIN 14, 84, [noparse][[/noparse]WAIT("?"), BIN val]
>
> (obviously without the '?' check)
>
> Now, you may ask yourself, why would I want to do that? If you
write a
> program in python that communicates things to the stamp and it
works
> flawlessly using the first loop, then switch to the second loop
(changing
> the write line in python to include a '?' of course), then the
Stamp will
> only receive data every *other* time the data is written to the
serial port.
> No amount of input or output flushing or reading from the port
makes any
> difference. I also have no idea why. I'm sure that there are some
> enlightened scripting/serial programmers here that can tell me.
>
> Hopefully I've spared some other poor soul the irritation of
wrestling with
> this particular issue.
>
> Kelley
the basic stamp deals with its waiting that borks the serial transfer. I've
spent a bit of time working up a very robust and tunable transmission scheme
between the computer and the BS2 that allows the BS2 to receive serial
transmission (mostly infallably, tunable with the 'interval' variable) and
maintain servo position as well. Occasionally an incorrect transmission will
get to the BS2, which is what the 'ack' is for. If what the BS2 received and
what you typed in are different, it will attempt to resend the new position
until the script and the BS2 agree on what they are supposed to do. The
lower the interval, the more likely they are to disagree. The higher the
interval, the slower the update, but the less likely they are to disagree.
Here is a cut'n'paste of the python script that handles all of this. If
somebody has a use for this, let me know. I did it more as a proof of
concept, but it's neat to know I can now script lengthy and complex Stamp
actions using the computer. Ooo... I can use a database and a laser range
finder connected to the servo to accurately give a 3D map of a room. Then I
can quickly determine if something else is in the room.... but I'm
blathering on.
Enjoy
# This should interact with the Basic Stamp on a Serial port
import serial
import string
import sys
import time
# Let's tune our servo to 180 degree motion
max = 1305
min = 435
# let's tune our serial port
interval = .09
# This opens our serial port with all of the proper settings
# (and closes it if the program crashed last time)
try:
ser.close()
except:
pass
ser = serial.Serial(0, 9600, 8, 0, 1, 0, 0, 0)
# Align our servo to a starting position and get a first ack
ack = ""
while ack == "":
ser.write(str(((max - min) / 2) + min) + "\n")
time.sleep(interval)
ack = string.strip(ser.readline())
time.sleep(interval)
# Get some input from the user
val = sys.stdin.readline()
# Loop through input
while val != "\n" and val != "":
val = int(val)
if val < min or val > max:
print "You must enter a value between " + str(min) + " and " +
str(max) + "."
else:
# Let's tell our servo to do something, and if it fails, try until
we win
ser.write(str(val) + "\n")
time.sleep(interval)
ack = string.strip(ser.readline())
time.sleep(interval)
# Everything converts to a string, but not everything converts to an
int
# That's why we compare the ack and val as strings
while ack == "" or str(ack) != str(val):
ser.write(str(val) + "\n")
time.sleep(interval)
ack = string.strip(ser.readline())
time.sleep(interval)
val = sys.stdin.readline()
# Return the servo to the middle and get our last ack
ser.write(str(((max - min) / 2) + min) + "\n")
time.sleep(interval)
ack = string.strip(ser.readline())
time.sleep(interval)
# Close the port
ser.close()
Original Message
From: <gtdesrosi@c...>
To: <basicstamps@yahoogroups.com>
Sent: Saturday, December 28, 2002 1:35 PM
Subject: [noparse][[/noparse]basicstamps] Re: Scripting Languages and BS2 Serial Communication
> What happens if you do....
>
> SERIN 14, 84, [noparse][[/noparse]WAIT("?"]
> SERIN 14, 84, [noparse][[/noparse]BIN val]
>
> --- In basicstamps@yahoogroups.com, "Kelley Reynolds"
> <schnozzy@v...> wrote:
> > For those who are interested, I wrestled with the BS2 and pyserial
> (a Python
> > serial port module) last night and discovered some wackiness
> regarding it's
> > serial capabilities. If one writes a loop like so:
> >
> > InLoop:
> > SERIN 14, 84, 10000, InLoop, [noparse][[/noparse]BIN val]
> >
> > for input, then it partially simulates a loop like so:
> >
> > InLoop:
> > SERIN 14, 84, [noparse][[/noparse]WAIT("?"), BIN val]
> >
> > (obviously without the '?' check)
> >
> > Now, you may ask yourself, why would I want to do that? If you
> write a
> > program in python that communicates things to the stamp and it
> works
> > flawlessly using the first loop, then switch to the second loop
> (changing
> > the write line in python to include a '?' of course), then the
> Stamp will
> > only receive data every *other* time the data is written to the
> serial port.
> > No amount of input or output flushing or reading from the port
> makes any
> > difference. I also have no idea why. I'm sure that there are some
> > enlightened scripting/serial programmers here that can tell me.
> >
> > Hopefully I've spared some other poor soul the irritation of
> wrestling with
> > this particular issue.
> >
> > Kelley
>
>
> To UNSUBSCRIBE, just send mail to:
> basicstamps-unsubscribe@yahoogroups.com
> from the same email address that you subscribed. Text in the Subject and
Body of the message will be ignored.
>
>
> Your use of Yahoo! Groups is subject to http://docs.yahoo.com/info/terms/
>
>
>
things. [noparse];)[/noparse]
'{$STAMP BS2}
'{$PORT COM2}
' This will in theory be able to answer things about the state of LCDs, and
' then be able to set things. That's the theory.
Baud96 CON 84
Servo CON 0
RxD CON 14
TxD CON 15
val VAR Word
pos VAR Word
Initialize:
Dir0 = 1
pos = 870
Main:
PULSOUT Servo, pos
SERIN RxD, Baud96, 10, Main, [noparse][[/noparse]DEC val]
GOTO UpdateServoPos
End
UpdateServoPos:
pos = val
SEROUT TxD, Baud96, 10, [noparse][[/noparse]DEC val, CR, 10]
GOTO Main
So...You will not wait. If there's nothing to read() then you'll get
control back immediately. Not sure if that's your intent but it
doesn't look like it. Use serial.Serial(0) and take the defaults for
9600, 8N1, and most importantly, timeout=None.
If this doesn't make sense it's probably because I don't know Python.
--- In basicstamps@yahoogroups.com, "Kelley Reynolds"
<schnozzy@v...> wrote:
> I have tried all of those sorts of things. There is something
about the way
> the basic stamp deals with its waiting that borks the serial
transfer. I've
> spent a bit of time working up a very robust and tunable
transmission scheme
> between the computer and the BS2 that allows the BS2 to receive
serial
> transmission (mostly infallably, tunable with the 'interval'
variable) and
> maintain servo position as well. Occasionally an incorrect
transmission will
> get to the BS2, which is what the 'ack' is for. If what the BS2
received and
> what you typed in are different, it will attempt to resend the new
position
> until the script and the BS2 agree on what they are supposed to
do. The
> lower the interval, the more likely they are to disagree. The
higher the
> interval, the slower the update, but the less likely they are to
disagree.
> Here is a cut'n'paste of the python script that handles all of
this. If
> somebody has a use for this, let me know. I did it more as a proof
of
> concept, but it's neat to know I can now script lengthy and
complex Stamp
> actions using the computer. Ooo... I can use a database and a
laser range
> finder connected to the servo to accurately give a 3D map of a
room. Then I
> can quickly determine if something else is in the room.... but I'm
> blathering on.
>
> Enjoy
> # This should interact with the Basic Stamp on a Serial port
> import serial
> import string
> import sys
> import time
>
> # Let's tune our servo to 180 degree motion
> max = 1305
> min = 435
>
> # let's tune our serial port
> interval = .09
> # This opens our serial port with all of the proper settings
> # (and closes it if the program crashed last time)
> try:
> ser.close()
> except:
> pass
> ser = serial.Serial(0, 9600, 8, 0, 1, 0, 0, 0)
>
> # Align our servo to a starting position and get a first ack
> ack = ""
> while ack == "":
> ser.write(str(((max - min) / 2) + min) + "\n")
> time.sleep(interval)
> ack = string.strip(ser.readline())
> time.sleep(interval)
>
> # Get some input from the user
> val = sys.stdin.readline()
>
> # Loop through input
> while val != "\n" and val != "":
> val = int(val)
>
> if val < min or val > max:
> print "You must enter a value between " + str(min) + "
and " +
> str(max) + "."
> else:
> # Let's tell our servo to do something, and if it fails,
try until
> we win
> ser.write(str(val) + "\n")
> time.sleep(interval)
> ack = string.strip(ser.readline())
> time.sleep(interval)
> # Everything converts to a string, but not everything
converts to an
> int
> # That's why we compare the ack and val as strings
> while ack == "" or str(ack) != str(val):
> ser.write(str(val) + "\n")
> time.sleep(interval)
> ack = string.strip(ser.readline())
> time.sleep(interval)
> val = sys.stdin.readline()
>
> # Return the servo to the middle and get our last ack
> ser.write(str(((max - min) / 2) + min) + "\n")
> time.sleep(interval)
> ack = string.strip(ser.readline())
> time.sleep(interval)
>
> # Close the port
> ser.close()
>
>
>
>
Original Message
> From: <gtdesrosi@c...>
> To: <basicstamps@yahoogroups.com>
> Sent: Saturday, December 28, 2002 1:35 PM
> Subject: [noparse][[/noparse]basicstamps] Re: Scripting Languages and BS2 Serial
Communication
>
>
> > What happens if you do....
> >
> > SERIN 14, 84, [noparse][[/noparse]WAIT("?"]
> > SERIN 14, 84, [noparse][[/noparse]BIN val]
> >
> > --- In basicstamps@yahoogroups.com, "Kelley Reynolds"
> > <schnozzy@v...> wrote:
> > > For those who are interested, I wrestled with the BS2 and
pyserial
> > (a Python
> > > serial port module) last night and discovered some wackiness
> > regarding it's
> > > serial capabilities. If one writes a loop like so:
> > >
> > > InLoop:
> > > SERIN 14, 84, 10000, InLoop, [noparse][[/noparse]BIN val]
> > >
> > > for input, then it partially simulates a loop like so:
> > >
> > > InLoop:
> > > SERIN 14, 84, [noparse][[/noparse]WAIT("?"), BIN val]
> > >
> > > (obviously without the '?' check)
> > >
> > > Now, you may ask yourself, why would I want to do that? If you
> > write a
> > > program in python that communicates things to the stamp and it
> > works
> > > flawlessly using the first loop, then switch to the second loop
> > (changing
> > > the write line in python to include a '?' of course), then the
> > Stamp will
> > > only receive data every *other* time the data is written to the
> > serial port.
> > > No amount of input or output flushing or reading from the port
> > makes any
> > > difference. I also have no idea why. I'm sure that there are
some
> > > enlightened scripting/serial programmers here that can tell me.
> > >
> > > Hopefully I've spared some other poor soul the irritation of
> > wrestling with
> > > this particular issue.
> > >
> > > Kelley
> >
> >
> > To UNSUBSCRIBE, just send mail to:
> > basicstamps-unsubscribe@yahoogroups.com
> > from the same email address that you subscribed. Text in the
Subject and
> Body of the message will be ignored.
> >
> >
> > Your use of Yahoo! Groups is subject to
http://docs.yahoo.com/info/terms/
> >
> >
> >
any output. For example, every 20 microseconds or (however it is set in the
program) it will send another pulse to the servo to help it maintain it's
position. It is possible, though unlikely, that during this brief diversion
to updating the servo that the computer will send something over the wire
serially. It could come over incompletely, or not at all, in which case the
stamp just keeps going through it's loop like nothing ever happened, the
python program keeps going like the stamp received it, and the servo just
doesn't move. This is why I had to add the 'ack' or acknowledgement from the
BS2 to be sure that what the BS2 got is what it was supposed to get. The
second problem was that if the BS2 never got the serial data, and the python
script was waiting for the ack either without a timeout or in a non-blocking
manner (waiting until it gets something), the program would seem to hang. The
reason I have it set to return instantly, is so that if something is sitting
in the buffer (the BS2 has responded), then it will be downloaded the program
can move on. Otherwise, send it again, because the BS2 never got it.
On Sunday 29 December 2002 04:39 pm, "gtdesrosi wrote:
> I noticed that you use 0 instead of None in serial.Serial().
> So...You will not wait. If there's nothing to read() then you'll get
> control back immediately. Not sure if that's your intent but it
> doesn't look like it. Use serial.Serial(0) and take the defaults for
> 9600, 8N1, and most importantly, timeout=None.
>
> If this doesn't make sense it's probably because I don't know Python.
>
>
> --- In basicstamps@yahoogroups.com, "Kelley Reynolds"
>
> <schnozzy@v...> wrote:
> > I have tried all of those sorts of things. There is something
>
> about the way
>
> > the basic stamp deals with its waiting that borks the serial
>
> transfer. I've
>
> > spent a bit of time working up a very robust and tunable
>
> transmission scheme
>
> > between the computer and the BS2 that allows the BS2 to receive
>
> serial
>
> > transmission (mostly infallably, tunable with the 'interval'
>
> variable) and
>
> > maintain servo position as well. Occasionally an incorrect
>
> transmission will
>
> > get to the BS2, which is what the 'ack' is for. If what the BS2
>
> received and
>
> > what you typed in are different, it will attempt to resend the new
>
> position
>
> > until the script and the BS2 agree on what they are supposed to
>
> do. The
>
> > lower the interval, the more likely they are to disagree. The
>
> higher the
>
> > interval, the slower the update, but the less likely they are to
>
> disagree.
>
> > Here is a cut'n'paste of the python script that handles all of
>
> this. If
>
> > somebody has a use for this, let me know. I did it more as a proof
>
> of
>
> > concept, but it's neat to know I can now script lengthy and
>
> complex Stamp
>
> > actions using the computer. Ooo... I can use a database and a
>
> laser range
>
> > finder connected to the servo to accurately give a 3D map of a
>
> room. Then I
>
> > can quickly determine if something else is in the room.... but I'm
> > blathering on.
> >
> > Enjoy
> > # This should interact with the Basic Stamp on a Serial port
> > import serial
> > import string
> > import sys
> > import time
> >
> > # Let's tune our servo to 180 degree motion
> > max = 1305
> > min = 435
> >
> > # let's tune our serial port
> > interval = .09
> > # This opens our serial port with all of the proper settings
> > # (and closes it if the program crashed last time)
> > try:
> > ser.close()
> > except:
> > pass
> > ser = serial.Serial(0, 9600, 8, 0, 1, 0, 0, 0)
> >
> > # Align our servo to a starting position and get a first ack
> > ack = ""
> > while ack == "":
> > ser.write(str(((max - min) / 2) + min) + "\n")
> > time.sleep(interval)
> > ack = string.strip(ser.readline())
> > time.sleep(interval)
> >
> > # Get some input from the user
> > val = sys.stdin.readline()
> >
> > # Loop through input
> > while val != "\n" and val != "":
> > val = int(val)
> >
> > if val < min or val > max:
> > print "You must enter a value between " + str(min) + "
>
> and " +
>
> > str(max) + "."
> > else:
> > # Let's tell our servo to do something, and if it fails,
>
> try until
>
> > we win
> > ser.write(str(val) + "\n")
> > time.sleep(interval)
> > ack = string.strip(ser.readline())
> > time.sleep(interval)
> > # Everything converts to a string, but not everything
>
> converts to an
>
> > int
> > # That's why we compare the ack and val as strings
> > while ack == "" or str(ack) != str(val):
> > ser.write(str(val) + "\n")
> > time.sleep(interval)
> > ack = string.strip(ser.readline())
> > time.sleep(interval)
> > val = sys.stdin.readline()
> >
> > # Return the servo to the middle and get our last ack
> > ser.write(str(((max - min) / 2) + min) + "\n")
> > time.sleep(interval)
> > ack = string.strip(ser.readline())
> > time.sleep(interval)
> >
> > # Close the port
> > ser.close()
> >
> >
> >
> >
Original Message
> > From: <gtdesrosi@c...>
> > To: <basicstamps@yahoogroups.com>
> > Sent: Saturday, December 28, 2002 1:35 PM
> > Subject: [noparse][[/noparse]basicstamps] Re: Scripting Languages and BS2 Serial
>
> Communication
>
> > > What happens if you do....
> > >
> > > SERIN 14, 84, [noparse][[/noparse]WAIT("?"]
> > > SERIN 14, 84, [noparse][[/noparse]BIN val]
> > >
> > > --- In basicstamps@yahoogroups.com, "Kelley Reynolds"
> > >
> > > <schnozzy@v...> wrote:
> > > > For those who are interested, I wrestled with the BS2 and
>
> pyserial
>
> > > (a Python
> > >
> > > > serial port module) last night and discovered some wackiness
> > >
> > > regarding it's
> > >
> > > > serial capabilities. If one writes a loop like so:
> > > >
> > > > InLoop:
> > > > SERIN 14, 84, 10000, InLoop, [noparse][[/noparse]BIN val]
> > > >
> > > > for input, then it partially simulates a loop like so:
> > > >
> > > > InLoop:
> > > > SERIN 14, 84, [noparse][[/noparse]WAIT("?"), BIN val]
> > > >
> > > > (obviously without the '?' check)
> > > >
> > > > Now, you may ask yourself, why would I want to do that? If you
> > >
> > > write a
> > >
> > > > program in python that communicates things to the stamp and it
> > >
> > > works
> > >
> > > > flawlessly using the first loop, then switch to the second loop
> > >
> > > (changing
> > >
> > > > the write line in python to include a '?' of course), then the
> > >
> > > Stamp will
> > >
> > > > only receive data every *other* time the data is written to the
> > >
> > > serial port.
> > >
> > > > No amount of input or output flushing or reading from the port
> > >
> > > makes any
> > >
> > > > difference. I also have no idea why. I'm sure that there are
>
> some
>
> > > > enlightened scripting/serial programmers here that can tell me.
> > > >
> > > > Hopefully I've spared some other poor soul the irritation of
> > >
> > > wrestling with
> > >
> > > > this particular issue.
> > > >
> > > > Kelley
> > >
> > > To UNSUBSCRIBE, just send mail to:
> > > basicstamps-unsubscribe@yahoogroups.com
> > > from the same email address that you subscribed. Text in the
>
> Subject and
>
> > Body of the message will be ignored.
> >
> > > Your use of Yahoo! Groups is subject to
>
> http://docs.yahoo.com/info/terms/
>
>
>
>
>
> To UNSUBSCRIBE, just send mail to:
> basicstamps-unsubscribe@yahoogroups.com
> from the same email address that you subscribed. Text in the Subject and
> Body of the message will be ignored.
>
>
> Your use of Yahoo! Groups is subject to http://docs.yahoo.com/info/terms/
weirdness going on in the pySerial package, not the BasicStamp. I
wrote a simple python script to send a 1 byte command to the
BasicStamp which receives and interprets the command and then sends
back a response. The python script waits for the response and prints
it out. Valid commands are "1" and "2", other commands cause an
error message to be sent back. I'm using port 16 (the programming
port or whatever it's called) so I put in a delay after the port is
opened to wait for the BasicStamp to reset. Okay, here's the python
code followed by the BasicStamp code.
import sys
import serial
import time
ser = serial.Serial(0)
# Wait for the BasicStamp to reset after the open above
time.sleep(.9)
ser.flushInput()
arg = ""
for arg in sys.argv[noparse][[/noparse]1:]:
print "Sending command => [noparse][[/noparse]" + arg + "]"
ser.write(arg)
ser.flushOutput()
ser.read() # read the echoed command
ch = ""
line = ""
while ch != "\r":
ch = ser.read()
line = line + ch
print line
time.sleep(.5) # IF YOU TAKE THIS OUT IT WILL NOT WORK THIS IS A
pySerial BUG!
ser.close()
#Test out using: python test.py 1 2 3
And running on the Basic Stamp:
'{$STAMP BS2}
cmd var byte
loop:
serin 16,84,[noparse][[/noparse]cmd]
if cmd = "1" then do_cmd1
if cmd = "2" then do_cmd2
serout 16,84,[noparse][[/noparse]"Unknown or unsupported command",CR]
goto loop
do_cmd1:
serout 16,84,[noparse][[/noparse]"Got command 1",CR]
goto loop
do_cmd2:
serout 16,84,[noparse][[/noparse]"Got command 2",CR]
goto loop
If you take out the sleep(.5) The basic stamp gets the "1" command
and python prints out the BasicStamp's response but the BasicStamp
never gets the "2" command. This is definitely a Python or pySerial
bug not BasicStamp's fault. I never thought it could possibly be a
BasicStamp problem. The serial code is rock solid and thoroughly
tested by many-many people.
I also tested out the BasicStamp code using hyperterminal under
windoze. Works flawlessly.
Hope this helps.
Gary
BTW: My Python setup was Python 2.2.1 running under Linux running
under VmWare running under WindowsXP.
--- In basicstamps@yahoogroups.com, Kelley Reynolds <schnozzy@v...>
wrote:
> The problem with a non-blocking serial input, is that the stamp
may not return
> any output. For example, every 20 microseconds or (however it is
set in the
> program) it will send another pulse to the servo to help it
maintain it's
> position. It is possible, though unlikely, that during this brief
diversion
> to updating the servo that the computer will send something over
the wire
> serially. It could come over incompletely, or not at all, in which
case the
> stamp just keeps going through it's loop like nothing ever
happened, the
> python program keeps going like the stamp received it, and the
servo just
> doesn't move. This is why I had to add the 'ack' or
acknowledgement from the
> BS2 to be sure that what the BS2 got is what it was supposed to
get. The
> second problem was that if the BS2 never got the serial data, and
the python
> script was waiting for the ack either without a timeout or in a
non-blocking
> manner (waiting until it gets something), the program would seem
to hang. The
> reason I have it set to return instantly, is so that if something
is sitting
> in the buffer (the BS2 has responded), then it will be downloaded
the program
> can move on. Otherwise, send it again, because the BS2 never got
it.
>
> On Sunday 29 December 2002 04:39 pm, "gtdesrosi wrote:
> > I noticed that you use 0 instead of None in serial.Serial().
> > So...You will not wait. If there's nothing to read() then you'll
get
> > control back immediately. Not sure if that's your intent but it
> > doesn't look like it. Use serial.Serial(0) and take the defaults
for
> > 9600, 8N1, and most importantly, timeout=None.
> >
> > If this doesn't make sense it's probably because I don't know
Python.
> >
> >
> > --- In basicstamps@yahoogroups.com, "Kelley Reynolds"
> >
> > <schnozzy@v...> wrote:
> > > I have tried all of those sorts of things. There is something
> >
> > about the way
> >
> > > the basic stamp deals with its waiting that borks the serial
> >
> > transfer. I've
> >
> > > spent a bit of time working up a very robust and tunable
> >
> > transmission scheme
> >
> > > between the computer and the BS2 that allows the BS2 to receive
> >
> > serial
> >
> > > transmission (mostly infallably, tunable with the 'interval'
> >
> > variable) and
> >
> > > maintain servo position as well. Occasionally an incorrect
> >
> > transmission will
> >
> > > get to the BS2, which is what the 'ack' is for. If what the BS2
> >
> > received and
> >
> > > what you typed in are different, it will attempt to resend the
new
> >
> > position
> >
> > > until the script and the BS2 agree on what they are supposed to
> >
> > do. The
> >
> > > lower the interval, the more likely they are to disagree. The
> >
> > higher the
> >
> > > interval, the slower the update, but the less likely they are
to
> >
> > disagree.
> >
> > > Here is a cut'n'paste of the python script that handles all of
> >
> > this. If
> >
> > > somebody has a use for this, let me know. I did it more as a
proof
> >
> > of
> >
> > > concept, but it's neat to know I can now script lengthy and
> >
> > complex Stamp
> >
> > > actions using the computer. Ooo... I can use a database and a
> >
> > laser range
> >
> > > finder connected to the servo to accurately give a 3D map of a
> >
> > room. Then I
> >
> > > can quickly determine if something else is in the room.... but
I'm
> > > blathering on.
> > >
> > > Enjoy
> > > # This should interact with the Basic Stamp on a Serial port
> > > import serial
> > > import string
> > > import sys
> > > import time
> > >
> > > # Let's tune our servo to 180 degree motion
> > > max = 1305
> > > min = 435
> > >
> > > # let's tune our serial port
> > > interval = .09
> > > # This opens our serial port with all of the proper settings
> > > # (and closes it if the program crashed last time)
> > > try:
> > > ser.close()
> > > except:
> > > pass
> > > ser = serial.Serial(0, 9600, 8, 0, 1, 0, 0, 0)
> > >
> > > # Align our servo to a starting position and get a first ack
> > > ack = ""
> > > while ack == "":
> > > ser.write(str(((max - min) / 2) + min) + "\n")
> > > time.sleep(interval)
> > > ack = string.strip(ser.readline())
> > > time.sleep(interval)
> > >
> > > # Get some input from the user
> > > val = sys.stdin.readline()
> > >
> > > # Loop through input
> > > while val != "\n" and val != "":
> > > val = int(val)
> > >
> > > if val < min or val > max:
> > > print "You must enter a value between " + str(min) + "
> >
> > and " +
> >
> > > str(max) + "."
> > > else:
> > > # Let's tell our servo to do something, and if it
fails,
> >
> > try until
> >
> > > we win
> > > ser.write(str(val) + "\n")
> > > time.sleep(interval)
> > > ack = string.strip(ser.readline())
> > > time.sleep(interval)
> > > # Everything converts to a string, but not everything
> >
> > converts to an
> >
> > > int
> > > # That's why we compare the ack and val as strings
> > > while ack == "" or str(ack) != str(val):
> > > ser.write(str(val) + "\n")
> > > time.sleep(interval)
> > > ack = string.strip(ser.readline())
> > > time.sleep(interval)
> > > val = sys.stdin.readline()
> > >
> > > # Return the servo to the middle and get our last ack
> > > ser.write(str(((max - min) / 2) + min) + "\n")
> > > time.sleep(interval)
> > > ack = string.strip(ser.readline())
> > > time.sleep(interval)
> > >
> > > # Close the port
> > > ser.close()
> > >
> > >
> > >
> > >
Original Message
> > > From: <gtdesrosi@c...>
> > > To: <basicstamps@yahoogroups.com>
> > > Sent: Saturday, December 28, 2002 1:35 PM
> > > Subject: [noparse][[/noparse]basicstamps] Re: Scripting Languages and BS2 Serial
> >
> > Communication
> >
> > > > What happens if you do....
> > > >
> > > > SERIN 14, 84, [noparse][[/noparse]WAIT("?"]
> > > > SERIN 14, 84, [noparse][[/noparse]BIN val]
> > > >
> > > > --- In basicstamps@yahoogroups.com, "Kelley Reynolds"
> > > >
> > > > <schnozzy@v...> wrote:
> > > > > For those who are interested, I wrestled with the BS2 and
> >
> > pyserial
> >
> > > > (a Python
> > > >
> > > > > serial port module) last night and discovered some
wackiness
> > > >
> > > > regarding it's
> > > >
> > > > > serial capabilities. If one writes a loop like so:
> > > > >
> > > > > InLoop:
> > > > > SERIN 14, 84, 10000, InLoop, [noparse][[/noparse]BIN val]
> > > > >
> > > > > for input, then it partially simulates a loop like so:
> > > > >
> > > > > InLoop:
> > > > > SERIN 14, 84, [noparse][[/noparse]WAIT("?"), BIN val]
> > > > >
> > > > > (obviously without the '?' check)
> > > > >
> > > > > Now, you may ask yourself, why would I want to do that? If
you
> > > >
> > > > write a
> > > >
> > > > > program in python that communicates things to the stamp
and it
> > > >
> > > > works
> > > >
> > > > > flawlessly using the first loop, then switch to the second
loop
> > > >
> > > > (changing
> > > >
> > > > > the write line in python to include a '?' of course), then
the
> > > >
> > > > Stamp will
> > > >
> > > > > only receive data every *other* time the data is written
to the
> > > >
> > > > serial port.
> > > >
> > > > > No amount of input or output flushing or reading from the
port
> > > >
> > > > makes any
> > > >
> > > > > difference. I also have no idea why. I'm sure that there
are
> >
> > some
> >
> > > > > enlightened scripting/serial programmers here that can
tell me.
> > > > >
> > > > > Hopefully I've spared some other poor soul the irritation
of
> > > >
> > > > wrestling with
> > > >
> > > > > this particular issue.
> > > > >
> > > > > Kelley
> > > >
> > > > To UNSUBSCRIBE, just send mail to:
> > > > basicstamps-unsubscribe@yahoogroups.com
> > > > from the same email address that you subscribed. Text in the
> >
> > Subject and
> >
> > > Body of the message will be ignored.
> > >
> > > > Your use of Yahoo! Groups is subject to
> >
> > http://docs.yahoo.com/info/terms/
> >
> >
> >
> >
> >
> > To UNSUBSCRIBE, just send mail to:
> > basicstamps-unsubscribe@yahoogroups.com
> > from the same email address that you subscribed. Text in the
Subject and
> > Body of the message will be ignored.
> >
> >
> > Your use of Yahoo! Groups is subject to
http://docs.yahoo.com/info/terms/
with HyperTerminal and the Stamp code is fine, this is not a Basic Stamp
issue.
Original Message
> This is really bugging me. Can you tell? There's definitely some
> weirdness going on in the pySerial package, not the BasicStamp.
<snip>
return to this thread when I have an answer of some sort. Thanks for
everybody's help.
On Sunday 29 December 2002 10:16 pm, "gtdesrosi wrote:
> This is really bugging me. Can you tell?
said that many bugs where fixed in that release. No luck [noparse]:([/noparse]
Please let us know if you solve the problem. I'm sure that
interoperability with the BasicStamp is something that everyone here
would be interested in.
--- In basicstamps@yahoogroups.com, Kelley Reynolds <schnozzy@v...>
wrote:
> Well, I suppose then that I'll take up this with the pyserial
people, and
> return to this thread when I have an answer of some sort. Thanks
for
> everybody's help.
>
> On Sunday 29 December 2002 10:16 pm, "gtdesrosi wrote:
> > This is really bugging me. Can you tell?
Original Message
From: <gtdesrosi@c...>
To: <basicstamps@yahoogroups.com>
Sent: Sunday, December 29, 2002 10:16 PM
Subject: [noparse][[/noparse]basicstamps] Re: Scripting Languages and BS2 Serial Communication
> This is really bugging me. Can you tell? There's definitely some
> weirdness going on in the pySerial package, not the BasicStamp. I
> wrote a simple python script to send a 1 byte command to the
> BasicStamp which receives and interprets the command and then sends
> back a response. The python script waits for the response and prints
> it out. Valid commands are "1" and "2", other commands cause an
> error message to be sent back. I'm using port 16 (the programming
> port or whatever it's called) so I put in a delay after the port is
> opened to wait for the BasicStamp to reset. Okay, here's the python
> code followed by the BasicStamp code.
<SNIP>
> time.sleep(.5) # IF YOU TAKE THIS OUT IT WILL NOT WORK THIS IS A
> pySerial BUG!
</SNIP>
See, that's strange because it works just fine for me without that line. Not
only that, but the author of pyserial wrote back and said
<SNIP>
> ser.flushOutput()
does it work without this line?
it is very unlikely that you want this here!
flushOutput() throws away what in the queue (line flushInput())
it does NOT act like flush on files!
</SNIP>
So, I rewrote your originally posted pyserial script to say the following
import sys
import serial
import time
ser = serial.Serial(1)
# Wait for the BasicStamp to reset after the open above
time.sleep(.9)
args = [noparse][[/noparse]"1","2","3"]
for arg in args:
print "Sending command => [noparse][[/noparse]" + arg + "]"
ser.write(arg)
# Take this line out if you aren't using pin 16
ser.read() # read the echoed command
line = ""
ch = ""
while ch != "\r":
ch = ser.read()
line += ch
print line
ser.close()
And that works for me just fine. Of course, the BS2 is waiting for input and
won't be sending pulses to the servo, which was the original intent anyway,
and the BS2 program doesn't use the WAIT identifier in the SERIN command
(again, against the servo use), but we are making progress. Now to try to
get the WAIT command to work (non-servo purposes).
As a side note, an interesting idea might be designing a BS2 program that
does nothing but execute commands sent to it via python so that extremely
long, complex programs could be written and just relayed to the stamp via a
serial link. Less useful for remote robotics, (unless you go pc104 or
cardpc), but more useful for lengthy and complex scripted actions (hence
python)
Kelley
(the plot thickens)
the BS2/Python behave exactly like they should, including WAIT(). I think
the problem I was having was that I wasn't allowing time for the BS2 to
reset itself after the serial connection opened, something which was
commented in Gary's python program. After I allowed for that to occur,
everything appears to be working exactly as it should including WAITing,
etc. I wouldn't have figured that out if it weren't for Gary's very
informative and well commented e-mails. Back to arguing about battery
sulfating. [noparse];)[/noparse]
Happy Holidays,
Kelley