Skip to content

Commit 9d2890f

Browse files
cleaned up code,updated comments
Made the logic more intuitive from not true to just false inside the while loop. Added comments Added a very basic over view of the code to the file
1 parent 98ef270 commit 9d2890f

File tree

3 files changed

+149
-36
lines changed

3 files changed

+149
-36
lines changed
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
No,Date,Time,Unix Time,Humidity,Soil Moisture,Temperature,Light Intensity
2+
1,11 March 2024,08:05:42,1710124542,47,39,43,42
3+
2,11 March 2024,08:05:43,1710124543,70,42,64,510
4+
3,11 March 2024,08:05:44,1710124544,63,39,40,85
5+
4,11 March 2024,08:05:45,1710124545,82,32,27,839
6+
5,11 March 2024,08:05:46,1710124546,67,39,80,340
7+
6,11 March 2024,08:05:47,1710124547,43,39,49,773
8+
7,11 March 2024,08:05:48,1710124548,50,43,89,470
9+
8,11 March 2024,08:05:49,1710124549,56,45,87,146
10+
9,11 March 2024,08:05:50,1710124550,52,37,70,65
11+
10,11 March 2024,08:05:51,1710124551,69,39,69,741
12+
11,11 March 2024,08:05:52,1710124552,57,42,83,712
13+
12,11 March 2024,08:05:53,1710124553,75,35,38,331
14+
13,11 March 2024,08:05:54,1710124554,84,47,71,129
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
No,Date,Time,Unix Time,Humidity,Soil Moisture,Temperature,Light Intensity
2+
1,11 March 2024,08:47:58,1710127078,47,39,43,42
3+
2,11 March 2024,08:47:59,1710127079,70,42,64,510
4+
3,11 March 2024,08:48:00,1710127080,63,39,40,85
5+
4,11 March 2024,08:48:01,1710127081,82,32,27,839
6+
5,11 March 2024,08:48:02,1710127082,67,39,80,340
7+
6,11 March 2024,08:48:03,1710127083,43,39,49,773

Python_PC_Side/python-ttkbootstrap-data-logger.py

Lines changed: 128 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,73 @@
1-
#requires pyserial installed
2-
#requires ttkbootstrap installed
1+
'''
2+
GUI Tkinter (ttkbootstrap) program to read data from arduino or DAQ and log into a CSV file.
3+
CSV file name automatically generated using current date and time
34
5+
6+
requires: pyserial installed
7+
: ttkbootstrap installed
8+
9+
Author : Rahul.S
10+
11+
(c) www.xanthium.in (2024)
12+
13+
14+
#============================ Very Basic Overview of the Code ==========================================#
15+
16+
#below function runs inside a thread,all action takes place inside this
17+
18+
def acquire_arduino_data(serialport_name,baud_rate,logging_interval):
19+
#(log_count) logging count = 1
20+
#Create the Serial port object inside try catch
21+
#Create a file name using Current Date and time,create_filename_current_date_time()
22+
#Create CSV file,Write header to CSV file
23+
24+
while True:
25+
26+
if start_logging_event.is_set() == True:
27+
# Read Data from Arduino using SerialPort,read_arduino_sensors(serialport_obj)
28+
# Get time stamp using time.time()
29+
# Create a List to write to CSV file
30+
# Write list to CSV file
31+
# Wait here, based on logging_interval
32+
#increment logging count (log_count = log_count +1)
33+
34+
elif start_logging_event.is_set() == False:
35+
# Close SerialPort
36+
# break ,Exit from While loop
37+
38+
39+
40+
41+
start_logging_event set by def start_log_btn_handler(): of start_log_btn
42+
start_logging_event cleared by def stop_log_btn_handler(): of stop_log_btn
43+
44+
'''
45+
46+
#GUI Library Imports for Tkinter and ttkbootsrap
447
from tkinter import *
548
import ttkbootstrap as ttkb
649
from ttkbootstrap.dialogs import Messagebox
750
from ttkbootstrap.scrolled import ScrolledText
851
import tkinter as tk
952

1053

11-
import serial
12-
import threading
13-
import time
14-
import csv
15-
import webbrowser
16-
import os
54+
import serial # for serial communication
55+
import threading # for creating threads
56+
import time # for delays and getting timestamps for data logging
57+
import csv # creating CSV files
58+
import webbrowser # for opening tutorial webpage using button in a web browser
59+
import os # for getting current working directory
1760

1861

