Python, serial - changing baudrate, strange behaviour - python

I am having troubles with changing baudrate while the port is running. All the communication is run at 100k baud, but I also need to send some data at 10k baud. I've read I should use setBaudrate method, so I tried this:
ser = serial.Serial(2, baudrate=BAUD, timeout=TIMEOUT)
def reset(string):
if string:
ser.flushInput() #erase input and output buffers
ser.flushOutput()
ser.setBaudrate(RESET_BAUD) #change baudrate to 10k
ser.write(string)
ser.setBaudrate(BAUD) #go back to 100k
The problem is, it doesn't work right. I don't know what is wrong here, but the string just isn't received properly. But here is interesting part - if I remove the last line (going back to 100k) and run this function from the shell, everything is fine. Then I can just run the last command directly in shell, not inside function.
My question is what exactly happens here and how to avoid it? All I need is a function to send a string with different baudrate and then return to the original baudrate...

You need to wait long enough for the string to be sent before resetting the BAUD rate - otherwise it changes while some of it is still in the serial port (hardware) buffer.
Add time.sleep(0.01*len(string)) before the last line.
BTW try not to use reserved words like string as variable names as it can cause problems.

My guess is that the baud rate is being changed before the data is actually sent. A good bet is to force the data to be sent before trying to change the baud rate.
According to the docs, this is done by calling Serial.flush() (not flushInput() or flushOutput(), as these just discard the buffer contents).

Related

Scapy - persistent RandIP

I am trying to simulate a TCP communication between two hosts with scapy.
My problem is, that I can't save the random IP addresses scapy generates for me.
This code
src_IP = RandIP()
print(src_IP)
print(src_IP)
print(src_IP)
gives me an output like this
234.200.98.20
147.3.56.17
135.102.142.49
So every time I access src_IP it has a new value.
Is there a way to save a random IP from scapy? So I could generated 2 IPs at the beginning of my function and use them as source and destination for my TCP communication.
I could generate the IPs myself, but I thought there had to be a more elegant solution to it.
BTW. non of the packets are going to be sent, they will be written into a PCAP file. Therefor I have to create both sides of the communication.
The accepted answer is a hack; it is correct (as in "it works and do what was asked"), but it is not the correct way to do that in Scapy.
The method you are looking for is ._fix(). It will work with any volatile value type.
src_IP = RandIP()._fix()
If you also need for example a random source port, you could do:
src_port = RandShort()._fix()
I found an answer.
RandIP() creates an instance of an object, and every time this object gets accessed, to print or do send a packet or something else, it generates a new IP.
So my solution is to cast it to a string
src_IP = str(RandIP())
print(src_IP)
print(src_IP)
print(src_IP)
And the output is just as intended
232.119.133.38
232.119.133.38
232.119.133.38

Python - can't decipher serial port bits

