-
-
Notifications
You must be signed in to change notification settings - Fork 8.2k
esp32: BLE support using Nimble #5171
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
esp32: BLE support using Nimble #5171
Conversation
Great, thanks!
I would suggest that BLE be enabled unconditionally for all esp32 boards. It's a useful feature and I think would confuse users if it were missing from some boards and enabled in others. Of course it should still be possible to disable BLE via some compile-time config settings (eg in .mk or .h board file), so someone who wants to build a custom board without BLE can easily do this. |
I started implementing my code using this branch and discovered that support for encrypted characteristics is missing. In my case I set a password into the BLE device and don't want to send it plaintext. This should be a matter of passing the right flags down into the BLE stack, right? The native stack will do the encrypt/decrypt. |
How do I encode a 128b service UUID on the advertisement?
I also tried this:
But the bluetooth.UUID class does not implement the bytes member. Edit: The first failure is because the advertising string is slightly too long. If I make it shorter it will work. The bytes member function would be quite helpful so that I don't have to figure out the correct endian encoding for the byte string. |
Cannot build this branch for ESP32. (Looks like Travis cannot build it as well.) Am I doing something wrong? I just followed the README. |
Checked with git bisect; the compilation problem is introduced in 579bc8fb2142be5 . The error message is: Found that the problem is because corresponding include directories are added only if I see now: currently BLE support is only enabled for TINYPICO board, sorry for the noise. |
Can some helping hand give me a compiled binary please, even of a work-on-progress version? George gave this link https://micropython.org/resources/firmware/esp32-bluetooth.bin in #4589 but it's dead. There is a esp32-bluetooth.bin at the micropython download page but with no info about it. I am craving to test the ESP32's BLE, but as a C embedded programmer making first steps into the vast & beautiful ESP32 & micropython world, I am at a loss at the install & compile shebang. |
54789eb
to
4068afc
Compare
I've enabled it for
Yeah good catch. I will add this to the list. #5186
Yep, if you want this to work for 128-bit service uuids, you'll need a longer payload, which means active scans (i.e. you need to set the scan response data too). I think this currently works for the advertising role (set
Yup, my mistake. Have fixed that now so that it builds with or without nimble/ble being enabled. |
0c52cb5
to
fef750e
Compare
extmod/modbluetooth_nimble.c
Outdated
@@ -25,13 +25,13 @@ | |||
* THE SOFTWARE. | |||
*/ | |||
|
|||
#if MICROPY_PY_BLUETOOTH && MICROPY_BLUETOOTH_NIMBLE |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These guards usually go after the standard py/ includes, so that they can (in principle) be configured by a header file like mpconfigport.h. Is there a reason to move it up here?
extmod/modbluetooth_nimble.c
Outdated
@@ -238,36 +158,7 @@ typedef struct { | |||
/******************************************************************************/ | |||
// RUN LOOP |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this comment header needed now almost all code from this section is gone? Maybe just delete it and leave mp_bluetooth_nimble_ble_state
where it is, in this top section.
ports/esp32/nimble.c
Outdated
* THE SOFTWARE. | ||
*/ | ||
|
||
#if MICROPY_PY_BLUETOOTH && MICROPY_BLUETOOTH_NIMBLE |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can this move down to below the 3 py/ includes?
ports/stm32/nimble.c
Outdated
* THE SOFTWARE. | ||
*/ | ||
|
||
#if MICROPY_PY_BLUETOOTH && MICROPY_BLUETOOTH_NIMBLE |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Move down?
On other ports (e.g. ESP32) they provide a complete Nimble implementation (i.e. we don't need to use the code in extmod/nimble). This change extracts out the bits that we don't need to use in other ports: - malloc/free/realloc for Nimble memory. - pendsv poll handler - depowering the cywbt Also cleans up the root pointer management.
fef750e
to
cdeed34
Compare
Thanks, all done. |
cdeed34
to
a1005f2
Compare
a1005f2
to
fa23033
Compare
Merged! |
The esp32 binaries at https://micropython.org/download/#esp32 now have BLE included. |
|
Just flashed the above release. There is Jimmo's doc at docs/library/bluetooth.rst but no example (yet), so bad.
Normally, I should see "Micropython" using a BT scanner. But I don't see it, what's wrong with my lines above? A weird thing is the MAC address changes constantly each time it is read manually in the console using ble.config('mac'). |
You need to pass in an advertising packet, eg `b'\x02\x01\x02\x04\x09MPY' |
Thank you dpgeorge, I see the ESP32 as "MicroPython" on my smartphone now using this (don't know where you got this syntax from nor what the prefix means, but well...):
Then I am stuck from there on because without examples, the doc is like ciphered Chinese to me.
|
For a UART service try something like this: import bluetooth
bt = bluetooth.Bluetooth()
bt.active(1)
def bt_irq(event, data):
print(event, data)
bt.irq(bt_irq)
def adv_encode_name(name):
name = bytes(name, 'ascii')
return bytearray((len(name) + 1, 0x09)) + name
UART_TX = (
bluetooth.UUID('6E400003-B5A3-F393-E0A9-E50E24DCCA9E'),
bluetooth.FLAG_READ | bluetooth.FLAG_NOTIFY,
)
UART_RX = (
bluetooth.UUID('6E400002-B5A3-F393-E0A9-E50E24DCCA9E'),
bluetooth.FLAG_WRITE,
)
UART_SERVICE= (
bluetooth.UUID('6E400001-B5A3-F393-E0A9-E50E24DCCA9E'),
(UART_TX, UART_RX),
)
bt.gatts_register_services((UART_SERVICE,))
bt.gap_advertise(100, bytearray('\x02\x01\x02') + adv_encode_name('MicroPython')) |
Hi, great work for BLE in ESP32.
How can we know the power output of esp32, or change if it'snt the best?
https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/bluetooth/controller_vhci.html?highlight=esp_ble_tx_power_set#_CPPv417esp_power_level_t
The better would be ESP_PWR_LVL_P9 = 7
For SCAN, ADV, DEFAULT (ESP_BLE_PWR_TYPE_ADV = 9, ESP_BLE_PWR_TYPE_SCAN =
10, ESP_BLE_PWR_TYPE_DEFAULT = 11)
esp_err_t errRc=esp_ble_tx_power_set(ESP_BLE_PWR_TYPE_DEFAULT,ESP_PWR_LVL_P9);
esp_err_t errRc=esp_ble_tx_power_set(ESP_BLE_PWR_TYPE_ADV, ESP_PWR_LVL_P9);
esp_err_t errRc=esp_ble_tx_power_set(ESP_BLE_PWR_TYPE_SCAN ,ESP_PWR_LVL_P9);
Best regards.
Angel.
El jue., 10 oct. 2019 a las 3:20, Damien George (<notifications@github.com>)
escribió:
… For a UART service try something like this:
import bluetooth
bt = bluetooth.Bluetooth()
bt.active(1)def bt_irq(event, data):
print(event, data)
bt.irq(bt_irq)
def adv_encode_name(name):
name = bytes(name, 'ascii')
return bytearray((len(name) + 1, 0x09)) + name
UART_TX = (
bluetooth.UUID('6E400003-B5A3-F393-E0A9-E50E24DCCA9E'),
bluetooth.FLAG_READ | bluetooth.FLAG_NOTIFY,
)UART_RX = (
bluetooth.UUID('6E400002-B5A3-F393-E0A9-E50E24DCCA9E'),
bluetooth.FLAG_WRITE,
)UART_SERVICE= (
bluetooth.UUID('6E400001-B5A3-F393-E0A9-E50E24DCCA9E'),
(UART_TX, UART_RX),
)
bt.gatts_register_services((UART_SERVICE,))
bt.gap_advertise(100, bytearray('\x02\x01\x02') + adv_encode_name('MicroPython'))
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
<#5171?email_source=notifications&email_token=ABQBAUXREQ2DDWDHNG74B7LQNZ7ONA5CNFSM4I4KDENKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEA2AJUA#issuecomment-540280016>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/ABQBAUVN4OSMSMNIOZWM4HTQNZ7ONANCNFSM4I4KDENA>
.
--
Angel Maza Claver
*PRODEO Ingenieria y Consultoría*
*www.prodeo.es <http://www.prodeo.es/>*
*m. 654.095.413t. 974.316.493 / 976.291.839 / 978.830.554f. 901.955.109 *
|
This is not currently exposed. But it could easily be, using the |
Thanks for the great work. Is it somehow possible to scan for devices like described in #5051 (comment)? Managed it with def bt_irq(event, data):
if event == IRQ_SCAN_RESULT:
addr_type, addr, connectable, rssi, adv_data = data
print('Scan result', adv_decode_name(adv_data))
elif event == IRQ_SCAN_COMPLETE:
print('Scan complete')
bt.irq(bt_irq, IRQ_ALL)
bt.scan(2000) # Scan for 2000 ms |
@dpgeorge, code doesn't work. The device is seen by the BLE scan but can't be connected to. |
I found doc here : https://github.com/micropython/micropython/pull/5192/files?short_path=5ec29c7#diff-5ec29c7721a8f70cfaf860c248b3d623 |
@hobby16-design this helps a lot. Thank you |
Also getting stuck with the encoding of the Edit: After diving into it a little bit I guess the |
Hi, I have installed the latest firmware but i cannot activate the BLE module.
am I missing something, or is there an example of correct code that should run out of the box? |
It looks like your esp32 board does not have a stable power supply. |
thank you for your suggestion, I will investigate that further. |
I'm having the same problem as @hobby16-design . Im trying to make a bluetooth connection with a cellphone. When I run the code described by @dpgeorge few comments above ( using Also I have some questions about the library (the documentation is not very usefull).
|
@aamacaya try something like this: # Import of modules and classes
import bluetooth
# Configuration
ble = bluetooth.BLE()
ble.active(True)
# Event Handling
def ble_irq(event, data):
# print received data
print(ble.gatts_read(rx))
ble.irq(ble_irq)
# GATT Server
UART_UUID = bluetooth.UUID('6E400001-B5A3-F393-E0A9-E50E24DCCA9E')
UART_TX = (bluetooth.UUID('6E400003-B5A3-F393-E0A9-E50E24DCCA9E'), bluetooth.FLAG_READ | bluetooth.FLAG_NOTIFY,)
UART_RX = (bluetooth.UUID('6E400002-B5A3-F393-E0A9-E50E24DCCA9E'), bluetooth.FLAG_WRITE,)
UART_SERVICE = (UART_UUID, (UART_TX, UART_RX,),)
SERVICES = (UART_SERVICE,)
((tx, rx,), ) = ble.gatts_register_services(SERVICES)
# Advertiser
def adv_encode_name(name):
name = bytes(name, 'ascii')
return bytearray((len(name) + 1, 0x09)) + name
ble.gap_advertise(100, bytearray('\x02\x01\x02') + adv_encode_name('ESP32')) I can connect to ESP32 and send it data from the smartphone (using the Serial Bluetooth Terminal [https://play.google.com/store/apps/details?id=de.kai_morich.serial_bluetooth_terminal&hl=pt_BR] on Android), even though they are displayed as b'sent data\r\n'. I also cannot send data to the smartphone through the ESP32 (remembering that this is an initial draft). Hope this helps, greetings from Brazil. |
@HexVitor First of all thanks for the help. The code runs with no problems in the ESP32 I still have problems with the pairing of the device. When I go to my smartphone bluetooth settings I can see the 'ESP32' Device. When I select it it tries to make the connection but then it fails. Does it have something to do with the UUID numbers? Or is it something else? maybe the smartphone? |
I don't believe pairing is implemented yet. |
@aamacaya Got the point. Although I can connect through the application, there is no pairing either (odd that there was pairing when I used Arduino IDE). I imagine the pairing function is not yet implemented (I've been researching a lot and haven't seen anything about it). From what I understand about UUIDs, they are essential parts of BLE and identify the services provided by the device to be connected (e.g. battery indicator, external sound player, heart rate sensor ...). A list of some of these services and their UUIDs can be found at this link https://www.bluetooth.com/specifications/gatt/services/. |
It's nice to finally have BLE for mainline Micopython on ESP32. I did find however, that the garbage collection is deleting something important to do with BLE. This bug can be replicated by using the snippet sample above by @HexVitor and using the following steps:
|
I have just received some BLE 5.0 Temp/humidity beacons. Would it be possible to provide some sample code of how to scan for, connect to and read from a slave device ?? These beacons broadcast their values once a second, this can also be changed by a bluetooth write to the device. Many Thanks |
@sunbeamer This could be caused by the print() function that I put into the ble_irq() interrupt function. I read in the Random Nerd Tutorials that this practice should be avoided (https://randomnerdtutorials.com/micropython-interrupts-esp32-esp8266/).
Thanks for the feedback! |
@HexVitor I removed the It appears the following will provoke a core dump irrespective of whether the ISR is used or not:
|
@aamacaya @jonsmirl That's right -- neither pairing or bonding is supported yet. See #5186 Note that you don't need pairing and bonding to connect from a phone. I have a HID keyboard demo that works fine on Android from an ESP32 and PYBD. I'm working on tidying it up to post as an example (continuing on from #5223 )
@sunbeamer Thanks for the report. I will attempt to repro and get this fixed ASAP.
@HexVitor As the site says, it's good to keep interrupt handlers short, but there's actually nothing wrong with using print. The main thing is that in "hard" handlers, you can't allocate memory, so sometimes that makes it hard to generate a string to print. But in "soft" handlers (which run via micropython.schedule) you can do pretty much anything. All the BLE interrupts, with the exception of _IRQ_READ_REQUEST (only on PYBD, not available on ESP32), are "soft".
@aamacaya As @HexVitor has pointed out, these UUIDs are documented at https://www.bluetooth.com/specifications/gatt/services/ and https://www.bluetooth.com/specifications/gatt/characteristics/ These "official" services and characteristics have "short" 16-bit UUIDs. There are vendor-specific ones, which have 128-bit UUIDs (the Nordic UART Service is a good example). A BLE peripheral device is fundamentally a set of services and their associated characteristics. (Note this is different to BT Classic, which relies on "profiles" as the way of describing the types of functionality). Just as a general point about this API though -- it's explicitly designed to be a very low-level BLE API and as such it prioritises access to functionality and minimalism over ease-of-use. Some understanding of the BLE specification is unfortunately required. As I mentioned above, I am working on example code using this API, but probably more usefully, I plan for there to be higher-level wrappers around specific functionality, so that a lot of these details can be ignored. i.e. common scenarios like UART, writing and accessing various sensor types, beacons, scanners, etc should just be a couple of lines of code. |
It's great to have further discussions about BLE, but they are going to get lost in this merged and closed pull request. So please use https://forum.micropython.org for discussion and questions about how to use BLE, open new issues for bugs, and add (reasonable) feature requests to #5186 Thanks! |
Split off into #5226
There are now some BLE examples in |
Turn on unicode for FATFS
This PR adds BLE support for ESP32, extending on #5051.
Note: This requires building with IDF 4.x. Some thought is required as to how we want to enable this for various boards (i.e. the TINYPICO commit shouldn't be merged).
Some minor refactoring of
modbluetooth_nimble.c
was required as the IDF version of Nimble doesn't require any supporting port-specific code.