-
-
Notifications
You must be signed in to change notification settings - Fork 94
Expand file tree
/
Copy path_ev3_port_view.py
More file actions
325 lines (296 loc) · 11.1 KB
/
_ev3_port_view.py
File metadata and controls
325 lines (296 loc) · 11.1 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
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
from pybricks.hubs import EV3Brick
from pybricks.ev3devices import (
Motor,
ColorSensor as EV3ColorSensor,
TouchSensor as EV3TouchSensor,
GyroSensor,
UltrasonicSensor as EV3UltrasonicSensor,
InfraredSensor,
)
from pybricks.nxtdevices import (
ColorSensor as NXTColorSensor,
LightSensor,
SoundSensor,
UltrasonicSensor as NXTUltrasonicSensor,
)
from pybricks.parameters import Button, Port, ImageFile
from pybricks.tools import wait
# Load and decompress images once.
IMG_EV3_COLOR_AMBIENT = ImageFile._PORT_VIEW_EV3_COLOR_AMBIENT
IMG_EV3_COLOR_COLOR = ImageFile._PORT_VIEW_EV3_COLOR_COLOR
IMG_EV3_COLOR_REFLECTION = ImageFile._PORT_VIEW_EV3_COLOR_REFLECTION
IMG_EV3_GYRO = ImageFile._PORT_VIEW_EV3_GYRO
IMG_EV3_IR_BEACON = ImageFile._PORT_VIEW_EV3_IR_BEACON
IMG_EV3_IR_BUTTON = ImageFile._PORT_VIEW_EV3_IR_BUTTON
IMG_EV3_IR_PROXIMITY = ImageFile._PORT_VIEW_EV3_IR_PROXIMITY
IMG_EV3_MOTOR_LARGE = ImageFile._PORT_VIEW_EV3_MOTOR_LARGE
IMG_EV3_MOTOR_MEDIUM = ImageFile._PORT_VIEW_EV3_MOTOR_MEDIUM
IMG_EV3_TOUCH = ImageFile._PORT_VIEW_EV3_TOUCH
IMG_EV3_ULTRASONIC = ImageFile._PORT_VIEW_EV3_ULTRASONIC
IMG_NXT_COLOR_AMBIENT = ImageFile._PORT_VIEW_NXT_COLOR_AMBIENT
IMG_NXT_COLOR_COLOR = ImageFile._PORT_VIEW_NXT_COLOR_COLOR
IMG_NXT_COLOR_REFLECTION = ImageFile._PORT_VIEW_NXT_COLOR_REFLECTION
IMG_NXT_LIGHT_AMBIENT = ImageFile._PORT_VIEW_NXT_LIGHT_AMBIENT
IMG_NXT_LIGHT_REFLECTION = ImageFile._PORT_VIEW_NXT_LIGHT_REFLECTION
IMG_NXT_SOUND = ImageFile._PORT_VIEW_NXT_SOUND
IMG_NXT_ULTRASONIC = ImageFile._PORT_VIEW_NXT_ULTRASONIC
PORT_NONE_TOP = ImageFile._PORT_VIEW_P0_TOP
PORT_NONE_BOTTOM = ImageFile._PORT_VIEW_P0_BOTTOM
PORT_IMG = [
ImageFile._PORT_VIEW_PA,
ImageFile._PORT_VIEW_PB,
ImageFile._PORT_VIEW_PC,
ImageFile._PORT_VIEW_PD,
ImageFile._PORT_VIEW_P1,
ImageFile._PORT_VIEW_P2,
ImageFile._PORT_VIEW_P3,
ImageFile._PORT_VIEW_P4,
]
# Initialize brick for display and buttons.
ev3 = EV3Brick()
# We navigate through the ports with directional buttons.
# Center button increments (and wraps) mode.
PORTS = [Port.A, Port.B, Port.C, Port.D, Port.S1, Port.S2, Port.S3, Port.S4]
modes = [0] * len(PORTS)
selected = 0
# Generator that repeatedly tests which device is plugged in, reading
# values until it is unplugged, then trying again.
def port_process(index):
while True:
# Reset mode on plugged in.
modes[index] = 0
# Large and Medium Motor
try:
motor = Motor(PORTS[index], reset_angle=False)
image = (
IMG_EV3_MOTOR_LARGE
if motor.control.pid()[0] > 12000
else IMG_EV3_MOTOR_MEDIUM
)
while True:
try:
short = motor.angle()
detail = str(short) + " deg"
yield image, short, detail
except OSError:
motor.close()
break
except OSError:
pass
# EV3 Touch Sensor
try:
sensor = EV3TouchSensor(PORTS[index])
while True:
try:
pressed = sensor.pressed()
detail = "pressed" if pressed else "released"
yield IMG_EV3_TOUCH, pressed, detail
except OSError:
break
except OSError:
pass
# EV3 Ultrasonic Sensor
try:
sensor = EV3UltrasonicSensor(PORTS[index])
while True:
try:
distance = sensor.distance()
detail = f"{distance:>4} mm"
yield IMG_EV3_ULTRASONIC, distance, detail
except OSError:
break
except OSError:
pass
# EV3 Color Sensor
try:
sensor = EV3ColorSensor(PORTS[index])
while True:
try:
mode = modes[index] % 3
if mode == 2:
detail = str(sensor.color())[6:].lower()
short = detail[0:3]
image = IMG_EV3_COLOR_COLOR
else:
image = (
IMG_EV3_COLOR_AMBIENT if mode else IMG_EV3_COLOR_REFLECTION
)
short = sensor.ambient() if mode else sensor.reflection()
detail = f"{short:>3} %"
yield image, short, detail
except OSError:
break
except OSError:
pass
# EV3 Infrared Sensor
try:
sensor = InfraredSensor(PORTS[index])
while True:
try:
mode = modes[index] % 3
if mode == 0:
short = sensor.distance()
detail = f"{short:>3} %"
image = IMG_EV3_IR_PROXIMITY
elif mode == 1:
image = IMG_EV3_IR_BUTTON
pressed = [str(b)[7:] for b in sensor.buttons(1)]
short = len(pressed)
if len(pressed) == 1:
detail = pressed[0]
elif len(pressed) == 2:
detail = pressed[0] + "\n" + pressed[1]
else:
detail = "Channel 1\nNo buttons"
else:
image = IMG_EV3_IR_BEACON
distance, angle = sensor.beacon(1)
if distance is None or angle is None:
short = "Non"
detail = "Channel 1\nNo beacon"
else:
short = distance or 0
detail = f"{distance} %\n{angle} deg"
yield image, short, detail
except OSError:
break
except OSError:
pass
# EV3 Gyro Sensor
try:
gyro = GyroSensor(PORTS[index])
while True:
try:
short = gyro.angle()
detail = f"{short:>4} deg\n{gyro.speed():>4} deg/s"
yield IMG_EV3_GYRO, short, detail
except OSError:
break
except OSError:
pass
# NXT Color Sensor
try:
sensor = NXTColorSensor(PORTS[index])
while True:
try:
mode = modes[index] % 3
if mode == 2:
detail = str(sensor.color())[6:].lower()
short = detail[0:3]
image = IMG_NXT_COLOR_COLOR
else:
image = (
IMG_NXT_COLOR_AMBIENT if mode else IMG_NXT_COLOR_REFLECTION
)
value = sensor.ambient() if mode else sensor.reflection()
detail = f"{value:>5.1f} %"
yield image, round(value), detail
except OSError:
break
except OSError:
pass
# NXT Light Sensor
try:
sensor = LightSensor(PORTS[index])
while True:
try:
ambient = modes[index] % 2
image = (
IMG_NXT_LIGHT_AMBIENT if ambient else IMG_NXT_LIGHT_REFLECTION
)
value = sensor.ambient() if ambient else sensor.reflection()
detail = f"{value:>5.1f} %"
yield image, round(value), detail
except OSError:
break
except OSError:
pass
# NXT Sound Sensor
try:
sensor = SoundSensor(PORTS[index])
while True:
try:
value = sensor.intensity()
detail = f"{value:>5.1f} %"
yield IMG_NXT_SOUND, round(value), detail
except OSError:
break
except OSError:
pass
# NXT Ultrasonic Sensor
try:
sensor = NXTUltrasonicSensor(PORTS[index])
while True:
try:
distance = sensor.distance()
detail = f"{distance:>4} mm"
yield IMG_NXT_ULTRASONIC, distance, detail
except OSError:
break
except OSError:
pass
# Nothing on this port.
yield None, "---", "No device"
# Each port has its own process that we draw values from.
processes = [port_process(i) for i in range(len(PORTS))]
def draw_ui():
# Draw main boxes.
ev3.screen.clear()
ev3.screen.draw_image(0, 7, PORT_IMG[selected] if selected <= 3 else PORT_NONE_TOP)
ev3.screen.draw_image(0, 33, ImageFile._PORT_VIEW_EMPTY)
ev3.screen.draw_image(
0, 92, PORT_IMG[selected] if selected > 3 else PORT_NONE_BOTTOM
)
ev3.screen.draw_line(50, 42, 50, 82)
# Draw all port states.
for i in range(len(PORTS)):
# Get the state of this port.
image, value, detail = next(processes[i])
if i == selected:
# For selection, show main image and larger value.
if image:
ev3.screen.draw_image(4, 40, image)
y = 45 if "\n" in detail or "%" in detail else 55
ev3.screen.draw_text(60, y, text=detail)
if "%" in detail and "\n" not in detail:
ev3.screen.draw_box(60, 65, 160, 75)
ev3.screen.draw_box(60, 65, 60 + value, 75, fill=True)
else:
# Otherwise show value only.
x = 15 + (i % 4) * 40
y = 11 if i <= 3 else 100
# Move integers slightly right and add optional short minus.
if isinstance(value, int):
x += 3
if value < 0:
ev3.screen.draw_line(x - 5, y + 7, x - 2, y + 7)
value = -value
if value > 999:
value = 999
elif isinstance(value, str):
value = value[0:3]
if isinstance(value, bool):
# Visualize bool as empty or filled box
ev3.screen.draw_box(x + 7, y + 1, x + 17, y + 11, fill=value)
else:
# Else draw text value in the small box.
ev3.screen.draw_text(x, y, text=str(value))
# Monitor the buttons to change ports, refreshing the
# screen while we wait.
while True:
while not (pressed := ev3.buttons.pressed()):
draw_ui()
wait(100)
if Button.LEFT in pressed:
selected = (selected - 1) % len(PORTS)
elif Button.RIGHT in pressed:
selected = (selected + 1) % len(PORTS)
elif Button.UP in pressed and selected > 3:
selected -= 4
elif Button.DOWN in pressed and selected <= 3:
selected += 4
elif Button.CENTER in pressed:
modes[selected] += 1
while any(ev3.buttons.pressed()):
draw_ui()
wait(100)