-
-
Notifications
You must be signed in to change notification settings - Fork 7
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
The future of BLE, Bluetooth, and USB #262
Comments
This would be really cool!! My hope is that basic functionality may be feasible with ubluetooth module (# 3), even before you are able to prioritize it, as we start to see examples making use of it. |
Partly inspired by the existing Peripherals: from pybricks.messaging import PeripheralHub
# Can make only one of these
peripheral = PeripheralHub()
# Starts advertising.
peripheral.advertise(True)
# Waits for incoming connection. On success, stops advertising and returns a stream object, else raises TimeOutException.
hub_connection = peripheral.listen(timeout=1000)
# Now you can send and receive data using hub_connection.read and hub_connection.write The central: from pybricks.messaging import CentralHub
# Can make only one of these
central = CentralHub()
# Starts scanning for hubs that are advertising.
central.scan(True)
# Results will be stored in central.scan_results, a dict of name:address pairs
# So you could wait until some devices are found, or look for a specific one:
while 'my_other_hub' not in central.scan_results:
pass
# Found it!
address = central.scan_results['my_other_hub']
# Stop scanning
central.scan(False)
# Connect. Returns a stream object on success, else raises TimeOutException.
hub_connection = central.connect(address, timeout=1000)
# Now you can send and receive data using hub_connection.read and hub_connection.write Peripherals (simplified API idea) from pybricks.messaging import ble_wait_for_connection
# Waits for incoming connection. On success, stops advertising and returns a stream object, else raises TimeOutException.
stream = ble_wait_for_connection(timeout=1000)
# Now you can send and receive data using stream.read and stream.write The central (simplified API idea) from pybricks.messaging import ble_connect
# Connect. Returns a stream object on success, else raises TimeOutException.
stream = ble_connect(address_or_name, timeout=1000)
# Now you can send and receive data using stream.read and stream.write |
Really like to see this roadmap! |
So it looks halfway done already! :D Meanwhile maybe playing around these examples could lead us somewhere. |
The examples for Our objectives are just a little different. Compare those examples with the suggested code snippets above. We're aiming to let you do it with two lines of code and about 10x fewer system resources used. |
Fully understood your approach! To get it working guess one needs to add the |
No, it doesn't work that way. |
Your referring to the official spike prime firmware, correct? |
Ah, that's interesting. I haven't tried all of the examples. The @mwinkler, as you've expressed interest in having |
With the described use cases, is all covered what I have currently in mind. My idea is a track based racing game, where every player controls his own vehicle via game pad (or pu remote). So in the end, if all is implemented in pybricks, I don't need the ubluetooth module. Btw, thank you for the great work you do (you both) with this project. |
Interesting dicussion! I have been playing around with the I second @laurensvalk statement on the complexity of the code necessary to get everything setup and the resources the Just a few questions that came to my mind on the implementation of Scenario 3A:
|
Thanks @NStrijbosch -- some good points there. We're not sure yet about the connection limits. I think we could enable the user to monitor the connection status so they can reconnect if they want to. But hopefully it should be stable enough within reasonable distances to the point where most users might not need to do this. How is your experience with connectivity and stability, since you've worked with 9 hubs at once? |
From my experience the connection limit of the Robot Inventor/Spike Prime hub:
The stability has some issues from time to time, once again not sure if this is hardware/firmware/my software. But some of my observations:
|
Thanks a lot for sharing this. This will set the minimal benchmark for us 😉 We would certainly be interested in your findings once you test our stuff. We welcome contributions to the code as well. And good to know that a hub can be both a central and a peripheral, too. We need that, since we use BLE for programming as well, where it is the peripheral to the PC. |
Going back to a previous issue which is now referring to this issue for the solution: #164 How do I communicate few floats back and forward between a normal python program running in my PC and the hub micropython? I don't quite see this simple scheme in the description above. Thanks |
For EV3, we have https://pybricks.github.io/ev3-micropython/messaging.html For Powered Up hubs, this is not implemented yet. |
That would be use case 3b. This pictures a phone as an example, but it could be a PC as well. The PC could use any language with BLE support, such as Python with the And indeed, this is all still in the concept stage. |
One thing I have been thinking about that is specific to BLE UART is that we have write with response or write without response in one direction and indicate (with response) or notify (without response) in the other direction. In the with response case, there should be no packets dropped, but throughput will be lower since there is the extra overhead of a response sent for each packet. In the without response case, the transmitter has no way of knowing if the receiver actually received the data and the receiver has no way of knowing if they missed something (unless it is handled at the protocol level). So I'm thinking we probably want to default to the slower, safer option. But we might want to add an option for the faster lossy option if there are use cases that require high bandwitdh. |
At the moment, we have I've been brainstorming what that absolute minimum might be, which will still support all of the communication use cases above. It might all boil down to just this: # SPDX-License-Identifier: MIT
# Copyright (c) 2018-2020 The Pybricks Authors
"""
pybricks.ble: Bluetooth Low Energy communication tools.
"""
class BLEDevice:
address = "AA:BB"
"""Address of the connected device"""
name = "my_city_hub"
"""Name of the connected device"""
mtu = 23
"""Maximum transmission unit."""
# Add methods and/or attributes such as to configure write with/without response, etc
class NUSDevice(BLEDevice, PybricksIOBuffer):
pass
def nus_connect(address, timeout=3000) -> NUSDevice:
"""Connects to a peripheral that is currently accepting a connection.
This hub will act as the central. It can connect to any other peripheral
that advertises the Nordic UART Service (NUS).
Arguments:
address: Bluetooth address or name of the device you wish to connect to.
timeout: How long to scan for the device before giving up, or
``None`` to wait indefinitely.
Raises:
TimeoutException: If the connection could not be made within the
given timeout.
Returns:
Stream object representing the connection to the peripheral.
"""
pass
def nus_wait_for_connection(timeout=None) -> NUSDevice:
"""Accepts an incoming connection from a central.
This hub will act as a peripheral and advertise the Nordic UART Service
until a connection is made or the timeout is reached.
Arguments:
timeout: How long to wait for a connection before giving up, or
``None`` to wait indefinitely.
Raises:
TimeoutException: If the connection could not be made within the
given timeout.
Returns:
stream object representing the connection to the central.
"""
pass # Peripheral
from pybricks.ble import nus_wait_for_connection
prime_hub_stream = nus_wait_for_connection()
prime_hub_stream.write("Hello!") # Central
from pybricks.ble import nus_connect
city_stream = nus_connect("my_city_hub")
technic_stream = nus_connect("AA:BB:CC") class LWP3Device(BLEDevice):
pass
def lwp_connect("....") -> LWP3Device
pass
class pybricks.pupdevices.RemoteControl(LWP3Device):
pass
my_duplo_hub = lwp_connect("Duplo Hub")
Could we add this as a parameter above? Or is this a hub-wide setting that will affect all subsequently made connections? |
Is this the lowest level possible? I am thinking beyond Nordic UART, e.g., LWP ;) My main question: what are your thoughts on support for LWP, i.e., either by allowing specific characteristics in this low-level BLE to communicate with LWP devices, or by extending scenario 6 beyond the PoweredUp Remote? I have been diving into the LWP docs lately (that would be extending scenario 6). For myself I see a few advantages (and of course also disadvantages) in using this protocol to communicate between a SPIKE Prime/Robot Inventor hub to any other PU hub supporting LWP. The advantages I enjoy at the moment:
Of course the disadvantages are numerous:
|
Thanks for your quick response.
No, this is mainly the low level for the NUS communication stuff, hence the
In other words, this leaves room for other functions in |
Thanks everyone! Please move the gamepad findings and discussion over to #1024. Thanks! |
I am interested in the possibility of using a USB connection to run Python code on the Spike Prime Hub. I understand that this may not be a readily available feature, but I would like to explore any potential solutions or workarounds. If there is no existing method to achieve this, could you please provide some guidance or suggestions on how I might approach implementing a USB connection for this purpose? Any information or resources you can share would be greatly appreciated. |
Do you have a particular reason why Bluetooth can't be used? |
My client's users are already used to using USB to connect their lego robots and having them change to Bluetooth is not an option unfortunately. |
Thanks for the response. I'm still not sure that I follow - no user action is required to use Bluetooth in pybricks (no need to press the Bluetooth button). You can still have USB plugged in for charging. In other words, whether it not the cable is plugged in, the user work flow is the same. Can you elaborate on why this won't work? Just trying to get a better picture to see if this would help other users, too. |
The type of user are kids so it's more difficult for them to stablish a bluetooth connection rather than just plug an usb (and the teachers are also used to the usb connection).
I'm highly curious about this. How would this work? Should there not be some prior configuration for the connection to be established between the device and the computer? Even so there's also another two reasons and those are that:
|
- https://www.raspberrypi.com/news/raspberry-pi-build-hat-lego-education/
- https://www.raspberrypi.com/products/build-hat/
Raspberry Pi meets LEGO® Education
The Build HAT (Hardware Attached on Top), priced at $25, is a new
add-on board for your Raspberry Pi. It connects to the 40-pin GPIO header
and can be used to control up to four LEGO® Technic™ motors and sensors
from the LEGO® Education SPIKE™ Portfolio.
The new HAT works with all 40-pin GPIO Raspberry Pi boards, including
Raspberry Pi 4 and Raspberry Pi Zero. With the addition of a ribbon cable
or other extension device, you can also use it with Raspberry Pi 400.
Raspberry Pi (and other compatible SBCs with a 40 pin GPIO) have USB and
Power.
USB-C and/or USB-A on a new or refreshed LEGO hub product may also solve
for your use cases
…On Wed, Apr 5, 2023, 7:59 AM Marcos Horno ***@***.***> wrote:
The main reason is user action. The type of user are kids so it's more
difficult for them to stablish a bluetooth connection rather than just plug
an usb and them and the teachers are already used to the usb connection.
- no user action is required to use Bluetooth in pybricks (no need to
press the Bluetooth button)
I'm highly curious about this. How would this work? Should there not
be some prior configuration for the connection to be established between
the device and the computer?
—
Reply to this email directly, view it on GitHub
<#262 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAAMNS4UD2ZPHYMKFXFKLMDW7VNCRANCNFSM4YIEEWRQ>
.
You are receiving this because you were mentioned.Message ID:
***@***.***>
|
You click the connect button in the app. Give it a try if you like. Since this is a web app, the procedure would be the same for USB. The browser won't let us auto-connect for security reasons. You could also use the official LEGO apps with Python if you prefer. |
Thank you for the information on Bluetooth connectivity. However, due to our users' specific requirements I mentioned earlier, we are seeking a USB-based solution and are curious if there's a way to implement it with Pybricks. Is it not possible to achieve this, then? If you have any suggestions or insights, I'd appreciate your input. I understand that this might be a complex task, but any guidance would be valuable. |
It's certainly possible technically. We get a lot of feature requests, so we normally try to prioritize features that help the most users. We do also work with commercial partners on some new features, and USB support could be a good example of that --- feel free to reach out at [email protected] if you'd like to learn more. |
Another reason for USB support is so we can use pybricks for First Lego League Challenge competitions. Our FLL organization here does not allow bluetooth during the competitions and it is crucial to be able to tweak the code and make adjustments based on previous runs on the tables. I have been teaching my group of kids how to use pybricks and it would be awesome if we can stick with pybricks for the robot competitions this coming season. Thank you for pybricks! |
Me too. I just get spike prime for my kids to upgrade from ev3 to enter WRO Competition. During competition wireless connection is not allowed. So, either run pybricks in ev3 or move to lego officials for spike prime. |
Let's see if I can summarize weeks later from a deep dive on a weekend iirc: Is this a usable UX workflow for connecting a bluetooth ble gamepad to a LEGO hub?:
|
@laurensvalk @dlech Do you have any ideas or requirements for USB support in case we wanted to try to implement and submit a pull request? I'm running an FLL team and would like to avoid Bluetooth at competitions. |
@nkarstens I am willing to help with this effort if you need the help. |
Ideas:
|
FWIW also there are pylgbst and ipylgbst. pylgbst wraps various Python Bluetooth backends for various OS;
ipylgbst wraps WebBluetooth for use as a JupyterLab extension |
All right I've looked into this a little bit and I'm hoping I'm not too far out of my depth here... @dlech It looks like there was support for a USB serial connection at one point (usb_stm32_serial.c), but that was removed. What can you tell me about the history there? It looks like you suggested WinUSB; would a serial protocol be a better option for wrapping the GATT profile? Do you have any documentation on options for debugging firmware (such as JTAG or a printf)? @lawrencet149 Thanks for the offer, do you know much about firmware development? |
Since BLE is message-based instead of stream-based, I don't think serial is a good fit. Also we don't want the official LEGO apps to "see" devices that are running Pybricks firmware. The initial USB serial implementation was just to debug before we got Bluetooth working. Debugging is a bit tricky since there is no JTAG (lock bit was set at the factory, so it doesn't work) and printf has to be used with much caution. If we really need to, we can hijack one of the I/O ports for printing via UART. This is discussed in a bit more detail at pybricks/pybricks-micropython#80 (comment). |
@dlech I got a NUCLEO-F413ZH board to help with prototyping the initial USB work and will then plan to migrate to pybricks-micropython from there. It looks like we will need a USB vendor ID and product ID. pid.codes does subassignments of their vendor ID, 1209, for open source projects that meet their criteria. Can you please review the prerequisites listed here and let me know if this sounds good to you? If so, I will take care of making a pull request and send to you for approval, or you can do that yourself and let me know when it has been merged in. |
We should use the LEGO USB VID/PIDs that are already assigned to these hubs. https://github.com/pybricks/technical-info/blob/master/assigned-numbers.md#usb-device-ids |
I was under the impression that VID and PID help determine which driver is
loaded, which may cause conflict with the factory firmware (see
https://unix.stackexchange.com/questions/391919/do-vendor-id-and-product-id-alone-determine-the-driver-used-for-a-usb-device
for one discussion about this). In that case, using a unique set of IDs
would be preferable. What do you think?
Nate
…On Thu, Sep 28, 2023, 08:05 David Lechner ***@***.***> wrote:
We should use the LEGO USB VID/PIDs that are already assigned to these
hubs.
https://github.com/pybricks/technical-info/blob/master/assigned-numbers.md#usb-device-ids
—
Reply to this email directly, view it on GitHub
<#262 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AGKEWXQU4RH65EZKYIH22Q3X4VY3LANCNFSM4YIEEWRQ>
.
You are receiving this because you were mentioned.Message ID:
***@***.***>
|
They can be, but for the SPIKE and MINDSTORMS hubs, there is no special driver. It is using the class/subclass/protocol to match to a driver instead. The official LEGO firmware is using the standard serial port (CDC ACM) class/subclass/protocol. If we are using a vendor-specific class/subclass/protocol, then there shouldn't be any conflict. |
@dlech I got it to a point where Windows will load a WinUSB driver for it. Please see the draft patch at pybricks/pybricks-micropython#208 and let me know if you have any suggestions. Thanks! |
Nice! Looking forward to see what you came up with. |
Just FYI for anyone monitoring this issue. The following pull requests have enough USB support implemented to push a program: @dlech has incorporated these into a |
Introduction
This issue gathers some ideas for Bluetooth and USB to help us keep track of the big picture while we work on low-level details.
Note that most of this won't be done any time soon (if ever). This is mainly intended to avoid implementation choices now which might come back to hurt us later. If you want us to prioritize this, please consider becoming a sponsor 🚀 .
Nomenclature
code
in boxes is pseudocode for commands in user scripts.1. Single-hub coding scenario
This is what we are working on today. We are working on a Pybricks BLE service to handle things like starting and stopping programs in a clean way. Standard I/O (
print
/input
) may be a separate service or characteristic on the same connection.Until now, both were handled on one and the same characteristic, which made it easy to mess up the connection by sending the wrong characters.
Cleaning this up and documenting it also paves the way for other editors or extensions to support Pybricks.
This is the only use case we will target for the upcoming v3.0 release. That is likely also the last release for Move Hub; it won't have enough space for the other features listed below.
2. Multi-hub coding scenario
This might work as above, but there are many elements still missing such as:
3a. Multi-hub communication scenario
This is still to be explored. At the basic level, there might be serial i/o streams between hubs that could be used with standard MicroPython tools. Higher level abstractions such as mailboxes could be added on top of these later.
3b. Other BLE UART devices
This is really the same as above, but worth showing in a separate diagram because this really opens up interesting possibilities.
4. BLE HID Peripherals
We may support connecting to generic HID devices over BLE (and possibly classic). Users could build on this to add specific mappings for certain devices like popular gaming consoles.
5. Bluetooth classic scenario
This is only available on Prime Hub and Inventor Hub. Therefore, we will not use Bluetooth classic for any system purposes. So, you won't be able to download and run programs with it.
Rather, it might be used within end-user scripts. For example, you might set up a generic RFCOMM connection with a server or client. This could be another Prime Hub, an EV3 Brick, a laptop, and so on.
6. LEGO Powered Up Remote
See #186.
7. USB scenario
This is only available on Prime Hub and Inventor Hub. Therefore, we will probably not use USB for system purposes. So, you probably won't be able to download and run programs with it. USB will be used primarily for charging the hub. We may re-enable REPL over USB if users want this. Since REPL is treated as a regular program, we'd have to define a way to start and stop it. Perhaps USB can also be used for fast(er) file transfer.
The text was updated successfully, but these errors were encountered: