pySerial: how to check the current baud rate - python

I have a device (GT511C3 fingerprint scanner) that I am connecting to Raspberry Pi and programming it using Python Serial module. The GT511 device has a default baud rate of 9600, and there is capability of changing the it. Once you change the GT511 baudrate, it keeps this setting until next restart.
The question is if there is a way for me to check the current baud rate of the connected device (in case the device was already programmed, and connected by a different host). I know it is possible to do it using stty:
$> stty < /dev/ttyAMA0
speed 57600 bud; line = 0
...
Is there a way to do it using Python serial or any other module, or do I have to write an iterative checking procedure to find it out?
UPDATE 1:
Current solution I use to find the accepted baud rate:
ser = serial.Serial('/dev/ttyAMA0')
ser.timeout = 0.5
for baudrate in ser.BAUDRATES:
if 9600 <= baudrate <= 115200:
ser.baudrate = baudrate
ser.write(packet)
resp = ser.read()
if resp != '':
break
if ser.baudrate > 115200:
raise RuntimeError("Couldn't find appropriate baud rate!")
UPDATE 2:
Please, stop suggesting serial.baudrate - this is NOT what I am asking.

Maybe you shoul use stty until you find a better alternative.
You can call it from Python code and parse the result to obtain what you need.
Here is a basic example (not tested):
import subprocess
import shlex
def get_baudrate(device):
command = 'stty < {0}'.format(device)
proc_retval = subprocess.check_output(shlex.split(command))
baudrate = int(proc_retval.split()[1])
return baudrate

Found your question while searching, and this is working great for me:
import serial
def baud_rate_test(serial_port, packet = b' '):
ser = serial.Serial(serial_port)
ser.timeout = 0.5
for baudrate in ser.BAUDRATES:
if 300 <= baudrate <= 57600:
ser.baudrate = baudrate
ser.write(packet)
resp = ser.readall()
if resp == packet:
return baudrate
return 'Unknown'
a = baud_rate_test('/dev/ttyUSB1')
print(a)
The devices I have checked it with to this point echo back the "b' '" with no issue. I do plan on testing it on more devices as time goes on, and I'm thinking I may need to change the "test packet" and the response criteria.
The resp != '': line didn't work for me -- because different "weird" characters are returned at different baud rates.

Related

Read from serial in Python

I have a weight scale
Which is connected to the serial port, and I'm trying to know the weight is currently reading.
This is the code I'm using in Python.
import serial
s = serial.Serial(port="COM3")
s.read(10)
It makes the connection but it just keeps loading and doesn't give any output.
I also Tried:
ser = serial.Serial()
ser.baudrate = 9600
ser.port = 'COM3'
print(ser)
and this is the output:
Serial<id=0x192eaed4c40, open=True>(port='COM3', baudrate=9600, bytesize=8, parity='N',
stopbits=1, timeout=None, xonxoff=False, rtscts=False, dsrdtr=False)
Thank you.
If the device you are connected to, doesn't write 10 bytes, your read call will block until it has gotten all those 10 bytes.
Typically, you as a reader have to say to the device that "hey, im here, could you give me data", and only then they will return you something. Also, you can check ser.in_waiting property to see if there is any data that can be read (and how much of data there is)
import serial
ser = serial.Serial(
port = "COM2",
timeout = 1,
baudrate=9600,
parity=serial.PARITY_EVEN,
stopbits=serial.STOPBITS_ONE,
bytesize=serial.SEVENBITS,
)
ser.write(str.encode("W"))
weight = ser.read(8)
print(weight.decode('ascii'), weight)
You want to get the input from the weight scale device. You should follow the following steps:
Firstly, check the connection between the device and computer is normal (cable, USB port, computer). You can use the terminal software.
If the connection is ok. Now let's start with the following code:
port='COM8',
baudrate = 2400,
parity=serial.PARITY_EVEN,
stopbits=serial.STOPBITS_ONE,
bytesize=serial.SEVENBITS,
timeout=None
)
while 1:
x = ser.readline()
print(x)

serial communication with USB device using 'GNET' protocol

I have a USB device with the following specification. Page 22 describes the GNET protocol that should be used to interact with the device.
The connection is fine but the device just doesn't give me any response, so I think I am not sending the correct data to it, maybe missing the handshake?
From Specification
Support TTY (TELE TYPE) OPERATION - Use TTY to send commands and messages
Use ASCII value for each field and use Separator "," between two
Fields.
connect_and_send.py
import serial
port = "COM3"
baud = 9600
ser = serial.Serial(port, baud, timeout=1)
if ser.isOpen():
print(ser.name + ' is open...')
# STX, N, CR
to_send = b'\x02\x4e\x0d'
print "Sending {}".format(to_send)
ser.write(to_send)
out = ser.read()
print('Receiving...'+out)
COM3 is the correct port:
Any help and guidance would be greatly appreciated.
You havenever​ to use \x4e, this is the Negative Acknowledge from the device.
Try
to_send = b'\x02F\x0d'
to get Firmware Version
I contacted the supplier in the end and the issue was setting to wrong baud rate. Changing from 9600 to 19200 resolved the problem.

get device name connected to port /dev/ttyACM0

