0

I am fairly new to using pyserial and I am currently having difficulty with reading a scale. I believe that it has to do with some initialization that I am not doing correctly on python. I have been running the scale with LabVIEW but am trying to get away from it since my knowledge there is severely limited. When I execute the following code I get b ' ' printed. Without the timeout, the code will go on forever unless I unplug the device(i have also used ser.readline()). I have attached the initialization code that is used from labview if that helps (I know the settings on the block diagram differ from the code but you can manually change them on the front panel to match the scale settings). I appreciate any help in advance!

ser = serial.Serial("COM3", 
                     9600, 
                     timeout = 2, 
                     bytesize=serial.EIGHTBITS, 
                     parity=serial.PARITY_ODD)
print('Connected')
ser.read(5)

Labview Diagram

srm
  • 3,062
  • 16
  • 30
Z.Tyler
  • 11
  • 3
  • We miss information to answer can you tell us which kind of instruments you aim to connect. What cable are you using (direct or null modem). What error do you get? Can you connect? Are there bad symbols? – jlandercy Feb 29 '20 at 06:45
  • I am trying to connect a sartorius scale with a direct connection. With the above code I don’t get any errors but I also don’t receive any information. All that is returned after the timeout is b’’. – Z.Tyler Feb 29 '20 at 07:13
  • Can you be more specific, which model is it? Think I will have to find documentation to discover what protocol you must use to poll the scale. – jlandercy Feb 29 '20 at 07:33
  • I think I have addressed your problem, let me know it is solved. Cheers – jlandercy Feb 29 '20 at 08:56
  • Yes this helped thank you! I just had to poll the scale to get the reading. – Z.Tyler Mar 01 '20 at 20:18

1 Answers1

0

Setup

Your cable should be fine as you can connect the Scale UART. Then, you must properly setup the connection. According to your figure and some documentation (p. 55, also see) it should be:

import serial    
ser = serial.Serial("COM3", 
                     1200, 
                     timeout = 2, 
                     bytesize=serial.SEVENBITS, 
                     parity=serial.PARITY_ODD,
                     stopbits=serial.STOPBITS_ONE)

If you got scrambled characters during communication, it is most likely the setup above that should be fixed to match the Scale setup.

Communication

Timeout occurs because there is not character to read from the UART. Most likely the device works in poll mode or streams character on specific conditions which are not met during the read call.

Manual says (p. 65):

The print command can be transmitted by a software command or by pressing .

Poll

In the first case (poll mode), you must send commands (defined by a protocol) before reading any information back. This manual (p. 53-63) adds some shed of light on the protocol used to exchange information. Eg. if we want to poll the Scale Model:

ser.write(b"\x1bx1_\r\n") # Send data, stands for: ESC x 1 _ CR LF (p. 62)
rep = ser.read(64)        # Try to read up to 64 bytes

To read data from Scale, use:

ser.write(b"\x1bP\r\n")        # Equivalent to press button
                               # (block auto print, see p. 61)
rep = ser.read(ser.in_waiting) # Read pending bytes, should returns 16 bytes
                               # eg.: b"+****72.55*g**\r\n" (p. 57)

Stream

You can check this behaviour using:

rep = ser.read_until()

It will wait for \n (Line Feed) before returning, start your script and press the button. You should receive data from the scale.

If the scale streams data on a specific event (eg.: button pressed) then you need to address a totally different problem. You will need to implement a Listener as you will need to continuously listen to the UART. It is generally done using a queue, the main idea is (emulated using a bytearray for simplicity sake):

q = bytearray()    
while True:
   # Read until Line Feed:
   d = ser.read_until()
   # Update queue:
   q.extend(d)
   # Logic here to consume queue:
   # ...

Do not use this last snippet in production, it just a dummy example to fix ideas. If you go to this solution you better implement a listener service to address the Producer-Consumer Problem.

Choosing between poll and stream is determined by the device capabilities and your application requirements.

jlandercy
  • 7,183
  • 1
  • 39
  • 57