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

8.- PushButton in ESP2 sends HIGH/LOW to App Inventor. Notify.

p110_esp32_ble_notifica_Pulsador.aia (185.0 KB)

  • PushButton in pin12 of ESP32 sends “HIGH” or “LOW” to App Inventor by BLE Notify.

  • It also turns ON/OFF LED2 of the ESP32 (it is a LED_BUILTIN)



      /*    Based on Neil Kolban example for IDF:
         https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLE%20Tests/SampleNotify.cpp
         Ported to Arduino ESP32 by Evandro Copercini updated by chegewara
         Create a BLE server that, once we receive a connection, will send periodic notifications.
         A connect hander associated with the server starts a background task that performs notification
         every couple of seconds. */
    
      // Modificado por Juan A. Villalpando
      // http://kio4.com/arduino/160i_Wemos_ESP32_BLE.htm
    
      #include <BLEDevice.h>
      #include <BLEServer.h>
      #include <BLEUtils.h>
      #include <BLE2902.h>
      #define pin12 12 //  pin12 PushButton
      #define pin2 2 //  pin2  LED2
      int valor12; // Status PushButton
      String output ="LOW"; // Output to App. Notify.
    
      BLEServer* pServer = NULL;
      BLECharacteristic* pCharacteristic = NULL;
      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;
      }
      };
    
      void setup() {
      pinMode(pin12, INPUT); // pin12 PushButton
      pinMode(pin2, OUTPUT); // pin2 LED2
      Serial.begin(115200);
    
        // Create the BLE Device
        BLEDevice::init("MyESP32");
    
        // Create the BLE Server
        pServer = BLEDevice::createServer();
        pServer->setCallbacks(new MyServerCallbacks());
    
        // Create the BLE Service
        BLEService *pService = pServer->createService(SERVICE_UUID);
    
        // Create a BLE Characteristic
        pCharacteristic = pService->createCharacteristic(
                        CHARACTERISTIC_UUID,
                        BLECharacteristic::PROPERTY_READ   |
                        BLECharacteristic::PROPERTY_WRITE  |
                        BLECharacteristic::PROPERTY_NOTIFY |
                        BLECharacteristic::PROPERTY_INDICATE
                      );
    
        // Create a BLE Descriptor
        pCharacteristic->addDescriptor(new BLE2902());
    
        // Start the service
        pService->start();
    
        // Start advertising
        BLEAdvertising *pAdvertising = BLEDevice::getAdvertising();
        pAdvertising->addServiceUUID(SERVICE_UUID);
        pAdvertising->setScanResponse(false);
        pAdvertising->setMinPreferred(0x0);  // set value to 0x00 to not advertise this parameter
        BLEDevice::startAdvertising();
        Serial.println("Waiting a client connection to notify...");
      }
    
      void loop() {
      // notify changed value
      if (deviceConnected) {
        pCharacteristic->setValue(output.c_str()); // Output
        pCharacteristic->notify();
        
      valor12 = digitalRead(pin12); // Read  pin12 --> valor12. ( 0 or 1)
      if (valor12 == HIGH) { 
      digitalWrite(pin2, HIGH); // if valor12 is HIGH, set pin2 HIGH
      Serial.println("Pulsado");
      output ="HIGH"; // Notify HIGH
      } 
    
      if (valor12 == LOW) { 
      digitalWrite(pin2, LOW); // If valor12 is LOW, set pin2 LOW
      Serial.println("No Pulsado");
      output ="LOW"; // Notify LOW
      } 
      delay(100); // bluetooth stack will go into congestion, if too many packets are sent.       
      }
      // disconnecting
      if (!deviceConnected && oldDeviceConnected) {
          delay(500); // give the bluetooth stack the chance to get things ready
          pServer->startAdvertising(); // restart advertising
          Serial.println("start advertising");
          oldDeviceConnected = deviceConnected;
      }
      // connecting
      if (deviceConnected && !oldDeviceConnected) {
          // do stuff here on connecting
          oldDeviceConnected = deviceConnected;
      }
      }
1 Like

9.- App sends three values ​​for a tricolor LED RGB. Receive those same values.

p110i_esp32_ble_LED.aia (236.1 KB)


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

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

String valor;
String red;
String green;
String blue;
int ind1;
int ind2;
int ind3;


#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 = ");
        Serial.println(valor);
        ind1 = valor.indexOf(',');
        red = valor.substring(0, ind1);
        ind2 = valor.indexOf(',', ind1+1 );
        green = valor.substring(ind1+1, ind2);
        ind3 = valor.indexOf(',', ind2+1 );
        blue = valor.substring(ind2+1);

        Serial.print("red = ");
        Serial.println(red);
        Serial.print("green = ");
        Serial.println(green);
        Serial.print("blue = ");
        Serial.println(blue);
        Serial.println();

      analogWrite(12, red.toInt());
      analogWrite(14, green.toInt());
      analogWrite(27, blue.toInt());

      pCharacteristic->setValue(valor.c_str()); // Devuelve el valor.
      }
    }
};

