Converting Data From Serial Port to Display as Decimal in Python - python

I am starting a program that reads data from a radio receiver. The data is 6 bytes long and updates every 1 second. The program reads the serial port USB data, but the data is in some format that does not display correctly. What I do know is that it should be in an unsigned integer.
Each data string comes in as 6 bytes and each byte represents a number corresponds to the data the receiver has logged.
import serial
t = 0
while t == 0:
ser = serial.Serial('/dev/tty.SLAB_USBtoUART', 9600, bytesize=8, stopbits=1, timeout=None, xonxoff=0, rtscts=0, dsrdtr=0)
s=ser.readline(6)
#s=ser.read(6)
print("Streams received during interval: ")
print (s)
print("__________")
end
I am expecting an output that looks like:
0 101 0 0 91 145
but what I am getting is:
eV�
I think there is something off in the data coming in and how it prints in the print statement. I just need to make sure the data is coming in correctly before I move on.

That's because you are converting bytes to a string with your '%s' % s statement. It's showing up as whatever random ASCII character corresponds to your bytes.
Instead, try printing the bytes as integers:
print ' '.join([ord(ss) for ss in s])

Okay I figured it out and thought I would post my solution for the problem. Using NumPy I was able to easily output the correct data. I am working with a Dorji DRF4432S receiver and a Dorji DRF5150S transmitter. These are setup to send analog voltages from a sensor that basically outputs nothing until it is triggered, the the voltages with remain high for a few seconds then return to the zero value. Hopefully this might help someone looking for coding help with this sensor.
import serial
import numpy as np
t = 0
while t == 0:
ser = serial.Serial('/dev/tty.SLAB_USBtoUART', 9600, bytesize=8, stopbits=1, timeout=None, xonxoff=0, rtscts=0, dsrdtr=0)
s=ser.readline(6)
#s=ser.read(6)
print("Streams received during interval: ")
ss=np.fromstring(s, dtype=np.uint8, count=6)
sen_1_group=ss[0]
sen_1_id=ss[1]
sen_1_voltage=ss[2]+ss[3]
sen_1_battery=ss[4]
sen_1_signal=ss[5]
print (ss)
print "Group Id = ", sen_1_group , "Sensor ID = ", sen_1_id
print "Sensor ", sen_1_id, " Voltage = ", sen_1_voltage
print "Sensor ", sen_1_id, " Battery = ", sen_1_battery
print "Sensor ", sen_1_id, " Signal Strength = ", sen_1_signal
print("__________")
end
This resulted in the data coming out correctly as can be seen below:
>> Streams received during interval:
>>[ 0 101 0 0 84 169]
>>Group Id = 0 Sensor ID = 101
>>Sensor 101 Voltage = 0
>>Sensor 101 Battery = 84
>>Sensor 101 Signal Strength = 169
>>__________

Related

bind takes a long time

I am using over 20 raspberry pis to control heating and other functions in my house. For instance each room has a pi (client) with a temperature sensor, which sends a message to another pi (server) at one of three manifolds to open or close a valve on the heating system.
My problem is the amount of time the server takes to execute the bind instruction. A newly set up pi will typically take a few millisecond to execute the line, but soon the time becomes variable, sometimes milliseconds, usually seconds, but frequently tens of seconds or even hundreds of seconds.
typical code,
elapselp = default_timer() # timing start
port = 12571 # port number, many different ones used
while bound == 0:
try:
s1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s1.bind(('', port))
bound = 1
elapselp1 = default_timer() - elapselp
print ('bind time = ', elapselp1)
As stated above elapselp1 can be at the low millisecond level, or 200 seconds which causes significant problems.
I usually find I can get back to short times by changing the port number used, which means changing on all the clients, but after some time running happily the times will increase again. Rebooting or powering down does not help. I am using Raspberry 4s and Zero Ws, no difference.
I suspect that some register is not clearing, but outside that am clueless. Can somebody advise please.
I am running Rasparian 3.6 and Python3
Thank you for all your replies, here is the remainder of this section of the code.
As I’m not sure how to input his I’m breaking it down over a number of comments.
elapselp = default_timer()
port =12571
while bound == 0:
try:
s1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s1.bind(('', port))
bound = 1
elapselp1 = default_timer()- elapselp
print (‘bind time = ‘, elapselp2)
except:
dummy = 1
s1.listen(5)
print ('waiting for input ', end='')
while True:
conn, addr = s1.accept()
print ('connected by ', addr)
conn.send('thank you'.encode())
data = conn.recv(1024).decode()
print ('data = ', data)
time.sleep(5)
conn.close()
s1.close()
if data == '10':
startdaw = default_timer()
GPIO.output(22, GPIO.LOW)
print ('switch dining area heating off')
h1 = 0
dawl = edaw
startdawr = default_timer()
elif data == '11':
GPIO.output(22, GPIO.HIGH)
## A lot of other actions depending on data received here
else:
print ('another code ', data)
if not data:
break
print ('yet another')
I have a number of Raspberry pi Zeros running the code for test along with 7 doing so as part of my control system. The performance is very erratic.
One unit running through the code every 30 seconds in response to a client has been running over 5 days, majority of the bind times have been under 1 millsec, I see some between 1 and 10, but it has recorded one time of 130 seconds.
Another unit which failed to bind for over two hours has now completed over 33,000 binds (this one just closes after the bind, no if statements), and the longest time for a bind is 710 msec.
If I take out the try/except I get no error message, it just drops through and loops back.
I hope there is some useful information in there.

