BLE ESP32. Bluetooth. Send. Receive. Arduino IDE. Multitouch

This tutorial is about send/receive image Android/Arduino by BT.

ESP32 works with Bluetooth classic and BLE, try with Bluetoot classic first.
Use small files to try.

Heey i followed the guide to send and receive data but i get this error everytime i run companion.

Error from Companion: java.lang.NoClassDefFoundError: edu.mit.appinventor.ble.BluetoothLEint$1

Then i get this when i press enable BT
invoke: no method named `EnableBluetooth' in class java.lang.Boolean

and goes like that .
Seems its the extensions causing it , i know for sure bluetoothLE is causing me issues cuz i can run the app without it ,but i need the extensions to read and send sensor data .
any ideas what this could be ?

Check that you are using the current version of the Companion, 2.60 or 2.60u
If that's not the problem, export and post your .aia file here.


Please export your project and post it here.

Hey ABG you can find my original post here , Ai2 application has stopped

Hello Juan Antonio,
Thanks for your tutos and developpments.
Completely new with ESP and Mit app Inventor, you gave me the possibility to develop what I needed based on your sketches ( 10.- From App ON/OFF 3 LEDs. Get status of the LEDs.) ie. a remote base with 5 relays and specifically a BLE remote to control 2 relays for an E Scooter. (ON OFF Motor / ON OFF Lights).
Since I need to connect to 4 different EScooter (separately) i registered all 4 x 2 UUIDS and after list picking (with device Name) the connection is done displaying also a picture of each E Scoot model.
Also I get connection infos from the ESP as a returned string to make sure that the order is taken into consideration (instead of displaying from the app when sending ON OFF (A0 A1, B0 , B1,....) "commands.

Hereby the Esp & App Inventor Sketches
Again thank you so much.

I also facing a small difficulty (where I mostly find similar questions on the net) that is proper disconnection from the app with the ESP and its re-connection. For exemple I connect to 1 scooter and change my mind to disconnect and connect to another one to check it and come back to the 1st one the connection is quite tough (even if disconnected on the app with BLE disconect, Disconnect with adress or both. Even with a "reboot" from the ESP (ON OFF). So far I have seen accordingly to several same issue on the net, the solution might be as per your description

""
bool deviceConnected = false;
bool oldDeviceConnected = false;
//uint32_t value = 0;

#define SERVICE_UUID "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
#define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"

class MyServerCallbacks: public BLEServerCallbacks {
void onConnect(BLEServer* pServer) {
deviceConnected = true;
};

void onDisconnect(BLEServer* pServer) {
  deviceConnected = false;
}

};

////////////////////// WriteStrings /////////////////////////////
class MyCallbacks: public BLECharacteristicCallbacks {
void onWrite(BLECharacteristic *pCharacteristic) {
std::string value = pCharacteristic->getValue();

  if (value.length() > 0) {
    valor = "";
    for (int i = 0; i < value.length(); i++){
      // Serial.print(value[i]); // Presenta value.
      valor = valor + value[i];
    }

    Serial.println("*********");
    Serial.print("valor = ");
    Serial.println(valor); // Presenta valor.
  }
}

};
But.....I have no clue how to implement it with your APP dvlpment 10- ON/OFF 3 Leds with Led status.

If you can help, I would appreciate.
In case not I 'll continue looking around and testing.
In any case thank You for your publications and the way you are helping readers.
It is very helpfull.

Best Regards,
Jean-Luc
Trot1.aia (3.5 MB)
ESP32.pdf (10.8 KB)

Thanks for this relevant informations. What about Firmware OTA Bluetooth? I found for WiFi but I'm still looking for AI2 Bluetooth method. Any cue?

Regards

Martin

I have only used OTA with WiFi, not with BLE.

Try https://learn.sparkfun.com/tutorials/esp32-ota-updates-over-ble-from-a-react-web-application/all

Hola Antonio,

Estoy tratando de hacer funcionar este ejemplo, con algunas modificaciones para lo que necesito. Estoy leyendo un pin nalógico del esp32 en el main loop mediante una interrupción. Estos valores los voy guardando en un array de 500 y después los imprimo en pantalla con un for, fuera de la interrupción.

El problema es que quiero enviar esos datos uno a uno a mit app inventor por BLE, y no logro que le lleguen los datos. Si pongo el pCharacteristic->setValue en ese for dentro del main loop, me salta un error, y necesito declarar pCharacteristic como global. Pero si hago eso, no funciona.

Y si paso todo el código de la interrupción/lectura a la clase Callbacks, no funciona la interrupción.

Dejo acceso al código: https://create.arduino.cc/editor/mvblanco/29bc59b8-e59b-479f-8487-5a4af2bcd5bf/preview

Si pudieras darme una idea sobre cómo seguir, me ayudaría mucho.
Gracias!

@Queenie wrote to me in a PM:

I moved all the code from the loop to setup, and I run it inside a while (1). A workaround solution but it worked perfectly!

Hello,

Don't you need different characteristic for writing (send to BLE), and reading from the BLE. Here it seems that you are using the same characteristics.

Thank you

BLECharacteristic *pCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID,
BLECharacteristic::PROPERTY_READ |
BLECharacteristic::PROPERTY_WRITE
);

1 Like

This is an excellent tutorial on the topic. Thank you for providing this information and for all of the good work.

Unfortunately, the AppInventor application appears to use a BLE extension (20201223) that was specially built to work around an issue. That extension is not available online. I've tried using the available extension (which was dated August 2020) but it won't connect. I will need to take this example application, duplicate it to get the library that's attached to it, and then rewrite pieces for my needs. Hopefully, the BLE connection issue will be resolved soon in a new AppInventor extension.

I have tracked BLE releases at

I see a download link there for the latest.

However the latest version 20201223 is for Testing, it is not as yet released.

Thanks ABG. I had already seen that page and there is no link to a 20201223 release of the BluetoothLE extension. There's a link that is labeled as such, but it leads to a thread that does not have the extension. It may have had it at one time, but it no longer does.

ChrisWard, I figured it was for testing only since it wasn't published at the standard location. However, the existing published extension doesn't work much at all with my BLE peripheral, whereas a test app I had downloaded that uses the test extension connects fairly well. So I am willing to be a guinea pig. :slight_smile:

I have asked if we can make it a formal release..........

Thank you, Juan! This is really helpful.

Unfortunately, I am having trouble using the RegisterForStrings method. For some reason, StringsReceived is never triggered. This happens for both examples 6 and 7. I did not change anything in the code except for upgrading the BLE extension to the latest release, which I have attached. If I do ReadForStrings then everything works fine so I am not sure what is the issue here. I am using Samsung Galaxy A8s. Could you give me some advice?

Thank you!

Jerry

edu.mit.appinventor.ble-20200828.aix (195.3 KB)

@Jerry_Tang

Try changing UUIDs on ESP32 and in the app.

https://www.uuidgenerator.net/

14A.- Send a message longer than 20 characters. MTU.

p110i_esp32_ble_mtu.aia (203.7 KB)

  • The BLE extension sends the messages in 20-byte packets, this is called MTU (Minimum Transmission Unit). The size of these packets can be changed using the RequestMTU block, but this size change would have to be changed in the Block code and on the device code.

  • We are going to see a code to send a long text in 20-byte packets that will be concatenated in the ESP32 code, that is, 20-byte packets will be sent and they will be joined in the code until the complete text is obtained.

  • We will send this text:
    La cigüeña voló a su nido.\nEl "Niño" provocó grandes inundaciones.\nEl señor Sánchez no es de Cádiz.\nThe stork flew to its nest.\nThe "Niño" caused great floods.\nMr. Sánchez is not from Cádiz.\n

  • We will split the text into 15-character, this is because language characters such as ü, ñ, ó, á, need two bytes, if we send:

La cigüeña voló

  • we have cut 15 characters, but we are sending 18 bytes, since ü, ñ, ó need 2 bytes. We are actually sending a 20-byte packet, the indicated 18 bytes and 2 more bytes to complete the 20.

  • Those 15 characters will reach the ESP32 and will be displayed on the Serial Monitor:

Serial.print (valor);

  • As these packages arrive, they will be shown.

  • In addition, in another variable called valor_return, all the characters that arrive will be added.

  • When the "#" character arrives, the valor_return variable will be reset.

// Juan A. Villalpando
// http://kio4.com/arduino/160_Wemos_ESP32_BLE.htm

#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEServer.h>

String valor;
String valor_return = "";

#define SERVICE_UUID        "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
#define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"

class MyCallbacks: public BLECharacteristicCallbacks {
    void onWrite(BLECharacteristic *pCharacteristic) {
      std::string value = pCharacteristic->getValue();
      if (value.length() > 0) {
        valor = "";
        for (int i = 0; i < value.length(); i++){
          valor = valor + value[i];          
        }
        Serial.print(valor); // Presenta valor.
        valor_return = valor_return + valor;
      }
      pCharacteristic->setValue(valor_return.c_str()); // Valor return.
      if(valor_return.indexOf("#") != -1){valor_return = "";}
    }

};

void setup() {
  Serial.begin(115200);

  BLEDevice::init("MyESP32");
  BLEServer *pServer = BLEDevice::createServer();
  BLEService *pService = pServer->createService(SERVICE_UUID);
  BLECharacteristic *pCharacteristic = pService->createCharacteristic(
                                         CHARACTERISTIC_UUID,
                                         BLECharacteristic::PROPERTY_READ |
                                         BLECharacteristic::PROPERTY_WRITE
                                       );

  pCharacteristic->setCallbacks(new MyCallbacks());
  pService->start();

  BLEAdvertising *pAdvertising = pServer->getAdvertising();
  pAdvertising->start();
}

void loop() {
  // put your main code here, to run repeatedly:
}

oooooooooooooooooOOOOOOOOOOOOOOooooooooooooooooo

14B.- Send a message longer than 20 characters. MTU.
Simplified code.

p110i_esp32_ble_mtu2.aia (205.0 KB)

  • By means of this code the characters are sent one by one.

// Juan A. Villalpando
// http://kio4.com/arduino/160_Wemos_ESP32_BLE.htm

#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEServer.h>

String valor;
String valor_return = "";

#define SERVICE_UUID        "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
#define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"

class MyCallbacks: public BLECharacteristicCallbacks {
    void onWrite(BLECharacteristic *pCharacteristic) {
      std::string value = pCharacteristic->getValue();
      
      if (value.length() > 0) {
        valor = "";
        for (int i = 0; i < value.length(); i++){
          valor = valor + value[i];          
        }
      valor_return = valor_return + valor;
     }
      pCharacteristic->setValue(valor_return.c_str()); // Valor return.
      if(valor_return.indexOf("#") != -1){Serial.print(valor_return); valor_return = "";}
    }
};

void setup() {
  Serial.begin(115200);

  BLEDevice::init("MyESP32");
  BLEServer *pServer = BLEDevice::createServer();
  BLEService *pService = pServer->createService(SERVICE_UUID);
  BLECharacteristic *pCharacteristic = pService->createCharacteristic(
                                         CHARACTERISTIC_UUID,
                                         BLECharacteristic::PROPERTY_READ |
                                         BLECharacteristic::PROPERTY_WRITE
                                       );

  pCharacteristic->setCallbacks(new MyCallbacks());
  pService->start();

  BLEAdvertising *pAdvertising = pServer->getAdvertising();
  pAdvertising->start();
}

void loop() {
  // put your main code here, to run repeatedly:
}

15.- Two ESP32 with BLE send random temperature and humidity by Notification. Common Slider.

ESP32 with BLE generates (at random times) two random numbers temperatureBLE1 and humidityBLE2, and notifies them to the application.

Another ESP32 with BLE generates (at random times) two random numbers temperatureBLE2 and humidityBLE2, and notifies them to the application.

App sends a value to the two ESP32s through a Slider.

- Code for ESP32 with BLE1:

// Juan A. Villalpando
// http://kio4.com/arduino/160_Wemos_ESP32_BLE.htm

#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEServer.h>

String valor;
long previousMillis_BLE1 = 0;
int interval_BLE1 = 1000;

BLEServer* pServer = NULL;
BLECharacteristic* pCharacteristic = NULL;

#define SERVICE_UUID        "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
#define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"

class MyCallbacks: public BLECharacteristicCallbacks {
    void onWrite(BLECharacteristic *pCharacteristic) {
      std::string value = pCharacteristic->getValue();

      if (value.length() > 0) {
        valor = "";
        for (int i = 0; i < value.length(); i++){
          // Serial.print(value[i]); // Presenta value.
          valor = valor + value[i];
        }

        Serial.println("*********");
        Serial.print("valor = ");
        Serial.println(valor); // Presenta valor.
      }
    }
};
///////////////////////////////////////////////////

void setup() {
  Serial.begin(115200);

  // Create the BLE1 Device
  BLEDevice::init("MyESP32_BLE1");

  // Create the BLE Server
  pServer = BLEDevice::createServer();

  BLEService *pService = pServer->createService(SERVICE_UUID);

  pCharacteristic = pService->createCharacteristic(
                      CHARACTERISTIC_UUID,
                      BLECharacteristic::PROPERTY_READ   |
                      BLECharacteristic::PROPERTY_WRITE  |
                      BLECharacteristic::PROPERTY_NOTIFY |
                      BLECharacteristic::PROPERTY_INDICATE
                    );

  pCharacteristic->setCallbacks(new MyCallbacks());
  pService->start();

  BLEAdvertising *pAdvertising = pServer->getAdvertising();
  pAdvertising->start();
}

void loop() {
  unsigned long currentMillis = millis();

  if(currentMillis - previousMillis_BLE1 > interval_BLE1) {
  float TemperatureBLE1 = random(10,60000)/1000.0; // 3 decimals
  float HumidityBLE1 = random(5,99000)/1000.0;  // 3 decimals

  String temperatureBLE1 = String(TemperatureBLE1,3);
  String humidityBLE1 = String(HumidityBLE1,3);
  String tem_hum_BLE1 = temperatureBLE1 + "," + humidityBLE1;

      std::string value = pCharacteristic->getValue();
      pCharacteristic->setValue(tem_hum_BLE1.c_str()); // Notify.
      pCharacteristic->notify();
      
  previousMillis_BLE1 = currentMillis;     
  interval_BLE1 = random(500,1000);
  }
}

- Code for ESP32 with BLE2:

// Juan A. Villalpando
// http://kio4.com/arduino/160_Wemos_ESP32_BLE.htm

#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>

String valor;
long previousMillis_BLE2 = 0;
int interval_BLE2 = 1000;

BLEServer* pServer = NULL;
BLECharacteristic* pCharacteristic = NULL;

#define SERVICE_UUID        "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
#define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"

class MyCallbacks: public BLECharacteristicCallbacks {
    void onWrite(BLECharacteristic *pCharacteristic) {
      std::string value = pCharacteristic->getValue();

      if (value.length() > 0) {
        valor = "";
        for (int i = 0; i < value.length(); i++){
          // Serial.print(value[i]); // Presenta value.
          valor = valor + value[i];
        }

        Serial.println("*********");
        Serial.print("valor = ");
        Serial.println(valor); // Presenta valor.
      }
    }
};
///////////////////////////////////////////////////

void setup() {
  Serial.begin(115200);

  // Create the BLE2 Device
  BLEDevice::init("MyESP32_BLE2");

  // Create the BLE Server
  pServer = BLEDevice::createServer();

  BLEService *pService = pServer->createService(SERVICE_UUID);

  pCharacteristic = pService->createCharacteristic(
                      CHARACTERISTIC_UUID,
                      BLECharacteristic::PROPERTY_READ   |
                      BLECharacteristic::PROPERTY_WRITE  |
                      BLECharacteristic::PROPERTY_NOTIFY |
                      BLECharacteristic::PROPERTY_INDICATE
                    );

  pCharacteristic->setCallbacks(new MyCallbacks());
  pService->start();

  BLEAdvertising *pAdvertising = pServer->getAdvertising();
  pAdvertising->start();
}

void loop() {
  unsigned long currentMillis = millis();

  if(currentMillis - previousMillis_BLE2 > interval_BLE2) {
  float TemperatureBLE2 = random(10,60000)/1000.0; // 3 decimals
  float HumidityBLE2 = random(5,99000)/1000.0;  // 3 decimals

  String temperatureBLE2 = String(TemperatureBLE2,3);
  String humidityBLE2 = String(HumidityBLE2,3);
  String tem_hum_BLE2 = temperatureBLE2 + "," + humidityBLE2;

      std::string value = pCharacteristic->getValue();
      pCharacteristic->setValue(tem_hum_BLE2.c_str()); // Notify.
      pCharacteristic->notify();
      
  previousMillis_BLE2 = currentMillis;     
  interval_BLE2 = random(500,2000);
  }
}