pySerial buffer won't flush - pyserial

I'm having a problem with serial IO under both Windows and Linux using pySerial. With this code the device never receives the command and the read times out:
import serial
ser = serial.Serial('/dev/ttyUSB0',9600,timeout=5)
ser.write("get")
ser.flush()
print ser.read()
This code times out the first time through, but subsequent iterations succeed:
import serial
ser = serial.Serial('/dev/ttyUSB0',9600,timeout=5)
while True:
ser.write("get")
ser.flush()
print ser.read()
Can anyone tell what's going on? I tried to add a call to sync() but it wouldn't take a serial object as it's argument.
Thanks,
Robert

Put some delay in between write and read
e.g.
import serial
ser = serial.Serial('/dev/ttyUSB0',9600,timeout=5)
ser.flushInput()
ser.flushOutput()
ser.write("get")
# sleep(1) for 100 millisecond delay
# 100ms dely
sleep(.1)
print ser.read()

Question is really old, but I feel this might be relevant addition.
Some devices (such as Agilent E3631, for example) rely on DTR. Some ultra-cheap adapters do not have DTR line (or do not have it broken out), and using those, such devices may never behave in expected manner (delays between reads and writes get ridiculously long).
If you find yourself wrestling with such a device, my recommendation is to get an adapter with DTR.

This is because pyserial returns from opening the port before it is actually ready. I've noticed that things like flushInput() don't actually clear the input buffer, for example, if called immediately after the open(). Following is code to demonstrate:
import unittest
import serial
import time
"""
1) create a virtual or real connection between COM12 and COM13
2) in a terminal connected to COM12 (at 9600, N81), enter some junk text (e.g.'sdgfdsgasdg')
3) then execute this unit test
"""
class Test_test1(unittest.TestCase):
def test_A(self):
with serial.Serial(port='COM13', baudrate=9600) as s: # open serial port
print("Read ASAP: {}".format(s.read(s.in_waiting)))
time.sleep(0.1) # wait for 100 ms for pyserial port to actually be ready
print("Read after delay: {}".format(s.read(s.in_waiting)))
if __name__ == '__main__':
unittest.main()
"""
output will be:
Read ASAP: b''
Read after delay: b'sdgfdsgasdg'
.
----------------------------------------------------------------------
Ran 1 test in 0.101s
"""
My workaround has been to implement a 100ms delay after opening before doing anything.

Sorry that this is old and obvious to some, but I didn't see this option mentioned here. I ended up calling a read_all() when flush wasn't doing anything with my hardware.
# Stopped reading for a while on the connection so things build up
# Neither of these were working
conn.flush()
conn.flushInput()
# This did the trick, return value is ignored
conn.read_all()
# Waits for next line
conn.read_line()

Related

Can't read serial response using pyserial

Trying to use pyserial to talk to a Korad KD3005P power supply. (Using Python 3.6)
import serial
ser = serial.Serial('/dev/ttyACM0', baudrate=9600, bytesize=8, parity='N', stopbits=1, timeout=1)
ser.write(b'VSET1:2')
ser.write(b'VOUT1?')
response = ser.readline()
print(response)
VSET1:2 sets the voltage to 2 volts
VOUT1? tells the device to return the current voltage.
But all I get from the VOUT1? part seems to be:
b''
Stuff I've checked or tried without success:
The device works - I can talk to the device and get responses successfully with these commands through a serial terminal like CuteCom
Pyserial is kinda working - if I run the above program, the VSET1:2 does change the voltage.
I've tried different timeouts
I've tried ser.read() instead with various bit lengths
I've tried putting the read commands in a while loop
Any suggestions?
Oh.
It's a timing thing of some kind. Removing the VSET command or putting a time.sleep() command in between them and voila.. I get a response.
I'm going to mark this resolved but if anyone can enlighten me as to the nuances of this, thanks.

Need to create an <input()> function that responds to either stdin or a serial port

I am using a PC with Python to control an ASCII API through a serial connection to a micro.
The Python code sends commands to the API as a result of Keyboard events.
I need to extend input() - or write a new version - that monitors the serial
connection "simultaneously". In this way a process on the micro serial connection can signal the python code and cause an event in the same way a key command on the PC causes an event.
Since input() stops code execution until (string + \n), input() needs to be
extended.
I have a working serial connection to the micro API.
I am clueless how to do this.
Things I've tried are too embarrassing to show.
You didn't specify the problem at best. However from what I understand you would like to change the input () function to your liking. Something like this can be done, even if it represents a rough solution.
# -*- coding: utf-8 -*-
"""
Created on Mon Nov 4 20:16:13 2019
#author: Roberto Bellarosa
"""
import builtins
def fake_input(prompt):
print(prompt)
return "trgy"
builtins.input = fake_input
name = input("Enter your name >")
print("Hello,"+name+"!")

I want to stop packet capture while sniffing continuously once a condition is met

