Serial port failure

R

Rob

Hi all,

I am fairly new to python, but not programming and embedded. I am
having an issue which I believe is related to the hardware, triggered
by the software read I am doing in pySerial. I am sending a short
message to a group of embedded boxes daisy chained via the serial port.
When I send a 'global' message, all the connected units should reply
with their Id and Ack in this format '0 Ack' To be certain that I
didn't miss a packet, and hence a unit, I do the procedure three times,
sending the message and waiting for a timeout before I run through the
next iteration. Frequently I get through the first two iterations
without a problem, but the third hangs up and crashes, requiring me to
remove the Belkin USB to serial adapter, and then reconnect it. Here
is the code:

import sys, os
import serial
import sret
import time

from serial.serialutil import SerialException
####################################################################
#### GetAck Procedure
####################################################################
def GetAck(p):
response = ""

try:
response = p.readline()
except SerialException:
print ">>>>>Timed out<<<<<"
return -1
res = response.split()

#look for ack in the return message
reslen = len(response)
if reslen > 5:
if res[1] == 'Ack':
return res[0]
elif res[1] == 'Nak':
return 0x7F
else:
return -1

####################################################################
#### GetNumLanes Procedure
####################################################################
def GetNumLanes(Lanes):
print "Looking for connected units"
# give a turn command and wait for responses
msg = ".g t 0 336\n"

for i in range(3):
port = OpenPort()
time.sleep(3)
print port.isOpen()
print "Request #%d" % (i+1)
try:
port.writelines(msg)
except OSError:
print "Serial port failure. Power cycle units"
port.close()
sys.exit(1)

done = False
# Run first connection check
#Loop through getting responses until we get a -1 from GetAck
while done == False:
# lane will either be -1 (timeout), 0x7F (Nak),
# or the lane number that responded with an Ack
lane = GetAck(port)
if lane >= '0':
if False == Lanes.has_key(lane):
Lanes[lane] = True
else:
done = True
port.close()
time.sleep(3)

# Report number of lanes found
NumLanes = len(Lanes)
if NumLanes == 1:
print "\n\nFound 1 unit connected"
else:
print "\n\nFound %d units connected" % NumLanes

return NumLanes

####################################################################
#### Main Program Code Section
####################################################################

#open the serial port
# capture serial port errors from trying to open the port

port = OpenPort()

# If we got to here, the port exists. Set the baud rate and timeout
values

# I need to determine how many lanes are on this chain
# First send a turn command

#Create a dictionary of lanes so I can check each lane's responses
Lanes = {}
#<><><><><><><><><><><><><><><><>
# Call the lane finder utility
NumLanes = GetNumLanes(Lanes)
#<><><><><><><><><><><><><><><><>

#if no lanes responded, exit from the utility
if 0 == NumLanes:
print "I can't find any units connected."
print "Check your connections and try again"
sys.exit(1)

# list the lanes we have in our dictionary
for n in Lanes:
print "Lane - %s" % n

Now, here is the error message that I get

dad@nb29:~/py$ ./Thex.py
Looking for connected units
True
Request #1
True
Request #2
Serial port failure. Power cycle units
dad@nb29:~/py$ ./Thex.py
The serial port is unavailable.
Disconnect your USB to Serial adapter, Then
reconnect it and try again.
dad@nb29:~/py$

Does anyone have any ideas?

Thanks,

rob < (e-mail address removed) >
 
N

Nick Craig-Wood

Rob said:
I am fairly new to python, but not programming and embedded. I am
having an issue which I believe is related to the hardware, triggered
by the software read I am doing in pySerial. I am sending a short
message to a group of embedded boxes daisy chained via the serial port.
When I send a 'global' message, all the connected units should reply
with their Id and Ack in this format '0 Ack'

What is to stop all the embedded boxes talking at once?

I suspect that the embedded boxes all taking at once is confusing the
serial port driver. Maybe it is creating a break condition that it
doesn't deal with properly? Or perhaps I've misunderstood the
topology!

What sort of flow control are you using? Could it have got out of
step with XON-XOFF?

Assuming the driver is locking up then it looks like a serial port
driver bug. In my day job I do a lot of stuff with serial ports and
I've found that drivers vary wildly in quality!

