Puck Controlling Puck - Troubleshooting Help

Posted on
  • I am trying to implement the code in the example in this link: https://www.espruino.com/Puck.js+Controlling+Other+Pucks

    I have two Puck.js v1.0 running firmware 2v09. I flashed one with the "peripheral" code and saved it to flash before disconnecting from the Web IDE and power-cycling the Puck. I flashed the other with the "central" code with a few added debug statements in the catch blocks to print out the error.

    When I press the button on the central puck, my the LED flashes red to indicate error and the error is printed to the console: BLE error 0x11 (BUSY). After that, any button presses just report the error "No device found matching filters" until I power-cycle the peripheral Puck. I assume my central puck is successfully connecting but not disconnecting when the error is caught (even though I call the disconnect()) function. This leaves the peripheral Puck in an odd state that can only be fixed with a power-cycle.

    My question is twofold:
    1) Where am I going wrong with the sample code (in the link above) because my peripheral Puck is always busy?
    2) How can I disconnect cleanly on error so I don't have to power-cycle my peripheral Puck every time?

    Since I modified the example code (to add debug statements in the catch() blocks), here is my code:

    // Are we busy?
    var busy = false;
    
    // The device, if we're connected
    var connected = false;
    
    // The 'tx' characteristic, if connected
    var txCharacteristic = false;
    
    // Function to call 'toggle' on the other Puck
    function sendToggle() {
      if (!busy) {
        busy = true;
        if (!connected) {
          NRF.requestDevice({ filters: [{ name: 'Puck.js ....' }] }).then(function(device) {
            return device.gatt.connect();
          }).then(function(d) {
            connected = d;
            return d.getPrimaryService("6e400001-b5a3-f393-e0a9-e50e24dcca9e");
          }).then(function(s) {
            return s.getCharacteristic("6e400002-b5a3-f393-e0a9-e50e24dcca9e");
          }).then(function(c) {
            txCharacteristic = c;
            busy = false;
            // Now actually send the toggle command
            sendToggle();
          }).catch(function(e) {  
            console.log("error: ", e);
            connected=false;
            digitalPulse(LED1, 1, 500); // light red if we had a problem
            busy = false;
            if (connected) connected.disconnect();
          });
        } else {
          txCharacteristic.writeValue("toggle()\n").then(function() {
            digitalPulse(LED2, 1, 500); // light green to show it worked
            busy = false;
          }).catch(function(e) {
            console.log("error: ", e);
            digitalPulse(LED1, 1, 500); // light red if we had a problem
            busy = false;
            if (connected) connected.disconnect();
          });
        }
      }
    }
    
    // Call sendToggle when the button is pressed
    setWatch(sendToggle, BTN, { edge:"rising", debounce:50, repeat: true });
    

    As additional information, the example code in the following documentation articles also fails with a BLE error 0x11 (BUSY) message.

    1. https://www.espruino.com/Reference#l_NRF_requestDevice
    2. https://www.espruino.com/Reference#t_l_NRF_connect

    The sample code in the documentation here: https://www.espruino.com/Reference#t_BluetoothDevice does execute without error. This is leading me to believe that my two Pucks can connect to each other but when I try to use the UART service to send commands, the BLE error 0x11 (BUSY) error is thrown.

  • Hi - this is an odd one. I get this too. It seems like you're doing everything right on the code front.

    Please could you try:

          NRF.requestDevice({ filters: [{ name: 'Puck.js ....' }] }).then(function(device) {
            return device.gatt.connect();
          }).then(function(d) {
            connected = d;
            return new Promise(r => setTimeout(r,500)); //< ---------- added this delay
          }).then(function() {
            return connected.getPrimaryService("6e400001-b5a3-f393-e0a9-e50e24dcca9e");
          }).then(function(s) {
            return s.getCharacteristic("6e400002-b5a3-f393-e0a9-e50e24dcca9e");
          }).then(function(c) {
         ...
    

    That's what worked well for me...

    I'm a bit busy today but I just filed an issue for this at https://github.com/espruino/Espruino/issues/2008 and I'll try and get it fixed properly as soon as I can.

  • Gordon -

    Works like a champ with the added delay. Here's the full code just for anybody looking to see it all together:

    // Are we busy?
    var busy = false;
    
    // The device, if we're connected
    var connected = false;
    
    // The 'tx' characteristic, if connected
    var txCharacteristic = false;
    
    // Function to call 'toggle' on the other Puck
    function sendToggle() {
      if (!busy) {
        busy = true;
        if (!connected) {
          NRF.requestDevice({ filters: [{ name: 'Puck.js ....' }] }).then(function(device) {
            return device.gatt.connect();
          }).then(function(d) {
            connected = d;
            console.log("Connected");
            return new Promise(r => setTimeout(r,500));
          }).then(function() {
            return connected.getPrimaryService("6e400001-b5a3-f393-e0a9-e50e24dcca9e");
          }).then(function(s) {
            return s.getCharacteristic("6e400002-b5a3-f393-e0a9-e50e24dcca9e");
          }).then(function(c) {
            txCharacteristic = c;
            busy = false;
            // Now actually send the toggle command
            sendToggle();
          }).catch(function(e) {
            console.log("error: ", e);
            connected=false;
            digitalPulse(LED1, 1, 500); // light red if we had a problem
            busy = false;
            if (connected) connected.disconnect();
          });
        } else {
          txCharacteristic.writeValue("toggle()\n").then(function() {
            digitalPulse(LED2, 1, 500); // light green to show it worked
            busy = false;
          }).catch(function(e) {
            console.log("error: ", e);
            digitalPulse(LED1, 1, 500); // light red if we had a problem
            busy = false;
            if (connected) connected.disconnect();
          });
        }
      }
    }
    
    // Call sendToggle when the button is pressed
    setWatch(sendToggle, BTN, { edge:"rising", debounce:50, repeat: true });
    

    Thanks for the help!

  • Great - thanks for letting me know! I'll try and get a fix in soon - I'm not sure how that crept into 2v09

  • I'm just looking into this, and with latest firmwares I can't reproduce it running your original code.

    Any hints as to how I might reproduce it here?

  • Ok, I figured it out (I think). This is due to negotiation of a higher MTU since this was added in Espruino 2v09.

    I think if you're connecting to a device with an older firmware you can connect just fine. It's when you connect between two devices with 2v09+ firmware that you have the issue. Follow this on the GitHub issue.

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

Puck Controlling Puck - Troubleshooting Help

Posted by Avatar for Kymvaris @Kymvaris

Actions