I have a MaxiMet GMX600 weather station.
Here is the manual:
http://gillinstruments.com/data/manuals/maximet-manual-iss1.pdf
I have it connect to my serial port and it's spitting out data every 1 second. Which is great!
Unfortunately, I can't decipher the data...
I should be seeing strings like this:
$WIMWV ,069,R,004.06,N,A*00
$WIMWV,122,T,,N,A*14
$WIXDR,C,+023.2,C,TEMP,P,1.0281,B,PRESS,H,037,P,RH,Y,000.0,M,PRECIP*0A
Followed 1 second later by:
$WIMWV ,238,R,000.46,N,A*06
$WIMWV,303,T,,N,A*15
$WIXDR,C,+023.2,C,TEMP,P,1.0281,B,PRESS,H,037,P,RH,Y,000.0,M,PRECIP*0A
Followed 1 second later by:
$WIMWV ,130,R,000.21,N,A*0C
$WIMWV,205,T,,N,A*12
$WIXDR,C,+023.2,C,TEMP,P,1.0281,B,PRESS,H,038,P,RH,Y,000.0,M,PRECIP*05
Unfortunately, all I'm seeing is gobbledy-gook such as:
�����������������W���������������������������������������������������������������]���}���������������������u���+��+����; ���; �����; k��K; ���K;k��;� ����;���;� ���;���u������������
Followed one second later by:
�叙���������������������W�����������������������������������������������������������������]��哙���������������������W���������������������������������������������������������������]��坙
Followed one second later by:
�����]���y����������������������W�����������������������������������������������������������������]��叙���������������������W�����������������������������������������������������������������]�
Here's my Python code:
import time
import serial
import binascii
import struct
ser=serial.Serial(
port='/dev/ttyAMA0',
baudrate=19200,
parity=serial.PARITY_NONE,
stopbits=serial.STOPBITS_ONE,
bytesize=serial.EIGHTBITS,
timeout=5
)
while 1:
y=0
str=""
while y<200:
#x=binascii.b2a_qp(ser.read()).strip().strip("=")
#x=binascii.hexlify(ser.read()).strip()
x=ser.read().strip()
#x=struct.pack('<h',int(ser.read()))
str=x+str
y=y+1
#ser.flush()
print str
You can see I've been trying to manipulate the bytes, but nothing is happening. I keep getting gobbldy-gook.
If I uncomment the line bin2ascii.hexlify(ser.read()).strip(), I get output like:
9fa78d919fa75dfb00ebe59599f9a79f9f9f9fa78fa3979fa9a795a38d998b9f958b9f9d57999fa59b9da5959d9f9ba79fa39f9f9fa79fa39f9f9f9f9fa79ba38d9f9fa9a79da39f9b9fa9a78d979fa799a39d9d9f9da78d9b9fa79d9fa39f9f9fa7998f9fa75dfb00ebe57d99f9a79f9f9f9fa78fa3979fa9a795a38f998b9f958b9f9d57999fa59b9da5959d9f9ba79fa39f9f9fa79fa39f9f9f9f9fa79ba38d9f9fa9a79da39f9b9fa9a78d979fa799a39d9d9f9da79b999fa79f9fa39f9f9fa7938f9fa75dfb
Followed one second later by:
9f9fa79d9fa39f9f9fa78d959fa75dfb00ebe57999f9a79f9f9f9fa78fa3979fa9a795a39d978b9f958b9f9d57999fa59b9da5959d9f9ba79fa39f9f9fa79fa39f9f9f9f9fa79ba38d9f9fa9a79da39f9b9fa9a78d979fa799a39d9d9f9da79d9599a79d9fa39f9f9fa795979fa75dfb00ebe59b99f9a79f9f9f9fa78fa3979fa9a795a39f978b9f958b9f9d57999fa59b9da5959d9f9ba79fa39f9f9fa79fa39f9f9f9f9fa79ba38d9f9fa9a79da39f9b9fa9a78d979fa799a39d9d9f9da7959b9fa79d9fa39f9f
Followed one second later by:
99a39d9d9f9da79b9d9fa79d9fa39f9f9fa793939fa75dfb00ebe57b99f9a79f9f9f9fa78fa3979fa9a795a399978b9f958b9f9d57999fa59b9da5959d9f9ba79fa39f9f9fa79fa39f9f9f9f9fa79ba38d9f9fa9a79da39f9b9fa9a78d979fa799a39d9d9f9da79f9d9fa79d9fa39f9f9fa797939fa75dfb00ebe59f99f9a79f9f9f9fa78fa3979fa9a795a39b978b9f958b9f9d57999fa59b9da5959d9f9ba79fa39f9f9fa79fa39f9f9f9f9fa79ba38d9f9fa9a79da39f9b9fa9a78d979fa799a39d9d9f9da795
ASCII only goes up to 0x7F, so I guess all these 0x9_ numbers are producing the funny characters?
I'm afraid I'm really stuck. I can't decipher it - my Python skills aren't good enough and I've been at this for hours... Does anyone have any Python suggestions as to how I can fix this output?

Python for Keithley

I hooked up the Keithley 2701 DMM, installed the software and set the IPs right. I can access and control the instrument via the internet explorer webpage and the Keithley communicator. When I try to use python, it detects the instrument
i.e. a=visa.instrument("COM1") doesn't give an error.
I can write to the instrument as well:
a.write("*RST")
a.write("DISP:ENAB ON/OFF")
a.write("DISP:TEXT:STAT ON/OFF")
etc all don't give any error but no change is seen on the instrument screen.
However when I try to read back, a.ask("*IDN?") etc give me an error
saying timeout expired before operation completed.
I tried redefining as:
a=visa.instrument("COM1",timeout=None)
a=visa.instrument("TCPIP::<the IP adress>::1354::SOCKET")
and a few other possible combinations but I'm getting the same error.
Please do help.
The issue with communicating to the 2701 might be an invalid termination character. By default the termination character has the value CR+LF which is “\r\n”.
The python code to set the termination character is:
theInstrument = visa.instrument(“TCPIP::<IPaddress>::1394::SOCKET”, term_chars = “\n”)
or
theInstrument = visa.instrument(“TCPIP::<IPaddress>::1394::SOCKET”)
theInstrument.term_chars = “\n”
I hope this helps,

