I am trying to save Arduino sensor data that I receive via serial communication. I tried CSV writer and I had partial success. It did what I wanted but it saved data in a single row rather than storing them in columns. I tried writerow and writerows as well both did not work as I wanted. How can I solve this problem?
I also had one more issue, is there a way of displaying this data in Tkinter in real time? I tried treeview but it did not work.
Here is my code
def arduino_read_serialdata():
global ser
ser = serial.Serial('COM4', 9800, timeout=1)
time.sleep(0.9)
ser.flushInput()
while True:
global analog_voltage, Voltage, Temperature, Current, yp
incoming_data = ser.inWaiting()
incoming_data = ser.readline()
incoming_data = incoming_data.decode()
cleaned_data = incoming_data.strip("/n")
data_to_sort.append(cleaned_data)
time.sleep(1)
for everyrow in data_to_sort:
if everyrow.startswith("Measuring voltage and current with INA219 ..."):
pass
elif everyrow.startswith("MAX31855 test"):
pass
elif everyrow.startswith("Initializing sensor...DONE checking reading the values now."):
pass
elif everyrow.startswith("The Analog Voltage is:"):
anvol = everyrow[-8:]
analog_voltage.append(float(anvol))
elif everyrow.startswith("Bus Voltage............:"):
vol = everyrow[-8:]
Voltage.append(float(vol))
elif everyrow.startswith("Current..............:"):
cur = everyrow[-8:]
Current.append(float(cur))
elif everyrow.startswith("Temperature in celcius:"):
temp = everyrow[-7:]
Temperature.append(float(temp))
else:
pass
with open("Sensor_data.csv", 'w ', newline='') as output_file:
output_file.flush()
output_file = csv.writer(output_file)
fields = ['Analog Voltage V', 'Voltage V', 'Current mA', 'Temperature °C']
output_file.writerow(fields)
output_file.writerow([analog_voltage,Voltage, Current,Temperature])
if keyboard.is_pressed("q"):
print("Manually interrupted by user")
ser.close()
print("Serial port closed")
break
But I want it in columns vertically from top to bottom
CodePudding user response:
I'm assuming that all arrays have the same amount of items. Then iterate over one of them, e.g. range(0, len(analog_voltage))
and access each item in the lists individually by their index.
for idx in range(0, len(analog_voltage)):
output_file.writerow([analog_voltage[idx],Voltage[idx], Current[idx],Temperature[idx]])
Just some thoughts:
It would certainly be faster if the Arduino would just send the data without all the human readable information. I also think that the Arduino would always process the data in the same order and could send the data in CSV format already. This would probably simplify both the Arduino program and the Python program.
CodePudding user response:
I would recommend you open your output file before the while loop and keep it open. That way you can write a row at a time. It also avoids you writing multiple headers to the file.
Try the following kind of approach:
def arduino_read_serialdata():
global ser
ser = serial.Serial('COM4', 9800, timeout=1)
time.sleep(0.9)
ser.flushInput()
with open("Sensor_data.csv", 'w', newline='') as f_output:
csv_output = csv.writer(f_output)
csv_output.writerow(['Analog Voltage V', 'Voltage V', 'Current mA', 'Temperature °C'])
while True:
incoming_data = ser.inWaiting()
incoming_data = ser.readline()
incoming_data = incoming_data.decode()
cleaned_data = incoming_data.strip("/n")
data_to_sort.append(cleaned_data)
time.sleep(1)
# Defaults if value missing
anvol = ''
vol = ''
cur = ''
temp = ''
for everyrow in data_to_sort:
if everyrow.startswith("The Analog Voltage is:"):
anvol = everyrow[-8:].strip()
elif everyrow.startswith("Bus Voltage............:"):
vol = everyrow[-8:].strip()
elif everyrow.startswith("Current..............:"):
cur = everyrow[-8:].strip()
elif everyrow.startswith("Temperature in celcius:"):
temp = everyrow[-7:].strip()
csv_output.writerow([anvol, vol, cur, temp])
if keyboard.is_pressed("q"):
print("Manually interrupted by user")
ser.close()
print("Serial port closed")
break
You could also add a timestamp to the output filename if needed so you don't overwrite previous sessions.
Note: not tested as I don't have a suitable environment