Chapter 27 Bluetooth

This chapter mainly introduces how to make simple data transmission through Bluetooth of ESP32-WROVER and mobile phones.

Project 27.1 is classic Bluetooth and Project 27.2 is low power Bluetooth.If you are an iPhone user, please start with Project 27.2.

Project 27.1 Bluetooth Low Energy Data Passthrough

Component List

ESP32-WROVER x1

Chapter01_00

Micro USB Wire x1

Chapter08_00

In this tutorial we need to use a Bluetooth APP called Serial Bluetooth Terminal to assist in the experiment. If you’ve not installed it yet, please do so by clicking: https://www.appsapk.com/serial-bluetooth-terminal/ The following is its logo.

../../../_images/Chapter27_00.png

Lightblue

If you can’t install Serial Bluetooth on your phone, try LightBlue.If you do not have this software installed on your phone, you can refer to this link: https://apps.apple.com/us/app/lightblue/id557428110#?platform=iphone

../../../_images/Chapter27_43.png

Code

Move the program folder “Freenove_Ultimate_Starter_Kit_for_ESP32/Python/Python_Codes” to disk(D) in advance with the path of “D:/Micropython_Codes”.

Open “Thonny”, click “This computer” -> “D:” -> “Micropython_Codes” -> “27.1_BLE”. Select “ble_advertising.py”, right click your mouse to select “Upload to /”, wait for “ble_advertising.py” to be uploaded to ESP32-WROVER and then double click “BLE.py”.

27.1_BLE

../../../_images/Chapter27_33.png

Click run for BLE.py.

../../../_images/Chapter27_34.png

Turn ON Bluetooth on your phone, and open the Lightblue APP.

../../../_images/Chapter27_35.png

In the Scan page, swipe down to refresh the name of Bluetooth that the phone searches for. Click ESP32.

../../../_images/Chapter27_36.png

After Bluetooth is connect successfully, Shell will printer the information.

../../../_images/Chapter27_37.png

Click “Receive”. Select the appropriate Data format in the box to the right of Data Format. For example, HEX for hexadecimal, utf-string for character, Binary for Binary, etc. Then click SUBSCRIBE.

../../../_images/Chapter27_38.png

You can type “Hello” in Shell and press “Enter” to send.

../../../_images/Chapter27_39.png

And then you can see the mobile Bluetooth has received the message.

../../../_images/Chapter27_40.png

Similarly, you can select “Send” on your phone. Set Data format, and then enter anything in the sending box and click Write to send.

../../../_images/Chapter27_41.png

You can check the message from Bluetooth in “Shell”.

../../../_images/Chapter27_42.png

And now data can be transferred between your mobile phone and computer via ESP32-WROVER.

The following is the program code:

  1# This example demonstrates a UART periperhal.
  2
  3import bluetooth
  4import random
  5import struct
  6import time
  7from ble_advertising import advertising_payload
  8
  9from micropython import const
 10
 11_IRQ_CENTRAL_CONNECT = const(1)
 12_IRQ_CENTRAL_DISCONNECT = const(2)
 13_IRQ_GATTS_WRITE = const(3)
 14
 15_FLAG_READ = const(0x0002)
 16_FLAG_WRITE_NO_RESPONSE = const(0x0004)
 17_FLAG_WRITE = const(0x0008)
 18_FLAG_NOTIFY = const(0x0010)
 19
 20_UART_UUID = bluetooth.UUID("6E400001-B5A3-F393-E0A9-E50E24DCCA9E")
 21_UART_TX = (
 22    bluetooth.UUID("6E400003-B5A3-F393-E0A9-E50E24DCCA9E"),
 23    _FLAG_READ | _FLAG_NOTIFY,
 24)
 25_UART_RX = (
 26    bluetooth.UUID("6E400002-B5A3-F393-E0A9-E50E24DCCA9E"),
 27    _FLAG_WRITE | _FLAG_WRITE_NO_RESPONSE,
 28)
 29_UART_SERVICE = (
 30    _UART_UUID,
 31    (_UART_TX, _UART_RX),
 32)
 33
 34
 35class BLESimplePeripheral:
 36    def __init__(self, ble, name="ESP32"):
 37        self._ble = ble
 38        self._ble.active(True)
 39        self._ble.irq(self._irq)
 40        ((self._handle_tx, self._handle_rx),) = self._ble.gatts_register_services((_UART_SERVICE,))
 41        self._connections = set()   
 42        self._write_callback = None
 43        self._payload = advertising_payload(name=name, services=[_UART_UUID])
 44        self._advertise()
 45
 46    def _irq(self, event, data):
 47        # Track connections so we can send notifications.
 48        if event == _IRQ_CENTRAL_CONNECT:
 49            conn_handle, _, _ = data
 50            print("New connection", conn_handle)
 51            print("\nThe BLE connection is successful.")
 52            self._connections.add(conn_handle)
 53        elif event == _IRQ_CENTRAL_DISCONNECT:
 54            conn_handle, _, _ = data
 55            print("Disconnected", conn_handle)
 56            self._connections.remove(conn_handle)
 57            # Start advertising again to allow a new connection.
 58            self._advertise()
 59        elif event == _IRQ_GATTS_WRITE:
 60            conn_handle, value_handle = data
 61            value = self._ble.gatts_read(value_handle)
 62            if value_handle == self._handle_rx and self._write_callback:
 63                self._write_callback(value)
 64
 65    def send(self, data):
 66        for conn_handle in self._connections:
 67            self._ble.gatts_notify(conn_handle, self._handle_tx, data)
 68
 69    def is_connected(self):
 70        return len(self._connections) > 0
 71
 72    def _advertise(self, interval_us=500000):
 73        print("Starting advertising")
 74        self._ble.gap_advertise(interval_us, adv_data=self._payload)
 75
 76    def on_write(self, callback):
 77        self._write_callback = callback
 78
 79
 80def demo():
 81    ble = bluetooth.BLE()
 82    p = BLESimplePeripheral(ble)
 83
 84    def on_rx(rx_data):
 85        print("RX", rx_data)
 86
 87    p.on_write(on_rx)
 88
 89    print("Please use LightBlue to connect to ESP32.")
 90
 91    while True:
 92        if p.is_connected():
 93            # Short burst of queued notifications.
 94            tx_data = input("Enter anything: ")
 95            print("Send: ", tx_data)
 96            p.send(tx_data)
 97
 98
 99if __name__ == "__main__":
