Shop OBEX P1 Docs P2 Docs Learn Events
Scripting Languages and BS2 Serial Communication — Parallax Forums

Scripting Languages and BS2 Serial Communication

ArchiverArchiver Posts: 46,084
edited 2002-12-30 23:07 in General Discussion
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

Comments

  • ArchiverArchiver Posts: 46,084
    edited 2002-12-28 18:35
    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
  • ArchiverArchiver Posts: 46,084
    edited 2002-12-29 18:37
    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/
    >
    >
    >
  • ArchiverArchiver Posts: 46,084
    edited 2002-12-29 18:39
    Oh, and the BS2 code. It's short and sweet, leaving lots of room for other
    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
  • ArchiverArchiver Posts: 46,084
    edited 2002-12-29 21:39
    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/
    > >
    > >
    > >
  • ArchiverArchiver Posts: 46,084
    edited 2002-12-29 22:04
    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/
  • ArchiverArchiver Posts: 46,084
    edited 2002-12-30 03:16
    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.

    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/
  • ArchiverArchiver Posts: 46,084
    edited 2002-12-30 03:23
    Is there not a user group or email list for Python or PySerial? If it works
    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>
  • ArchiverArchiver Posts: 46,084
    edited 2002-12-30 17:43
    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?
  • ArchiverArchiver Posts: 46,084
    edited 2002-12-30 20:53
    Today, I tried upgrading to python 2.2.2 since the sourceforge site
    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?
  • ArchiverArchiver Posts: 46,084
    edited 2002-12-30 22:41

    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)
  • ArchiverArchiver Posts: 46,084
    edited 2002-12-30 23:07
    The saga continues.... I believe that I have found the problem, and this far
    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
Sign In or Register to comment.