My advice is to try a different serial port hardware. I've found ones
based on the PL2303 chip to be very reliable both under windows and
linux.

Eg this one :-

http://www.scan.co.uk/Products/ProductInfo.asp?WebProductID=98192

Or one of these (which were based on PL2303 last time I bought one)

http://www.comtrol.com/products/catalog.asp?group=usbserialhubs

I don't think anything you can do from python/user-space should be
able to lock up the kernel mode serial driver. If it does lock up it
is a driver bug.

Here you'll find a little program I wrote which, with the help of a
loopback connector, you can check your serial port out

http://www.craig-wood.com/nick/pub/cambert.exe

Run the program from a cmd prompt and it will tell you how to use it.

I've broken a lot of serial port drivers with that program ;-)
 
D

drake

Rob said:
Hi all,

I am fairly new to python, but not programming and embedded. I am
having an issue which I believe is related to the hardware, triggered
by the software read I am doing in pySerial. I am sending a short
message to a group of embedded boxes daisy chained via the serial port.
When I send a 'global' message, all the connected units should reply
with their Id and Ack in this format '0 Ack' To be certain that I
didn't miss a packet, and hence a unit, I do the procedure three times,
sending the message and waiting for a timeout before I run through the
next iteration. Frequently I get through the first two iterations
without a problem, but the third hangs up and crashes, requiring me to
remove the Belkin USB to serial adapter, and then reconnect it. Here
is the code:

import sys, os
import serial
import sret
import time

from serial.serialutil import SerialException
####################################################################
#### GetAck Procedure
####################################################################
def GetAck(p):
response = ""

try:
response = p.readline()
except SerialException:
print ">>>>>Timed out<<<<<"
return -1
res = response.split()

#look for ack in the return message
reslen = len(response)
if reslen > 5:
if res[1] == 'Ack':
return res[0]
elif res[1] == 'Nak':
return 0x7F
else:
return -1

####################################################################
#### GetNumLanes Procedure
####################################################################
def GetNumLanes(Lanes):
print "Looking for connected units"
# give a turn command and wait for responses
msg = ".g t 0 336\n"

for i in range(3):
port = OpenPort()
time.sleep(3)
print port.isOpen()
print "Request #%d" % (i+1)
try:
port.writelines(msg)
except OSError:
print "Serial port failure. Power cycle units"
port.close()
sys.exit(1)

done = False
# Run first connection check
#Loop through getting responses until we get a -1 from GetAck
while done == False:
# lane will either be -1 (timeout), 0x7F (Nak),
# or the lane number that responded with an Ack
lane = GetAck(port)
if lane >= '0':
if False == Lanes.has_key(lane):
Lanes[lane] = True
else:
done = True
port.close()
time.sleep(3)

# Report number of lanes found
NumLanes = len(Lanes)
if NumLanes == 1:
print "\n\nFound 1 unit connected"
else:
print "\n\nFound %d units connected" % NumLanes

return NumLanes

####################################################################
#### Main Program Code Section
####################################################################

#open the serial port
# capture serial port errors from trying to open the port

port = OpenPort()

# If we got to here, the port exists. Set the baud rate and timeout
values

# I need to determine how many lanes are on this chain
# First send a turn command

#Create a dictionary of lanes so I can check each lane's responses
Lanes = {}
#<><><><><><><><><><><><><><><><>
# Call the lane finder utility
NumLanes = GetNumLanes(Lanes)
#<><><><><><><><><><><><><><><><>

#if no lanes responded, exit from the utility
if 0 == NumLanes:
print "I can't find any units connected."
print "Check your connections and try again"
sys.exit(1)

# list the lanes we have in our dictionary
for n in Lanes:
print "Lane - %s" % n

Now, here is the error message that I get

dad@nb29:~/py$ ./Thex.py
Looking for connected units
True
Request #1
True
Request #2
Serial port failure. Power cycle units
dad@nb29:~/py$ ./Thex.py
The serial port is unavailable.
Disconnect your USB to Serial adapter, Then
reconnect it and try again.
dad@nb29:~/py$

Does anyone have any ideas?

