arduino-libraries / ArduinoBLE

ArduinoBLE library for Arduino
GNU Lesser General Public License v2.1
311 stars 205 forks source link

analogWrite() while BLE is connected causes CPU crash #118

Closed bitbank2 closed 3 years ago

bitbank2 commented 4 years ago

On the Arduino Nano 33 BLE board, with an active BLE connection, if you use analogWrite() on a GPIO pin, the BLE connection will immediately drop and the CPU will crash such that it sits blinking the D13 LED. This problem is 100% reproducible on the latest Nano33 BLE + ArduinoBLE library.

polldo commented 4 years ago

Hi @bitbank2 , I've tried to reproduce this issue with the test conditions listed below, but I've not found the effects you described. Could you post a sketch triggering this issue and your test conditions? Thanks.

Test conditions: ArduinoBLE library: version 1.1.3-11-g524b3a6 Arduino-nRF582x core: version 1.1.6 BLE peripheral: nano 33 iot running the example LED BLE central: nano33ble running the sketch posted below. This sketch is basically a simple customization of the example LedControl . Here, while a BLE connection is established, the analogWrite function is called on an analog output. sketch:


#include <ArduinoBLE.h>

#define ANALOG_PIN (A2)

void setup() {
  Serial.begin(115200);
  while (!Serial);

  pinMode(ANALOG_PIN, OUTPUT);

  // initialize the BLE hardware
  BLE.begin();

  Serial.println("BLE Central - LED control");

  // start scanning for peripherals
  BLE.scanForUuid("19b10000-e8f2-537e-4f6c-d104768a1214");
}

void loop() {
  // check if a peripheral has been discovered
  BLEDevice peripheral = BLE.available();

  if (peripheral) {
    // discovered a peripheral, print out address, local name, and advertised service
    Serial.print("Found ");
    Serial.print(peripheral.address());
    Serial.print(" '");
    Serial.print(peripheral.localName());
    Serial.print("' ");
    Serial.print(peripheral.advertisedServiceUuid());
    Serial.println();

    if (peripheral.localName() != "LED") {
      return;
    }

    // stop scanning
    BLE.stopScan();

    controlLed(peripheral);

    // peripheral disconnected, start scanning again
    BLE.scanForUuid("19b10000-e8f2-537e-4f6c-d104768a1214");
  }
}

void controlLed(BLEDevice peripheral) {
  // connect to the peripheral
  Serial.println("Connecting ...");

  if (peripheral.connect()) {
    Serial.println("Connected");
  } else {
    Serial.println("Failed to connect!");
    return;
  }

  // discover peripheral attributes
  Serial.println("Discovering attributes ...");
  if (peripheral.discoverAttributes()) {
    Serial.println("Attributes discovered");
  } else {
    Serial.println("Attribute discovery failed!");
    peripheral.disconnect();
    return;
  }

  // retrieve the LED characteristic
  BLECharacteristic ledCharacteristic = peripheral.characteristic("19b10001-e8f2-537e-4f6c-d104768a1214");

  if (!ledCharacteristic) {
    Serial.println("Peripheral does not have LED characteristic!");
    peripheral.disconnect();
    return;
  } else if (!ledCharacteristic.canWrite()) {
    Serial.println("Peripheral does not have a writable LED characteristic!");
    peripheral.disconnect();
    return;
  }

  while (peripheral.connected()) {
    static unsigned long time = millis();
    static uint8_t ledState = 0;
    static uint8_t analogValue = 0;
    if (millis() - time >= 5000) {
      time = millis();
      analogValue += 10;
      if (analogValue >= 250)
        analogValue = 0;
      analogWrite(ANALOG_PIN, analogValue);
      Serial.println("Analog written");
      ledCharacteristic.writeValue(ledState);
      ledState ^= 0x01;
    }
  }

  Serial.println("Peripheral disconnected");
}
bitbank2 commented 4 years ago

Thanks for trying to tackle the issue. My steps were:

1) Set digital pins 2-9 as type OUTPUT 2) Connect to BLE peripheral 3) Set the state of pins 2-9 using analogWrite() --> Crash

polldo commented 4 years ago

@bitbank2 Thanks for reporting. Actually this issue is not related to BLE, the problem is that the nordic chip is configured through mbed to only have 4 instances of pwm HERE. So, using more than 4 pwm results in a mbed failure. We will address this problem by giving users the possibility to disable an already active PWM. However, users should be careful not to use more than 4 analog out pins active at the same time. https://github.com/arduino/ArduinoCore-nRF528x-mbedos/pull/105

bitbank2 commented 4 years ago

What's interesting about this comment is that in my early experiments with the Nano33 I was actively using 8 PWM outputs at once and they worked as expected. It wasn't until I added the BLE connection that the CPU crashed.

polldo commented 3 years ago

I confirm that the problem is not related to BLE but to the mbed ADC limitation that I mentioned here https://github.com/arduino-libraries/ArduinoBLE/issues/118#issuecomment-701264384 . Also, the fix I was mentioning has been implemented and merged here https://github.com/arduino/ArduinoCore-mbed/commit/1efbfac0e57c717e4974c61b68cdcf0aaddb0be9 @bitbank2 thanks for reporting!