Connecting through Bluetooth BLE

I have a test program put together with AI that will eventually let me share info between a Seeed nRF52840 and Android device through Bluetooth BLE. The Seeed is running in the Arduino environment and the sketch works fine. I can connect to the Seeed with LightBlue and look at the Characteristic UUID and see the info changing.
When I use my AI App, my phone will connect to the Seeed but the info doesn't seem to transfer. It's a simple button click to change an output on the Seeed. Can someone identify what I might be doing wrong in the AI App?
Link to AI App

I have not used the Seeed nRF52840, but I think it works similar to ESP32, can you check if these codes work?

Thanks Juan, I just tried that example code and it doesn't detect any devices. When I click on Scan Bluetooth, it just sits there with no change. If I click Select and Connect, it comes up with a blank list. Would that indicate there is something wrong on the Arduino side of things even though I can use apps like nRF Connect and Blue Light and see the Seeed device?

BTW, I also have to add the "Bluetooth Client" to the program. Otherwise I don't get the option my phone to give permission for "nearby devices". I think this is a known bug in the App Inventor BLE driver.

Did you test with Companion or the APK?

I've only done the APK

Ask for permissions on Android 11+. Search the forum. I have posted several times on this topic.

You mean on the MIT App site or some other Android 11+ site?

So I just tested my code with the AI Companion and it works just fine. When I Scan for for devices I get all the devices I would expect and my Seeed. However it still does not work as a standalone APK.
I searched the MIT Forum for Anke and Android 11 and didn't see any hits.

Show here the code of the Arduino Sketch.

Juan,

It seems to be an issue with the APK version of the Inventor app. The app works when using companion but eventually I will want it to be a stand alone app.

Here is the arduino code though, it's been reduced to a pretty simple sample at this point as I was trying to figure out what the problem was.

#include <ArduinoBLE.h>

const int ledPin = LED_BUILTIN; // set ledPin to on-board LED
const int buttonPin = 3; // set buttonPin to digital pin 4
int led_st = 0, btn_st = 0;

BLEService ledService("19B10010-E8F2-537E-4F6C-D104768A1214"); // create service

// create switch characteristic and allow remote device to read and write
BLEByteCharacteristic ledCharacteristic("19B10011-E8F2-537E-4F6C-D104768A1214", BLERead | BLEWrite | BLENotify);
// create button characteristic and allow remote device to get notifications
BLEByteCharacteristic buttonCharacteristic("19B10012-E8F2-537E-4F6C-D104768A1214", BLERead | BLENotify);

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

  pinMode(ledPin, OUTPUT); // use the LED as an output
  pinMode(buttonPin, INPUT_PULLUP); // use button pin as an input

  // begin initialization
  if (!BLE.begin()) {
    Serial.println("starting Bluetooth® Low Energy module failed!");

    while (1);
  }

  // set the local name peripheral advertises
  BLE.setLocalName("ButtonLED");
  // set the UUID for the service this peripheral advertises:
  BLE.setAdvertisedService(ledService);

  // add the characteristics to the service
  ledService.addCharacteristic(ledCharacteristic);
  ledService.addCharacteristic(buttonCharacteristic);

  // add the service
  BLE.addService(ledService);

  ledCharacteristic.writeValue(led_st);
  buttonCharacteristic.writeValue(btn_st);

  // start advertising
  BLE.advertise();

  Serial.println("Bluetooth® device active, waiting for connections...");
}

void loop() {
  // poll for Bluetooth® Low Energy events
  BLE.poll();

  // read the current button pin state
  if(digitalRead(buttonPin) != btn_st)
  {
    btn_st = !btn_st;
    Serial.println(btn_st);
    buttonCharacteristic.writeValue(btn_st);
  }

  if (ledCharacteristic.written())
  {
    Serial.print("ledCharacteristic = ");
    Serial.println(ledCharacteristic.value());
    
    // update LED, either central has written to characteristic or button state has changed
    if (ledCharacteristic.value()) {
      Serial.println("LED on");
      digitalWrite(ledPin, HIGH);
    } else {
      Serial.println("LED off");
      digitalWrite(ledPin, LOW);
    }
  }
}

For example:

So I tried the app you shared. It worked and the permissions aren't an issue.
I'm still not able to send info from my AI App to my arduino sketch. The data can be shared through the nRF app, so the Arduino sketch is working as expected. I'm really at a loss for what I'm doing wrong on the AI app.

Just sharing again in case anyone sees a glaring error.
I thought the problem might have been how I was sending the character. So I've tried different blocks in the "when LED_On.Click of sending WriteBytes, WriteInteger, Writetext and they all react the same way in that nothing seems to get sent.

#include <ArduinoBLE.h>

