Skip to content

Commit ca467a2

Browse files
committed
improved python example + added reading_from_computer_python_row_by_row.ino
1 parent ec4195f commit ca467a2

5 files changed

Lines changed: 334 additions & 13 deletions

File tree

examples/reading_from_computer_python/arduino_serial.py

Lines changed: 49 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,18 @@
88
python arduino_serial.py --csv hurricanes.csv
99
python arduino_serial.py --csv hurricanes.csv --baudrate 115200
1010
python arduino_serial.py --csv ../path_to_some_other_csv/data.csv --baudrate 9600
11+
python arduino_serial.py --csv ../path_to_some_other_csv/data.csv --baudrate 9600 --substring ch340
12+
python arduino_serial.py --csv ../path_to_some_other_csv/data.csv --baudrate 9600 --substring arduino
13+
python arduino_serial.py --csv ../path_to_some_other_csv/data.csv --baudrate 9600 --substring ch340 --timeout 5
1114
1215
The sript requires "pyserial" library to be installed,
1316
it can be installed through pip:
1417
python -m pip install pyserial
18+
19+
We can view connected USB communication devices with:
20+
python -m serial.tools.list_ports -v
21+
22+
(that's how we know what substring we can use to find Arduino/ESP port)
1523
'''
1624

1725
import serial # pip install pyserial
@@ -37,18 +45,37 @@
3745
help = 'What BAUD rate (communication speed) to use. This must match "Serial.begin(<BAUD>);" in Arduino code (e.g. 9600, 115200).'
3846
)
3947

48+
parser.add_argument(
49+
'--substring',
50+
default = 'arduino',
51+
type = str,
52+
required = False,
53+
help = 'String to match in USB device description. This is used to find Arduino/ESP port.'
54+
)
55+
56+
parser.add_argument(
57+
'--timeout',
58+
type = int,
59+
default = 3,
60+
required = False,
61+
metavar = '',
62+
help = 'How many seconds to wait for a response from Arduino before exiting.'
63+
)
64+
65+
print('Parsing arguments')
4066
args = parser.parse_args()
4167

68+
print('Reading CSV file')
4269
with open(args.csv.name, 'rb') as f:
4370
csv_bytes = f.read()
4471

4572
arduino_ports = []
46-
print('All ports:')
73+
# print('All ports:')
4774
for i, p in enumerate(list_ports.comports()):
48-
print(f'{i+1}. device={p.device} name={p.name} description={p.description} manufacturer={p.manufacturer}')
75+
# print(f'{i+1}. device={p.device} name={p.name} description={p.description} manufacturer={p.manufacturer}')
4976
# for k,v in vars(p).items():
5077
# print(k,v)
51-
if "arduino" in str(p).lower():
78+
if args.substring in str(p).lower():
5279
arduino_ports.append(p)
5380

5481
print()
@@ -72,19 +99,35 @@
7299
s = serial.Serial()
73100
s.baudrate = 115200
74101
s.port = port
102+
# set other port parameters
103+
# s.bytesize = serial.EIGHTBITS #number of bits per bytes
104+
# s.parity = serial.PARITY_NONE #set parity check: no parity
105+
# s.stopbits = serial.STOPBITS_ONE #number of stop bits
106+
75107
s.open()
76108

77109
s.write(csv_bytes)
78110
s.flush()
79111

112+
start_time = time.time()
113+
80114
try:
81-
while True:
115+
while time.time() - start_time < args.timeout:
82116
time.sleep(0.01)
83117
if s.in_waiting: # Or: while ser.inWaiting():
84-
in_str = ""
118+
# in_str = ""
119+
in_bytes = bytes()
85120
while s.in_waiting:
86-
in_str += s.read().decode('utf-8')
121+
try:
122+
c = s.read()
123+
# print('char = ', c)
124+
in_bytes += c
125+
# in_str += s.read().decode('ascii') #.decode('utf-8')
126+
except Exception as e:
127+
print(f'EXCEPTION: {e}')
128+
87129
print('Received:')
130+
in_str = in_bytes.decode('utf-8', errors='replace')
88131
print(in_str)
89132
if in_str.endswith('end'):
90133
exit()

examples/reading_from_computer_python/reading_from_computer_python.ino

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -60,17 +60,32 @@ Note: I suggest to close Serial Monitor window (if it's open) before running the
6060
otherwise the port may be busy.
6161
*/
6262

63+
int read_serial(char *dst, int timeout, bool blocking) {
64+
int recv_count = 0;
65+
if (blocking) {
66+
while(!Serial.available()) {}
67+
}
68+
unsigned long last_char_time = millis();
69+
while(millis() - last_char_time < timeout) {
70+
if(Serial.available()) {
71+
dst[recv_count++] = Serial.read();
72+
last_char_time = millis();
73+
}
74+
}
75+
dst[recv_count] = '\0';
76+
return recv_count;
77+
}
78+
6379
void setup() {
6480
Serial.begin(115200);
65-
CSV_Parser cp(/*format*/ "sfccccccccccc");
81+
// CSV_Parser cp(/*format*/ "sfccccccccccc");
82+
CSV_Parser cp(/*format*/ "sf-----------");
6683

67-
// wait for python script to start sending the csv file
68-
while(!Serial.available()) {}
84+
char buffer[400];
6985

70-
// receive the file and pass it to CSV_Parser object
71-
while(Serial.available()) {
72-
cp << Serial.read();
73-
}
86+
int count = read_serial(buffer, 1000, /*blocking*/ true); // wait for the python script to send the file
87+
88+
cp << buffer;
7489

7590
cp.parseLeftover(); // just in case if the csv file doesn't end with "\n"
7691

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
'''
2+
This script opens the port associated with Arduino,
3+
writes to it, reads response, and terminates once it receives
4+
the "end" message.
5+
6+
Usage examples:
7+
python arduino_serial.py --help
8+
python arduino_serial.py --csv hurricanes.csv
9+
python arduino_serial.py --csv hurricanes.csv --baudrate 115200
10+
python arduino_serial.py --csv ../path_to_some_other_csv/data.csv --baudrate 9600
11+
python arduino_serial.py --csv ../path_to_some_other_csv/data.csv --baudrate 9600 --substring ch340
12+
python arduino_serial.py --csv ../path_to_some_other_csv/data.csv --baudrate 9600 --substring arduino
13+
python arduino_serial.py --csv ../path_to_some_other_csv/data.csv --baudrate 9600 --substring ch340 --timeout 5
14+
15+
The sript requires "pyserial" library to be installed,
16+
it can be installed through pip:
17+
python -m pip install pyserial
18+
19+
We can view connected USB communication devices with:
20+
python -m serial.tools.list_ports -v
21+
22+
(that's how we know what substring we can use to find Arduino/ESP port)
23+
'''
24+
25+
import serial # pip install pyserial
26+
import serial.tools.list_ports as list_ports
27+
import time
28+
import argparse
29+
30+
parser = argparse.ArgumentParser()
31+
parser.add_argument(
32+
'--csv',
33+
metavar = '',
34+
required = True,
35+
type = argparse.FileType(mode='r'),
36+
help = 'CSV file to send through serial'
37+
)
38+
39+
parser.add_argument(
40+
'--baudrate',
41+
type = int,
42+
default = 115200,
43+
required = False,
44+
metavar = '',
45+
help = 'What BAUD rate (communication speed) to use. This must match "Serial.begin(<BAUD>);" in Arduino code (e.g. 9600, 115200).'
46+
)
47+
48+
parser.add_argument(
49+
'--substring',
50+
default = 'arduino',
51+
type = str,
52+
required = False,
53+
help = 'String to match in USB device description. This is used to find Arduino/ESP port.'
54+
)
55+
56+
parser.add_argument(
57+
'--timeout',
58+
type = int,
59+
default = 3,
60+
required = False,
61+
metavar = '',
62+
help = 'How many seconds to wait for a response from Arduino before exiting.'
63+
)
64+
65+
print('Parsing arguments')
66+
args = parser.parse_args()
67+
68+
print('Reading CSV file')
69+
with open(args.csv.name, 'rb') as f:
70+
csv_bytes = f.read()
71+
72+
arduino_ports = []
73+
# print('All ports:')
74+
for i, p in enumerate(list_ports.comports()):
75+
# print(f'{i+1}. device={p.device} name={p.name} description={p.description} manufacturer={p.manufacturer}')
76+
# for k,v in vars(p).items():
77+
# print(k,v)
78+
if args.substring in str(p).lower():
79+
arduino_ports.append(p)
80+
81+
print()
82+
83+
if not arduino_ports:
84+
raise Exception('Arduino port was not found')
85+
86+
if len(arduino_ports) > 1:
87+
print('Multiple arduino ports were found:')
88+
for i, p in enumerate(arduino_ports):
89+
print(f' {i+1}. device={p.device} name={p.name} description={p.description} manufacturer={p.manufacturer}')
90+
91+
i = int(input('\nSelect the port to use\n> '))
92+
port = arduino_ports[i-1].device
93+
else:
94+
print('A single arduino port was found and will be used')
95+
print(arduino_ports[0])
96+
port = arduino_ports[0].device
97+
98+
99+
s = serial.Serial()
100+
s.baudrate = 115200
101+
s.port = port
102+
# set other port parameters
103+
# s.bytesize = serial.EIGHTBITS #number of bits per bytes
104+
# s.parity = serial.PARITY_NONE #set parity check: no parity
105+
# s.stopbits = serial.STOPBITS_ONE #number of stop bits
106+
107+
s.open()
108+
109+
s.write(csv_bytes)
110+
s.flush()
111+
112+
start_time = time.time()
113+
114+
try:
115+
while time.time() - start_time < args.timeout:
116+
time.sleep(0.01)
117+
if s.in_waiting: # Or: while ser.inWaiting():
118+
# in_str = ""
119+
in_bytes = bytes()
120+
while s.in_waiting:
121+
try:
122+
c = s.read()
123+
# print('char = ', c)
124+
in_bytes += c
125+
# in_str += s.read().decode('ascii') #.decode('utf-8')
126+
except Exception as e:
127+
print(f'EXCEPTION: {e}')
128+
129+
print('Received:')
130+
in_str = in_bytes.decode('utf-8', errors='replace')
131+
print(in_str)
132+
if in_str.endswith('end'):
133+
exit()
134+
finally:
135+
print('Closing port')
136+
s.close()
137+
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
Month,Average,2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015
2+
May,0.1,0,0,1,1,0,0,0,2,0,0,0
3+
Jun,0.5,2,1,1,0,0,1,1,2,2,0,1
4+
Jul,0.7,5,1,1,2,0,1,3,0,2,2,1
5+
Aug,2.3,6,3,2,4,4,4,7,8,2,2,3
6+
Sep,3.5,6,4,7,4,2,8,5,2,5,2,5
7+
Oct,2.0,8,0,1,3,2,5,1,5,2,3,0
8+
Nov,0.5,3,0,0,1,1,0,1,0,1,0,1
9+
Dec,0.0,1,0,1,0,0,0,0,0,0,0,1
10+

0 commit comments

Comments
 (0)