void setup() {
  analogWriteResolution(12, 8); // Resolución 8 bits
  analogWriteResolution(14, 8);
  analogWriteResolution(27, 8);
  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());
  pCharacteristic->setValue("Iniciado.");
  pService->start();

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

void loop() {
//
}
1 Like

10.- From App ON/OFF 3 LEDs. Get status of the LEDs.

p110i_esp32_ble_3LED.aia (185.7 KB)

  • We can use independent LEDs, in my example I have used a tricolor LED.
  • Every time ON/OFF a LED we get a response.
  • When we press “Check status” we obtain the status of the three LEDs.

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

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

String valor;
#define LED12  12    // LED pin 12
#define LED14  14    // LED pin 14
#define LED27  27    // LED pin 27
String estado ="";


#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.println(valor);
 if (valor == "on12") {digitalWrite(LED12,HIGH); pCharacteristic->setValue("LED12 ON");}
 if (valor == "off12"){digitalWrite(LED12,LOW);  pCharacteristic->setValue("LED12 OFF");}
 if (valor == "on14") {digitalWrite(LED14,HIGH); pCharacteristic->setValue("LED14 ON");}
 if (valor == "off14"){digitalWrite(LED14,LOW);  pCharacteristic->setValue("LED14 OFF");}
 if (valor == "on27") {digitalWrite(LED27,HIGH); pCharacteristic->setValue("LED27 ON");}
 if (valor == "off27"){digitalWrite(LED27,LOW);  pCharacteristic->setValue("LED27 OFF");}
 if (valor == "check"){
   estado ="";
   if (digitalRead(LED12) == HIGH) {estado = "LED12 ON,";} else {estado = "LED12 OFF,";}
   if (digitalRead(LED14) == HIGH) {estado = estado + "LED14 ON,";} else {estado = estado + "LED14 OFF,";}
   if (digitalRead(LED27) == HIGH) {estado = estado + "LED27 ON";} else {estado = estado + "LED27 OFF";}
   pCharacteristic->setValue(estado.c_str()); // Return status
  }
      }
    }
};

void setup() {
  pinMode(LED12, OUTPUT);
  pinMode(LED14, OUTPUT);
  pinMode(LED27, OUTPUT);
  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());
  pCharacteristic->setValue("Iniciado.");
  pService->start();

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

void loop() {
//
}
1 Like

11.- App sends Bytes by WriteBytesWithResponse.

p110i_esp32_ble_Bytes.aia (184.3 KB)

  • App sends list of Bytes as decimal numbers: 97,109,105,103,111 (ASCII: a,m,i,g,o)
  • ESP32 receives those bytes and converts them to binaries:
    01100001
    01101101
    01101001
    01100111
    01101111
  • Return values as list.

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

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

String valor;

#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.println(valor);
            // Convert valor to bytes.
            for(int i=0; i<valor.length(); i++){
               char myChar = valor.charAt(i);
                for(int i=7; i>=0; i--){
                  byte bytes = bitRead(myChar,i);
                  Serial.print(bytes, BIN);
                }
                 Serial.println("");
            }
 
   pCharacteristic->setValue(valor.c_str()); // Return valor
      }
    }
};

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());
  pCharacteristic->setValue("Iniciado.");
  pService->start();

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

void loop() {
//
}

Check Serial Monitor:

This tutorial in Spanish.

1 Like

@Juan_Antonio, I’m getting started with esp32 BLE connection and MIT app inventor. I don’t know what is happening, but I got this error when I try to use any off the apps. Can someone help me?
Note: I’m just copying and pasting both code and app

Location needs to be enabled for Bluetooth Low Energy Scanning.

Use ESP32_BLE.zip library in this page:
http://kio4.com/arduino/160_Wemos_ESP32_BLE.htm

You can Scan UUID with this app:

12.- Notify. Simple and didactic example.

Important: each mobile device must have a CHARACTERISTIC_UUID. If you have multiple mobiles, set a CHARACTERISTIC_UUID for each one. You can generate UUID: https://www.uuidgenerator.net/

// Modified Juan A. Villalpando.
// http://kio4.com/arduino/160_Wemos_ESP32_BLE.htm			
			
#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>

// Each client, mobile with a CHARACTERISTIC_UUID.
// Generate UUID: https://www.uuidgenerator.net/
#define SERVICE_UUID "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
//#define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"
  #define CHARACTERISTIC_UUID "d6f841fa-a37d-11ea-bb37-0242ac130002"

BLEServer* pServer = NULL;
BLECharacteristic* pCharacteristic = NULL;
bool deviceConnected = false;
int value = 0;
String valor = "";

// These functions will detect when the device is connected or disconnected.
class MyServerCallbacks: public BLEServerCallbacks {
    void onConnect(BLEServer* pServer) {
      deviceConnected = true;
    }; 
    void onDisconnect(BLEServer* pServer) {
      deviceConnected = false;
    }
};