Problem
I have written a script that sniffs packet from a host, however, I am sniffing the packets in continuous mode and would like to stop sniffing on a timeout. I have written the following code to stop packet sniffing, but it doesn't seem to stop when the time has clearly exceeded the timeout. What could I be doing wrong in here?
import time
import pyshark
prog_start = time.time()
capture = pyshark.LiveCapture(interface='en0')
capture.sniff(timeout=10)
start_time = capture[0].frame_info.time_epoch
end_time = capture[-1].frame_info.time_epoch
print("Capture lasted:", float(end_time) - float(start_time))
pkt_num = 0
for pkt in capture:
pkt_num += 1
print("Time", time.time() - prog_start, "Pkt#", pkt_num)
We then get this output, with thousands of additional packets a second, past when the capture should have stopped:
Capture lasted: 9.148329019546509
Time 10.346031188964844 Pkt# 1
Time 10.348641157150269 Pkt# 2
Time 10.351708889007568 Pkt# 3
Time 10.353564977645874 Pkt# 4
Time 10.35555100440979 Pkt# 5
...
Question
Why does PyShark continue to capture packets after the timeout?
I was having this same issue, I managed to find a bit of a solution for it. It isn't perfect but it works by telling the capture loop to stop on the next packet and sends an empty packet it will see to make it end. I made it a udp packet on a high port for my case because I use a filter that filters out most traffic so this solution worked for me
class PacketCapture(threading.Thread):
capture = 1
def __init__(self, interface_name):
threading.Thread.__init__(self)
self.interface_name = interface_name
def stop(self):
self.capture = 0
def run(self):
capture = pyshark.LiveCapture(interface=self.interface_name)
try:
for packet in capture.sniff_continuously():
if not self.capture:
capture.close()
except pyshark.capture.capture.TSharkCrashException:
self.exited = 1
print("Capture has crashed")
#start capture
pcap = PacketCapture(interface_name)
pcap.start()
#stop capture
pcap.stop()
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
msg = bytes("", "UTF-8")
sock.sendto(msg, ("external IP", 12345))
sock.close
I'm relatively new to python myself but I think this should be a somewhat acceptable solution given the scenario
Problems with PyShark
It looks like you're running into a known issue with PyShark that hasn't been fixed in years. Per the thread, the author wrote
You can subclass LiveCapture and override the get_parameters() function, adding your own parameters.
You could modify the parameters sent to tshark, but at this point, why not just use a tshark command directly?
Using Tshark Instead
PyShark is just a wrapper for tshark on your system. If you want to use subprocess with Python, the equivalent tshark command is tshark -a duration:5. The other advantage of using tshark directly is that subprocess gives you a pid that you can kill on an arbitrary condition.
See the manpage for more details.
You can use the following line in bash or even in python within os.system, os.popen or even subprocess:
while IFS= read -r line; do if [[ $line =~ 'some protocol' ]]; then <SOME_ACTION>; break; fi; done < <(sudo tshark)

Trouble with communication with usb B type machine with Matlab

I am using matlab to communicate with several machines.
I am trying to connect with LCC25 (Liquid crystal retarder controller made by Thorlabs) using usb b to usb a cable.
I made a code like this.
clear all; clc;
%%
ss=serial('COM7','BaudRate',9600,'DataBits',8);
set(ss,'Parity','none');
set(ss,'Terminator','LF');
fopen(ss);
fprintf(ss,'*idn?');
aa=fscanf(ss)
fclose(ss)
Then I get "Warning : Unsuccessful read : A timeout occurred before the Terminator was reached aa=="
Is there any problem in my code?
I am also interested in buying the LCC25 and controlling it with MATLAB, so this is very interesting for me and I would love to find out whether it works...
To debug your code, I am wondering what happens when you comment out everything but:
ss=serial('COM7','BaudRate',9600,'DataBits',8);
set(ss,'Parity','none');
set(ss,'Terminator','LF');
fopen(ss);
Since then we can now if the problem is in establishing the connection itself (which you should not run every time btw!), or in trying to send a command to the device...
If the object creation is succesful, you should see something like this:
Serial Port Object : Serial-COM4
Communication Settings
Port: COM7
BaudRate: 9600
Terminator: 'LF'
Communication State
Status: closed
RecordStatus: off
Read/Write State
TransferStatus: idle
BytesAvailable: 0
ValuesReceived: 0
ValuesSent: 0
Then you can try to add run
fopen(ss)
fscanf(ss)
in a seperate file, and see what the output is. If all of this works, you can start to try sending commands using the 'fprintf' command, but make sure not to run the 'serial' and 'fopen' command every
I am wondering where you obtained the command string '*idn?', did you find this in the help file? The same for the terminator 'LF', are you sure this is the correct terminator to use for the LCC25? When reading the error message you received, I suspect the problem to be that you might need to use other terminators, such as 'CR'.

I2C read - repeated start needed?

I have a doubt regarding read operation in I2C, bit banging. The protocol which I am following for read as below:
Start-slave address with write-ack-register loc-ack-stop. ...... Start-slave address with read-ack-read data-stop.
I am reading data as FFh which is wrong.
My doubt is, before sending the another start, do in need to send stop or can continue the another start for reading data without stop, which actually is a repeated start. Does sending a stop bit or not makes any difference. Also can someone tell what can be the possible reason if data read is FFh. But I can guarantee that write operation is successful, after seeing the scope shot. Please guide me.
Thanks
The i2c protocol works like this
WRITE:
send START
write slave address with last bit as WRITE ACCESS(0)
write sub-address: this is usually the address of the register you what to write to; if not applicable skip to 4.
write data
send STOP
Each byte you write to the slave device should be answered with an ACK if the operation was successful.
READ:
send START
write slave address with last bit as WRITE ACCESS(0)
write sub-address: this is usually the address of the register you what to read from
send START (this is a second start condition - a restart)
write slave address with last bit as READ ACCESS(1)
read data
send STOP
All write and read operations (except the last read) are answered with a ACK if successful.
So in the case of a restart you don't send a second Stop.
As far as the 0xFF read result is concerned, you need to check the datasheet of the device, but some will return this value if the data you are trying to read is not available, yet!
Hope this helps.
I just had this issue and found the reason: if you receive FFh in reading all the time, you are missing the repeated start.