I am a newbie in machine automation. I am working on collecting data from 2 Micrometers using python. I am collecting data from 2 induvial COM ports. I run the following python script to record the data and display it on python shell.
import time
import datetime
import serial
import matplotlib.pyplot as plt
import pandas as pd
# configure the serial connections
ser1 = serial.Serial(
port='COM4', baudrate=115200,
bytesize=8,
stopbits=1, timeout=0.02)
print("Connected to: " + ser1.port)
ser2 = serial.Serial(
port='COM5', baudrate=115200,
bytesize=8,
stopbits=1, timeout=0.02)
print("Connected to: " + ser2.port)
ser1.isOpen()
ser2.isOpen()
# Read data from the serial port, which will run in an infinite loop.
print("Instrument Type: Micrometer")
file_name = str(input('\nInsert Filename: '))
run_time = float(input('\nInsert Runtime: '))
start = time.time()
with open('./' + file_name + '.csv', 'w+') as output_file:
output_file.write('Timestamp,Data1, Data2\r')
while time.time()-start < run_time:
timestamp = str.format('{0:.3f}', (time.time()-start))
data1 = ser1.readline().decode().rstrip()
data2 = ser2.readline().decode().rstrip()
output_file.write(timestamp + ',' + data1 + ',' + data2 + '\r')
time.sleep(0.01 -(time.time()-start)%0.01)
print(timestamp, data1, data2)
print('Data Recorded')
It gives me the following output that I want (don't worry about the values).
Now, I want to apply shift() like function on data1(i.e., ser1) values to create a new column alongside, which will start storing data1 values from 4th row onwards and first 3 will be null/nan. Needless to say, it needs to be completed in real-time as a continuous output.
Related
I have to compare the lag in a server-client model in 2,4G and 5G.
My anticipation is that 5G is faster than the 2,4G by a large margin. I have already taken the 5G measurments. The average lag turned out to be 40.2ms -which is above what I was predicting-. The issue beacme visible when I tried the same with the 2,4G setup, and the lag was calculated to be a negative value. The two computers on which I was running the codes werent really synchronised. I would appriciate any input on how I would solve this issue.
I wrote the code on Jupyter as a Notebook.
Below you can find powerpoints of the setups used and the respective code used for the client and the server. The results displayed are in micro seconds.
5G Setup
2,4G Setup
Server Code:
#!/usr/bin/env python
# coding: utf-8
# In[1]:
from flask import Flask
from flask import request
from datetime import datetime
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import csv
import time
from time import sleep
from decimal import Decimal
# In[2]:
test = 1
# In[3]:
#create csv. file to append data
file_name = "2.4G_Time_Data_" + str(test)
test = test + 1
print(file_name)
with open(file_name+'.csv', 'w', newline='') as time_file:
spamwriter = csv.writer(time_file, delimiter=',',
quotechar='|', quoting=csv.QUOTE_MINIMAL)
spamwriter.writerow(['Packet','Lag(uS)'])
# In[ ]:
#start running a server, saves the in coming data in a csv file
received_package = 0
app = Flask(__name__)
#app.route('/postjson', methods = ['POST'])
def postJsonHandler():
global received_package
received_package = received_package + 1
print(request.is_json)
content = request.get_json()
print (content)
now = datetime.now();
time = content["time"]
time_now = datetime.timestamp(now)
print("Sent : " + str(time))
print("Received : " + str(time_now) )
delta_time = (time_now - time) * (10**6) # in micro seconds
print("Packet Travel Time(s) : " + str(delta_time) )
with open(file_name+'.csv', 'a') as f:
writer = csv.writer(f)
writer.writerow([str(received_package), str(delta_time)])
return 'JSON Received'
app.run(host = '0.0.0.0' , port = 8090)
Client Code:
from datetime import datetime
import requests
import signal
from time import sleep
import time
import os
import sys
import json
sample_size = 1000
for i in range(sample_size) :
now = datetime.now()
time = now.strftime("%H:%M:%S") + ":" + str(now.microsecond)
#time = str(now)
timestamp = datetime.timestamp(now)
requests.post('http://myIP:8090/postjson', json={'time': timestamp})
print ("Estimated size: " + str(sys.getsizeof(json) / 1024) + "KB")
sleep(0.1)
My 2.4G Measurment
The following code should read the serial interface into log file. The code can log with significantly high sampling rates (yes, serial synchronization is missing). But since the code is faster than the data rate of the serial device (which should be the case), it reads duplicate points.
Clarification edit: As we can see from the source code, thread is reading the serial port and writing it to the buffer rawData. Another function getSerialData() should unpack the rawData into 4 variables and write to the log file. But as it is faster than data rate of serial device, it reads rawData even when no new reading available. I would like to make the function getSerialData() unpack rawData only when thread writes new data to rawData.
I want to make sure that the code only gets last sample from serial device. This could be done by comparing the new sample with the previous sample, but it is too slow.
There are many examples of how it is done, but not for a raw connection.
#!/usr/bin/env python
from threading import Thread
import serial
import time
import collections
import struct
import copy
import pandas as pd
import numpy as np
import sys
import os
import h5py
class serialPlot:
def __init__(self, serialPort, serialBaud, bufferLength, dataNumBytes, numVal):
self.port = serialPort
self.baud = serialBaud
#self.plotMaxLength = bufferLength
self.dataNumBytes = dataNumBytes # number of bytes for single value
self.numVal = numVal
self.rawData = bytearray(numVal * dataNumBytes)
self.data = []
for i in range(numVal): # give an array for each type of data and store them in a list
self.data.append(collections.deque(
[0] * bufferLength, maxlen=bufferLength))
self.isRun = True
self.isReceiving = False
self.thread = None
self.plotTimer = 0
self.previousTimer = 0
print('Trying to connect to: ' + str(serialPort) +
' at ' + str(serialBaud) + ' BAUD.')
try:
self.serialConnection = serial.Serial(
serialPort, serialBaud, timeout=4)
print('Connected to ' + str(serialPort) +
' at ' + str(serialBaud) + ' BAUD.')
except:
print("Failed to connect with " + str(serialPort) +
' at ' + str(serialBaud) + ' BAUD.')
def readSerialStart(self):
# start thread if not started yet
if self.thread == None:
self.thread = Thread(target=self.retrieveData)
self.thread.start()
# Block till we start receiving values
while self.isReceiving != True:
time.sleep(0.01)
def getSerialData(self, bufferLength):
hdf5Buffer = [[0 for x in range(self.numVal)] for y in range(
bufferLength)] # Create array to hold data
# Calculate time delta between data points
currentTimer = time.perf_counter_ns()
# the first reading will be erroneous
self.plotTimer = int((currentTimer - self.previousTimer) / 1000)
self.previousTimer = currentTimer
for e in range(bufferLength):
privateCopy = copy.deepcopy(self.rawData[:])
for i in range(self.numVal):
bytedata = privateCopy[(i * self.dataNumBytes):
(self.dataNumBytes + i * self.dataNumBytes)]
value, = struct.unpack('f', bytedata)
# get the latest data point and append it to our array
self.data[i] = value
for f in range(self.numVal):
hdf5Buffer[e][f] = self.data[f]
hdf5Buffer[e].insert(0, self.plotTimer)
return hdf5Buffer
def retrieveData(self): # retrieve data
time.sleep(0.1) # give some buffer time for retrieving data
self.serialConnection.reset_input_buffer() # flush input buffer
while (self.isRun):
# read n bytes into array (rawData) and return num of bytes read
self.serialConnection.readinto(self.rawData)
self.isReceiving = True
def close(self):
self.isRun = False
self.thread.join()
self.serialConnection.close()
print('Disconnected...')
def main():
time.sleep(0.1)
portName = 'COM15'
baudRate = 230400
bufferLength = 10 # number of samples buffered before saving it to HDF5
dataNumBytes = 4 # number of bytes for single data point
numData = 4 # number of data points in single sample
rawData = bytearray(numData * dataNumBytes)
s = serialPlot(portName, baudRate, bufferLength,
dataNumBytes, numData) # initializes all required variables
# Starts background thread
s.readSerialStart()
dataArray = s.getSerialData(bufferLength)
while(True):
# Prepare data to write
dataArray = s.getSerialData(bufferLength)
'''
PROCEDURE FOR WRITING LATEST DATA INTO HDF5
'''
# TESTING
print(str(dataArray[-1]), end=' \r')
s.close()
if __name__ == '__main__':
try:
main()
except KeyboardInterrupt:
print('Interrupted')
try:
sys.exit(0)
except SystemExit:
os._exit(0)
I send a data from the serial port as
1H|\^&|||c111^Roche^c111^2.0.0.0710^1^3334
44|||||host|TSREQ^REAL|
To serial port and at receiving end string got split as
1H|\^
and
&|||c111^Roche^c111^2.0.0.0710^1^3334
44|||||host|TSREQ^REAL|
why it happened, i want to send it as a single string.
This is my code
import serial
import requests
ser = serial.Serial(port='COM1',baudrate=9600,parity=serial.PARITY_NONE,stopbits=serial.STOPBITS_ONE,bytesize=serial.EIGHTBITS,timeout=0.5)
concat = str()
concat01=str()
header = "b'\x021H|\^&||||||||||P||'\r\n"
sample = "b'\x023Q|1|^0101645900^10^0^4^^SAMPLE^NORMAL||ALL||||||||O'\r\n"
eol="b'\x024L|1|I'\r\n"
patient_info = "b'\x022P|1'\r\n"
while 1:
z=ser.readline()
print(z)
print("Str Result",str(z))
if str(z)!="b''":
if str(z) == str(b'\x06'):
print("verfied 06")
concat = header + patient_info + sample + eol
ser.write(concat.encode())
I am using a BananaPi to read UART data coming from a device. I know for sure what is the data generated by the device, it's the same 40 byte sequence sent in a loop, I know for sure because I mesure it with an oscilloscope. The data sent looks like(on the oscilloscope): 6A000496ED47.... 6A000496ED47....
I want to read this data in the BananaPi and I write a python script that looks like:
import serial
import time
if __name__ == '__main__':
connection = serial.Serial()
connection.port = "/dev/ttyS2"
connection.baudrate = 4000000
connection.timeout = 1
try:
connection.open()
print("serial port open")
idx = 0
while(idx < 10):
data = connection.read(size=40)
newData = data.encode('hex')
print newData
idx += 1
connection.close()
except:
print("Opening serial error")
The output is:
b777fbdc63e76....
So I get different sets of 40 bytes data on every of the 10 while loops.
Any ideea what might be wrong?
The serial setup is the same as in the oscilloscope meaning the baudrate is 4000000
I am new to programming and after a few weeks have made some programs to do simple things; like capture serial data from an arduino and save it to a text file.
Now I want to combine a couple things. I want to use python to capture serial data, prompt for port and filename, take that data and plot it real time, then when the arudino is no longer connected, save and close file. Here is the code I have so far.
problem is the graph is not real time at all. The sensors show almost no change. I also sometimes get a matplotlib depreciation warning. I wondering if there is a quick fix or if I am missing something crucial. Thank you so much!
import numpy
import matplotlib.pyplot as plt
import math
import time
import pylab
from drawnow import drawnow
import csv
import serial
import os
import glob
import sys
filename = raw_input("Save file as: ")
saveFile = open(filename, 'w')
print "Available ports: "
def serial_port():
if sys.platform.startswith('win'):
ports = ['COM%s' % (i + 1) for i in range (256)]
elif sys.platform.startswith('linux') or sys.platform.startswith('cygwin'):
ports = glob.glob('/dev/tty/[A-Za-z]*')
elif sys.platform.startswith('darwin'):
ports = glob.glob('/dev/tty.*')
else:
raise EnvironmentError('Unsupported Platform')
result = []
for port in ports:
try:
s = serial.Serial(port)
s.close()
result.append(port)
except (OSError, serial.SerialException):
pass
return result
if __name__ == '__main__':
print serial_port()
serialport = raw_input("Enter Port: ")
port1 = serialport
print "Connecting to port...", port1
arduino1 = serial.Serial(port1, 115200)
print "Arduino Detected"
#create arrays with the following names
Time = []
analog0 = []
analog1 = []
voltage0 = []
voltage1 = []
Temp = []
RH = []
#reading data from the serial port
#telling Matplot.lib to plot live data
plt.ion()
#creates a function to make a plot we want
def Fig1():
plt.plot(analog0, 'r-')
plt.title("Analog0 Data")
plt.ylim(405, 425)
plt.grid(True)
plt.ylabel("analog")
plt.xlabel("milliseconds")
x = os.path.exists(port1)
while x==0:
arduinoString = arduino1.readline()
saveFile.write(arduinoString)
dataArray = arduinoString.split(',')
time = float(dataArray[0])
a0 = float(dataArray[1])
a1 = float(dataArray[2])
v0 = float(dataArray[3])
v1 = float(dataArray[4])
temp = float(dataArray[5])
rh = float(dataArray[6])
#filling our arrays with those new data values (floats)
Time.append(time)
analog0.append(a0)
analog1.append(a1)
voltage0.append(v0)
voltage1.append(v1)
Temp.append(temp)
RH.append(rh)
drawnow(Fig1)
plt.pause(0.00010)
else:
saveFile.close()
I also had a same problem.
It was solved by using set_data() like blow link.
Draw now and Matplotlib