Data saved to text file is inconsistent

My controller is receiving data from a radio module through a serial port, it's recording temperature and humidity to two decimal places every 1 second, using 'a' as a signal to time stamp it. For example:
a21.12 65.43
a21.13 65.40
Here is the code I'm using:
import serial
import datetime
connected = False
locations=['/dev/ttyUSB0','/dev/ttyUSB1','/dev/ttyUSB2','/dev/ttyUSB3']
for device in locations:
try:
print "Trying...",device
ser = serial.Serial(device, 9600)
break
except:
print "Failed to connect on",device
while not connected:
serin = ser.read()
connected = True
with open('tempdata.txt', 'w') as text_file:
while 1:
if ser.read() is 'a':
text_file.write(datetime.datetime.now().strftime('%d/%m/%Y %H:%M:%S'))
text_file.write(" ")
x = ser.read()
text_file.write(x)
text_file.flush()
ser.close()
When I check my text file afterwards the result seems to be different every time. If I let it run for just 2 or 3 seconds I sometimes get a correct result, sometimes I only get the humidity, sometimes I get the time stamp with a number that is half temperature, half humidity (like 2.16.3). If I let it run for more than a few seconds the file is just completely blank.
The basis for my code is from a question previously asked on here and it worked fine until I added the time stamp part. I tried changing the radio transfer rate from 9600 to 4800 but that just turned the numbers into garbage characters.
I'm running this on a Raspberry Pi 2 model B so I could be demanding too much from it in a short time.
You are calling read() twice and writing only the output of the second call. I don't imagine that is your intent.
You can change this section:
with open('tempdata.txt', 'a') as text_file:
while 1:
content = ser.read()
if content is 'a':
text_file.write(datetime.datetime.now().strftime('%d/%m/%Y %H:%M:%S'))
text_file.write(" ")
text_file.write(content)
text_file.flush()

Serial data transmission input-output delay with Raspberry Pi

