I am trying to program an Lego EV3 robot using MicroPython for a robotics demo in 2 days. I have most functionality working except for one main issue. If one of the sensors is triggered (like the Touch Sensor, for example) the robot is supposed to speak. However, if the robot is actively recieving input from the IR Remote (which controls movement) when the sensor is triggered, that movement will continue while the robot is speaking, regardless of what buttons are pressed on the remote. I know this is because the ev3.speaker.say() function is a "blocking call".
I know I need to set up coroutines so the the robot can continue checking for input from the IR remote while it is speaking. I have looked up how to do this, and looked at Legos "Gyro Boy" demo for it, but I still can't get it to work. With this current version of the code, the robot doesnt move at all, even when I press the buttons on the remote, which should make it exit the while loop and do the movement code, but it doesnt for some reason.
I have also tried using multithreading instead of coroutines, but that didn't work either.
If somebody is unfamiliar with the specifics of the EV3 programming, the documentation is a bunch of HTML files that come with the download, so I uploaded a copy of it to my Google Drive. Here is a link to that folder: https://drive.google.com/drive/folders/1m0HGmr_yqeg9nrS03VS4Ddk56q-s_NmG?usp=sharing. I recommend downloading the entire EV3 Python Documentation folder.
Here is my current code:
(I know we are supposed to put the minimum reproducible code, but idk where in here the issue is, so i can't really isolate it to make reproducible code. Also, I don't really have time to worry about that. (I need this working in the morning of the day after tomorrow, and I am working all day tomorrow and am busy this evening, so i have literally a couple hours to figure this out.)
#!/usr/bin/env pybricks-micropython
from ucollections import namedtuple
from pybricks.hubs import EV3Brick
from pybricks.ev3devices import (Motor, TouchSensor, ColorSensor,
InfraredSensor, UltrasonicSensor, GyroSensor)
from pybricks.parameters import Port, Stop, Direction, Button, Color
from pybricks.tools import wait, StopWatch, DataLog
from pybricks.robotics import DriveBase
from pybricks.media.ev3dev import SoundFile, ImageFile
#### Define Robot Hardware and Connections ####
armMotor = Motor(Port.A)
leftMotor = Motor(Port.B)
rightMotor = Motor(Port.C)
touchSensor = TouchSensor(Port.S1)
gyroSensor = GyroSensor(Port.S2)
colorSensor = ColorSensor(Port.S3)
irSensor = InfraredSensor(Port.S4)
#### Define Constants ####
WHEEL_DIAMETER = 30.5 # mm
AXLE_TRACK = 200 # mm
LEG_MOTOR_SPEED = 500 # deg/s
GYRO_INIT_VALUE = gyroSensor.angle()
ARM_MOTOR_SPEED = 600 # deg/s
CAN_USE_COLOR_SENSORS = True
#### Define Objects ####
ev3 = EV3Brick()
# Not currently using the DriveBase
# robotDriveBase = DriveBase(leftMotor, rightMotor, WHEEL_DIAMETER, AXLE_TRACK)
#### Settings / Config ####
ev3.speaker.set_speech_options(None, "m1", 180, 80)
#### Define Functions Here ####
def MotorControlAndActions():
# Remote Control
# ----> COROUTINE IMPLEMENTATION ATTEMPT
while len(irSensor.buttons(1)) == 0 and len(irSensor.buttons(2)) == 0:
yield
if Button.LEFT_UP in irSensor.buttons(1):
leftMotor.run(LEG_MOTOR_SPEED)
elif Button.LEFT_DOWN in irSensor.buttons(1):
leftMotor.run(-LEG_MOTOR_SPEED)
else:
leftMotor.brake()
if Button.RIGHT_UP in irSensor.buttons(1):
rightMotor.run(LEG_MOTOR_SPEED)
elif Button.RIGHT_DOWN in irSensor.buttons(1):
rightMotor.run(-LEG_MOTOR_SPEED)
else:
rightMotor.brake()
# Shooting Control
if Button.LEFT_UP in irSensor.buttons(2):
armMotor.run(ARM_MOTOR_SPEED)
else:
armMotor.brake()
# MAIN NON-COROUTINE FUNCTION
def SensorDetectAndReact():
# Sensor Control
if touchSensor.pressed() == True:
# {
ev3.speaker.say("Yo Dawg! I grabbed somethin... I wonder what it is? Alas, I ain't got no way of figuring dat out...")
# }
elif colorSensor.ambient() > 30:
ev3.speaker.say("YO! Its too bright in here! Turn the lights down, please?")
elif colorSensor.ambient() == 0:
ev3.speaker.say("Hey... I can't see. Can somebody turn a light on? I'm too short...")
elif CAN_USE_COLOR_SENSORS == True:
if colorSensor.color() == Color.RED:
ev3.speaker.say("AHH! There's something red on my shoulder! Get It Off!")
elif colorSensor.color() == Color.BLUE:
ev3.speaker.say("Coooool dude. I got somethin blue on me.")
elif colorSensor.color() == Color.WHITE:
ev3.speaker.say("Some white stuff has fallen on my shoulder. Does it feel frosty in here or is it just me?")
elif colorSensor.color() == Color.BROWN:
ev3.speaker.say("HEY! Who put this brown")
ev3.speaker.beep()
ev3.speaker.say("on my shoulder! That's nasty!")
elif colorSensor.color() == Color.YELLOW:
ev3.speaker.say("I sense something yellow. Reminds me of sunny days...")
elif colorSensor.color() == Color.GREEN:
ev3.speaker.say("GREEN MEANS GO!")
# robotDriveBase.straight(100)
ev3.speaker.say("Oh... wait... sorry.")
# robotDriveBase.straight(-100)
# elif colorSensor.color() == Color.BLACK:
# ev3.speaker.say("Theres something black on me... I dont know what to do with that...")
# if gyroSensor.angle() > GYRO_INIT_VALUE + 70 or gyroSensor.angle() < GYRO_INIT_VALUE - 70:
# rightMotor.brake()
# leftMotor.brake()
# ev3.speaker.say("Whoops!!! It looks like I just bit the dirt!! Can somebody help me back up please?")
return
# }
#### Main Code Loop ####
while True:
# {
SensorDetectAndReact()
MotorControlAndActions()
# }