Internet of Things

Demonstrate communication between a microcontroller and another device. Optionally, work with a partner to control a device remotely.

I want to use a Bluetooth connection in my final project, so I took this week's assignment as an opportunity to learn how to use Bluetooth Low Energy (BLE). I used the Huzzah+BLE tutorial on the course website as a starting point.

I wired one LED to the Huzzah in order to demonstrate connection between the ESP32 and my phone and adapted the code from the tutorial to include lighting up the LED. Code below:

        /*
            Based on Neil Kolban example for IDF: https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLE%20Tests/SampleWrite.cpp
            Ported to Arduino ESP32 by Evandro Copercini
        */

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

        // See the following for generating UUIDs:
        // https://www.uuidgenerator.net/

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

        int LED_PIN = 5;
        char LED_STATUS;

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

              if (value.length() > 0) {
                Serial.println("*********");
                Serial.print("New value: ");
                for (int i = 0; i < value.length(); i++)
                  Serial.print(value[i]);

                Serial.println();
                Serial.println("*********");
                for (int i = 0; i < value.length(); i++){
                  LED_STATUS = value[i];
                }
              }
            }
        };

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

          Serial.println("1- Download and install an BLE scanner app in your phone");
          Serial.println("2- Scan for BLE devices in the app");
          Serial.println("3- Connect to MyESP32");
          Serial.println("4- Go to CUSTOM CHARACTERISTIC in CUSTOM SERVICE and write something");
          Serial.println("5- See the magic =)");

          BLEDevice::init("MyESP32PK");
          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("Hello World");
          pService->start();

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

          pinMode(LED_PIN, OUTPUT);
          digitalWrite(LED_PIN, LOW);
        }

        void loop() {
          // put your main code here, to run repeatedly:
          int val = (int)LED_STATUS;  // cast the char* as an int 
          if (val == 49)              // ASCII code for the number 1
            digitalWrite(LED_PIN, HIGH);
          else 
            digitalWrite(LED_PIN, LOW);

          delay(2000);
        }
      

The BLE scanner app recommended by the tutorial didn't work, so after downloading several different BLE scanners, I found one that worked: LightBlue. When I opened up the app and scanned for BLE connections, I got a long list of possible connections, most of them unnamed. I named my device "MyESP32PK" in the code, so I searched for that, and was able to connect.

The LightBlue interface: scanning for nearby devices, then the connection screen with my ESP32.

I had programmed the code to turn the LED on when it received a 1 and turn off for any other value. In the above screenshot, you can see that I had sent many values that were not 1. Although LightBlue works to connect better than any of the other BLE apps, it writes and reads in hex. Once I figured this out, I realized that 0x31 is equivalent to 1.

It worked just like I wanted it to! When I sent a 1 aka 0x31, the LED turned on a split second later. Sending anything else turned off the LED.

My BLE connection experiment was a success. For my final project, I'd like to be able to establish a connection without a specific app, but that's not strictly necessary.