Losing data in received serial string

So part of a larger project needs to receive a long hex character string from a serial port using a raspberry pi. I thought I had it all working but then discovered it was losing a chunk of data in the middle of the string.
def BUTTON_Clicked(self, widget, data= None):
ser = serial.Serial("/dev/ex_device", 115200, timeout=3)
RECEIVEDfile = open("RECIEVED.txt", "r+", 0) #unbuffered
#Commands sent out
ser.write("*n\r")
time.sleep(1)
ser.flush()
ser.write("*E")
ser.write("\r")
#Read back string rx'd
RECEIVED= ser.read()
RECEIVED= re.sub(r'[\W_]+', '', RECEIVED) #remove non-alphanumeric characters (caused by noise maybe?)
RECEIVEDfile.write(re.sub("(.{4})", "\\1\n", RECEIVED, 0, re.DOTALL)) #new line every 4 characters
RECEIVEDfile.close
ser.write("*i\r")
ser.close
This is the script used to retrieve the data, the baud rate and serial commands are set right and the script is run as "unbuffered" (-u) but yet the full string is not saved. The string is approx 16384 characters long but only approx 9520 characters (it varies) are being saved (can't supply the string for analysis). Anyone know what I'm missing? Cheers for any help you can give me.
Glad my comment helped!
Set timeout to a low number, e.g. 1 second. Then try something like this. It tries to read a large chunk, but times out quickly and doesn't block for a long time. Whatever has been read is put into a list (rx_buf). Then loop forever, as long as you've got pending bytes to read. The real problem is to 'know' when not to expect any more data.
rx_buf = [ser.read(16384)] # Try reading a large chunk of data, blocking for timeout secs.
while True: # Loop to read remaining data, to end of receive buffer.
pending = ser.inWaiting()
if pending:
rx_buf.append(ser.read(pending)) # Append read chunks to the list.
else:
break
rx_data = ''.join(rx_buf) # Join the chunks, to get a string of serial data.
The reason I'm putting the chunks in a list is that the join operation is much more efficient than '+=' on strings.
According to this question you need to read the data from the in buffer in chunks (here single byte):
out = ''
# Let's wait one second before reading output (let's give device time to answer).
time.sleep(1)
while ser.inWaiting() > 0:
out += ser.read(1)
I suspect what is happening in your case is that you're getting an entire 'buffers' full of data, which depending on the state of the buffer may vary.

TCP Sockets: Double messages

I'm having a problem with sockets in python.
I have a a TCP server and client that send each other data in a while 1 loop.
It packages up 2 shorts in the struct module (struct.pack("hh", mousex, mousey)). But sometimes when recving the data on the other computer, it seems like 2 messages have been glued together. Is this nagle's algorithm?
What exactly is going on here? Thanks in advance.
I agree with other posters, that "TCP just does that". TCP guarantees that your bytes arrive in the right order, but makes no guarantees about the sizes of the chunks they arrive in. I would add that TCP is also allowed to split a single send into multiple recv's, or even for example to split aabb, ccdd into aab, bcc, dd.
I put together this module for dealing with the relevant issues in python:
http://stromberg.dnsalias.org/~strombrg/bufsock.html
It's under an opensource license and is owned by UCI. It's been tested on CPython 2.x, CPython 3.x, Pypy and Jython.
HTH
To be sure I'd have to see actual code, but it sounds like you are expecting a send of n bytes to show up on the receiver as exactly n bytes all the time, every time.
TCP streams don't work that way. It's a "streaming" protocol, as opposed to a "datagram" (record-oriented) one like UDP or STCP or RDS.
For fixed-data-size protocols (or any where the next chunk size is predictable in advance), you can build your own "datagram-like receiver" on a stream socket by simply recv()ing in a loop until you get exactly n bytes:
def recv_n_bytes(socket, n):
"attempt to receive exactly n bytes; return what we got"
data = []
while True:
have = sum(len(x) for x in data)
if have >= n:
break
want = n - have
got = socket.recv(want)
if got == '':
break
return ''.join(data)
(untested; python 2.x code; not necessarily efficient; etc).
You may not assume that data will become available for reading from the local socket in the same size pieces it was provided for sending at the other source end. As you have seen, this might sometimes be usually true, but by no means reliably so. Rather, what TCP guarantees is that what goes in one end will eventually come out the other, in order without anything missing or if that cannot be achieved by means built into the protocol such as retries, then whole thing will break with an error.
Nagle is one possible cause, but not the only one.

Categories