-
Notifications
You must be signed in to change notification settings - Fork 7
Expand file tree
/
Copy pathrecord-data.py
More file actions
155 lines (121 loc) · 4.74 KB
/
Copy pathrecord-data.py
File metadata and controls
155 lines (121 loc) · 4.74 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
"""
RECORD ACCELEROMETER MEASUREMENTS FOR ACCELEROMETER CALIBRATION
VIA MAGNETO
Code By: Michael Wrona
Created: 17 Aug 2021
This code reads acceleroemter measurements in G's over a serial connection
and logs them to a tab-delimited text file. It also pauses between each
reading and averages a few measurements.
"""
import os
import math
import pandas
import serial
# global variables
MAX_MEAS = 200 # max number of readings in the session, so that we don't create an infinite loop
AVG_MEAS = 25 # for each reading, take this many measurements and average them
SER_PORT = 'COM4' # serial port the device is connected to
SER_BAUD = 115200 # serial port baud rate
FILENAME = os.path.join(os.getcwd(), 'acceldata.txt') # output file
class SerialPort:
"""Create and read data from a serial port.
Attributes:
read(**kwargs): Read and decode data string from serial port.
"""
def __init__(self, port, baud=9600):
"""Create and read serial data.
Args:
port (str): Serial port name. Example: 'COM4'
baud (int): Serial baud rate, default 9600.
"""
if isinstance(port, str) == False:
raise TypeError('port must be a string.')
if isinstance(baud, int) == False:
raise TypeError('Baud rate must be an integer.')
self.port = port
self.baud = baud
# Initialize serial connection
self.ser = serial.Serial(
self.port, self.baud, timeout=None, xonxoff=False, rtscts=False, dsrdtr=False)
self.ser.flushInput()
self.ser.flushOutput()
def Read(self, clean_end=True) -> str:
"""
Read and decode data string from serial port.
Args:
clean_end (bool): Strip '\\r' and '\\n' characters from string. Common if used Serial.println() Arduino function. Default true
Returns:
(str): utf-8 decoded message.
"""
self.ser.flushInput()
bytesToRead = self.ser.readline()
decodedMsg = bytesToRead.decode('utf-8')
if clean_end == True:
decodedMsg = decodedMsg.rstrip() # Strip extra chars at the end
return decodedMsg
def Close(self) -> None:
"""Close serial connection."""
self.ser.close()
def RecordDataPt(ser: SerialPort) -> tuple:
"""Record data from serial port and return averaged result."""
# do a few readings and average the result
ax = ay = az = 0.0
for _ in range(AVG_MEAS):
# read data
try:
data = ser.Read().split(',')
ax_now = float(data[0])
ay_now = float(data[1])
az_now = float(data[2])
except:
ser.Close()
raise SystemExit("[ERROR]: Error reading serial connection.")
ax += ax_now
ay += ay_now
az += az_now
return (ax / AVG_MEAS, ay / AVG_MEAS, az / AVG_MEAS)
def List2DelimFile(mylist: list, filename: str, delimiter: str = ',', f_mode='a') -> None:
"""Convert list to Pandas dataframe, then save as a text file."""
df = pandas.DataFrame(mylist)
df.to_csv(
filename, # path and filename
sep=delimiter,
mode=f_mode,
header=False, # no col. labels
index=False # no row numbers
)
def main():
ser = SerialPort(SER_PORT, baud=SER_BAUD)
data = [] # data list
print('[INFO]: Place sensor level and stationary on desk.')
input('[INPUT]: Press any key to continue...')
# take measurements
for _ in range(MAX_MEAS):
user = input(
'[INPUT]: Ready for measurement? Type \'m\' to measure or \'q\' to save and quit: ').lower()
if user == 'm':
# record data to list
ax, ay, az = RecordDataPt(ser)
magn = math.sqrt(ax**2 + ay**2 + az**2)
print('[INFO]: Avgd Readings: {:.4f}, {:.4f}, {:.4f} Magnitude: {:.4f}'.format(
ax, ay, az, magn))
data.append([ax, ay, az])
elif user == 'q':
# save, then quit
print('[INFO]: Saving data and exiting...')
List2DelimFile(data, FILENAME, delimiter='\t')
ser.Close()
print('[INFO]: Done!')
return
else:
print('[ERROR]: \'{}\' is an unknown input. Terminating!'.format(user))
List2DelimFile(data, FILENAME, delimiter='\t')
ser.Close()
return
# save once max is reached
print('[WARNING]: Reached max. number of datapoints, saving file...')
List2DelimFile(data, FILENAME, delimiter='\t')
ser.Close()
print('[INFO]: Done!')
if __name__ == '__main__':
main()