[Feature] Urgent Block Coding Feature. hub_menu() support, main() function name rename capability, and ability to disable run_task()
There does not appear to be a way in block coding to use hub_menu() which severely limits the ability to use block coding in FLL since you can't create/manipulate the hub() menu
Also, the current block coding does not let you rename the main() loop. This causes a problem when importing multiple tasks into a hub_menu program on Spike Prime. We created our hub_menu program outside of the block coding.
it appears i can use "as" in the hub_menu program:
from pybricks_class_task1_rev2 import main as pybricks_class_task1 from pybricks_class_task2_rev2 import main as pybricks_class_task2
but it would better to be able to rename the main() function and we also need a way to disable run_task(main()) otherwise the menu will automatically execute the tasks :(
however, the block coding leaves the run_task(main()) which can only be removed manually and thus breaking the the block code version.
how about the following:
Enable Menu Mode Block with one parameter which would be the name of the new "main()" for that module. it would also disable run_task(). if you add a second parameter "Enable" it would let you enable or disable run_task(). however, run_task() would use the new name for the main() routine.
there also appears to need to be an explicit way to move the hub and motor relate setup items to the menu.py otherwise you get;
OSError: [Errno 16] EBUSY: Device or resource busy
if you define your hub and motors more than once.
There does not appear to be a way in block coding to use hub_menu() which severely limits the ability to use block coding in FLL since you can't create/manipulate the hub() menu
You can combine multiple blocks programs like this: https://pybricks.com/project/spike-hub-menu/
For more advanced usage, perhaps you can make functions to import rather than entire main programs.
For example, you could make generic drive functions that take a drivebase as their argument. Then you need just a single setup, avoiding the problems above.
thanks but I still believe the current approach for using hub_menu with block is not a viable approach for kids.
its not really clear in Block how to generate non main() programs. it appears you can use the "make your task" block but that has 4 drop downs that don't seem to change the code so they don't make sense and the Program block is still present which is confusing. I should be able to remove the program block if I'm just trying to make task block
the documentation to make your task and what the 4 drop down options are does not appear to be in the docs.
also wouldn't you run into the reinstantiation of the hub/motors problem?
my recommendation
- create a special setup block for hub_menu that works l like multitask visually where the user inputs the name(s) of the .py files and the menu character for each file. if you select hub that has a menu capability and put the hub_menu block in it then no other blocks are allowed. this now becomes the hub_menu for your robot. additionally this should the default "root" or "base" program for your program so if you hit |> button it push the menu and all included .py files to the robot. see issue #2175 and #2173 in discussions. the program block goes away
- for tasks/mission .py files add a special setting for prime hub block called Enable Hub Menu (True/False) if set to True, it then requires a name for the program (which is really replacing the main() function name) and disables run_task(main())
just some thoughts on how to make it easier
btw, we primarily use straight python on my FLL teams. but we want to start using Block Coding in the "Recreational" Team so they can start learning.
#2175 and #2173 still apply to python about being able to set a hub_menu .py file as the "root" file so that when |> button is pressed no which .py I'm in the hub_menu and all files it imports is sent to the hub.
Thanks for the suggestions. This is certainly an area we need to work on. See also https://github.com/pybricks/support/issues/2193 on how we might get to a nice and simple solution in the medium term.
There does not appear to be a way in block coding to use hub_menu() which severely limits the ability to use block coding in FLL since you can't create/manipulate the hub() menu
You can combine multiple blocks programs like this: pybricks.com/project/spike-hub-menu
For more advanced usage, perhaps you can make functions to import rather than entire main programs.
For example, you could make generic drive functions that take a drivebase as their argument. Then you need just a single setup, avoiding the problems above.
after fiddling with the example above, unless I'm missing something i do not believe it is viable for FLL teams. The following reasons:
- we need to be able to run tasks multiple times. That is not supported in the example.
- if block coding task uses multitask it will not run at all
the approach we use with straight Python is below. but that does not work with Block Coding because there does not appear to be a way to not have either main() or function() automatically run in block coding based programs and you run into poly instantiation of the prime hub which causes an error.
So I really don't see how Pybricks block coding can be effectively used for FLL.
My recommendations are:
- ideally create a formal block coding set of block for hub_menu
- provide a way to disable run_task (for multitask based block coding examples)
- provide a way to disable function_name() appearing at the end of the block coding example.
- provide a way to move the prime hub object instantiation into a library and disable setup in the task block coding
if a setup option was added prime hub/robot inventor block that has a "Enable Hub Menu Support" setting then it would not create the run_task() or function_name() lines at the end of the file. Then a other option for importing a "custom robot library" This would allow the below approach to work and allow the programs to be run multiple times without issue.
# Pybricks Class Menu
# menu revision number
menu_revision="1"
#
# import our library
from pybricks.tools import hub_menu
from pybricks_class_library_rev1 import *
# The name of each task file minus the .py file extension
from pybricks_class_task1_rev1 import pybricks_class_task1
from pybricks_class_task2_rev1 import pybricks_class_task2
from pybricks_class_task3_rev1 import pybricks_class_task3
print("Robot Menu, rev#",menu_revision," using library rev=",lib_rev)
while True:
selected = hub_menu("M","1","2","3","X")
try:
if selected == "M":
# does nothing. used to show menu is active
break
if selected == "1":
wait(1000)
run_task(pybricks_class_task1())
elif selected == "2":
wait(1000)
run_task(pybricks_class_task2())
elif selected == "3":
wait(1000)
run_task(pybricks_class_task3())
elif selected == "X":
# does nothing used to show end of menu
break
except BaseException as menuException:
print("Stop was Pressed or a Critical Error Occurred.")
print(menuException)
break
then for the library (pybricks_class_library_rev1) that is included in the python task files is:
# Pybricks Python Class Library
lib_rev="1"
#
from pybricks.hubs import PrimeHub
from pybricks.parameters import Direction, Port, Stop
from pybricks.pupdevices import Motor
from pybricks.robotics import DriveBase
from pybricks.tools import multitask, run_task, wait
# Set up all devices.
prime_hub = PrimeHub()
right_motor = Motor(Port.A, Direction.CLOCKWISE)
left_motor = Motor(Port.B, Direction.COUNTERCLOCKWISE)
attachment_motor = Motor(Port.C, Direction.CLOCKWISE)
drive_base = DriveBase(left_motor, right_motor, 62.4, 204)
and each of the above tasks have something like this at the top of each file:
from pybricks_class_library_rev1 import *
or am I missing something in https://pybricks.com/project/spike-hub-menu/
Have there been any advancements on this for the purpose of using block coding for FLL?
I guess I didn't do my due diligence on the menu system within block coding. I found the basic script to run multiple programs and didn't catch the part that those programs could not be re-run. Our kids have really liked the transition from the Spike app to Pybricks blocks, but now I'm questioning if we will have to switch to scripting simply for not being able to run multiple programs as smoothly as we did on the Spike app.
If there is a way to do this, can we please get better documentation? I know many FLL teams would benefit from this.
There was some discussion about a special firmware build that would have 4 or 5 slots that you could load programs into. But I don't know the status of it.
I love pybricks, but lack of good hub_menu() support with Block Coding really limits pybricks.
we don't use block coding for a number of reasons and that is one of them. Though some of kids have used it to quickly prototype code but we end up just removing the first comment # line and manually converting over the regular pybricks
I think the best long term solution would be for pybricks to make the hub_menu() function largely obsolete by adding explicit slot support in the language.
something like this:
hub.slot(int SlotNumber, str SlotCharacter)
you would add a line like this at the beginning of your code
hub.slot(1,"1")
which would assign the function that the command was run in to slot "1". And they would create a block code version of it but it would require other changes to block coding mode to not run the function at the end of the code
another option would be to still use hub_menu() but change the way block_coding works by enabling a setting this makes in hub_menu() friendly like removing the function name at the end and letting your import a common library.
the link below shows how my FLL team used hub_menu() in Submerged last year
https://github.com/bcfletcher/lego_projects/tree/main/FLL/2024_Submerged_Pybricks_Code
Thanks @bcfletcher, I agree that ideally the program slot solution would be best.
@laurensvalk & @dlech - Are there any plans to have this done for this FLL season? For reference, our team has to start competing in December. We pretty much have to decide in the next couple of weeks if we have to shift and start teaching our team python.
There really should be a disclaimer on the main site that blocks really isn't FLL ready. Having to dig into GitHub forums to find out this information is not upfront and transparent.
@TakeControlSolutions,
I posted my Pybricks and Python courses for FLL and the source for the pybricks course at:
https://github.com/bcfletcher/lego_projects/tree/main/FLL/2025_MD_FLL_Coaches_Conf
in the source code are some Block Coding examples of how to use hub_menu().
not as clean as with straight python but you can do it. you might have to restart the robot sometimes between runs. I think it is an object reuse/reinstantiation issue related to primehub() being called more than once.
in my straight pybricks python examples, you will see how we avoid that.
let me know if you have questions or problems.
looks like work is progressing on the Slot support for the next release of pybricks
https://github.com/pybricks/pybricks-micropython/blob/master/CHANGELOG.md
https://github.com/pybricks/pybricks-micropython/pull/264
https://github.com/pybricks/pybricks-micropython/pull/312
Yes - we've been working round the clock on this 😄 We'll have something for you to try in a few days.
yeah!!!
To try it, you can now install the very latest experimental firmware using these instructions.
Once installed, you can toggle between 5 code slots using the hub buttons. When you press the ▶ icon in the app, it will go into that slot.
Looking forward to hearing what you think!
You can revert to the normal firmware any time you like by reinstalling firmware the normal way.
Caveats We changed a lot of other functions too, to prepare for other upcoming features. Everything else is supposed to work the same as before, but this isn't as well tested as our usual releases just yet. If you run into any issues or difference (for example, a sensor/motor issue), please do open an issue about it. We strive to keep all existing behaviors the same.
In other words, please don't switch to this version two days before competition day 😄
cool. that is good news. i will try to test this weekend
so no issues with instantiating primehub() and driveBase for each mission?
was number five solely related to the number of squares on the hub display?
if so, why not just do 0-9 numbers on the display instead?
That's right, they're all fully independent, normal programs to keep things simple. The last used menu selection stays active after a run.
If you really wanted to, each could even have a menu of its own to start a particular variant of a mission.
The number has to do with how the available storage is currently implemented, to keep execution really fast.
It is also designed to let you quickly see which program is running even while it runs, or even operate it without being able to see the display.
It's possible that we extend this in the future, but let's see how this goes first.
thanks. i suspect 5 slots would be sufficient for many teams using pybricks block coding.
what is the size limit for each slot?
is purely in KB of python code?
I loaded firmare: primehub-firmware-build-4272-git4cc72417
I tried 3 block coding examples that i know work.
loaded each one into their own slot.
tried running each but i get
The program was stopped (SystemExit).
I was still connected to the robot from the App
however rebooted the robot and DID NOT connect to the app and i could run the 3 block code examples
i reconnected the robot to the app and could run the tasks and the see print output from the block code.