Thanks,

rob < (e-mail address removed) >

In the second iteration of your loop, you appear to be opening a port
that is already open:

for i in range(3):
port = OpenPort()

thus the error message: "the serial port is unavailable".

--Drake Smith
 
D

drake

In the second iteration of your loop, you appear to be opening a port
that is already open:

for i in range(3):
port = OpenPort()

thus the error message: "the serial port is unavailable".

--Drake Smith

Skip that -- I didn't notice that your port.close() was indented.
 
H

hg

Rob said:
Hi all,

I am fairly new to python, but not programming and embedded. I am
having an issue which I believe is related to the hardware, triggered
by the software read I am doing in pySerial. I am sending a short
message to a group of embedded boxes daisy chained via the serial port.
When I send a 'global' message, all the connected units should reply
with their Id and Ack in this format '0 Ack' To be certain that I
didn't miss a packet, and hence a unit, I do the procedure three times,
sending the message and waiting for a timeout before I run through the
next iteration. Frequently I get through the first two iterations
without a problem, but the third hangs up and crashes, requiring me to
remove the Belkin USB to serial adapter, and then reconnect it. Here
is the code:

import sys, os
import serial
import sret
import time

from serial.serialutil import SerialException
####################################################################
#### GetAck Procedure
####################################################################
def GetAck(p):
response = ""

try:
response = p.readline()
except SerialException:
print ">>>>>Timed out<<<<<"
return -1
res = response.split()

#look for ack in the return message
reslen = len(response)
if reslen > 5:
if res[1] == 'Ack':
return res[0]
elif res[1] == 'Nak':
return 0x7F
else:
return -1

####################################################################
#### GetNumLanes Procedure
####################################################################
def GetNumLanes(Lanes):
print "Looking for connected units"
# give a turn command and wait for responses
msg = ".g t 0 336\n"

for i in range(3):
port = OpenPort()
time.sleep(3)
print port.isOpen()
print "Request #%d" % (i+1)
try:
port.writelines(msg)
except OSError:
print "Serial port failure. Power cycle units"
port.close()
sys.exit(1)

done = False
# Run first connection check
#Loop through getting responses until we get a -1 from GetAck
while done == False:
# lane will either be -1 (timeout), 0x7F (Nak),
# or the lane number that responded with an Ack
lane = GetAck(port)
if lane >= '0':
if False == Lanes.has_key(lane):
Lanes[lane] = True
else:
done = True
port.close()
time.sleep(3)

# Report number of lanes found
NumLanes = len(Lanes)
if NumLanes == 1:
print "\n\nFound 1 unit connected"
else:
print "\n\nFound %d units connected" % NumLanes

return NumLanes

####################################################################
#### Main Program Code Section
####################################################################

#open the serial port
# capture serial port errors from trying to open the port

port = OpenPort()

# If we got to here, the port exists. Set the baud rate and timeout
values

# I need to determine how many lanes are on this chain
# First send a turn command

#Create a dictionary of lanes so I can check each lane's responses
Lanes = {}
#<><><><><><><><><><><><><><><><>
# Call the lane finder utility
NumLanes = GetNumLanes(Lanes)
#<><><><><><><><><><><><><><><><>

#if no lanes responded, exit from the utility
if 0 == NumLanes:
print "I can't find any units connected."
print "Check your connections and try again"
sys.exit(1)

# list the lanes we have in our dictionary
for n in Lanes:
print "Lane - %s" % n

Now, here is the error message that I get

dad@nb29:~/py$ ./Thex.py
Looking for connected units
True
Request #1
True
Request #2
Serial port failure. Power cycle units
dad@nb29:~/py$ ./Thex.py
The serial port is unavailable.
Disconnect your USB to Serial adapter, Then
reconnect it and try again.
dad@nb29:~/py$

Does anyone have any ideas?

Thanks,

rob < (e-mail address removed) >


Where is OpenPort ?

hg
 
R

Rob

Here is OpenPort

####################################################################
#### OpenPort procedure
####################################################################
def OpenPort(name):
BRate = 19200
Tout = 3