Is there a way to get the device name connected to the serial port?
This code gives me just the name of the serial port. But I need the device name connected to it i.e. Nokia Phone
import serial
import time
ser = serial.Serial('/dev/ttyACM0',
460800,
timeout=5,
xonxoff = False,
rtscts = False,
bytesize = serial.EIGHTBITS,
parity = serial.PARITY_NONE,
stopbits = serial.STOPBITS_ONE)
sere = ser.name
print (ser, sere)
I've been checking other possibilities like gammu-detect but I would like to have a self standing python script that does this operation. Is there a way to get it done with pyserial?
Yes, of course.
But this is not strictly linked to serial port itself. It depends on the protocol the device is using.
In essential, you send some preset initial data to the device and it responds with manufacturer, name, model and version or some combination of these.
I am not sure whether this is standardized or not, you will have to search for it.
If it is standardized, it is most probably something like:
1. Open the port with 9600 baud rate
2. Send the request for info
3. Use info to reset the port etc.
I know that some programs do this. You can even hear old 56K modems reacting to the query when detection algorithm asks them who they are.
Now, you have to search whether this is a standard procedure or each device has its own.
If you are searching for phones, then very probably there is one for phone versions, perhaps each per OS like iOS, Symbian, Android, Windows *, ...
If you cannot find the protocol on the internet, then install virtual card for serial ports, perform man in the middle on looped ports to see what data is sent at initial communication with the phone application.
Note: Don't watch for data when connecting to the internet i.e. using the phone as a modem. You will see only AT&T protocol, which wouldn't help you much.
If you want to see how it works universally, use same technique with virtual serial card but when new device wizard detects for new hardware.
P.S. I found something!
Try sending:
"\x02S\x00\x00\x00\x00\x03"
You should get back some data containing numeric identifier of a device. Like serial number.
Now things work well! I had to type the .read command. Here the solution:
import serial
import time
ser = serial.Serial('/dev/ttyACM0',
460800,
timeout=5,
xonxoff = False,
rtscts = False,
bytesize = serial.EIGHTBITS,
parity = serial.PARITY_NONE,
stopbits = serial.STOPBITS_ONE)
#s = input('Enter AT command --> ')
#print ('AT command = ' + s)
ser.write(bytes('AT+CGMI' + '\r\n'))
ser.timeout = 1
response = ser.read(999)
print(response)
ser.close()

How do I get my GPIB interface to communicate correct values with python?

I have gotten the Simulator to finally start communicating back to me (see past question); however, I do not know what it is saying to me. Here is a simple code that sends a message to the simulator.
`import serial
port = '/dev/tty.usbserial-PXFO5L2L'
baudrate = 9600
timeout = 1
ser = serial.Serial(port = port, baudrate = baudrate, timeout = timeout)
ser.write('VOLT:LEVEL 4')
`
This is supposed to set the voltage 4, but all it returns is 12. Along with other commands, they all return ints. Can anyone tell me what this means? Or if I am using the write command correctly?

PySerial write() instant timeout

EDIT
I found out what the problem was and have answered my own question.
Original question below this line
I have a serial bridge between COM4 and COM5 implemented in software (Specifically, HDD's Free Virtual Serial Configuration Utility)
I have two different python scripts starting up in two different instances of Powershell, receive first:
import serial
receive = serial.Serial(port = 'COM5', baudrate = 9600)
text = receive.read(100)
receive.close()
print text
And then the sender:
import serial
send = serial.Serial(port = 'COM4', baudrate = 9600, timeout = 0)
send.write("Hello")
send.close()
When starting the sender script, the receiver script gets the sent message (So communication is clearly established) but the sender script immediately ends with an error:
Traceback (most recent call last):
File ".\sending.py", line 3, in <module>
send.writelines("Hello")
File "C:\Python27\lib\site-packages\serial\serialwin32.py", line 270, in write
raise writeTimeoutError
serial.serialutil.SerialTimeoutException: Write timeout
I get the same error when I change the sender script to
send = serial.Serial(port = 'COM4', baudrate = 9600)
So my question is: What exactly is timing out? How do I prevent that from happening? I mean, the data IS being sent so I could probably just put the whole thing in a try/except(and do nothing) block but that seems like a bad solution in the long run.
The clue is in the error message[1]
File "C:\Python27\lib\site-packages\serial\serialwin32.py", line 270, in write
raise writeTimeoutError
so we open that file and find:
if self._writeTimeout != 0: # if blocking (None) or w/ write timeout (>0)
# Wait for the write to complete.
#~ win32.WaitForSingleObject(self._overlappedWrite.hEvent, win32.INFINITE)
err = win32.GetOverlappedResult(self.hComPort, self._overlappedWrite, ctypes.byref(n), True)
if n.value != len(data):
raise writeTimeoutError
Read that first conditional again:
if self._writeTimeout != 0:
so let us rewrite our code from before
send = serial.Serial(port = 'COM4', baudrate = 9600, timeout = 0)
becomes
send = serial.Serial(port = 'COM4', baudrate = 9600, writeTimeout = 0)
and Et Voila: No exception.
[1] Well Designed Error Messages? That's new!
The problem may be that the interface tries to comply with RTS, CTS, DSR, or DTS signals. It is possible that if they are not properly virtually connected, they can mysteriously affect communication through a timeout.
I would also recommend looking at the configuration of the used virtual serial bridge.
One solution may be to ignore influence using rtscts=False and/or dsrdtr=False when opening the serial port in Python.
I could use an alternative solution for sniffing communication using hub4com, where I used the parameter --octs = off, for example in this way, but the virtual ports had to be created correctly before. hub4com --baud=115200 --route=0:All --route=1:All --route=2:All --no-default-fc-route=All:All --octs=off \\.\COM1 \\.\CNCB0 \\.\CNCB1

Categories