19-
baud_rate = 0
20-
21-
csv_delimiter = ','
22-
log_int = 0
62+
baud_rate = 0
63+
csv_delimiter = ',' # changing this would change the delimiter in CSV file Eg : ; |
64+
log_int = 0 # logging interval global value
2365

2466

2567
#create Dropdown options
26-
baudrates = [0,600,1200,2400,4800,9600,19200,38400]
27-
log_interval = [0,0.5,1,1.5,2,2.5,3,4,5,10,20,30,60,120]
68+
baudrates = [0,600,1200,2400,4800,9600,19200,38400] # dropdown for standard baudrates
69+
log_interval = [0,0.5,1,1.5,2,2.5,3,4,5,10,20,30,60,120] # dropdown for logging interval in seconds,0 means maximum speed
70+
2871

2972
tutorial_text = ''' Tutorial
3073
@@ -38,35 +81,49 @@
3881
3982
Data saved in disk\n'''
4083

84+
85+
#All Action takes place here
86+
#function to read data from arduino,create csv file,process button options
87+
#function runs inside thread t1
88+
4189
def acquire_arduino_data(serialport_name,baud_rate,logging_interval):
4290

4391
serialport_obj = None #declared here so accessible inside and outside try/catch
4492
log_count = 1
4593

46-
47-
94+
4895
#Create the Serial port object
4996
try:
5097
serialport_obj = serial.Serial(serialport_name,baud_rate) #open the serial port
98+
5199
text_log.insert(END,f'{serialport_name} selected,at {baud_rate} ,\n')
52100
text_log.insert(END,f'Logging Interval = {logging_interval} seconds,\n')
53101
text_log.insert(END,f'Wait for Arduino to Reset,\n')
102+
54103
time.sleep(2) #Some time for Arduino board to reset
104+
55105
text_log.insert(END,f'Arduino Ready Now ,\n\n')
56106

57107
except serial.SerialException as var : #In case of error
108+
58109
text_log.insert(END,f'{var} ,\n')
59110

60-
log_file_name = create_filename_current_date_time()
61111

112+
113+
log_file_name = create_filename_current_date_time() # create a file name using current date and time
114+
# Eg ard_11_March_2024_07h_29m_00s_daq_log.csv
62115

63116

117+
#create CSV header to write once into the created file
118+
64119
csv_header =['No','Date','Time','Unix Time','Humidity','Soil Moisture','Temperature','Light Intensity']
65120

121+
# write csv header into the createdfile
66122
with open(log_file_name,'a',newline ='') as File_obj:
67123
csvwriter_obj = csv.writer(File_obj, delimiter = csv_delimiter)
68124
csvwriter_obj.writerow(csv_header)
69-
125+
126+
#Write info into scrolled text box
70127
text_log.insert(END,f'Log file -> {log_file_name}\n\n')
71128
text_log.insert(END,f'Starting Logging @{logging_interval} interval\n\n')
72129
text_log.insert(END,f'{csv_header}\n')
@@ -75,59 +132,84 @@ def acquire_arduino_data(serialport_name,baud_rate,logging_interval):
75132
csv_filename_loc.insert(END,f'{log_file_name}\n')
76133

77134

135+
#infinite loop,that constantly checks for (start_logging_event) status set or clear
136+
#(start_logging_event) controlled by buttons
78137
while True:
79138

80-
#print(start_logging_event.is_set())
139+
81140
if start_logging_event.is_set() == True:
82141

83-
arduino_sensor_data_list = read_arduino_sensors(serialport_obj)
84-
#print(arduino_sensor_data_list)
85-
unix_timestamp = int(time.time()) #get current unix time to time stamp data
142+
arduino_sensor_data_list = read_arduino_sensors(serialport_obj) #communicate with arduino and get data
143+
144+
unix_timestamp = int(time.time()) #get current unix time to time stamp data
86145

87146
log_time_date = time.localtime(unix_timestamp) #Convert epoch time to human readable time,date format
88147
log_time = time.strftime("%H:%M:%S",log_time_date) #hh:mm:ss
89148
log_date = time.strftime("%d %B %Y",log_time_date) #dd MonthName Year
90149

91-
150+
#arduino_sensor_data_list[]
151+
#
152+
#arduino_sensor_data_list[0] = humidity_value
153+
#arduino_sensor_data_list[1] = soil_value
154+
#arduino_sensor_data_list[2] = temp_value
155+
#arduino_sensor_data_list[3] = light_value
92156

93157
arduino_sensor_data_list.insert(0,str(log_count))
94158
arduino_sensor_data_list.insert(1,str(log_date))
95159
arduino_sensor_data_list.insert(2,str(log_time))
96160
arduino_sensor_data_list.insert(3,str(unix_timestamp))
97161