unsigned long previousMillis = 0;        // will store last time LED was updated
const long interval = 1000;           // interval at which to blink (milliseconds)

const int ledPin = LED_BUILTIN; // set ledPin to on-board LED
const int buttonPin = 3; // set buttonPin to digital pin 4
int LED_st = 0, btn_st = 0;
unsigned long currentMillis;
    
BLEService ledService("19B10010-E8F2-537E-4F6C-D104768A1214"); // create service

// create switch characteristic and allow remote device to read and write
BLEByteCharacteristic ledCharacteristic("19B10011-E8F2-537E-4F6C-D104768A1214", BLERead | BLEWrite | BLENotify);
// create button characteristic and allow remote device to get notifications
BLEByteCharacteristic buttonCharacteristic("19B10012-E8F2-537E-4F6C-D104768A1214", BLERead | BLENotify);

void blePeripheralConnectHandler(BLEDevice central) {
  // central connected event handler
  Serial.println();
  Serial.print("Connected event, central: ");
  Serial.println(BLE.address());
}

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

  pinMode(ledPin, OUTPUT); // use the LED as an output
  pinMode(buttonPin, INPUT_PULLUP); // use button pin as an input

  // begin initialization
  if (!BLE.begin()) {
    Serial.println("starting Bluetooth® Low Energy module failed!");

    while (1);
  }

  // set the local name peripheral advertises
  BLE.setLocalName("ButtonLED");
  // set the UUID for the service this peripheral advertises:
  BLE.setAdvertisedService(ledService);
 BLE.setEventHandler(BLEConnected, blePeripheralConnectHandler);
 
  // add the characteristics to the service
  ledService.addCharacteristic(ledCharacteristic);
  ledService.addCharacteristic(buttonCharacteristic);

  // add the service
  BLE.addService(ledService);

  ledCharacteristic.writeValue(LED_st);
  buttonCharacteristic.writeValue(btn_st);

  // start advertising
  BLE.advertise();

  Serial.println("Bluetooth® device active, waiting for connections...");

  while(!BLE.connected())   // just wait here until a connection is established
  {
    currentMillis = millis();

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

      Serial.print(".");
    }
  }
}

void loop() {
  // poll for Bluetooth® Low Energy events
  BLE.poll();

  // read the current button pin state
  if(digitalRead(buttonPin) != btn_st)
  {
    btn_st = !btn_st;
    Serial.println(btn_st);
    buttonCharacteristic.writeValue(btn_st);
  }

  currentMillis = millis();

  if (currentMillis - previousMillis >= interval) {
    // save the last time you blinked the LED
    previousMillis = currentMillis;
  
    Serial.print(ledCharacteristic.value());  Serial.print("\t"); Serial.println(LED_st);
  }

  // update LED, either central has written to characteristic or button state has changed
  if(ledCharacteristic.value() != LED_st)
    if (ledCharacteristic.value()) {
      Serial.print("ledCharacteristic = ");
      Serial.println(ledCharacteristic.value());
      Serial.println("LED on");
      digitalWrite(ledPin, HIGH);
      LED_st = 1;
    } else {
      Serial.print("ledCharacteristic = ");
      Serial.println(ledCharacteristic.value());
      Serial.println("LED off");
      digitalWrite(ledPin, LOW);
      LED_st = 0;
    }
}

So I finally got my test app to work and send data to my arduino. I had to use a "BluetoothLE1.WriteIntegersWithResponse" and I'm not sure why. What is the difference between with and without the ...WithResponse part?

1 Like

See the documentation MIT App Inventor + Internet of Things

WriteIntegersWithResponse – Writes one or more 32-bit integer values to a connected BluetoothLE device and waits for an acknowledgement via the IntegersWritten event

Taifun

The documentation doesn't help explain why my App would actually send the data with the ...WithResponse and it doesn't send the data when it's just WriteIntegers. I don't even use the IntegersWritten event in my app but yet the WriteIntegersWithResponse still sends the data.

I posted this earlier but didn't see it on the forum, sorry if it's a repeat post.

I have my app doing mostly what I want. One thing I would like to do is determine which characteristic is sending short data when shorts are received. So I though an if...then would be the right thing to do. You can see in the lower right corner that I'm receiving shorts and then I try to determine which Characteristic is sending the shorts. Then I want to handle the data appropriately based on the Characteristic. When I put a logic true in the if..then it works but when I put the "get .... = get ...." if seems the comparison isn't done.

Am I even approaching this correctly or doing something wrong with my interpretation of how App Inventor works?

I merged your topics together.

Why? They are two different problems and the first was never really answered.

Well, you are using a Logic comparison when the Characteristics are strings, so normally a string comparison would be performed using a 'compare texts' Block.