MIT App Inventor cannot write to Characteristic

Can someone please help me with an issue?
I'm using an Arduino R4 Wifi/BLE board and I am trying to connect and write to a Characteristic. with MIT App Inventor, using the BluetoothLE addon.

The Arduino script compiles and runs and with an app on my phone called LightBlue, I can connect and read/write all my Characteristics.
The app I wrote with the help of a few YouTube tutorials will connect and it "sees" the Characteristics but can not update them.
How I know this is when I try and write to them, the section in the Arduino script never writes to the Serial Monitor, so I used a code block from the BluetoothLE called .CanWriteCharacteristic and it reports False.

PC OS: Windows 10
Phone: Samsung Galaxy S21, Android v15 UI v7.0

Steps I took.
Made sure I had the latest version of the MIT add on module for BluetoothLE from this page:MIT App Inventor Extensions

Modified the default BLE example to include 4 different type Characteristics thinking it was a byte vs string issue.

My Arduino Code:

/*
LED

This example creates a Bluetooth® Low Energy peripheral with service that contains a
characteristic to control an LED.

The circuit:

  • Arduino MKR WiFi 1010, Arduino Uno WiFi Rev2 board, Arduino Nano 33 IoT,
    Arduino Nano 33 BLE, or Arduino Nano 33 BLE Sense board.

You can use a generic Bluetooth® Low Energy central app, like LightBlue (iOS and Android) or
nRF Connect (Android), to interact with the services and characteristics
created in this sketch.

This example code is in the public domain.
*/

#include <ArduinoBLE.h>

#define SERVICE_UUID "19B10000-E8F2-537E-4F6C-D104768A1214"
#define CHARACTERISTIC1_UUID "19B10001-E8F2-537E-4F6C-D104768A1214"
#define CHARACTERISTIC2_UUID "19B10002-E8F2-537E-4F6C-D104768A1214"
#define CHARACTERISTIC3_UUID "19B10003-E8F2-537E-4F6C-D104768A1214"
#define CHARACTERISTIC4_UUID "19B10004-E8F2-537E-4F6C-D104768A1214"

BLEService ledService(SERVICE_UUID); // Bluetooth® Low Energy LED Service

// Bluetooth® Low Energy LED Switch Characteristic - custom 128-bit UUID, read and writable by central
BLEByteCharacteristic switchCharacteristic(CHARACTERISTIC1_UUID, BLERead | BLEWrite);
BLEByteCharacteristic byteCharacteristic(CHARACTERISTIC2_UUID, BLERead | BLEWrite | BLENotify);
BLEIntCharacteristic intCharacteristic(CHARACTERISTIC2_UUID, BLERead | BLEWrite | BLENotify);
BLEStringCharacteristic strCharacteristic(CHARACTERISTIC3_UUID, BLERead | BLEWrite | BLENotify, 20);
BLEFloatCharacteristic floatCharacteristic(CHARACTERISTIC4_UUID, BLERead | BLEWrite | BLENotify);

// This needs to be "2901", have no idea why
BLEDescriptor switchCharacteristicDescriptor("2901", "LED Switch");
BLEDescriptor byteCharacteristicDescriptor("2901", "Byte Char");
BLEDescriptor intCharacteristicDescriptor("2901", "Int Char");
BLEDescriptor strCharacteristicDescriptor( "2901", "String Char");

const int ledPin = LED_BUILTIN; // pin to use for the LED
int value = 0;

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

// set LED pin to output mode
pinMode(ledPin, OUTPUT);

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

while (1);

}

// set advertised local name and service UUID:
BLE.setLocalName("Arduino LED");
BLE.setAdvertisedService(ledService);

// add the descriptor to the characteristic
switchCharacteristic.addDescriptor(switchCharacteristicDescriptor);
byteCharacteristic.addDescriptor(byteCharacteristicDescriptor);
intCharacteristic.addDescriptor(intCharacteristicDescriptor);
strCharacteristic.addDescriptor(strCharacteristicDescriptor);

// add the characteristic to the service
ledService.addCharacteristic(switchCharacteristic);
ledService.addCharacteristic(byteCharacteristic);
ledService.addCharacteristic(intCharacteristic);
ledService.addCharacteristic(strCharacteristic);
ledService.addCharacteristic(floatCharacteristic);

