Nano esp32 keeps disconnecting from usb after code upload

Hi. I've been working on a program that will turn on LEDs if any bluetooth devices with a set name are within a certain range. The code was working fine; I was able to upload to two boards, and the onboard LEDs would behave as expected. I've suddenly run into a problem getting code to upload to either board though. They keep connecting and disconnecting from the usb every few seconds, causing most uploads to fail. I am eventually able to get a basic sketch uploaded either by spamming the upload button until I get lucky, or sometimes by putting it into bootloader mode. Any basic example code runs fine, causes no disconnections. But the moment I upload my code again, the problem reappears.

I've tried walking back through changes I've made in the code, but I'm still running into the same problem. I've done some very simple arduino stuff with LEDs and servos before, but nothing with bluetooth, so maybe there's something I'm missing in the code. I've scanned through the forums looking for anything that might be related, but any help or advice would be appreciated.

Nano ESP32
Windows 11
Arduino IDE 2.3.7 (but I've tried and get the same results from other versions)

/*
  Bluetooth Proximity

  This example scans for Bluetooth® Low Energy peripherals with a specific name, and then turns on LEDs if within a certain range

  The circuit:
  - Arduino Nano ESP32

  SimpleKalmanFilter(e_mea, e_est, q);
  e_mea: Measurement Uncertainty 
  e_est: Estimation Uncertainty 
  q: Process Noise
*/

#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEScan.h>
#include <BLEAdvertisedDevice.h>
#include <SimpleKalmanFilter.h>

int scanTime = 10; //In seconds
BLEScan* pBLEScan;

const int CUTOFF = -42;   // signal strength limit (closer to 0 the closer the devices have to be)

bool flip = true;
const int led = 9;              // the PWM pin the LED is attached to
int brightness = 0;             // how bright the LED is
int fadeAmount = 5;             // how many points to fade the LED by
unsigned long ledTimePrev = 0;  // will store last time pin 9 was update
const long ledInterval = 30;    // interval at which to fade led
bool inRange = false;

SimpleKalmanFilter bleFilter(4, 4, .1);
const long SERIAL_REFRESH_TIME = 1;
long refreshTime;

class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {
    void onResult(BLEAdvertisedDevice advertisedDevice) {
      // Serial.printf("Advertised Device: %s \n", advertisedDevice.toString().c_str());

      String strName;
      strName = advertisedDevice.getName().c_str();
      if ( strName == "SS13" ) {

        float signal = advertisedDevice.getRSSI();
        float estimatedSignal = bleFilter.updateEstimate(signal);

        if (millis() > refreshTime) {
          refreshTime = millis() + SERIAL_REFRESH_TIME;
        }

        if (estimatedSignal > CUTOFF) {                  // device is in range
          inRange = true;
        } else {                                        // device is out of range
          inRange = false;
        }
      }
      BLEDevice::getScan()->stop();
    }
};

void setup() {
  Serial.begin(115200);
  Serial.println("Scanning...");

  pinMode(LED_RED, OUTPUT);

  if (flip) {
    brightness = 255;
  }
  
  BLEDevice::init("SS13");
  BLEDevice::startAdvertising();
  pBLEScan = BLEDevice::getScan(); //create new scan
  pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
  pBLEScan->setActiveScan(true); //active scan uses more power, but get results faster
  pBLEScan->setInterval(100);
  pBLEScan->setWindow(99);  // less or equal setInterval value
}

void loop() {
  BLEScanResults foundDevices = pBLEScan->start(scanTime, false);

  fadeLED(LED_RED);

  pBLEScan->clearResults();   // delete results fromBLEScan buffer to release memory
}

void fadeLED(int l) {

  unsigned long currentMillis = millis();

  if (currentMillis - ledTimePrev >= ledInterval) {
    // save the last time you blinked the LED
    ledTimePrev = currentMillis;

    if (flip) {
      if (inRange && brightness > 0) {        // if in range and less than max, increase
        brightness = brightness - fadeAmount;
      } else if (!inRange && brightness < 255) {  // if out of range and greater than 0, decrease
        brightness = brightness + fadeAmount;
      }  
    } else {
      if (inRange && brightness < 255) {        // if in range and less than max, increase
        brightness = brightness + fadeAmount;
      } else if (!inRange && brightness > 0) {  // ir out of range and greater than 0, decrease
        brightness = brightness - fadeAmount;
      }
    }
    // set brightness
    analogWrite(l, brightness);
  }
}

Two "solutions" on this link... maybe one will work for you...

Yeah, I had seen that thread and tried those. Getting it into bootloader mode does allow me to upload different code to it, like one of the example sketches. But the moment I upload my code again, it goes right back to disconnecting.

Remove that from the callback and set the scantime shorter, like few seconds.

I'll try that. Is there a way to get the scan faster than a second though?

Not with that approach.
Did you get it booting?

Thanks, yes that uploaded fine, and didn't start disconnecting. What would be the approach to get this working in milliseconds rather than seconds?

Never tried something like that on arduino. What is your approach, what you are you looking for to scan in milliseconds and why?

I'm making some prop replicas of the sankara stones from The Temple of Doom, where the stones glow when they get within a foot of another stone. I figured I could use the bluetooths RSSI as a way to determine their proximity to each other, and I'm using a kalman filter to smooth out some of the noise in that signal. This method does work fairly well for getting the distance pretty close, but even at 1 second too much movement can happen, and I need it to be more responsive.

Did you consider espnow for this?

No that didn't pop up when I was researching possible ways to do this for some reason. I'll have to look into that.