Python decode issue with PySerial data - python

I have a Python script reading a serial port and I am receiving data from my serial port but the data comes in I believe hex format.
Here is my code:
import serial
import time
ser = serial.Serial(
port='COM4',\
baudrate=9600,\
parity=serial.PARITY_NONE,\
stopbits=serial.STOPBITS_ONE,\
bytesize=serial.EIGHTBITS,\
timeout=3)
counter=0
while 1:
x=ser.readline()
print (x)
Here is the data I am getting back from the serial port:
b'\x82P0000000\xb1\x035\xb2\x82P0000000\xb1\x035\xb2\x82P0000000\xb1\x035\xb2'
The data is supposed to be in ASCII but I am new to Python and am kind of stuck. I have tried to use decode() in different ways but no luck.
If someone can point me in the right direction I would greatly appreciate it.
Thanks in advance!

Related

python3 serial read v/s python 2

I am using a raspberry pi to send data through TCP/IP where the raspberry pi is the server and my local windows machine is the client.
When I try to read data in python 3, I am getting weird characters for example:
send 20 decimal I receive #4
send 21 decimal I receive #5
send 22 decimal I receive #6
Below is the code running on my local machine:
import socket
host = '192.168.1.100'
port = 25000
mySocket = socket.socket()
mySocket.connect((host,port))
data = mySocket.recv(4).decode()
print (data)
Using python 2 is no problem and characters received with no decoding needed. I know I need to do some decoding on the data but not sure what. Any advise will be very helpful.
I finally figured this by using the following code:
data = mySocket2.recv(4)
newData = int.from_bytes(data, byteorder='big', signed=False)
The sender is sending uint32 data, that is obviously not-signed and is bigEndian. This has to be specified at the receiver side as well (my python3 script). If the sender changes and starts sending int8 data then I will need to update the receiver code to the following:
data = mySocket2.recv(1)
newData = int.from_bytes(data, byteorder='big', signed=True)
P.S. serial or TCP/IP receiving seem to follow the same logic in python, this means that data received requires the same encoding.

pyserial - how to continuously read and parse

I'm trying to capture data from a hardware device that's connected via usb to my linux computer that's running ubuntu. Here's the very simple script I currently have:
import serial
ser = serial.Serial('/dev/ttyUB0', 9600)
s = ser.read(10000)
print(s)
How do I make this print continuously?
The data is coming through in hexadecimal which I'd like to interpret. Should I have the continuous data save to a text file and then have another script analyze? Essentially, I'm trying to build a sniffer to grab the data and interpret.
Thanks for your help! I'm a newbie :)
1)
Just put the read and print within a while True: section.
Example:
import serial
ser = serial.Serial('/dev/ttyUB0', 9600)
while True:
s = ser.read(10000)
print(s)
Checkout another answer for some more info if you need to sniff both send and receive. https://stackoverflow.com/a/19232484/3533874
2)
For speed I would save the data without processing to a file and have the other script do the decoding/processing of the hex data. Make sure you write to the file in binary mode.
Example:
import serial
ser = serial.Serial('/dev/ttyUB0', 9600)
# This will just keep going over and over again
with open('hexdatafile.dat', 'wb') as datafile:
datafile.write(ser.read(10000))

Struct pack python to arduino

I am trying to send x and y coordinates from my Python on my Raspberry Pi to a Arduino Nano. Currently, I am using serial communication, packing the coordinates with struct.pack(), but my Arduino is not receiving the coordinates the way I would expect.
import serial
import struct
ser = serial.Serial('/dev/ttyUSB0', 115200, timeout = 1)
def sendpacket(x,y) # x and y are integers
packet = struct.pack('BsBs',x, ',' , y, ',')
print packet
print ord(packet)
ser.write(packet)
I have inserted commas so that the Arduino can tell the difference between x's and y's. I know that the Arduino can only read one byte at a time, which is why I was packing the data before sending it, but I don't really understand what is going on.
I know struct.pack() converts my packet to Unicode, or at least it appears to from my above print statements. Is that what is actually being send over serial? How should I read this in the Arduino code?
Alternatively, is there a better way to send/receive xy coordinates over serial?
I am a beginner, I know/understand very little of what I am trying to do.

