Playing sound from balance bot #1774
Replies: 2 comments 8 replies
-
Can you share the full Python script?
This makes a blocking timer because there is no It doesn't look like it is documented, but For this particular application, it might be best to disable the main loop delay by setting it to 0. Maybe something like this? from pybricks.hubs import InventorHub
from pybricks.pupdevices import Motor, ColorSensor
from pybricks.parameters import Port, Direction
from pybricks.tools import wait, StopWatch
from pybricks.geometry import Axis
# Initialize motors.
left = Motor(Port.C, Direction.COUNTERCLOCKWISE)
right = Motor(Port.D)
left.reset_angle(0)
right.reset_angle(0)
# Initialize hub and color sensor.
# You can also use the TechnicHub and/or the ColorDistanceSensor
# instead.
hub = InventorHub()
sensor = ColorSensor(Port.A)
async def balance():
# Initialize position buffer for speed calculation.
DT = 5
window = 300 // DT
buf = [0] * window
idx = 0
angle = 0
DRIVE_SPEED = 300
PAUSE = 5000
# Timer to generate reference position.
watch = StopWatch()
while True:
# Get angular rate and estimated angle.
rate = hub.imu.angular_velocity(Axis.Y)
angle += rate * DT / 1000
# Get motor position.
position = (left.angle() + right.angle()) / 2
# Calculate motor speed.
speed = (position - buf[idx]) / (window * DT) * 1000
buf[idx] = position
idx = (idx + 1) % window
# Calculate reference position, which just grows linearly with
# time.
reference = -max(watch.time() - PAUSE, 0) / 1000 * DRIVE_SPEED
# Calculate duty cycle.
diff = position - reference
duty = 0.018 * rate + 19 * angle + 0.45 * diff + 0.16 * speed
# Account for battery level and type.
duty *= 7200 / hub.battery.voltage()
# Calculate steering.
reflection = await sensor.reflection()
steering = (reflection - 28) * 0.6
# Apply duty cycle for balancing and steering.
left.dc(duty + steering)
right.dc(duty - steering)
await wait(DT)
async def sound():
# TODO - replace with actual code
while True:
await wait(1)
async def main():
await multitask(balance(), sound())
run_task(main(), loop_time=0) |
Beta Was this translation helpful? Give feedback.
-
Thanks. I tried |
Beta Was this translation helpful? Give feedback.
-
Hi,
I've modified the balance bot code found here to let the bot be controlled by an XBox controller. That works well.
Now I'd like the bot to be able to play sounds. To do this, I think I need one coroutine making the
hub.speaker.play_notes
calls while another one runs the main balance loop. So I added an async main() method around the main loop. I added anawait
to the last line, ieawait wait(DT)
. However, that makes the balance bot fall over. I'm guessing that the context switching for the await takes too long.So I tried making my own wait implementation instead:
The robot does a better job balancing in that case, but it never yields execution so the sounds don't play. So I tried yielding execution every 100 ms (where await_watch is a StopWatch created outside of the loop):
This seems to work decently well, though I'm not sure if it balances quite as well as the non-async version.
My solution seems pretty hacky though. Is there a better way to handle this?
Thanks!
Beta Was this translation helpful? Give feedback.
All reactions