pybricks / support

Pybricks support and general discussion

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

[Feature] Is there any function like "thread" (not multitask) implement in pybricks with SPIKE Prime?

a10036gt opened this issue · comments

In robotics programing, we ofter using thread or multi task to do some staff, for example, WRO RoboSport we have a main task to do, and other task will doing sensor processing, odometry task..., like following image:

EV3G-Thread

Here is the video about robot run: https://youtu.be/a0pwdxfojIo?si=5DHkKBV64Dm3L_QP&t=1384

The Pybricks provide the multitask but it works not well for us, because the task is in while loop and can't get out. We want to import _thread but it has been remove in firmware.

Is there anyway to doing this kind of function? Following code is a arduino with FreeRTOS, that's the things we want to do:
image

Thanks!

And As I know the SPIKE App doing in similar way to solve the thread problem:

Scratch block:
image

Compiled Code:

async def stack(this):
    while True:
        with this as event:
            await event
            # Control repeat
            for _ in range(10):
                # Light display image on for time
                hub.light_matrix.show([int((int(p) * (global_state[DISPLAY_BRIGHTNESS] / 9)) + 0.5) for p in "9909999099000009000909990"])
                try:
                    await this.wait(2000)
                except scratch._StackStop as ex:
                    hub.light_matrix.clear()
                    raise ex
                hub.light_matrix.clear()
                yield

async def stack_1(this):
    while True:
        with this as event:
            await event
            # Control forever
            while True:
                # Play sound until done
                if tunnel.connected():
                    corr = (global_state[TUNNEL_CORRELATION] + 1) % 255
                    global_state[TUNNEL_CORRELATION] = corr
                    await send_tunnel_data(struct.pack(">BBIBhb", 23, corr, 2365347937, int(global_state[SOUND_VOLUME] + 0.5), int(global_state[SOUND_PITCH] + 0.5), int(global_state[SOUND_PAN] + 0.5)))
                    try:
                        await request_tunnel_data(corr, False)
                    except scratch._StackStop as ex:
                        await send_tunnel_data(struct.pack(">BB", 27, corr))
                        raise ex
                yield

vm = scratch.VM()
vm.add_start(stack)
vm.add_start(stack_1)
vm.run()

Yes, you can do that by just adding another start block:

image

OK I give a try and it work, but seems if I have any while loop in task, I need add await wait(1), or other task will be block?

I need add await wait(1), or other task will be block?

This is done for your automatically.

image

If you have an example where that was not done correctly, please let us know and we'll fix it.

Maybe we'll also add an option to omit the wait(1) so advanced users can turn it off. After all, they aren't needed in this example since the loops contain other awaitables.

I using Python mode not block mode, I mean seems it is necessary to add wait(1) in any loop I use in task? Because When I remove it, seems other task will be block.

Yes, it is generally necessary in loops that take a some time (or forever) if they don't already have anything awaitable inside. This is how async/await works, also in official MicroPython or the standard LEGO firmware.

Having such a wait allows your code on other "tasks" to be executed.

If you'd like to share some of your code, perhaps we can help with that.

OK, I see, thanks!