void setup() {
Serial.begin(115200);
BLEDevice::init("MyESP32");

// Create BLE Server.
BLEServer *pServer = BLEDevice::createServer();
pServer->setCallbacks(new MyServerCallbacks());

// Create BLE Service with properties READ, WRITE, NOTIFY, INDICATE
BLEService *pService = pServer->createService(SERVICE_UUID);
pCharacteristic = pService->createCharacteristic(
                      CHARACTERISTIC_UUID,
                      BLECharacteristic::PROPERTY_READ   |
                      BLECharacteristic::PROPERTY_WRITE  |
                      BLECharacteristic::PROPERTY_NOTIFY |
                      BLECharacteristic::PROPERTY_INDICATE
                    );
// BLE descriptor.                    
pCharacteristic->addDescriptor(new BLE2902());

// Start BLE service.
pService->start();

// Start BLE advertising.
pServer->getAdvertising()->start(); 
}  

void loop() {
if (deviceConnected) { 
Serial.printf("*** NOTIFY: %d ***\n", value);
valor = (String) value;
pCharacteristic->setValue(valor.c_str()); // Set value.
pCharacteristic->notify();                // Notify value.
//pCharacteristic->indicate(); 
value++; 
delay(800);
}
}
2 Likes

Hello Gianfranco

See below, June 1st, Notifications. You can use “Register for Strings” to receive data when it is available (every time it is available), rather than having to request it.

hmm, that cool

1 Like

Hi Juan

Take a look at this DIY UNO:
https://www.instructables.com/id/See-Through-Arduino-UNO/?
:star_struck:

13.- Multitouch. Press several buttons at the same time.

p110i_esp32_ble_Multitouch.aia (204.6 KB)

In this topic we can see an example of Multitouch with/without Clock using classic Bluetooth:

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

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

String valor;
byte byte_received;
byte bytes;
#define LED12  12    // LED pin 12
#define LED14  14    // LED pin 14
#define LED27  27    // LED pin 27
#define LED16  16    // LED pin 16
String estado ="";
void motores();

#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];
        }
          byte_received = valor.charAt(0);
          Serial.print(byte_received);  
          Serial.print("    "); 
          
       /**  // print byte_received in byte, ejemplo: 00000110
            // Convert valor to bytes.
            for(int i=0; i<valor.length(); i++){
               char myChar = valor.charAt(i);
                for(int i=7; i>=0; i--){
                 bytes = bitRead(myChar,i);
                 Serial.print(bytes, BIN); // Binario
                }
                 Serial.println("");
            }
            */

motores();
pCharacteristic->setValue(estado.c_str()); // Return status
 }

    }
};

void setup() {
  pinMode(LED12, OUTPUT);
  pinMode(LED14, OUTPUT);
  pinMode(LED27, OUTPUT);
  pinMode(LED16, OUTPUT);
  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());
  pCharacteristic->setValue("Iniciado.");
  pService->start();

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

void loop() {
//
}

void motores(){
if (bitRead(byte_received, 0)){digitalWrite(LED12,HIGH); Serial.print("Motor0: RUN  ");}
else {digitalWrite(LED12,LOW); Serial.print("Motor0: ---  ");}
if (bitRead(byte_received, 1)){digitalWrite(LED14,HIGH); Serial.print("Motor1: RUN  ");} 
else {digitalWrite(LED14,LOW); Serial.print("Motor1: ---  ");}
if (bitRead(byte_received, 2)){digitalWrite(LED27,HIGH); Serial.print("Motor2: RUN  ");} 
else {digitalWrite(LED27,LOW); Serial.print("Motor2: ---  ");}
if (bitRead(byte_received, 3)){digitalWrite(LED16,HIGH); Serial.print("Motor3: RUN  ");} 
else {digitalWrite(LED16,LOW); Serial.print("Motor3: ---  ");} 
Serial.println();
   estado ="";
   if (digitalRead(LED12) == HIGH) {estado = "Motor0: RUN,";} else {estado = "Motor0: ---,";}
   if (digitalRead(LED14) == HIGH) {estado = estado + "Motor1: RUN,";} else {estado = estado + "Motor1: ---,";}
   if (digitalRead(LED27) == HIGH) {estado = estado + "Motor2: RUN,";} else {estado = estado + "Motor2: ---";}
   if (digitalRead(LED16) == HIGH) {estado = estado + "Motor3: RUN";} else {estado = estado + "Motor3: ---";}
}
1 Like

ThankYouuu

Hi Juan,

Thanks for this detailed tutorial. I am using the 6.- ESP32 sends automatically (Notify) a random number to App.. But my use requires me to get multiple analog readings and display them in different labels. Could you guide me on how it can be done? I am attaching the desired app screenshot.

Try this:

    int aleatorio_1 = random(1,100); // Crea el numero random.
	int aleatorio_2 = random(100,200); // Crea el numero random.
	int aleatorio_3 = random(200,300); // Crea el numero random.
	
    String alea = (String) aleatorio_1 + "," + (String) aleatorio_2 + "," + (String) aleatorio_3; // Lo convierte en String.
    pCharacteristic->setValue(alea.c_str()); // Pone el numero random
    pCharacteristic->notify();

Hi Juan,

I am trying to send audio files from phone to sd card connected on esp32 board via its BT/BLE. Can you please help.

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)