I'm trying to collect serial data from a device, timestamp and export it to a .csv file.
The following program writes date and time to csv but not the data returned from the device module:
import time
import csv
import fio2
def Csv_creator():
my_file = open('test_csv.csv', 'w+')
with my_file:
new_file = csv.writer(my_file)
def Timestamp():
date_now = time.strftime('%d/%m/%y')
time_now = time.strftime('%H:%M:%S')
return [date_now,time_now]
def Write_loop():
Csv_creator()
fio2.Initialize()
with open('test_csv.csv', 'a') as f:
csv_file = csv.writer(f)
for num in range(0,20):
[date_now,time_now] = Timestamp()
fio2_data = fio2.Reader()
print(fio2_data)
csv_file.writerow([date_now,time_now,fio2_data])
Write_loop()
The device module is as shown below. It returns the data and I'm able to print it. The only problem is not being able to write it on to the csv file.
import serial
ser = serial.Serial("COM4",
baudrate=2400,
bytesize=serial.EIGHTBITS,
parity =serial.PARITY_ODD)
def Initialize():
global ser
try:
ser.isOpen()
print("\n Serial is open")
except:
print ("Error: serial Not Open")
def Reader():
global ser
if (ser.isOpen()):
try:
x = ser.readline().decode()
x = (x)
return x
except:
return "unable to print"
else:
return "cannot open serial port"
I figured it out. I had to remove some garbage letters that were associated with the decimal values. First, I change the received data to string and replaced the garbage letters. Here's how I changed it:
[date_now,time_now] = Timestamp()
fio2_data = str(fio2.Reader()).replace("\r\n","")
fio2_data = fio2_data.replace("\x000","")
write_list = [date_now,time_now,fio2_data]
Related
I just got to know the world of programming and python was the first thing I learned.. This program already can extract data from .txt file and send it to API..
But the things is I don't know how to delete the file,after the data have been extracted and send to the API... Here is my coding...
from fileinput import close
import os
import requests
from datetime import datetime
import glob
import time
'''List'''
data_send_list = []
'''Path'''
path = "./file"
'''File List'''
file_name = []
URL = 'http://.......'
def main():
#Main
print("Main Def" "\n")
#ScanFile
data_send_list = scan_files(path)
#send_API
for json in data_send_list:
send_api(URL, json)
def read_text_file(file_path):
with open (file_path, 'r') as file:
data_dictionary={}
data = file.readlines()
...............
'''UPDATE THE DICTIONARY'''
data_dictionary.update([(...)(...)])
return data_dictionary
def scan_files(path):
list = []
os.chdir(path)
for file in glob.glob("*.txt"):
list.append(read_text_file(file))
return list
def send_api(url,json,):
requests_session = requests.session()
post_api = requests_session.post(url,data=json)
print("Sending API")
if(post_api.status_code >= 200 and post_api.status_code <300):
print("Successful. Status code: ",post_api.status_code)
print("\n")
#i hope that i can delete the file here
else:
print("Failed to send to API. Status code: ",post_api.status_code)
print("\n")
close()
return post_api.status_code
I was hoping that if the data can be sent to API... and give output "status code: 200" the data file will be deleted... while the data that is not sent, the file will remain
There would be a lot of better ways other than my answer.
import os
...
def send_api(url,json,path): # You need to add function parameter path to use at this function
requests_session = requests.session()
post_api = requests_session.post(url,data=json)
print("Sending API")
if(post_api.status_code >= 200 and post_api.status_code <300):
print("Successful. Status code: ",post_api.status_code)
print("\n")
os.remove(path) # use os.remove function to remove file
else:
print("Failed to send to API. Status code: ",post_api.status_code)
print("\n")
close()
return post_api.status_code
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)
Im trying to write a script that will constantly listen to a serial device and write everything to a file. But its not writing anything to the file. What am I doing wrong?
import serial
import time
i = 0
ser = serial.Serial('/dev/cu.SLAB_USBtoUART', 115200, timeout = 1)
while True:
readOut = ser.readline().decode('ascii')
file = open("output.txt","w")
file.write(readOut)
file.close()
You're opening it as w each time, which erases the content. Change to:
import serial
import time
i = 0
ser = serial.Serial('/dev/cu.SLAB_USBtoUART', 115200, timeout = 1)
while True:
readOut = ser.readline().decode('ascii')
file = open("output.txt","a")
file.write(readOut)
file.close()
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
I'm trying to read output from a serial port and write it to a text file. So far this connects and prints the output, but I can't figure out how to send the output to a text file (preferrable a csv file).
#! /usr/bin/env python3
import serial
import csv
import sys
import io
#excel stuff
#from time import gmtime, strftime
#resultFile=open('MyData.csv','wb')
#end excel stuff
def scan():
"""scan for available ports. return a list of tuples (num, name)"""
available = []
for i in range(256):
try:
s = serial.Serial(i)
available.append( (i, s.portstr))
s.close() # explicit close 'cause of delayed GC in java
except serial.SerialException:
pass
return available
if __name__=='__main__':
print ("Found ports:")
for n,s in scan():
print ("(%d) %s" % (n,s))
selection = input("Enter port number:")
try:
ser = serial.Serial(eval(selection), 9600, timeout=1)
print("connected to: " + ser.portstr)
except serial.SerialException:
pass
while True:
# Read a line and convert it from b'xxx\r\n' to xxx
line = ser.readline().decode('utf-8')[:-1]
if line: # If it isn't a blank line
# f=open('testing.txt','w+')
print(line)
#print >> f.write('test.txt')
f.close()
#print(line)
#with open('test.csv', 'w') as csv_file:
# writer = csv.DictWriter(csv_file, fieldnames=['header1'], lineterminator='\n')
ser.close()
import sys
sys.stdout = open('file', 'w')
print 'test'
or redirect the shell-output
$ python foo.py > file
Duplicate of this:
Redirect stdout to a file in Python?