4. Chapter BLE
This chapter mainly introduces how to make simple data transmission through BLE of ESP32-S3 WROOM and mobile phones.
4.1. Project 4.1 Bluetooth Low Energy Data Passthrough
4.1.1. Component List
ESP32-S3 WROOM x1 |
USB cable x1 |
|---|---|
|
|
4.1.2. Component knowledge
ESP32-S3’s integrated Bluetooth function Bluetooth is a short-distance communication system, which can be divided into two types, namely Bluetooth Low Energy(BLE) and Classic Bluetooth. There are two modes for simple data transmission: master mode and slave mode.
4.1.2.1. Master mode
In this mode, works are done in the master device and it can connect with a slave device. And we can search and select slave devices nearby to connect with. When a device initiates connection request in master mode, it requires information of the other Bluetooth devices including their address and pairing passkey. After finishing pairing, it can connect with them directly.
4.1.2.2. Slave mode
The Bluetooth module in slave mode can only accept connection request from a host computer, but cannot initiate a connection request. After connecting with a host device, it can send data to or receive from the host device.
Bluetooth devices can make data interaction with each other, as one is in master mode and the other in slave mode. When they are making data interaction, the Bluetooth device in master mode searches and selects devices nearby to connect to. When establishing connection, they can exchange data. When mobile phones exchange data with ESP32-S3, they are usually in master mode and ESP32-S3 in slave mode.
4.1.3. Circuit
Connect Freenove ESP32-S3 to the computer using the Type C cable.
4.1.3.1. 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
4.1.4. Code
Move the program folder “Freenove_ESP32_S3_WROOM_Board_Lite/Python/Python_Codes” to disk(D) in advance with the path of “D:/Micropython_Codes”.
Open “Thonny”, click “This computer” -> “D:” -> “Micropython_Codes” -> “04.1_BLE”. Select “ble_advertising.py”, right click your mouse to select “Upload to /”, wait for “ble_advertising.py” to be uploaded to ESP32-S3 and then double click “BLE.py”.
4.1.4.1. 04.1_BLE
Click run for BLE.py.
Turn ON Bluetooth on your phone, and open the Lightblue APP.
In the Scan page, swipe down to refresh the name of Bluetooth that the phone searches for. Click ESP32S3.
After Bluetooth is connect successfully, Shell will printer the information.
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.
You can type “Hello” in Shell and press “Enter” to send.
And then you can see the mobile Bluetooth has received the message.
Similarly, you can select “Send” on your phone. Set Data format, and then enter anything in the sending box and click Write to send.
You can check the message from Bluetooth in “Shell”.
And now data can be transferred between your mobile phone and computer via ESP32S3.
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="ESP32S3"):
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("\nRX", rx_data)
86
87 p.on_write(on_rx)
88
89 print("Please use LightBlue to connect to ESP32S3.")
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="ESP32S3"):
When the mobile phone send data to ESP32-S3 via BLE Bluetooth, it will print them out with serial port; When the serial port of ESP32-S3 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("\nRX", rx_data)
7
8 p.on_write(on_rx)
9
10 print("Please use LightBlue to connect to ESP32S3.")
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)
4.2. Project 4.2 Bluetooth Control LED
In this section, we will control the LED with Bluetooth.
4.2.1. Component List
ESP32-S3 WROOM x1 |
USB cable x1 |
|---|---|
|
|
4.2.2. Code
Move the program folder “ Freenove_ESP32_S3_WROOM_Board_Lite/Python/Python_Codes “ to disk(D) in advance with the path of “ D:/Micropython_Codes “.
Open “Thonny”, click “This computer” -> “D:” -> “Micropython_Codes” -> “04.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-S3 and then double click “BLE_LED.py”.
4.2.2.1. 04.2_BLE_LED
Compile and upload code to ESP32S3. The operation of the APP is the same as 04.1, you only need to change the sending content to “led_on” and “led_off” to operate LEDs on the ESP32S3.
Data sent from mobile APP:
You can check the message sent by Bluetooth in “Shell”.
The phenomenon of LED
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="ESP32S3"):
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 led=Pin(2,Pin.OUT)
84 def on_rx(rx_data):
85 print("Received: ", rx_data)
86 if rx_data == b'led_on':
87 led.value(1)
88 elif rx_data == b'led_off':
89 led.value(0)
90 else:
91 pass
92
93 p.on_write(on_rx)
94
95 print("Please use LightBlue to connect to ESP32S3.")
96
97
98if __name__ == "__main__":
99 demo()
Compare received message with “led_on” and “led_off” and take action accordingly.
1if rx_data == b'led_on':
2 led.value(1)
3elif rx_data == b'led_off':
4 led.value(0)