The Goal:
Drive several servo/RC motors wireless from one pi to another pi.
In essence, I want to build a RC remote control using a pi, with a second pion the receiver end.
Now I have a serial transmission over a RF link module that is stable and has very few corrupt entries. The serial transmission has a max baud rate of 4800 due to the RF link module.
Problem:
It seems there is a 2-4 seconds difference between the transmitter pi printing values and the receiver pi printing values. I cannot figure out where and why this delay comes from and why is it so large. Please note that the signal on the receiving pi is exactly the same data that is sent by the transmitter pi, but 2-4 seconds later. EVEN when I bypassed the the transmitter/receiver module and connected the Tx and Rx pins with a jumper wire the same delay was seen.
What is causing the data on the receiving Pi to be decoded so much later? I have pasted in the code below.
---------- Tx Pi -----------------
import serial
import struct
ser = serial.Serial("/dev/ttyAMA0")
ser.baudrate = 4800
iCount = 0
bProgramLoop = True
while (bProgramLoop == True):
iOne = iCount
if (iOne == 100):
iOne = 0
iTwo += 1
iCount = 0
if (iTwo == 100):
iTwo = 0
iThree += 1
if (iThree == 100):
iThree = 0
iFour += 1
if (iFour == 100):
iFour = 0
iFive += 1
if (iFive == 100):
iFive = 0
lData = [iOne,iTwo,iThree,iFour,iFive] # i have done it like this so that I can track in real time where the transmitter is and receiver is with respect to real time changes on the transmitter side
sData = struct.pack('5B',*lData)
ser.write(sData)
print sData
iCount += 1
-------------- Rx Pi -----------------
import serial
import struct
ser = serial.Serial("/dev/ttyAMA0")
ser.baudrate = 4800
bProgramLoop = True
while (bProgramLoop == True):
sSerialRead = ser.read(5)
tData = struct.unpack('5B',sSerialRead)
print tData
The time difference between when the Tx Pi prints the string sData and the Rx Pi prints the touple tData is somewhere between 2-4 seconds. Is the struct.unpack function slow?
I need this time difference to be absolutely minimal. Any ideas?
First, I'm not sure the ser.write() is an async call. If this is using the pySerial library, the docs say that it is a blocking call.
Perhaps try:
...
ser.write(sData)
ser.flush() # Force the 'send'
print sData
...
Also, your ldata might be easier to populate like so:
lData = [iCount % 100, iCount % 10000, ...etc]
Also, setting a write timeout might help (but I don't think so).
(Posted on behalf of the OP).
As suggested by Doddie use the ser.flush command just after ser.write. This results in a near instant response on the Rx side. The overall mainloop sample rate has dropped a bit, but for me at least that is not a deal breaker.

How to quickly read single byte serial data using Python

I am reading serial data in Python using the following code:
port = "COM11"
baud = 460800
timeout=1
ser = serial.Serial()
ser.port = port
ser.baudrate = baud
ser.timeout = timeout
while 1:
# Read from serial port, blocking
data =ser.read(1)
print data
# some further processing of data
I am sending data at very fast rate but when I use this code I am getting data at a very slow rate, maybe around 2 - 3 data per second. This is too slow because I want to do real time plotting.
So, instead of above code I tried:
while 1:
# Read from serial port, blocking
data =ser.read(1)
data1=(data)
# If there is more than 1 byte, read the rest
n = ser.inWaiting()
data1 = (data1 + ser.read(n))
print data1
Now the speed at which data is updated is the same but instead of a single byte I am checking a number of bytes in input queue and reading them. I am receiving around 3850 bytes per loop so this one appears much faster to me but in fact it is almost the same, the only change is that I am not reading a greater number of bytes.
I want to read a single byte and check for the real time it was received. To do so I cannot use second method where I use ser.inWaiting(). How can I read single byte data faster than using the approaches above?
Here's some test code I wrote for a project that you can try different baud settings with. Basically it sends out some data on Tx (which could be connected directly to Rx) and expects the data to be echoed back. It then compares the returned data with the sent data and lets you know if/when errors occur. Note that if there are no errors then the output will remain blank and at the end of test it will print "0 Comm Errors".
import serial, time
test_data = "hello this is so freakin cool!!!" + '\r' #Must always be terminated with '\r'
echo_timeout = 1 #the time allotted to read back the test_data string in seconds
cycleNum = 0
errors = 0
try:
ser = serial.Serial(port="COM1", baudrate=115200, timeout=1)
ser.flush()
print "starting test"
for x in xrange(100):
cycleNum += 1
d = ser.write(test_data)
ret_char = returned = ''
start_time = time.time()
while (ret_char <> '\r') and (time.time() - start_time < echo_timeout):
ret_char = ser.read(1)
returned += ret_char
if not returned == test_data:
errors += 1
print "Cycle: %d Sent: %s Received: %s" % (cycleNum, repr(test_data), repr(returned) )
except Exception as e:
print 'Python Error:', e
finally:
if 'ser' in locals():
print "%d Comm Errors" % errors
if ser.isOpen():
ser.close()
print "Port Was Successfully Closed"
else:
print "Port Already Closed"
else:
print "Serial Variable Was Never Initialized"

python split string and pick substring

I am having a lot of trouble with the list returned by the split function in python. I am probably being incredibly dense.
My python code is as follows
str = "XXX:YYY:ZZZ"
var+=1
ins = str.split(':')
print ins
When the script runs it returns the following result
['XXX','YYY','ZZZ']
What i am struggling to do is pull out the string contained the second string in the list. I would have thought the following code at the end of the python code would work.
print ins[1]
but when i run it i get the following error
IndexError: list index out of range
Any help would be much appreciated
full code
import time
ser = serial.Serial("COM3", 9600)
print ser
time.sleep(3)
print "Sending serial data"
var = 0
while var<=10:
str = ser.readline()
print str
var+=1
ins = str.split(':')
print ins
print ins[0]
if (str.split(':')=='end\n'):
break
if(ser.isOpen()):
print "Serial connection is still open."
ser.close();
print "Serial connectionnow terminated."
This returns
Serial<id=0x2a7fc50, open=True>(port='COM3', baudrate=9600, bytesize=8, parity='N', stopbits=1, timeout=None, xonxoff=False, rtscts=False, dsrdtr=False)
Sending serial data
Program Initiated
['Program Initiated\n']
Program Initiated
0:addsd:1
['0', 'addsd', '1\n']
0
1:addsd:2
['1', 'addsd', '2\n']
1
2:end:2
['2', 'end', '2\n']
2
Your code will not work in instances where the input you're analyzing has a length <= 1.
Try checking for that and handling it in your code.
One of the lines you are reading probably has a two '\n' characters in a row. When that string is read with readlines() and then spit it has no [1] index only a [0] index.
What output do you get for the program:
import serial // Or is serial a builtin for the version of python you are using?
print repr(serial.Serial("COM3", 9600))
Thanks,
Marlen

Categories