100    demo()

Define the specified UUID number for BLE vendor.

1_UART_UUID = bluetooth.UUID("6E400001-B5A3-F393-E0A9-E50E24DCCA9E")
2_UART_TX = (
3    bluetooth.UUID("6E400003-B5A3-F393-E0A9-E50E24DCCA9E"),
4    _FLAG_READ | _FLAG_NOTIFY,
5)
6_UART_RX = (
7    bluetooth.UUID("6E400002-B5A3-F393-E0A9-E50E24DCCA9E"),
8    _FLAG_WRITE | _FLAG_WRITE_NO_RESPONSE,
9)

Write an _irq function to manage BLE interrupt events.

 1def _irq(self, event, data):
 2    # Track connections so we can send notifications.
 3    if event == _IRQ_CENTRAL_CONNECT:
 4        conn_handle, _, _ = data
 5        print("New connection", conn_handle)
 6        print("\nThe BLE connection is successful.")
 7        self._connections.add(conn_handle)
 8    elif event == _IRQ_CENTRAL_DISCONNECT:
 9        conn_handle, _, _ = data
10        print("Disconnected", conn_handle)
11        self._connections.remove(conn_handle)
12        # Start advertising again to allow a new connection.
13        self._advertise()
14    elif event == _IRQ_GATTS_WRITE:
15        conn_handle, value_handle = data
16        value = self._ble.gatts_read(value_handle)
17        if value_handle == self._handle_rx and self._write_callback:
18            self._write_callback(value)

Initialize the BLE function and name it.

1def __init__(self, ble, name="ESP32"):

When the mobile phone send data to ESP32 via BLE Bluetooth, it will print them out with serial port; When the serial port of ESP32 receive data, it will send them to mobile via BLE Bluetooth.

 1def demo():
 2    ble = bluetooth.BLE()
 3    p = BLESimplePeripheral(ble)
 4
 5    def on_rx(rx_data):
 6        print("RX", rx_data)
 7
 8    p.on_write(on_rx)
 9
10    print("Please use LightBlue to connect to ESP32.")
11
12    while True:
13        if p.is_connected():
14            # Short burst of queued notifications.
15            tx_data = input("Enter anything: ")
16            print("Send: ", tx_data)
17            p.send(tx_data)

Project 27.2 Bluetooth Control LED

In this section, we will control the LED with Bluetooth.

Component List

ESP32-WROVER x1

Chapter01_00

GPIO Extension Board x1

Chapter01_01

Micro USB Wire x1

Chapter08_00

Breadboard x1

Chapter01_02

LED x1

Chapter01_03

Resistor 220Ω x1

Chapter01_04

Jumper M/M x2

Chapter01_05

Circuit

Connect Freenove ESP32 to the computer using a USB cable.

Schematic diagram

Chapter27_27

Hardware connection

If you need any support, please feel free to contact us via: support@freenove.com

Chapter27_28

Code

Move the program folder “Freenove_Ultimate_Starter_Kit_for_ESP32/Python/Python_Codes” to disk(D) in advance with the path of “D:/Micropython_Codes”.

Open “Thonny”, click “This computer” -> “D:” -> “Micropython_Codes” -> “27.2_BLE_LED”. Select “ble_advertising.py”, right click your mouse to select “Upload to /”, wait for “ble_advertising.py” to be uploaded to ESP32-WROVER and then double click “BLE_LED.py”.