try:
# Initialize the port
p = serial.Serial(name)
# handle failures gracefully
except SerialException:
print "The serial port is unavailable."
print "Disconnect your USB to Serial adapter, Then"
print "reconnect it and try again."
sys.exit(1)

p.setBaudrate(19200)
p.setTimeout(3) #set timeout to 1.5 seconds

# finish opening the port and assign a file handle
p.open()
return p



Rob said:
I am fairly new to python, but not programming and embedded. I am
having an issue which I believe is related to the hardware, triggered
by the software read I am doing in pySerial. I am sending a short
message to a group of embedded boxes daisy chained via the serial port.
When I send a 'global' message, all the connected units should reply
with their Id and Ack in this format '0 Ack' To be certain that I
didn't miss a packet, and hence a unit, I do the procedure three times,
sending the message and waiting for a timeout before I run through the
next iteration. Frequently I get through the first two iterations
without a problem, but the third hangs up and crashes, requiring me to
remove the Belkin USB to serial adapter, and then reconnect it. Here
is the code:
import sys, os
import serial
import sret
import time
from serial.serialutil import SerialException
####################################################################
#### GetAck Procedure
####################################################################
def GetAck(p):
response = ""
try:
response = p.readline()
except SerialException:
print ">>>>>Timed out<<<<<"
return -1
res = response.split()
#look for ack in the return message
reslen = len(response)
if reslen > 5:
if res[1] == 'Ack':
return res[0]
elif res[1] == 'Nak':
return 0x7F
else:
return -1
Snip <<<<<<
####################################################################
#### GetNumLanes Procedure
####################################################################
def GetNumLanes(Lanes):
print "Looking for connected units"
# give a turn command and wait for responses
msg = ".g t 0 336\n"
for i in range(3):
port = OpenPort()
time.sleep(3)
print port.isOpen()
print "Request #%d" % (i+1)
try:
port.writelines(msg)
except OSError:
print "Serial port failure. Power cycle units"
port.close()
sys.exit(1)
done = False
# Run first connection check
#Loop through getting responses until we get a -1 from GetAck
while done == False:
# lane will either be -1 (timeout), 0x7F (Nak),
# or the lane number that responded with an Ack
lane = GetAck(port)
if lane >= '0':
if False == Lanes.has_key(lane):
Lanes[lane] = True
else:
done = True
port.close()
time.sleep(3)
# Report number of lanes found
NumLanes = len(Lanes)
if NumLanes == 1:
print "\n\nFound 1 unit connected"
else:
print "\n\nFound %d units connected" % NumLanes
return NumLanes
####################################################################
#### Main Program Code Section
####################################################################
#open the serial port
# capture serial port errors from trying to open the port
port = OpenPort()
# If we got to here, the port exists. Set the baud rate and timeout
values
# I need to determine how many lanes are on this chain
# First send a turn command
#Create a dictionary of lanes so I can check each lane's responses
Lanes = {}
#<><><><><><><><><><><><><><><><>
# Call the lane finder utility
NumLanes = GetNumLanes(Lanes)
#<><><><><><><><><><><><><><><><>
#if no lanes responded, exit from the utility
if 0 == NumLanes:
print "I can't find any units connected."
print "Check your connections and try again"
sys.exit(1)
# list the lanes we have in our dictionary
for n in Lanes:
print "Lane - %s" % n
Now, here is the error message that I get
dad@nb29:~/py$ ./Thex.py
Looking for connected units
True
Request #1
True
Request #2
Serial port failure. Power cycle units
dad@nb29:~/py$ ./Thex.py
The serial port is unavailable.
Disconnect your USB to Serial adapter, Then
reconnect it and try again.
dad@nb29:~/py$
Does anyone have any ideas?

rob < (e-mail address removed) >Where is OpenPort ?

hg
 
H

hg

Rob said:
Here is OpenPort

####################################################################
#### OpenPort procedure
####################################################################
def OpenPort(name):
BRate = 19200
Tout = 3

try:
# Initialize the port
p = serial.Serial(name)
# handle failures gracefully
except SerialException:
print "The serial port is unavailable."
print "Disconnect your USB to Serial adapter, Then"
print "reconnect it and try again."
sys.exit(1)

