Skip to content

Commit a967db1

Browse files
committed
bricks/ev3/modules: Split off DC motor control.
We'll also be using this for the IR Control app.
1 parent 22e765d commit a967db1

8 files changed

Lines changed: 146 additions & 126 deletions

File tree

bricks/_common/micropython.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -306,7 +306,7 @@ pbio_error_t pbsys_main_program_validate(pbsys_main_program_t *program) {
306306
return PBIO_SUCCESS;
307307
#endif
308308
#if PBSYS_CONFIG_FEATURE_BUILTIN_USER_PROGRAM_EV3_APPS
309-
case PBIO_PYBRICKS_USER_PROGRAM_ID_EV3_MOTOR_CONTROL:
309+
case PBIO_PYBRICKS_USER_PROGRAM_ID_EV3_MOTOR_BUTTON_CONTROL:
310310
return PBIO_SUCCESS;
311311
#endif
312312
default:
@@ -400,9 +400,9 @@ void pbsys_main_run_program(pbsys_main_program_t *program) {
400400
#endif
401401

402402
#if PBSYS_CONFIG_FEATURE_BUILTIN_USER_PROGRAM_EV3_APPS
403-
case PBIO_PYBRICKS_USER_PROGRAM_ID_EV3_MOTOR_CONTROL:
403+
case PBIO_PYBRICKS_USER_PROGRAM_ID_EV3_MOTOR_BUTTON_CONTROL:
404404
pb_package_pybricks_init(false);
405-
pyexec_frozen_module("_ev3_motor_control.py", false);
405+
pyexec_frozen_module("_ev3_motor_button_control.py", false);
406406
break;
407407
#endif
408408

bricks/ev3/manifest.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
include("../_common/manifest.py")
2-
freeze_as_mpy("../ev3/modules", "_ev3_motor_control.py")
2+
freeze_as_mpy("../ev3/modules", "_ev3_motor_button_control.py")
3+
freeze_as_mpy("../ev3/modules", "_ev3_motor_dc.py")
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
from pybricks.tools import wait
2+
from pybricks.parameters import ImageFile, Button, Port, Color
3+
from pybricks.hubs import EV3Brick
4+
from pybricks.ev3devices import Motor
5+
6+
from _ev3_motor_dc import motor_set_dc
7+
8+
9+
# True means A&D pair is active. False means B&C pair is active.
10+
pair_ad_active = False
11+
12+
# Power used for all motors if active.
13+
POWER = 100
14+
15+
# Preload to avoid repeated allocation.
16+
IMG_POS = ImageFile._ROTATE_CW18
17+
IMG_NEG = ImageFile._ROTATE_CCW18
18+
IMG_AD = ImageFile._APP_MOTOR_CONTROL_AD
19+
IMG_BC = ImageFile._APP_MOTOR_CONTROL_BC
20+
21+
# UI is one of two prebuilt images from lms2012.
22+
ev3 = EV3Brick()
23+
24+
25+
def draw_ui():
26+
file = IMG_AD if pair_ad_active else IMG_BC
27+
ev3.screen.draw_image(0, 20, file)
28+
ev3.screen.draw_box(0, 0, 177, 16, fill=True, color=Color.WHITE)
29+
30+
31+
draw_ui()
32+
33+
while True:
34+
# Start with light on and motors off.
35+
draw_ui()
36+
ev3.light.on(Color.GREEN)
37+
for m in range(4):
38+
motor_set_dc(m, 0)
39+
40+
# Wait for anything to happen.
41+
while not (pressed := ev3.buttons.pressed()):
42+
wait(10)
43+
44+
# Center button toggles motor pair
45+
if Button.CENTER in pressed:
46+
pair_ad_active = not pair_ad_active
47+
draw_ui()
48+
while any(ev3.buttons.pressed()):
49+
wait(10)
50+
continue
51+
52+
# Determine motor power for horizontal buttons.
53+
dc_x = 0
54+
if Button.RIGHT in pressed:
55+
dc_x += POWER
56+
if Button.LEFT in pressed:
57+
dc_x -= POWER
58+
59+
# Determine motor power for vertical buttons.
60+
dc_y = 0
61+
if Button.UP in pressed:
62+
dc_y += POWER
63+
if Button.DOWN in pressed:
64+
dc_y -= POWER
65+
66+
# Activity heartbeat.
67+
if dc_x or dc_y:
68+
ev3.light.blink(Color.GREEN, [100, 100, 800, 100])
69+
else:
70+
ev3.light.on(Color.GREEN)
71+
72+
# Drive one or two motors.
73+
output = [0, 0, 0, 0]
74+
index_x = 3 if pair_ad_active else 2
75+
index_y = 0 if pair_ad_active else 1
76+
output[index_x] = motor_set_dc(index_x, dc_x)
77+
output[index_y] = motor_set_dc(index_y, dc_y)
78+
79+
# Draw output indicators if active.
80+
for m in range(len(output)):
81+
if output[m]:
82+
ev3.screen.draw_image(20 + m * 40, 2, IMG_POS if output[m] > 0 else IMG_NEG)
83+
84+
# Keep going until button state changes.
85+
while ev3.buttons.pressed() == pressed:
86+
wait(10)

bricks/ev3/modules/_ev3_motor_control.py

Lines changed: 0 additions & 113 deletions
This file was deleted.
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
from pybricks.ev3devices import Motor
2+
from pybricks.parameters import Port
3+
4+
5+
motors = [None, None, None, None]
6+
ports = [Port.A, Port.B, Port.C, Port.D]
7+
8+
9+
def motor_set_dc(index: int, dc: int):
10+
"""Sets the DC value of a motor if it is plugged in.
11+
12+
Returns the given DC value if a nonzero value was set, else 0.
13+
"""
14+
15+
# If there was a motor, close if it got unplugged.
16+
if motors[index] is not None:
17+
try:
18+
motors[index].angle()
19+
except OSError:
20+
motors[index].close()
21+
motors[index] = None
22+
pass
23+
24+
# If there isn't a motor, try to initialize it now.
25+
if motors[index] is None:
26+
try:
27+
motors[index] = Motor(ports[index])
28+
except OSError:
29+
pass
30+
31+
# Drive the motor if there is one.
32+
if motors[index]:
33+
try:
34+
if dc:
35+
motors[index].dc(dc)
36+
return dc
37+
else:
38+
motors[index].stop()
39+
except OSError:
40+
motors[index].close()
41+
motors[index] = None
42+
43+
return 0

bricks/virtualhub/manifest.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
include("../_common/manifest.py")
2-
freeze_as_mpy("../ev3/modules", "_ev3_motor_control.py")
2+
freeze_as_mpy("../ev3/modules", "_ev3_motor_button_control.py")
3+
freeze_as_mpy("../ev3/modules", "_ev3_motor_dc.py")

lib/pbio/include/pbio/protocol.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ typedef enum {
7272
/**
7373
* Program to control EV3 motors with the buttons.
7474
*/
75-
PBIO_PYBRICKS_USER_PROGRAM_ID_EV3_MOTOR_CONTROL = 133,
75+
PBIO_PYBRICKS_USER_PROGRAM_ID_EV3_MOTOR_BUTTON_CONTROL = 133,
7676
} pbio_pybricks_user_program_id_t;
7777

7878
/**

lib/pbio/sys/hmi_ev3_ui.c

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ static pbsys_hmi_ev3_ui_t state;
8484
* Available apps on app tab.
8585
*/
8686
static const char *apps[] = {
87-
" Motor Control",
87+
" Motor Button Control",
8888
};
8989

9090
/**
@@ -279,13 +279,15 @@ pbsys_hmi_ev3_ui_action_t pbsys_hmi_ev3_ui_handle_button(pbio_button_flags_t but
279279
*payload = state.selection[PBSYS_HMI_EV3_UI_TAB_PROGRAMS];
280280
return PBSYS_HMI_EV3_UI_ACTION_RUN_PROGRAM;
281281
} else if (state.tab == PBSYS_HMI_EV3_UI_TAB_APPS) {
282-
if (state.selection[PBSYS_HMI_EV3_UI_TAB_APPS] == 0) {
283-
*payload = PBIO_PYBRICKS_USER_PROGRAM_ID_EV3_MOTOR_CONTROL;
284-
return PBSYS_HMI_EV3_UI_ACTION_RUN_PROGRAM;
282+
switch (state.selection[PBSYS_HMI_EV3_UI_TAB_APPS]) {
283+
case 0:
284+
*payload = PBIO_PYBRICKS_USER_PROGRAM_ID_EV3_MOTOR_BUTTON_CONTROL;
285+
return PBSYS_HMI_EV3_UI_ACTION_RUN_PROGRAM;
286+
default:
287+
// Other apps not yet implemented.
288+
state.overlay = PBSYS_HMI_EV3_UI_OVERLAY_COMING_SOON;
289+
return PBSYS_HMI_EV3_UI_ACTION_NONE;
285290
}
286-
// Other apps not yet implemented.
287-
state.overlay = PBSYS_HMI_EV3_UI_OVERLAY_COMING_SOON;
288-
return PBSYS_HMI_EV3_UI_ACTION_NONE;
289291
} else {
290292
// Settings don't currently do anything, just displays info.
291293
return PBSYS_HMI_EV3_UI_ACTION_NONE;

0 commit comments

Comments
 (0)