Bluetooth disconnecting after 1 second

Posted on
Page
of 2
/ 2
Next
  • I'm trying to use my Bangle.js 2 to connect to a Bluetooth service running on an ESP32.

    This is the Arduino code running on the ESP32: https://gist.github.com/jes/65832156dc0e­ded2b167c3c1da184cde - it creates a single characteristic that repeatedly writes "hello\0" and notifies. It is based on an example program I copied.

    This is the Espruino code running on the Bangle.js 2: https://gist.github.com/jes/36b8ea811706­ee1db4ceab6e37ab8af2 - it connects to the Bluetooth device and tells me how long it took to disconnect, it's always about 1.0 seconds.

    This is the output I get on the Web IDE console: https://gist.github.com/jes/731b57ce4c62­ba8fcb451858f7dfa024 - reason 62 is BLE_HCI_CONN_FAILED_TO_BE_ESTABLISHED.

    And this is a session using gatttool, just to show that the Arduino code actually does work: https://gist.github.com/jes/34b7dd8fb1ec­4737bb3950ce7f649dd6

    I'm using the "upload to RAM" method in the Web IDE, but the behaviour seems to be the same even if I write the code to disk, disconnect from Web Bluetooth, and send output to the LCD instead of the console.

    If instead of just connecting to the Bluetooth device, I actually try to get a service, then I get an additional error:

    Uncaught InternalError: BLE task completed that wasn't scheduled (SERVICE/NONE)

    From what I've been able to find on this forum, the most likely cause for this is that the device I'm trying to connect to is simply ignoring the connection attempt. I have tried varying the minInterval and maxInterval options, and it seems as though the disconnection always comes after 5x maxInterval, regardless of what I set it to.

    Can anyone see anything wrong in either my Arduino code or Espruino code that would cause the problem? Or otherwise suggest what I might be doing wrong? The 2 devices are within 20 centimetres on my desk, the Espruino-reported rssi is very good (about -40) and the problem happens every single time, not intermittently, do I don't think it's a signal strength problem.

    Thanks.

  • This is some sort of heavy stress test? You are sending notification every 10ms? That is very fast for BLE. The smallest connection interval (fastest request/response packet turnaround possible) in BLE is 7.5ms. I'd start with sending the notification slower.

  • It's not intended to be a stress test, it's just something I'm adapting to transmit sensor readings over Bluetooth. More frequent is better, but it doesn't need to be that frequent.

    Sadly no luck with your suggestion. I tried changing the delay(10) to delay(1000) but it still behaves the same: the Bangle.js 2 disconnects with reason 62 after almost exactly 1 second.

  • OK, maybe the reason is simple - the address is not correct so it cannot find your device, can you check http://www.espruino.com/Reference#l_NRF_­connect and see the hint about addresses on the bottom about static random etc. It would be best if you would first scan for your device and see how the address is reported and use exactly that string.

    EDIT: but since you actually get connection and then get disconnected this makes no sense

  • And BTW I took some ESP32 C3 board from drawer, installed latest Arduino, then installed ESP32 as per https://github.com/espressif/arduino-esp­32 and tried to do some example too. The one you are using look a bit strange but I see where it comes from :-)
    https://github.com/espressif/arduino-esp­32/blob/master/libraries/BLE/examples/BL­E_notify/BLE_notify.ino
    Well it is Arduino after all so no wonder it is so sketchy :-)
    Anyway, going through the BLE library sources is interesting - when calling notify() nothing is actually sent unless someone subscribed for notifications (which is good). Also I compiled that example and unfortunately it is working for me from Espruino side. My device is named C3 so this

    NRF.findDevices(function(devices) {
      console.log(devices);
    },{timeout:5000,filters : [{ name:"C3" }] }); 
    

    gives me

    [
      BluetoothDevice: {
        "id": "60:55:f9:79:a7:2a public",
        "rssi": -36,
        "data": new Uint8Array([2, 1, 6, 3, 9, 67, 51, 2, 10, 9, 17, 7, 75, 145, 49, 195, 201, 197, 204, 143, 158, 69, 181, 31, 1, 194, 175, 79]).buffer,
        "name": "C3",
        "services": [
          "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
         ]
       }
     ]
    

    and your code just with my mac address

    NRF.connect("60:55:f9:79:a7:2a").then(fu­nction(gatt) {
      console.log(gatt);
      console.log("connected");
      var t = getTime();
      gatt.device.on('gattserverdisconnected',­ function(reason) {
        console.log("disconnected (" + reason + ") after " + (getTime()-t) + " secs");
      });
    }).catch(function(e) {
      console.log("error: " + e);
    });
    

    gives me immediate connect

    =Promise: {  }
    BluetoothRemoteGATTServer: {
      "device": BluetoothDevice: {
        "id": "60:55:f9:79:a7:2a",
        "gatt":  ...
       },
      "connected": true }
    connected
    

    So I am not sure what is wrong in your case.
    My example is here https://gist.github.com/fanoush/cf64ab20­4f9f200ee15cf1c1ec60ed1c it is mostly the same as yours.

  • Oh, interesting. I was not using Bangle 2 but other board. With Bangle 2 I see the same issue

    =Promise: {  }
    BluetoothRemoteGATTServer: {
      "device": BluetoothDevice: {
        "id": "60:55:f9:79:a7:2a",
        "gatt":  ...
       },
      "connected": true, "handle": 0 }
    connected
    disconnected (62) after 0.99880981445 secs
    

    however it is inconsistent, when I try second time it often works.
    I do not 'upload to ram' I just copy paste( ctrl+v) that code into left side and then just press up key and run it again

  • Thanks for taking a look! It's encouraging that you can reproduce the problem, although I'm not sure why it's intermittent. I tried it using your exact code and it disconnects after ~1.0 seconds, exactly the same for me every single time. I'm running the 2v18 firmware on the watch. I tried both with "upload to ram" and pasting into the console.

    My Arduino is also an ESP32-C3 FWIW, it's a Xiao from "seeed studio".

  • for me it mostly works even with Bangle, when it disconnects in 1 second I see on arduino side that it did not notice the connection at all. Googled it and found one explanation

    The error code 0x3E means "failed to establish". The BT core spec states that if a master does not receive a packet from the slave within the first 6 connection events after sending a connection requests then the master considers the connection lost.

    You most likely are getting this because your slave device is not receiving the connection request, and therefore is just continuing to advertise. The master then tries 6 connection events and never gets a packet.

    I think this is what happens here Arduino side is ignoring the connection attempt.
    I build the example with Tools -> Core Debug Level -> Verbose and I see lot of info when connection is estabilished but in this case when it does not work I see nothing on Arduino side

  • I didn't know about the "core debug level" option. I just tried it with Verbose, and I see a bunch of stuff at startup, and a bunch of stuff when I connect using gatttool, but indeed nothing at all when the Bangle.js 2 tries to connect.

    So are we saying that the Bangle.js 2 is just (sometimes, in your case, and always, in my case) not sending the connection request?

    I wonder if I could try connecting it to some other type of device to see if that works, I'll try to think of something. Obviously Web Bluetooth works for the IDE so it's not like Bluetooth is completely non-functional.

  • I tried the same test with an old Bangle.js, running 2v11, and I see the same thing as you: sometimes it connects and stays connected, sometimes it disconnects after just under a second.

    At least, I think it stays connected - I haven't checked to see whether it actually works.

  • I tried with several nrf52832 and 52840 Espruino devices of various FW versions and I don't see this error on any of them except Bangle.js 2. I even tried nrf52840 dongle with 2v17(my Bangle.js 2 is also 2.v17) and same version of nordic SoftDevice and don't see it there either. So looks like something specific to Bangle2 build. The 52840 dongle build is very similar but not exactly same.

    So are we saying that the Bangle.js 2 is just (sometimes, in your case, and always, in my case) not sending the connection request?

    Can be it is sending it (because you are even connected for a second) but then does not get the response. Or manages to miss it somehow due to some timing. The bunch of stuff on Arduino can be there once both devices agree on connection. So can be there is nothing while the low level esp32 stack does get the connection attempt from Bangle.

    Can you try non C3 board? C3 is relatively new, there are bugs like this one https://github.com/espressif/esp-idf/iss­ues/11280 which could possibly affect it. Bangle can do 2M PHY but so can the 52840 dongle that works.

  • I don't have any ESP32 that's not a C3, so I'd have to wait for one to arrive. Can you suggest what I should buy?

    I am now finding that it doesn't work at all even on the original Bangle.js. In fact in total I think it only worked once, and it's not obvious to me whether it actually worked, or just didn't notice that it didn't work.

    I know it says "connected", but it's not obvious to me that that callback runs after it actually connected, compared to when it merely thinks it was connected. The "connection failed to be established" error suggests it was never connected in the first place.

  • I don't have any ESP32 that's not a C3, so I'd have to wait for one to arrive. Can you suggest what I should buy?

    Then it probably not worth getting it just for this. Classic ESP32 chip is there for years, C3,S3,S2 are all relatively new so can be more buggy. I do have some ESP32 somewhere, will try.

  • OK, some progress on the original Bangle.js. It very rarely works (maybe 1 in 30 times), but I have observed it working and successfully reading out data from the characteristic:

    NRF.connect("34:85:18:00:38:8e").then(fu­nction(gatt) {
      console.log(gatt);
      console.log("connected");
      var t = getTime();
      gatt.device.on('gattserverdisconnected',­ function(reason) {
        console.log("disconnected (" + reason + ") after " + (getTime()-t) + " secs");
      });
      return gatt.getPrimaryService("4fafc201-1fb5-45­9e-8fcc-c5c9c331914b");
    }).then(function(service) {
      console.log("got service: ");
      console.log(service);
      return service.getCharacteristic("beb5483e-36e1­-4688-b7f5-ea07361b26a8");
    }).then(function(characteristic) {
      console.log("got characteristic, value = ");
      characteristic.readValue().then(function­(v) { console.log(v); });
      characteristic.on('characteristicvaluech­anged', function() {
        console.log("characteristicvaluechanged:­ ");
      characteristic.readValue().then(function­(v) { console.log(v); });
      });
    }).catch(function(e) {
      console.log("error: " + e);
    });
    

    gives:

    BluetoothRemoteGATTServer: {
      "device": BluetoothDevice: {
        "id": "34:85:18:00:38:8e",
        "gatt":  ...
       },
      "connected": true }
    connected
    got service:
    BluetoothRemoteGATTService: {
      "uuid": "4fafc201-1fb5-459e-8fcc-c5c9c331914b",
      "isPrimary": true, "start_handle": 40, "end_handle": 65535 }
    got characteristic, value =
    DataView: {
      "buffer": new Uint8Array([4, 0, 0, 0]).buffer,
      "byteOffset": 0, "byteLength": 4 }
    

    However you'll notice that the "characteristicvaluechanged" callback is not firing. I left it running for several minutes and it didn't fire even once, so I think the "notify" response is not working. But this is progress, at least, and in the worst case I can probably read out the characteristic value on a timer, so there is light at the end of the tunnel!

    It would still be better if it worked on Bangle.js 2, and if it worked every time instead of only 1/30 times.

    (The MAC address is different because I'm using a different ESP32C3, but that's just an accident - it still doesn't work on the Bangle.js 2).

  • However you'll notice that the "characteristicvaluechanged" callback is not firing

    you're missing subscribing to notification step via startNotifications()
    see https://forum.espruino.com/comments/1675­2991/

    I found ESP32 Wroom-32 module and uploaded the very same sketch to it and from Bangle 2 it works almost fine. Like 9 out of 10 tries or even better. I've seen the same disconnect error but very very rarely - like 3 times out of many. Definitely never twice in a row.

  • Aha, service.startNotifications() was helpful, thanks.

    Sadly I've already built the device that has an ESP32-C3 potted inside it so it's inconvenient to change. Since it was working with gatttool I assumed it wouldn't be too much trouble to use it with a Bangle.js.

    I wrote a Bangle.js program that keeps retrying to connect until it works, but sometimes it takes several minutes to get a working connection even with the original Bangle.js (and it has still not worked even once on the Bangle.js 2). But it does work once it's connected.

    I'm thinking of inverting the "client" and "server" to see if that works any better. I.e. make the ESP32 connect to the Bangle.js and send readings that way instead. Slightly inconvenient that you can't use the Web IDE console while something else is connected to the Bangle.js though.

  • You could try NRF.setConnectionInterval(50) or something like that? I guess it's possible that because you are also connected to the Bangle via Bluetooth, it'll be in it's high-bandwidth 7.5ms mode, and maybe because it's spending a bunch of time doing that, it ends up not being able to service the ESP32 bluetooth connection within a time period the ESP32 is happy with?

    @fanoush when you tried the other devices, were they USB/Serial ones? Or did you try those when connecting to them over Bluetooth too?

  • Or did you try those when connecting to them over Bluetooth too?

    Yes, I tried it mostly over bluetooth and it worked too, no difference. It is strange. Only Bangle2 vs this C3 board causes the issue for me. Any other Espruino build has no issues and connects to this C3 just fine. Also bangle 2 to classic ESP32 chip with same arduino code source just build for different target board is almost flawless but I see it occasionally there too.

    Does NRF.setConnectionInterval affect future conections?
    I tried NRF.connect() also with options {minInterval:xx, maxInterval:yy}) but it did not fix the issue, maybe it made it even worse or same. What is clear is that it does affect the time where it 'disconnects'. By default it is exactly 1 second, changing max/minIterval make it shorter or longer but does not help with successful connection.

  • Thanks for the suggestion. I tried NRF.setConnectionInterval(50) on both the Bangle.js 1 and 2 and it didn't make any obvious improvement.

    I have had some success in making the ESP32 connect to the Bangle.js and draw the sensor readings on the screen. This seems more reliable than the other way around, but still quite unreliable. It does seem to work well once it's connected, but getting it connected can take a minute or 2. And again it's much worse on Bangle.js 2 than on the original Bangle.js, I haven't got it to work at all with the Bangle.js 2.

  • Oh, just an idea, I think my other builds (including nrf52840 dongle) are all using RC clock, bangle is using XTAL so may use stricter BLE timings? maybe this C3 has slightly bad BLE timings? I wonder if this strict timing https://github.com/espruino/Espruino/blo­b/25b7987897be6067ef83d9d0ce353dc8288362­2c/targets/nrf5x/app_config.h#L164 could affect it.

    I guess it keeps radio on a bit longer with RC when it is not so accurate?

    EDIT: however bangle 1 also uses RC clock, I don't see ESPR_LSE_ENABLE in its board file

  • @jes If you want, you can try attached file, it is build with this line https://github.com/espruino/Espruino/blo­b/master/boards/BANGLEJS2.py#L48
    commented out

    Use only if you don't mind flashing custom possibly broken firmware and can recover. When I get back home I'll try it myself.


    1 Attachment

  • Thanks @fanoush I will give that a go.

    For now I have found the most success by writing the sensor values into the "manufacturer data" field, and using NRF.findDevices to discover the manufacturer data. Since I only need one-way communication this will probably be good enough for me, but I'll give the firmware a try as it would obviously be better if it worked properly.

  • Your new firmware exhibits broadly the same behaviour. It disconnects after just under a second (about 0.93 seconds now, but I'm not sure if that's because of the new firmware or because I was messing with NRF.setConnectionInterval() earlier).

    I let it try over 100 times and it didn't work even once.

  • @jes OK, so the clock source change does not help. Here is another one, it disables larger MTU negotiation. This makes communication slower but more compatible to old devices and also the connection negotiation is simpler. Flashed it to my watch via the Firmware Update
    https://banglejs.com/apps/?q=firmware and it still works (don't have C3 board here).


    1 Attachment

  • Tried the zip above without higher MTU negotiation with the C3 board and it is much better for me. I still see the issue but now I mostly get the connection. Which means it is not related to MTU negotiation procedure itself as it still happens (sometimes even 3 times in a row) but looks like the shorter packets with more time between connection intervals has better success.

    Yet I retried with my other devices which negotiate higher MTU too and I really don't see this there. One device failed few times immediately with "error: Connection Timeout" but then it started to work, no disconnect. 52840 dongle with 2.17 works perfectly again, cannot see the issue there.

  • Post a reply
    • Bold
    • Italics
    • Link
    • Image
    • List
    • Quote
    • code
    • Preview
About

Bluetooth disconnecting after 1 second

Posted by Avatar for jes @jes

Actions