// add service
BLE.addService(ledService);

// set the initial value for the characteristic:
switchCharacteristic.writeValue(0);
intCharacteristic.writeValue(0);
strCharacteristic.writeValue("Nothing");
floatCharacteristic.writeValue(0);

// start advertising
BLE.advertise();

Serial.println("BLE LED Peripheral");
}

void loop() {
// listen for Bluetooth® Low Energy peripherals to connect:
BLEDevice central = BLE.central();

// if a central is connected to peripheral:
if (central) {
Serial.print("Connected to central: ");
// print the central's MAC address:
Serial.println(central.address());

// while the central is still connected to peripheral:
while (central.connected()) {

  // if the remote device wrote to the characteristic,
  // use the value to control the LED:
  // written: Query if the characteristic value has been written by another Bluetooth® Low Energy device.### Syntax
  if (switchCharacteristic.written()) {
    if (switchCharacteristic.value()) {   // read any value other than 0
      Serial.println("LED on");
      digitalWrite(ledPin, HIGH);         // will turn the LED on
    } else {                              // a 0 value
      Serial.println(F("LED off"));
      digitalWrite(ledPin, LOW);          // will turn the LED off
    }
  }

  if(intCharacteristic.written()) {
      Serial.println("Integer Written: " + intCharacteristic.value());
      Serial.print(intCharacteristic.value());
      Serial.println();
  }

  if(strCharacteristic.written()) {
      Serial.println("String Written:");
      Serial.print(String(strCharacteristic.value()));
      Serial.println();
  }

  if(floatCharacteristic.written()) {
      Serial.println("Float Written:");
      Serial.print(floatCharacteristic.value());
      Serial.println();
  }

// byteCharacteristic.setValue(value);
// intCounterCharacteristic.setValue(value);
// value++;
// delay(1000);
}

// when the central disconnects, print it out:
Serial.print(F("Disconnected from central: "));
Serial.println(central.address());

}
}

My App Inventor blocks:



image

My Phone screenshot:

The BLEWrite flag in Arduino is a BLE write with response, so you need to use the CanWriteCharacteristicWithResponse block instead. Alternatively, you can add the BLEWriteWithoutResponse flag to your characteristic.

You are awesome! I fought with this for hours.
OK, so if I understand you, if I use the BLEWrite in Arduino then I must use the .WriteStringsWithResponse in MIT, and in return I can read the response with .StringsWritten, like this:

Now I have more questions please...
The .StringsWritten sends me back the same string or list of strings that I sent. Is that just a check or is it good for anything.

What I intended to use this for was a control panel on a tablet that talks to the Arduino which is mounted on a car so it can control the motors.
I think I'd like live feed back too.

If I use the permission BLEWriteWithoutResponse, then it's like a "fire and forget post to the Arduino, correct?

What does the .StringsReceived block do? Can I send a value to the phone from the Arduino without the phone asking for it?

Thank you again. There doesn't seem (that I'm finding), a lot of information on this new Arduino's BLE.

If you need to queue a bunch of operations it can be helpful for coordinating them. All of the Write* functions do this.

Correct. If you're familiar with networking, BLEWrite is like TCP/IP and BLEWriteWithoutResponse is like UDP. The peripheral in the former case must acknowledge receipt of the message, so it's slower to communicate.

The StringsReceived block will run either when you call ReadStrings, which initiates a read, or RegisterForStrings, which will get notifications of changes when you update the characteristic on the Arduino.

I can call this topic closed.
If anyone else lands here looking for answers; if the Arduino has issues connecting, from the Designer, click on the BluetoothLE control and set the default timeout from 10 to 20. That fixed it for me.

If:
BLEBoolCharacteristic switchCharacteristic(CHARACTERISTIC1_UUID, BLERead | BLEWrite);
Then you need to write to it using .WriteBytesWithResponse

If:
BLEBoolCharacteristic switchCharacteristic(CHARACTERISTIC1_UUID, BLERead | BLEWriteWithoutResponse);
Then it's a fire and forget.

Using the .BytesReceived, you can add an If statement to it and check for what Characteristic was last written to.
When getting the characteristicUuid, it comes in in LOWER case, use an upcase on it.

As I learn more things, I'll add them here. That will keep other new people from stress.

Thank you again.

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.