Accelerometer bluetooth service has no characteristics
NAllred91 opened this issue · 18 comments
I'm using a micro:bit v1.3B and just today used makecode to generate a new hex file by dragging my old one in (built last year before the accelerometer changes).
My hex file turns on the accelerometer service.
I'm connecting to the micro:bit using web bluetooth, and when I try to get the characteristics of the accelerometer service I get an error that says no characteristics were found in the service.
My hex file also turns on other services, and they all continue to work as before.
I also deleted the "bluetooth accelerometer service" block in makecode and added it again from the toolbox. But I still get the same error when trying to get the characteristics of the accelerometer service.
My guess is that this is related to the addition of the partial flashing service and/or the magnetometer service calibration characteristic. If you have lots of services the last one created may no longer fit.
What services do you have?
Could you try removing one or more of the other services?
Could you share your MakeCode so I could try it out?
https://makecode.microbit.org/_9TeX0jfy9FvX
I'll try removing/reordering services now and see if that makes any difference.
moving the accelerometer block to the top of the list does seem to resolve the issue, and didn't seem to break any other services.
If the pin service is created last, its data characteristic is missing. I checked this with the nRF Connect app. There is a limited amount of memory in the GATT table for storing details of all the services and characteristics.
Creating the magnetometer service causes an out of memory panic. I think it will be difficult to create a hex with all these services enabled, especially including the magnetometer service.
To experiment, you could try editing the yotta options. To see these in MakeCode go to More...(cog)/Project Settings/Edit Settings As text. The yotta section looks like this:
"yotta": {
"config": {
"microbit-dal": {
"bluetooth": {
"open": 1,
"pairing_mode": 0,
"whitelist": 0
}
}
}
},
Replace that with:
"yotta": {
"config": {
"microbit-dal": {
"bluetooth": {
"open": 1,
"pairing_mode": 0,
"whitelist": 0,
"dfu_service": 1,
"event_service": 1,
"partial_flashing": 1,
"stack_size": 1280,
"gatt_table_size": "0x700"
}
}
}
},
The extra settings here are the defaults that MakeCode currently uses for a Bluetooth enabled hex.
If not using Bluetooth for flashing, the DFU and Partial Flashing services could be disabled by changing 1 to 0.
If you are not using the Event service, that too could be disabled. If you are using the Event service, you could choose to use button events to avoid needing the Button service.
If you were using fewer services the GATT table size (min 0x300 max 0x700) can be reduced to make more heap memory available. The accelerometer characteristics were missing because the GATT table space ran out.
Disabling the DFU, Event or Partial Flashing services will free up GATT table space for use by other services and release heap memory for the services and the rest of the program.
The stack size can be reduced to increase heap memory, but 1280 is already quite low. Reducing it further could make a particular program work but may also cause unpredictable behaviour and crashes as the stack and heap try to use the same memory, At 1280 these problems can already occur during compass calibration.
By the way, connecting to Bluetooth services allocates memory in the heap which is not freed by disconnecting. So, for example, compass calibration can work after a reset, but cause an OOM panic or a crash after using Bluetooth services.
Thanks, in my case I'll be fine for now just removing the pin service since I haven't actually started using that one yet.
In regards to your comment about memory not being freed by disconnecting. Are you saying that if I connect and disconnect from the micro:bit multiple times it will eventually run out of memory? I've tried connecting and disconnecting up to 10 times in a row and haven't run into issues yet.
No. I should have said "the first connection after a reset". The same memory gets used for subsequent connections.
Beware! The changed settings don't always take immediately. I thought the above was all wrong for a minute! Try refreshing the page. When it works there will be a message saying that compiling will take some time.
The option "device_info_service": 0
is also available to remove the device information service. That will save an entry in the GATT table, but not much memory outside it.
Martin, sorry for causing confusion! I posted my question using the wrong github account, deleted it and then got distracted by something so never reposted it.
I seem to remember trying to exclude these two services using MakeCode's project settings a good while ago and it didn't work for me. I'll try again. It would definitely be handy if this worked.
Cheers
Martin
Seems to work now. May cause problems, I guess. You described one in #261. I did say "To experiment..."! The original hex in this case is "no pairing".
Good morning @martinwork
Thanks for the tip on refreshing the page.... I'd tried editing config.json in MakeCode before but it had always seemed to have no effect. Now I see the "compiling will take some time" message.
Unfortunately (and we're doubtless straying into MakeCode issue territory here), my device no longer advertises after attempting to exclude the device information and event services with this fragment:
"bluetooth": {
"open": 1,
"whitelist": 0,
"event_service": 0,
"device_info_service": 0
}
If you have time, could you try this to sanity check please? If you get the same result, I'll drop an issue into the makecode issue tracker.
Thanks
https://makecode.microbit.org/_YDcgCHUV8fs7
Like this? I can connect to this with nRF connect from iOS. It lists services DFU and unknown (which goes if I add the line for partial_flashing). I'm assuming that means it's advertising.
nRF Connect on Android lists the 2 GAs too. The Windows dialogue for adding a Bluetooth device picked it up, once I remembered to remove the existing pairing. And macOS LightBlue too.
Does it work if you remove only the event service?
I suppose there could be caching getting in the way, either so that I can see it or you can't.
Hi @martinwork
your example works for me. I tried mine again and once again it's not advertising with both the event service and device information service disabled. My full settings text are very much like yours except that you have some version stuff at the end:
{
"name": "BDL temperature UART",
"dependencies": {
"core": "*",
"bluetooth": "*"
},
"description": "",
"files": [
"main.blocks",
"main.ts",
"README.md"
],
"yotta": {
"config": {
"microbit-dal": {
"bluetooth": {
"open": 1,
"whitelist": 0,
"event_service": 0,
"device_info_service": 0
}
}
}
}
}
With only event service disabled, I get the same result.
With only device information service disabled, I get the same result.
If I delete both those properties.... hey presto, the device is advertising again.
C'est weird, no?
... stranger than fiction. Maybe the version info is unlocking a new behaviour?
I removed the version info and nothing seems to work now. I can't seem to get it to recompile with different services. This would make sense to me if the version info is essential but it's puzzling because it's different from what you are now seeing. Maybe switching back to no-version text having cached different DAL builds is confusing MakeCode?
NAldred91's example has the version info. Have you tried pasting in the version info?
The version info doesn't seem to make any difference. Tres weird.
I'm out of time on this for today. Will revisit when I next have time. Might be as well to simply report it via the MakeCode tracker and see if they can figure it out.
For some context, one of the things that happens here is that we (the DAL) has configurable size for the GATT table in memory. We pick a sane default for MakeCode that is a balance between having loads of services and running out of memory in normal programs. Sadly, we can't dynamically reclaim unused GATT table space, just once at boot based on the defined size of the table.
As the DAL allows explicit setting of the GATT_TABLE_SIZE at compile time, and that can be overwritten by yotta config ( That's the "gatt_table_size": "0x700" in the config Martin posted above). If your collection of GATT services expands beyond the defined size at runtime, we unfortunately don't know this and your table is truncated. This is why the 'last' service gets cut off.
By expanding the table size, say to 0x800 or 0x900 you can get more services in, but you'll be reducing the free memory for your programme, so increasing the chance of 020 errors. You can try modifying the table sizes to see if there's an appropriate balance that's different to the MakeCode and DAL default.
If you need to reduce the overall memory consumption you can try a few things
- Reduce the number of services (for example, you can use the event service to get button events, or do some things over the UART)
- If you're not relying on MakeCode for people to reprogram your hex, use the DAL by building in C/C++ environment - for example @microbit-sam's latest version of the bluetooth samples hex https://github.com/microbit-sam/microbit-samples/tree/update-all-services/source/examples/bluetooth-services
- Use fewer event handlers and switch on the event type in them: for example Sam's commit here microbit-sam/microbit-samples@adfe8ca does this - it saves a few bytes and it actually counts!
I thought 0x700 was the largest GATT_TABLE_SIZE. Are we using S130 now?