Hello,
I am working on a simple BLE connected device to stream live data from a photodiode to an HTML based java program via the MKR 1010 BLE. I have been struggling with this issue for quite some time and I have finally turned to the community for some help.
The setup
I am using Github pages to host a website "ldrebes.github.io" that will be used as a GUI for my live data stream. A similar setup to that of "https://create.arduino.cc/projecthub/8bitkick/sensor-data-streaming-with-arduino-683a6c ". A java program on the webpage is responsible for connecting to and processing my sensor's data.
The Error
After selecting the MKR1010 from a list of Bluetooth devices, it returns the "device.gatt.connect" information, which is expected, but it gets stuck. After some time (30 seconds ish) it returns an error:
Connection failed! DOMExection: GATT Server is diconnected. Cannot retrieve sercives. (re)connect first with 'device.gatt.connect'.
I am successfully able to connect to, read, and subscribe to my characteristics using the LightBlue app, proving to me that at least some part of my communication scheme is working.
Troubleshooting
I have updated the board to the latest firmware that I am aware of/that it will let me, 1.3.0. I have tried using different browsers to see if Chrome has some weird compatibility error. As per one thread where someone had a similar issue albeit with a different microcontroller "Error: "GATT operation failed for unknown reasons" · Issue #28 · thegecko/web-bluetooth-dfu · GitHub", I have added a delay into the loop to slow down the write speeds, but seeing as this negatively affects the sampling rate, which I need to be relatively high (4000 Hz), this is not a fix nor does it solve it. I have found a case where again, someone was experiencing the same issue as me but with a python instead "[Bug] DOMException: GATT Server is disconnected. Cannot retrieve services. (Re)connect first with device.gatt.connect. · Issue #56 · pybricks/support · GitHub" and they mention it to be an issue with a windows update. Does this check out with what you all know?
Discloser:
I am fairly new to BLE, and wireless connectivity for that matter, so some of my terminology and theory may be off. Also, My code largely uses other projects like the aforementioned 8bitkicks project, but at this point, I am just trying to get something to work. I will link all the pertinent documentation that I can think of to aid in your investigation. Thank you for any help you can provide.
Aurduino Code:
#include <ArduinoBLE.h>
#include <Servo.h>
BLEService newService("180A");
BLEBoolCharacteristic switchPos("2A56", BLERead | BLENotify); //Create digital value
BLEIntCharacteristic inSignal("2A58", BLERead | BLENotify); //Create analog read value
pinMode(LED_BUILTIN, OUTPUT); //LED to blink when connected
pinMode(ledPin, OUTPUT); //LED to blink when connected
if (!BLE.begin()) {
Serial.println("starting BLE failed");
while(1);
}
BLE.setLocalName("MKR 1010");
BLE.setAdvertisedService(newService);
newService.addCharacteristic(switchPos);
newService.addCharacteristic(inSignal);
BLE.addService(newService);
switchPos.writeValue(0);
inSignal.writeValue(0);
BLE.advertise();
Serial.println("Bluetooth device active, waiting for connections...");
}
void loop() {
BLEDevice central = BLE.central(); // wait for a BLE central
if (central) { // if a central is connected to the peripheral
Serial.print("Connected to central: ");
Serial.println(central.address()); // print the central's BT address
digitalWrite(LED_BUILTIN, HIGH); // turn on the LED to indicate the connection
while (central.connected()) { // while the central is connected:
long currentMillis = millis();
servoctrl();
if(currentMillis - previousMillis >= 50) { //if 50ms have passed we check the battery level
previousMillis = currentMillis;
int posValue = !digitalRead(2); //gets data from digital input
switchPos.writeValue(posValue); //sends digtital sigal
delay(10);
int signalValue = analogRead(A1); //gets anaolg signal data
inSignal.writeValue(signalValue); //sends analog signal
}
}
digitalWrite(LED_BUILTIN, LOW); //turn off LED when not connected
Serial.print("Disconnected from central: ");
Serial.print(central.address());
}
}
The connection Code where the problem lies:
// fill your peripheral service and characteristic UUIDs here:
const myService = "0000180a-0000-1000-8000-00805f9b34fb"; // fill in a service you're looking for here
const analogCharacteristic = "00002a58-0000-1000-8000-00805f9b34fb"; // fill in analog characteristic from the service here
const digitalCharacteristic = "00002a56-0000-1000-8000-00805f9b34fb"; //fill in digital charcterstic from the service
var myDevice;
if ("bluetooth" in navigator) {
bigButton.addEventListener('click', function(event) {
connect();
});
// else the browser doesn't support bluetooth
} else {
status("browser not supported");
bigButton.style.backgroundColor = "red";
alert("Error: This browser doesn't support Web Bluetooth. Try using Chrome.");
}
function status(stat){
infoBar.innerHTML = stat;
}
// connect to the Bluetooth peripheral:
function connect(){
navigator.bluetooth.requestDevice({
// filters: [myFilters] // you can't use filters and acceptAllDevices together
optionalServices: [myService],
acceptAllDevices: true
})
.then(function(device) {
// save the device returned so you can disconnect later:
myDevice = device;
console.log(device);
// connect to the device once you find it:
return device.gatt.connect();
console.log("Here1");
})
.then(function(server) {
// get the primary service:
return server.getPrimaryService(myService);
console.log("Here2");
})
.then(function(service) {
// get the characteristic:
return service.getCharacteristics(a);
console.log("Here3");
})
.then(function(characteristics) {
// subscribe to the characteristic:
for (c in characteristics) {
characteristics[c].startNotifications()
.then(subscribeToChanges);
}
})
.catch(function(error) {
// catch any errors:
console.error('Connection failed!', error);
});
}
// handle incoming data:
function handleData(event) {
// get the data from the peripheral:
var x = event.target.value.getFloat32(0,true); // true = byte order from Arduino is littleEndian
updateData(x);
}
// disconnect function:
function disconnect() {
if (myDevice) {
// disconnect:
myDevice.gatt.disconnect();
}
}
A schematic of the connections to the Arduino is attached.
