# pip install pyserial matplotlib pandas import serial import matplotlib.pyplot as plt import pandas as pd from matplotlib.widgets import Button from datetime import datetime max_points = 20 # Number of points to display on the graph data = { 'Timestamp': [], **{f'Temp{i+1}': [] for i in range(16)}, **{f'Hum{i+1}': [] for i in range(16)} } # Initialize plots plt.ion() fig, (ax_temp, ax_hum) = plt.subplots(2, 1, figsize=(15, 10)) # Set plot titles and labels ax_temp.set_title('Temperature') ax_temp.set_xlabel('Time') ax_temp.set_ylabel('Temperature (°C)') ax_hum.set_title('Humidity') ax_hum.set_xlabel('Time') ax_hum.set_ylabel('Humidity (%)') # Global flag to control the data collection collecting_data = False exit_flag = False # Button callback functions def start_button_callback(event): global collecting_data collecting_data = True def exit_button_callback(event): global exit_flag exit_flag = True # Create the buttons ax_start_button = plt.axes([0.7, 0.05, 0.1, 0.075]) ax_exit_button = plt.axes([0.81, 0.05, 0.1, 0.075]) start_button = Button(ax_start_button, 'Start') start_button.on_clicked(start_button_callback) exit_button = Button(ax_exit_button, 'Exit') exit_button.on_clicked(exit_button_callback) # Display the plot window plt.show(block=False) # Wait here until 'Start' button is pressed while not collecting_data: plt.pause(0.1) # Use a short pause to handle UI events if exit_flag: plt.close(fig) raise SystemExit # Main loop try: # Set up the serial connection (adjust the COM port as needed) ser = serial.Serial('/dev/cu.usbmodem14101', 9600, timeout=1) while not exit_flag: line = ser.readline().decode('utf-8').strip() if line: try: # Split the line into groups and then into temperature and humidity values groups = line.split(';') if len(groups) == 16: timestamp = datetime.now().strftime('%H:%M:%S') data['Timestamp'].append(timestamp) temps = [] hums = [] for i, group in enumerate(groups): temp, hum = map(float, group.split(',')) temps.append(temp) hums.append(hum) data[f'Temp{i+1}'].append(temp) data[f'Hum{i+1}'].append(hum) # Update temperature graph with latest 20 points ax_temp.clear() ax_temp.set_title('Temperature') ax_temp.set_xlabel('Time') ax_temp.set_ylabel('Temperature (°C)') for i in range(16): ax_temp.plot(data['Timestamp'][-max_points:], data[f'Temp{i+1}'][-max_points:], label=f'Temp{i+1}') # Update humidity graph with latest 20 points ax_hum.clear() ax_hum.set_title('Humidity') ax_hum.set_xlabel('Time') ax_hum.set_ylabel('Humidity (%)') for i in range(16): ax_hum.plot(data['Timestamp'][-max_points:], data[f'Hum{i+1}'][-max_points:], label=f'Hum{i+1}') plt.pause(0.5) except ValueError as e: print(f"Could not convert data to float: {line}, error: {e}") except KeyboardInterrupt: plt.ioff() finally: # Save the data to a CSV file df = pd.DataFrame(data) csv_filename = 'arduino_data.csv' df.to_csv(csv_filename, index=False) print(f"Data saved to '{csv_filename}'") ser.close()