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.
Related
I am doing an instrument integration where the instrument name is Horiba ES60. I am using an RS232 port for communicating for PC and instrument.
I have tested the PC and instrument connection through the Advance Serial Port logger and am getting the monitor result.
I have confirmed that the instrument setting and my script setting are the same.
I have written a simple script in python to read the port data. below is the script.
import time
import serial
sSerialPort = serial.Serial(port = "COM1", baudrate=9600,
bytesize=8, timeout=1, stopbits=serial.STOPBITS_ONE)
sSerialString = "" # Used to hold data coming over UART
print("Connected to : ",sSerialPort.name)
while(True):
# Wait until there is data waiting in the serial buffer
if(sSerialPort.in_waiting > 0):
# Read data out of the buffer until a carraige return / new line is found
sSerialString = sSerialPort.readline()
# Print the contents of the serial data
print(sSerialString)
Output:
b'\x05'
b'\x04'
The expected output is different and I am getting the above one.
Can someone please help to understand what's going wrong?
how to deal with port data in python.
Trying to communicate with a McPherson 747 Device Controller for the Filter Wheel on a lab instrument. It is connected to the lab computer through RS232 to usb. I've connected and communicated with other devices through serial before.
It seems that for a read request, I need to send an enquiry and header and then the Device will acknowledge and send data.
The manual for the Device says that all data is exchanged in ASCII format. Though there are also a few tables in the manual that has inputs in Hex ASCII code. The manual says that a three-byte enquiry is Hex 4E2105 or text N!< ENQ >. Acknowledge is Hex 4E2106 or text N!< ACK > . The header is a mix of several Hex ASCII inputs for reading and writing based on what information the user wants.
The issue I am having is when I code the serial information and send the enquire input, it always sends an error due to communication with the device. I am unfamiliar with Hex. Do I need to be sending the entire enquire, headeras one input, or can I send them separately? I can also try to set up communication with PyVisa but I've gotten similar errors.
Through serial:
import codecs
import serial
try:
ser = serial.Serial(port='COM1',
baudrate = 9600,
timeout = None,
xonxoff = False,
parity = serial.PARITY_NONE,
stopbits = serial.STOPBITS_ONE,
bytesize = serial.EIGHTBITS,
)
ser.close()
string = '4E2105'
enquire = codecs.decode(string,'hex')
ser.open()
ser.write(enquire); #ascii intput for pressing enter on keyboard
ser.read_until(size=None) #reads out feedback until no data is left
ser.close()
msg = f"Program communication initialized"
print(msg)
except Exception as ex:
msg = f"Error: {ex}"
print(msg)
Error: could not open port 'COM1': FileNotFoundError(2, 'The system cannot find the file specified.', None, 2)
Through Pyvisa:
import pyvisa
import serial
import codecs
string = '4E2105'
enquire = codecs.decode(string,'hex')
rm = pyvisa.ResourceManager()
rm.list_resources()
# ('ASRL1::INSTR', 'ASRL2::INSTR', 'GPIB0::12::INSTR')
inst = rm.open_resource('asrl1::instr')
inst.write_termination='\r'
inst.read_termination='\r'
inst.baud_rate = 9600
inst.data_bits = 8
inst.parity = visa.constants.Parity.none
inst.flow_control = visa.constants.VI_ASRL_FLOW_NONE
inst.write(enquire)
print(inst.query("N!<ENQ>"))
rm.close()
VisaIOError: VI_ERROR_RSRC_NFOUND (-1073807343): Insufficient location information or the requested device or resource is not present in the system.
I am using a RS-232 to USB converter to connect my Agilent E3640A to my laptop. I am trying to return the manufacture's name using the command "*IDN" as stated in their manual. When i try to read the line, I get an empty string. I am also just having trouble putting the device in remote mode. Here is the link to their manual : https://all-guidesbox.com/model/agilent-technologies/e3640a.html
It seems that my power supply is not properly connected to my PC according to Keysight Connection Helper. It produces this error code:
! VI_ERROR_TMO: A timeout occurred
Visa ErrorCode: 0xBFFF0015 (-1073807339)
! Index was out of range. Must be non-negative and less than the size of the collection.
Parameter name: index
My Code:
ser = serial.Serial()
ser.timeout = 20
ser.baudrate = 9600
ser.port = 'COM8'
print('Connected to ' + ser.name)
ser.open()
ser.reset_input_buffer()
ser.reset_output_buffer()
#ser.write('SYST:INT{RS232}'.encode('utf-8'))
ser.write(b'SYST:REM')
ser.flush()
ser.write('*IDN?'.encode('utf-8'))
ser.flush()
print(ser.readline())
Actual Output:
Connected to COM8
b''
Desired Output:
Connected to COM8
‘‘Agilent Technologies,E3640A,0,X.X-Y.Y-Z.Z’’
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()
I have a PC Software (OS: Win 64bit) that communicates with a machine via physical serial port RS232 and I want to make a sniffer for that port using a python. Please note that I am beginner to serial ports.
I've read multiple documents and questions posted online but most of them asks to just use 3rd-party software, but I cannot do this way because raw bytes have to be decoded into string message (I have my way own of decode/encode method).
Currently I have setup like this:
/////////////////// Physical COM1 /////////////
// (PC) Software // <------------------------> // Machine //
/////////////////// /////////////
And I want a python to output any bytes that went through COM1.
Desired Behavior diagram (Virtual serial port has a question mark because I'm not sure if that is the right approach):
/////////////////// Physical COM1 /////////////
// (PC) Software // <------------------------> // Machine //
/////////////////// | Virtual /////////////
| serial port?
v
//////////////////
// (PC) Sniffer // (Python)
//////////////////
|
v
(output bytes)
Those of who knows Advanced Serial Port Monitor, its "spymode" functionality is exactly what I am trying to achieve using python.
I've tried to use com0com and PortMon but I can't find a way to configure com0com to sniff physical port (as far as my observation goes, com0com only makes virtual ports) and PortMon does not support Windows 64-bit.
I've been stuck at this for days... any comments/links/answers are appreciated.
Thank you,
You should go through pySerial
Only one function can acquire the serial port at a time.
For one-way communication(from machine to PC software), the only way I can think of to sniff from a serial port is to read from a port1 and write to port2, where your machine is writing to port1 and PC software has been modified to read from port2.
import serial
baud_rate = 4800 #whatever baudrate you are listening to
com_port1 = '/dev/tty1' #replace with your first com port path
com_port2 = '/dev/tty2' #replace with your second com port path
listener = serial.Serial(com_port1, baudrate)
forwarder = serial.Serial(com_port2, baudrate)
while 1:
serial_out = listener.read(size=1)
print serial_out #or write it to a file
forwarder.write(serial_out)
To achieve full duplex(asynchronous two way communication), you need to have a two processes, one for each direction. You will need to synchronize these process in some way. One way to do it could be, while one process reads from port1, the other writes to port2, and vice-versa.
Read this question
Why not echo something like:
PC S/W <--> COMn(COM0COM)COMm <--> python monitor & forward <--> COM1 <--> Machine
Software wise you need 2 serial tasks one opens COMm and one opens COM1 and a central logger and anything that comes in on COMm gets logged then forwarded to COM1 and vice verca.
We can use the code above without the need to go through threading to achieve a half duplex communication.
we are going to use an infinite loop, and a variable which gonna specify in which port we are reading.
import serial
import time
baud_rate = 9600 # whatever baudrate you are listening to
com_port1 = '/dev/ttyUSB0' # replace with your first com port path
com_port2 = '/dev/ttyUSB1' # replace with your second com port path
ComRead_timeout = 0.1 # Read timeout to avoid waiting while there is no data on the buffer
ComWr_timeout = 0.1 # Write timeout to avoid waiting in case of write error on the serial port
log = open('log.txt', 'a+') # Open our log file, to put read data
From_PC_To_Device = True # this variable is used to specify which port we're gonna read from
listener = serial.Serial(port=com_port1, baudrate=baud_rate, timeout=ComRead_timeout,
write_timeout=ComWr_timeout)
forwarder = serial.Serial(port=com_port2, baudrate=baud_rate, timeout=ComRead_timeout,
write_timeout=ComWr_timeout)
while 1:
while (listener.inWaiting()) and From_PC_To_Device:
serial_out = listener.readline()
localtime = time.asctime(time.localtime(time.time()))
Msg = "PC " + localtime + " " + serial_out
Msg += "\n"
log.write(Msg)
print(serial_out) # or write it to a file
forwarder.write(serial_out)
else:
From_PC_To_Device = False
while (forwarder.inWaiting()) and not From_PC_To_Device:
serial_out = forwarder.readline()
localtime = time.asctime(time.localtime(time.time()))
Msg = "DEVICE " + localtime + " " + serial_out + "\n"
log.write(Msg)
print(serial_out) # or write it to a file
listener.write(serial_out)
else:
From_PC_To_Device = True