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
|
#!/usr/bin/env python
from __future__ import print_function
import serial
import serial.tools.list_ports
import os.path
import argparse
from time import sleep
pyserial_version = None
try:
pyserial_version = int(serial.VERSION[0])
except:
pyserial_version = 2 # less than 2.3
parser = argparse.ArgumentParser(description='Reset an Arduino')
parser.add_argument('--zero', action='store_true', help='Reset Arduino Zero or similar Native USB to enter bootloader')
parser.add_argument('--caterina', action='store_true', help='Reset a Leonardo, Micro, Robot or LilyPadUSB.')
parser.add_argument('--verbose', action='store_true', help="Watch what's going on on STDERR.")
parser.add_argument('--period', default=0.1, help='Specify the DTR pulse width in seconds.')
parser.add_argument('port', nargs=1, help='Serial device e.g. /dev/ttyACM0')
args = parser.parse_args()
def list_ports(output=False):
""" Lists serial ports attached
:returns
A list of paths to serial ports on system
"""
ports = serial.tools.list_ports.comports()
connected = [port[0] for port in ports]
if output:
print(connected)
return connected
def new_port(old, new):
""" Checks if a new port has attached
Args:
old: previous list of ports to check
new: current list of ports to check
Returns:
index of port in 'new' if new port found, otherwise -1
"""
new_port = -1
for port in new:
if port not in old:
new_port = new.index(port)
break
return new_port
if args.zero:
# number of trys to attempt
zero_attempts = 20 # ~2 seconds
initial_ports = list_ports(args.verbose)
if args.verbose:
print('Attempting to enter bootloader using 1200 bps open/close on port %s' % args.port[0])
ser = serial.Serial(args.port[0], 57600)
ser.close()
if pyserial_version < 3:
ser.setBaudrate(1200)
else:
ser.baudrate = 1200
# do the open/close at 1200 BAUD
ser.open()
ser.close()
if args.verbose:
print('Done. Waiting for bootloader port to attach...')
# get new list of ports
reset_ports = list_ports(args.verbose)
# wait for new port or port to return
port_index = new_port(initial_ports, reset_ports)
# keep checking until new port appears or timeout
while port_index < 0:
# count down attempts and leave if expired
zero_attempts -= 1
if zero_attempts < 0:
break
sleep(0.1)
# get list of ports after bootloader toggle performed
reset_ports = list_ports(args.verbose)
# if a port drops, set initial ports to reset ports so that
# next attached device will be new port
if (len(reset_ports) < len(initial_ports)):
initial_ports = reset_ports
# check if a new port has attached and return the index if it has
port_index = new_port(initial_ports, reset_ports)
# return the new port if detected, otherwise return passed port
if port_index is -1:
bootloader_port = args.port[0]
else:
bootloader_port = reset_ports[port_index]
# print so that `tail -1` can be piped for bootloader port
print(bootloader_port)
elif args.caterina:
if args.verbose: print('Forcing reset using 1200bps open/close on port %s' % args.port[0])
ser = serial.Serial(args.port[0], 57600)
ser.close()
if pyserial_version < 3:
ser.setBaudrate (1200)
else:
ser.baudrate = 1200
ser.open()
ser.setRTS(True) # RTS line needs to be held high and DTR low
ser.setDTR(False) # (see Arduino IDE source code)
ser.close()
sleep(1)
while not os.path.exists(args.port[0]):
if args.verbose: print('Waiting for %s to come back' % args.port[0])
sleep(1)
if args.verbose: print('%s has come back after reset' % args.port[0])
else:
if args.verbose: print('Setting DTR high on %s for %ss' % (args.port[0],args.period))
ser = serial.Serial(args.port[0], 115200)
ser.setDTR(False)
sleep(args.period)
ser.setDTR(True)
ser.close()
|