BLE Stuck in Connected, Reconnect loop (GPS)

Hi! Now im reaching out here to see if someone has an solution on my issue. I have searched the Forum for answer but not found any that match my issue. I have tried the different BLE connections found here on the forum but still no success.

I have made a DIY GPS module with an Adafruit ESP32-S3 feather. It has built in Wifi and BT.
I got it working good with Wifi but cant figure out the BLE connection.

When i connect my phone to the DIY BLE it connects and stays connected. In the nRF app i can see it was pushing the NMEA msg. (GGA, RMC) but when connecting to it in the Racechrono app (Android) under "Other Devices - BLE - GPS" its constantly saying Connected, Connecting..., Connected in a never ending loop. If i set it up as a "monitor" it stays connected.

Here is my code now, I have fiddle alot and gave up alittle as i got it working with the Wifi connection, so the GPS MSG is maybe not structed correct right now.

// ESP32-S3 BLE GPS Adapter for RaceChrono+
// Hardware: Adafruit Feather ESP32-S3 + NMEA GPS module on Serial1
// GPS TX -> GPIO 16 (RX), GPS RX -> GPIO 17 (TX)

#include
#include
#include

// Setup GPS
HardwareSerial gpsSerial(1);
Adafruit_GPS GPS(&gpsSerial);
#define GPS_BAUD 115200
#define PMTK_SET_NMEA_UPDATE_8HZ "$PMTK220,125*2C" // 125ms = 8Hz

// UUIDs (aollin compatible)
#define SERVICE_UUID "00000001-0000-00fd-8933-990d6f411ff8"
#define CHAR_UUID_GPS_MAIN "00000003-0000-00fd-8933-990d6f411ff8"
#define CHAR_UUID_GPS_TIME "00000004-0000-00fd-8933-990d6f411ff8"

NimBLEServer* pServer = nullptr;
NimBLECharacteristic* gpsMainChar = nullptr;
NimBLECharacteristic* gpsTimeChar = nullptr;

bool isConnected = false;
uint8_t syncBits = 0;
int lastDateAndHour = -1;

class ServerCallbacks : public NimBLEServerCallbacks {
void onConnect(NimBLEServer* pServer) override {
isConnected = true;
Serial.println("BLE connected");
}

void onDisconnect(NimBLEServer* pServer) override {
isConnected = false;
Serial.println("BLE disconnected");
NimBLEDevice::startAdvertising();
}
};

void setupBLE() {
NimBLEDevice::init("RC-DIY-GPS");
pServer = NimBLEDevice::createServer();
pServer->setCallbacks(new ServerCallbacks());

NimBLEService* service = pServer->createService(SERVICE_UUID);

gpsMainChar = service->createCharacteristic(
CHAR_UUID_GPS_MAIN,
NIMBLE_PROPERTY::NOTIFY | NIMBLE_PROPERTY::READ
);

gpsTimeChar = service->createCharacteristic(
CHAR_UUID_GPS_TIME,
NIMBLE_PROPERTY::NOTIFY | NIMBLE_PROPERTY::READ
);

service->start();
NimBLEAdvertising* advertising = NimBLEDevice::getAdvertising();
advertising->addServiceUUID(SERVICE_UUID);
advertising->start();
Serial.println("BLE advertising started");
}

void setupGPS() {
gpsSerial.begin(GPS_BAUD, SERIAL_8N1, 16, 17);
GPS.begin(GPS_BAUD);
GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA); // Only RMC and GGA
GPS.sendCommand(PMTK_SET_NMEA_UPDATE_8HZ); // 8Hz
delay(1000);
GPS.println("$PMTK220,125*2C"); // Force 8Hz update rate
}

void setup() {
Serial.begin(115200);
setupBLE();
setupGPS();
}

void loop() {
GPS.read();
if (!GPS.newNMEAreceived()) return;
if (!GPS.parse(GPS.lastNMEA())) return;

if (!isConnected) return;

if (!GPS.fix) {
uint8_t dummy[20] = {0};
gpsMainChar->setValue(dummy, 20);
gpsMainChar->notify();
return;
}

int dateHour = (GPS.year * 8928) + ((GPS.month - 1) * 744) + ((GPS.day - 1) * 24) + GPS.hour;
if (dateHour != lastDateAndHour) {
syncBits++;
lastDateAndHour = dateHour;
}

int ms = GPS.milliseconds;
int timeSinceHour = (GPS.minute * 60000) + (GPS.seconds * 1000) + ms;

int32_t lat = GPS.latitude_fixed;
int32_t lon = GPS.longitude_fixed;
int altitude = (int)(GPS.altitude * 10.0f);
int speed = (int)(GPS.speed * 100.0f);
int bearing = (int)(GPS.angle * 100.0f);
int hdop = (int)(GPS.HDOP * 10.0f);

// Main packet
uint8_t mainData[20];
mainData[0] = ((syncBits & 0x7) << 5) | ((timeSinceHour >> 16) & 0x1F);
mainData[1] = (timeSinceHour >> 8);
mainData[2] = (timeSinceHour);
mainData[3] = ((std::min(3, (int)GPS.fixquality) << 6) | std::min(63, (int)GPS.satellites));
mainData[4] = (lat >> 24); mainData[5] = (lat >> 16); mainData[6] = (lat >> 8); mainData[7] = lat;
mainData[8] = (lon >> 24); mainData[9] = (lon >> 16); mainData[10] = (lon >> 8); mainData[11] = lon;
mainData[12] = (altitude >> 8); mainData[13] = altitude;
mainData[14] = (speed >> 8); mainData[15] = speed;
mainData[16] = (bearing >> 8); mainData[17] = bearing;
mainData[18] = hdop;
mainData[19] = 0xFF; // unused

gpsMainChar->setValue(mainData, 20);
gpsMainChar->notify();

// Time packet
uint8_t timeData[3];
timeData[0] = ((syncBits & 0x7) << 5) | ((dateHour >> 16) & 0x1F);
timeData[1] = dateHour >> 8;
timeData[2] = dateHour;
gpsTimeChar->setValue(timeData, 3);
gpsTimeChar->notify();

delay(1);
}

Comments

Sign In or Register to comment.