Read data from load cell

Your help is badly needed...
I'm trying to read data and print it to the python console from a load cell. My setup is as follow:
The load cell is a MD type from Eilersen connected to a load cell signal converter of type MCE2040 Seriel Communication Module also from Eilersen. The MCE2040 is connected to my PC through a USB to seriel connector like this link_http://www.usbgear.com/USB-COM-I-SI.html (I'm only allowed two links) one.
The load cell is connected to COM 1.
I have tried to run this snippet:
import serial
ser = serial.Serial(0) # open first serial port
print ser.portstr # check which port was really used
#ser.write("hello") # write a string
ser.close()
...and that prints 'COM1' to the console so I guess my connection should be okay.
My problem is that I don't know how to proceed. In the end I'd like to plot a graph of the incoming data and output a data file with time stamps, but for starters I'd like to print some load cell data to the console.
Any help will be highly appreciated. If further information is needed, please let me know.
Thx in advance.
Edit:
I have some documentation re MCE2040:
3.1 EVC Mode (without time stamp)
Specification: RS232/RS4422
Baudrate: 115200 bps
38400 bps (select with SW1.5)
Data bits: 7
Parity: Even
Stop bits: 1
Protocol: EVC protocol described below (Transmit Only)
3.1.1 EVC Protocol Format
After each sample period a new weight telegram is transmitted. The transmitted telegram has the following format:
<LF>WWWWWWWW<CR>
Each telegram contains a line feed character, a weight result and a carriage return character. The telegram contains:
<LF> Line Feed character (ASCII 0Ah).
WWWWWWWW Weight value for the loadcell. The value is an 8 byte ASCII hex number with MSB first.
<CR> Carriage Return character (ASCII 0Dh).
I was able to get some output from the following code:
import serial
ser = serial.Serial(0, baudrate=115000 ,timeout=100)
print ser.portstr
x = ser.read(50)
print x
ser.close()
print 'close'
Output:
COM1
ÆÆÆÆA0·5
ÆÆÆÆA0·6
ÆÆÆÆA0·5
ÆÆÆÆA0·±
ÆÆÆÆA0·±
close
First of all make sure it's really your com port, since COM1 is used by a lot of computers i'm not sure it's your com port.
You can use a simple wire to loop back info by connecting TX to RX at the USB to Serial converter, it will result in an echo (you will read what you write) it's a very simple way to verify that you are talking with the right com port.
Regarding how to continue:
Useful basic commands:
ser.write("command") with this command you send to the device some command.
ser.read(n) is for read n bytes from the device
ser.readline() will read line until it reached \n (new line)
Steps:
Send a command to your device.
Read all the data by some end byte (Frame Synchronization).
Parse data to structure (list or something like that..)
Plot it to graph.
Useful Links:
pyserial docs
tips for reading serial
plotly for graphs in python

Reading data from Simulink into Python over UDP

I want to send data from a Simulink model (running in real time) to a Python script (also running in real time. I am using Simulink's built-in "UDP Send" block, which works, but I don't know how to decode the data I'm getting. This is what my python script looks like:
import sys, struct
from socket import *
SIZE = 1024 # packet size
hostName = gethostbyname('0.0.0.0')
mySocket = socket( AF_INET, SOCK_DGRAM )
mySocket.bind((hostName,5002))
repeat = True
while repeat:
(data,addr) = mySocket.recvfrom(SIZE)
data = struct.unpack('d',data)
print data
I've suspected that the data stream should be something like a double, but while it's giving me numbers they aren't meaningful:
If simulink sends a constant "1", I get an output of "3.16e-322"
If Simulink sends a constant "2", I get an output of "3.038e-319"
Any ideas?
Turns out my network was reversing the packet bits. The solution was to read it in as bit-reversed:
data = struct.unpack('!d',data)
I have no clue why this happens over some networks and not others. Can someone comment on a way to tell if I need to use bit-reversal?
The problem occurs when the sender and receiver has different byte order.
See sys.byteorder.
Best practice should be to always convert to network order when sending and convert again when receiving.

Categories