p.setBaudrate(19200)
p.setTimeout(3) #set timeout to 1.5 seconds

# finish opening the port and assign a file handle
p.open()
return p



Rob said:
I am fairly new to python, but not programming and embedded. I am
having an issue which I believe is related to the hardware, triggered
by the software read I am doing in pySerial. I am sending a short
message to a group of embedded boxes daisy chained via the serial port.
When I send a 'global' message, all the connected units should reply
with their Id and Ack in this format '0 Ack' To be certain that I
didn't miss a packet, and hence a unit, I do the procedure three times,
sending the message and waiting for a timeout before I run through the
next iteration. Frequently I get through the first two iterations
without a problem, but the third hangs up and crashes, requiring me to
remove the Belkin USB to serial adapter, and then reconnect it. Here
is the code:
import sys, os
import serial
import sret
import time
from serial.serialutil import SerialException
####################################################################
#### GetAck Procedure
####################################################################
def GetAck(p):
response = ""
try:
response = p.readline()
except SerialException:
print ">>>>>Timed out<<<<<"
return -1
res = response.split()
#look for ack in the return message
reslen = len(response)
if reslen > 5:
if res[1] == 'Ack':
return res[0]
elif res[1] == 'Nak':
return 0x7F
else:
return -1
Snip <<<<<<
####################################################################
#### GetNumLanes Procedure
####################################################################
def GetNumLanes(Lanes):
print "Looking for connected units"
# give a turn command and wait for responses
msg = ".g t 0 336\n"
for i in range(3):
port = OpenPort()
time.sleep(3)
print port.isOpen()
print "Request #%d" % (i+1)
try:
port.writelines(msg)
except OSError:
print "Serial port failure. Power cycle units"
port.close()
sys.exit(1)
done = False
# Run first connection check
#Loop through getting responses until we get a -1 from GetAck
while done == False:
# lane will either be -1 (timeout), 0x7F (Nak),
# or the lane number that responded with an Ack
lane = GetAck(port)
if lane >= '0':
if False == Lanes.has_key(lane):
Lanes[lane] = True
else:
done = True
port.close()
time.sleep(3)
# Report number of lanes found
NumLanes = len(Lanes)
if NumLanes == 1:
print "\n\nFound 1 unit connected"
else:
print "\n\nFound %d units connected" % NumLanes
return NumLanes
Snip <<<<<<
####################################################################
#### Main Program Code Section
####################################################################
#open the serial port
# capture serial port errors from trying to open the port
port = OpenPort()
# If we got to here, the port exists. Set the baud rate and timeout
values
# I need to determine how many lanes are on this chain
# First send a turn command
#Create a dictionary of lanes so I can check each lane's responses
Lanes = {}
#<><><><><><><><><><><><><><><><>
# Call the lane finder utility
NumLanes = GetNumLanes(Lanes)
#<><><><><><><><><><><><><><><><>
#if no lanes responded, exit from the utility
if 0 == NumLanes:
print "I can't find any units connected."
print "Check your connections and try again"
sys.exit(1)
# list the lanes we have in our dictionary
for n in Lanes:
print "Lane - %s" % n
Now, here is the error message that I get
dad@nb29:~/py$ ./Thex.py
Looking for connected units
True
Request #1
True
Request #2
Serial port failure. Power cycle units
dad@nb29:~/py$ ./Thex.py
The serial port is unavailable.
Disconnect your USB to Serial adapter, Then
reconnect it and try again.
dad@nb29:~/py$
Does anyone have any ideas?

rob < (e-mail address removed) >Where is OpenPort ?

hg

I don't get it: you never pass any parameter to OpenPort

The second thing I wonder about is whether you need to reinit serial every
time .

hg
 
R

Rob

Craig,

In the embedded firmware, the each box re-transmits after it finishes
reading the packet. This is a very rudimentary system, and uses no
flow control. The topology is that each embedded box has a master and
a slave port. The master is used to receive data from the upstream
box, and send acks or naks back to the upstream box. The slave is
connected to the master of the next downstream box.

Does that clear up the picture a little bit?

Rob
 
G

Grant Edwards

Here is OpenPort