162+
#arduino_sensor_data_list[] after insert()
163+
#
164+
#arduino_sensor_data_list[0] = log_count
165+
#arduino_sensor_data_list[1] = log_date
166+
#arduino_sensor_data_list[3] = log_time
167+
#arduino_sensor_data_list[4] = light_value
168+
#arduino_sensor_data_list[5] = unix_timestamp
169+
#arduino_sensor_data_list[6] = soil_value
170+
#arduino_sensor_data_list[7] = temp_value
171+
#arduino_sensor_data_list[8] = light_value
172+
#
173+
#makes it easier to write into CSV file
174+
98175
#print(arduino_sensor_data_list)
176+
99177
text_log.insert(END,f'{arduino_sensor_data_list} ,\n')
100178
text_log.see(tk.END) #for auto scrolling
101179

180+
#write arduino_sensor_data_list to CSV file
181+
102182
with open(log_file_name,'a',newline='') as File_obj:
103183
csvwriter_obj = csv.writer(File_obj, delimiter = csv_delimiter)
104-
csvwriter_obj.writerow(arduino_sensor_data_list)
184+
csvwriter_obj.writerow(arduino_sensor_data_list) # write one row
105185

106-
#print('data acquiring')
107-
log_count = log_count + 1
186+
187+
log_count = log_count + 1 #increment logging count
108188

109189
time.sleep(logging_interval)
110190

111191

112-
elif start_logging_event.is_set() != True:
192+
elif start_logging_event.is_set() == False:
193+
113194
serialport_obj.close()
114195
text_log.insert(END,f'+==================================================+ \n')
115196
text_log.insert(END,f'Logging Ended \n')
116-
break
197+
198+
break # exit from infinite loop
117199

118200

119201

120202

121203

122-
204+
#Function sends and receive data from arduino connected to PC
123205
def read_arduino_sensors(serialport_obj):
124206

125207
return_list =[0,0,0,0]
126208

127209
polling_interval = 0.010 #In seconds,to give time for arduino to respond
128210

129-
serialport_obj.write(b'@')
130-
time.sleep(polling_interval)
211+
serialport_obj.write(b'@') #Send @ to Arduino to get humidity value
212+
time.sleep(polling_interval) #wait some time,to give arduino to respond
131213
humidity_value = serialport_obj.readline()
132214
humidity_value = humidity_value.strip()
133215

@@ -148,11 +230,18 @@ def read_arduino_sensors(serialport_obj):
148230

149231
#print(humidity_value,soil_value,temp_value,light_value)
150232

151-
return_list[0] = humidity_value.decode()
233+
return_list[0] = humidity_value.decode() #.decode is used to remove the byte 'b',convert to string
152234
return_list[1] = soil_value.decode()
153235
return_list[2] = temp_value.decode()
154236
return_list[3] = light_value.decode()
155237

238+
#return_list[]
239+
#
240+
#return_list[0] = humidity_value
241+
#return_list[1] = soil_value
242+
#return_list[2] = temp_value
243+
#return_list[3] = light_value
244+
156245
return return_list
157246

158247
def create_filename_current_date_time():
@@ -164,6 +253,8 @@ def create_filename_current_date_time():
164253
return filename
165254

166255

256+
#========================== Button Handlers ================================#
257+
167258
def tutorial_btn_handler():
168259
webbrowser.open_new(r'https://www.xanthium.in/multithreading-serial-port-data-acquisition-to-csv-file-using-producer-consumer-pattern-python')
169260

@@ -180,6 +271,7 @@ def stop_log_btn_handler():
180271
start_logging_event.clear()
181272

182273

274+
#========================== Drop Down Menu Handlers ================================#
183275

184276
def on_select_option_bind_baudrates(e):
185277
global baud_rate
@@ -189,14 +281,14 @@ def on_select_option_bind_baudrates(e):
189281
def on_select_option_bind_log_interval(e):
190282
global log_int
191283
log_int = float(log_interval_combo_box.get())
192-
print(log_int)
284+
#print(log_int)
193285

194286

195287

196-
197-
start_logging_event = threading.Event()
288+
start_logging_event = threading.Event() #Event Creation
289+
290+
#============================== Main Window Creation=======================================#
198291

199-
# Main Window Creation
200292
root = ttkb.Window(themename = 'superhero') # theme = superhero
201293
root.title('SerialPort Datalogging to CSV file')
202294
root.geometry('650x660') # Width X Height

0 commit comments

Comments
 (0)