lancaster-university / microbit-dal

http://lancaster-university.github.io/microbit-docs
Other
256 stars 130 forks source link

Accelerometer bluetooth service has no characteristics #443

Open NAllred91 opened 5 years ago

NAllred91 commented 5 years ago

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.

NAllred91 commented 5 years ago

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.

martinwork commented 5 years ago

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?

NAllred91 commented 5 years ago

https://makecode.microbit.org/_9TeX0jfy9FvX

I'll try removing/reordering services now and see if that makes any difference.

NAllred91 commented 5 years ago

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.

martinwork commented 5 years ago

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.

martinwork commented 5 years ago

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.

NAllred91 commented 5 years ago

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.

martinwork commented 5 years ago

No. I should have said "the first connection after a reset". The same memory gets used for subsequent connections.

martinwork commented 5 years ago

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.

ghost commented 5 years ago

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

martinwork commented 5 years ago

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".

smartyw commented 5 years ago

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

martinwork commented 5 years ago

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.

smartyw commented 5 years ago

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?

martinwork commented 5 years ago

... 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?

smartyw commented 5 years ago

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.

jaustin commented 5 years ago

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

martinwork commented 5 years ago

I thought 0x700 was the largest GATT_TABLE_SIZE. Are we using S130 now?