####################################################################
#### OpenPort procedure
####################################################################
def OpenPort(name):
BRate = 19200
Tout = 3
[...]
I don't get it: you never pass any parameter to OpenPort

The code he posted isn't the code he's actually running.
The second thing I wonder about is whether you need to reinit
serial every time.

I don't know what you mean by "reinit serial".
 
R

Rob

I have been modifying the code today, tracing through it and trying to
make it more robust and implement data hiding. That way as someone
reads through my main they will see intuitively what I am doing. For
that reason I went back and added a filename parameter to OpenPort.

The reason I am closing and opening the port is the same reason I
posted. I thought that by opening and closing the port each time (I
don't do it in the 'real' code, I could determine whether the bug lay
with hardware or software, or in the USB to Serial adapter.

Rob

Rob said:
Here is OpenPort
####################################################################
#### OpenPort procedure
####################################################################
def OpenPort(name):
BRate = 19200
Tout = 3
try:
# Initialize the port
p = serial.Serial(name)
# handle failures gracefully
except SerialException:
print "The serial port is unavailable."
print "Disconnect your USB to Serial adapter, Then"
print "reconnect it and try again."
sys.exit(1)
p.setBaudrate(19200)
p.setTimeout(3) #set timeout to 1.5 seconds
# finish opening the port and assign a file handle
p.open()
return p
Rob wrote:
Hi all,
I am fairly new to python, but not programming and embedded. I am
having an issue which I believe is related to the hardware, triggered
by the software read I am doing in pySerial. I am sending a short
message to a group of embedded boxes daisy chained via the serial port.
When I send a 'global' message, all the connected units should reply
with their Id and Ack in this format '0 Ack' To be certain that I
didn't miss a packet, and hence a unit, I do the procedure three times,
sending the message and waiting for a timeout before I run through the
next iteration. Frequently I get through the first two iterations
without a problem, but the third hangs up and crashes, requiring me to
remove the Belkin USB to serial adapter, and then reconnect it. Here
is the code:
import sys, os
import serial
import sret
import time
from serial.serialutil import SerialException
####################################################################
#### GetAck Procedure
####################################################################
def GetAck(p):
response = ""
try:
response = p.readline()
except SerialException:
print ">>>>>Timed out<<<<<"
return -1
res = response.split()
#look for ack in the return message
reslen = len(response)
if reslen > 5:
if res[1] == 'Ack':
return res[0]
elif res[1] == 'Nak':
return 0x7F
else:
return -1
Snip <<<<<<
####################################################################
#### GetNumLanes Procedure
####################################################################
def GetNumLanes(Lanes):
print "Looking for connected units"
# give a turn command and wait for responses
msg = ".g t 0 336\n"
for i in range(3):
port = OpenPort()
time.sleep(3)
print port.isOpen()
print "Request #%d" % (i+1)
try:
port.writelines(msg)
except OSError:
print "Serial port failure. Power cycle units"
port.close()
sys.exit(1)
done = False
# Run first connection check
#Loop through getting responses until we get a -1 from GetAck
while done == False:
# lane will either be -1 (timeout), 0x7F (Nak),
# or the lane number that responded with an Ack
lane = GetAck(port)
if lane >= '0':
if False == Lanes.has_key(lane):
Lanes[lane] = True
else:
done = True
port.close()
time.sleep(3)
# Report number of lanes found
NumLanes = len(Lanes)
if NumLanes == 1:
print "\n\nFound 1 unit connected"
else:
print "\n\nFound %d units connected" % NumLanes
return NumLanes
Snip <<<<<<
####################################################################
#### Main Program Code Section
####################################################################
#open the serial port
# capture serial port errors from trying to open the port
port = OpenPort()
# If we got to here, the port exists. Set the baud rate and timeout
values
# I need to determine how many lanes are on this chain
# First send a turn command
#Create a dictionary of lanes so I can check each lane's responses
Lanes = {}
#<><><><><><><><><><><><><><><><>
# Call the lane finder utility
NumLanes = GetNumLanes(Lanes)
#<><><><><><><><><><><><><><><><>
#if no lanes responded, exit from the utility
if 0 == NumLanes:
print "I can't find any units connected."
print "Check your connections and try again"
sys.exit(1)
# list the lanes we have in our dictionary
for n in Lanes:
print "Lane - %s" % n
Now, here is the error message that I get
dad@nb29:~/py$ ./Thex.py
Looking for connected units
True
Request #1
True
Request #2
Serial port failure. Power cycle units
dad@nb29:~/py$ ./Thex.py
The serial port is unavailable.
Disconnect your USB to Serial adapter, Then
reconnect it and try again.
dad@nb29:~/py$
Does anyone have any ideas?
Thanks,
rob < (e-mail address removed) >Where is OpenPort ?
hgI don't get it: you never pass any parameter to OpenPort

The second thing I wonder about is whether you need to reinit serial every
time .

hg
 
L

Leo Kislov

Rob said:
Hi all,

I am fairly new to python, but not programming and embedded. I am
having an issue which I believe is related to the hardware, triggered
by the software read I am doing in pySerial. I am sending a short
message to a group of embedded boxes daisy chained via the serial port.
When I send a 'global' message, all the connected units should reply
with their Id and Ack in this format '0 Ack' To be certain that I
didn't miss a packet, and hence a unit, I do the procedure three times,
sending the message and waiting for a timeout before I run through the
next iteration. Frequently I get through the first two iterations
without a problem, but the third hangs up and crashes, requiring me to
remove the Belkin USB to serial adapter, and then reconnect it. Here
is the code:

import sys, os
import serial
import sret
import time

from serial.serialutil import SerialException
####################################################################
#### GetAck Procedure
####################################################################
def GetAck(p):
response = ""

try:
response = p.readline()
except SerialException:
print ">>>>>Timed out<<<<<"
return -1
res = response.split()

#look for ack in the return message
reslen = len(response)
if reslen > 5:
if res[1] == 'Ack':
return res[0]
elif res[1] == 'Nak':
return 0x7F
else:
return -1

####################################################################
#### GetNumLanes Procedure
####################################################################
def GetNumLanes(Lanes):
print "Looking for connected units"
# give a turn command and wait for responses
msg = ".g t 0 336\n"

for i in range(3):
port = OpenPort()
time.sleep(3)
print port.isOpen()
print "Request #%d" % (i+1)
try:
port.writelines(msg)
except OSError:
print "Serial port failure. Power cycle units"
port.close()
sys.exit(1)

done = False
# Run first connection check
#Loop through getting responses until we get a -1 from GetAck
while done == False:
# lane will either be -1 (timeout), 0x7F (Nak),
# or the lane number that responded with an Ack
lane = GetAck(port)
if lane >= '0':

Your GetAck returns either string or number and then you compare it
with a string. If you compare string with a number python currently
returns result you probably don't expect
False

This is a wart and it will be fixed in python 3.0 (it will raise
exception) I think you should rewrite GetAck to return a tuple (state,
lane)

def GetAck(p):
response = ""

try:
response = p.readline()
except SerialException:
print ">>>>>Timed out<<<<<"
return 'Timeout', 'NoID'
res = response.split()

#look for ack in the return message
reslen = len(response)
if reslen > 5:
if res[1] == 'Ack':
return 'Ack', res[0]
elif res[1] == 'Nak':
return 'Nak', Does Nak response contain lane id?
else:
return 'Unknown', 'NoID'

And then instead of

lane = GetAck(port)
if lane >= '0':

use

state, lane = GetAck(port)
if state == 'Ack':

-- Leo
 
R

Rob

Leo,

I like your tuple idea. I will implement it. The ack and nak both
have the same format, namely: "Id Ack" or "Id Nak"

rob

Rob said:
I am fairly new to python, but not programming and embedded. I am
having an issue which I believe is related to the hardware, triggered
by the software read I am doing in pySerial. I am sending a short
message to a group of embedded boxes daisy chained via the serial port.
When I send a 'global' message, all the connected units should reply
with their Id and Ack in this format '0 Ack' To be certain that I
didn't miss a packet, and hence a unit, I do the procedure three times,
sending the message and waiting for a timeout before I run through the
next iteration. Frequently I get through the first two iterations
without a problem, but the third hangs up and crashes, requiring me to
remove the Belkin USB to serial adapter, and then reconnect it. Here
is the code:
import sys, os
import serial
import sret
import time
from serial.serialutil import SerialException
####################################################################
#### GetAck Procedure
####################################################################
def GetAck(p):
response = ""
try:
response = p.readline()
except SerialException:
print ">>>>>Timed out<<<<<"
return -1
res = response.split()
#look for ack in the return message
reslen = len(response)
if reslen > 5:
if res[1] == 'Ack':
return res[0]
elif res[1] == 'Nak':
return 0x7F
else:
return -1
Snip <<<<<<
####################################################################
#### GetNumLanes Procedure
####################################################################
def GetNumLanes(Lanes):
print "Looking for connected units"
# give a turn command and wait for responses
msg = ".g t 0 336\n"
for i in range(3):
port = OpenPort()
time.sleep(3)
print port.isOpen()
print "Request #%d" % (i+1)
try:
port.writelines(msg)
except OSError:
print "Serial port failure. Power cycle units"
port.close()
sys.exit(1)
done = False
# Run first connection check
#Loop through getting responses until we get a -1 from GetAck
while done == False:
# lane will either be -1 (timeout), 0x7F (Nak),
# or the lane number that responded with an Ack
lane = GetAck(port)
if lane >= '0':Your GetAck returns either string or number and then you compare it
with a string. If you compare string with a number python currently
returns result you probably don't expect

This is a wart and it will be fixed in python 3.0 (it will raise
exception) I think you should rewrite GetAck to return a tuple (state,
lane)

def GetAck(p):
response = ""

try:
response = p.readline()
except SerialException:
print ">>>>>Timed out<<<<<"
return 'Timeout', 'NoID'
res = response.split()

#look for ack in the return message
reslen = len(response)
if reslen > 5:
if res[1] == 'Ack':
return 'Ack', res[0]
elif res[1] == 'Nak':
return 'Nak', Does Nak response contain lane id?
else:
return 'Unknown', 'NoID'

And then instead of

lane = GetAck(port)
if lane >= '0':

use

state, lane = GetAck(port)
if state == 'Ack':

-- Leo
 
L

Leo Kislov

Rob said:
try:
response = p.readline()
except SerialException:
print ">>>>>Timed out<<<<<"

try:
port.writelines(msg)
except OSError:
print "Serial port failure. Power cycle units"
port.close()
sys.exit(1)
Does anyone have any ideas?

It'd be a good idea to print all exceptions, it can help debugging the
problem (if you don't like it going to the screen of an end user at
least write it to a log file):

except SerialException, err:
print err
print ">>>>>Timed out<<<<<"

except OSError, err:
print err
print "Serial port failure. Power cycle units"

and in your OpenPort function too.

-- Leo
 
N

Nick Craig-Wood

Rob said:
Craig,

In the embedded firmware, the each box re-transmits after it finishes
reading the packet. This is a very rudimentary system, and uses no
flow control. The topology is that each embedded box has a master and
a slave port. The master is used to receive data from the upstream
box, and send acks or naks back to the upstream box. The slave is
connected to the master of the next downstream box.

Does that clear up the picture a little bit?

Sure!

I suggest you run with the rest of my post and see what happens...
I've seen dozens of broken serial port drivers over the years!

....

My advice is to try a different serial port hardware. I've found ones
based on the PL2303 chip to be very reliable both under windows and
linux.

Eg this one :-

http://www.scan.co.uk/Products/ProductInfo.asp?WebProductID=98192

Or one of these (which were based on PL2303 last time I bought one)

http://www.comtrol.com/products/catalog.asp?group=usbserialhubs

I don't think anything you can do from python/user-space should be
able to lock up the kernel mode serial driver. If it does lock up it
is a driver bug.

Here you'll find a little program I wrote which, with the help of a
loopback connector, you can check your serial port out

http://www.craig-wood.com/nick/pub/cambert.exe

Run the program from a cmd prompt and it will tell you how to use it.

I've broken a lot of serial port drivers with that program ;-)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,763
Messages
2,569,563
Members
45,039
Latest member
CasimiraVa

Latest Threads

Top