27.2_BLE_LED

../../../_images/Chapter27_44.png

Compile and upload code to ESP32. The operation of the APP is the same as 27.1, you only need to change the sending content to “led_on” and “led_off” to operate LEDs on the ESP32-WROVER.

Data sent from mobile APP:

../../../_images/Chapter27_45.png

You can check the message sent by Bluetooth in “Shell”.

../../../_images/Chapter27_46.png

The phenomenon of LED

../../../_images/Chapter27_47.png

Attention: If the sending content isn’t “led_on’ or “led_off”, then the state of LED will not change. If the LED is on, when receiving irrelevant content, it keeps on; Correspondingly, if the LED is off, when receiving irrelevant content, it keeps off.

The following is the program code:

  1# This example demonstrates a UART periperhal.
  2
  3import bluetooth
  4import random
  5import struct
  6import time
  7from ble_advertising import advertising_payload
  8from machine import Pin
  9from micropython import const
 10
 11_IRQ_CENTRAL_CONNECT = const(1)
 12_IRQ_CENTRAL_DISCONNECT = const(2)
 13_IRQ_GATTS_WRITE = const(3)
 14
 15_FLAG_READ = const(0x0002)
 16_FLAG_WRITE_NO_RESPONSE = const(0x0004)
 17_FLAG_WRITE = const(0x0008)
 18_FLAG_NOTIFY = const(0x0010)
 19
 20_UART_UUID = bluetooth.UUID("6E400001-B5A3-F393-E0A9-E50E24DCCA9E")
 21_UART_TX = (
 22    bluetooth.UUID("6E400003-B5A3-F393-E0A9-E50E24DCCA9E"),
 23    _FLAG_READ | _FLAG_NOTIFY,
 24)
 25_UART_RX = (
 26    bluetooth.UUID("6E400002-B5A3-F393-E0A9-E50E24DCCA9E"),
 27    _FLAG_WRITE | _FLAG_WRITE_NO_RESPONSE,
 28)
 29_UART_SERVICE = (
 30    _UART_UUID,
 31    (_UART_TX, _UART_RX),
 32)
 33
 34
 35class BLESimplePeripheral:
 36    def __init__(self, ble, name="ESP32"):
 37        self._ble = ble
 38        self._ble.active(True)
 39        self._ble.irq(self._irq)
 40        ((self._handle_tx, self._handle_rx),) = self._ble.gatts_register_services((_UART_SERVICE,))
 41        self._connections = set()   
 42        self._write_callback = None
 43        self._payload = advertising_payload(name=name, services=[_UART_UUID])
 44        self._advertise()
 45
 46    def _irq(self, event, data):
 47        # Track connections so we can send notifications.
 48        if event == _IRQ_CENTRAL_CONNECT:
 49            conn_handle, _, _ = data
 50            print("New connection", conn_handle)
 51            print("\nThe BLE connection is successful.")
 52            self._connections.add(conn_handle)
 53        elif event == _IRQ_CENTRAL_DISCONNECT:
 54            conn_handle, _, _ = data
 55            print("Disconnected", conn_handle)
 56            self._connections.remove(conn_handle)
 57            # Start advertising again to allow a new connection.
 58            self._advertise()
 59        elif event == _IRQ_GATTS_WRITE:
 60            conn_handle, value_handle = data
 61            value = self._ble.gatts_read(value_handle)
 62            if value_handle == self._handle_rx and self._write_callback:
 63                self._write_callback(value)
 64
 65    def send(self, data):
 66        for conn_handle in self._connections:
 67            self._ble.gatts_notify(conn_handle, self._handle_tx, data)
 68
 69    def is_connected(self):
 70        return len(self._connections) > 0
 71
 72    def _advertise(self, interval_us=500000):
 73        print("Starting advertising")
 74        self._ble.gap_advertise(interval_us, adv_data=self._payload)
 75
 76    def on_write(self, callback):
 77        self._write_callback = callback
 78
 79
 80def demo():
 81    ble = bluetooth.BLE()
 82    p = BLESimplePeripheral(ble)
 83
 84    led=Pin(2,Pin.OUT)
 85
 86    def on_rx(rx_data):
 87        print("Received: ", rx_data)
 88        if rx_data == b'led_on':
 89            led.value(0)
 90        elif rx_data == b'led_off':
 91            led.value(1)
 92        else:
 93            pass
 94
 95    p.on_write(on_rx)
 96
 97    print("Please use LightBlue to connect to ESP32.")
 98
 99
100if __name__ == "__main__":
101    demo()

Compare received message with “led_on” and “led_off” and take action accordingly.

1if rx_data == b'led_on':
2    led.value(0)
3elif rx_data == b'led_off':
4    led.value(1)