使用 ESP32 作为蓝牙 adapter (适配器)

Ubuntu 系统使用 ESP32 作为蓝牙 adapter (适配器)

蓝牙可以通过 HCI 将 HOST 部分与 Controller 部分进行连接。

这篇文章说明了如何使用 ESP32-IDF 中包含的蓝牙示例应用程序 controller_hci_uart 通过主机控制器接口(Host Controller Interface)与 ESP32 蓝牙 controller 进行连接和通信。使用任何操作系统(Mac,Linux或Windows)的电脑都可以来编译此工程。

在此示例中使用的 Host 是 BlueZ 蓝牙协议栈。由于 BlueZ 是用于基于 Linux 内核的操作系统系列的蓝牙协议栈,因此本示例需要在一台运行 Linux OS 且安装了 BlueZ 的计算机与 ESP32 开发板进行通讯。

主机控制器接口(Host Controller Interface)可以使用 UART 连接 BlueZESP32 蓝牙的 controller

使用 uart 串口作为 hci 接口

外部串口链接 uart 对应管脚

串口 ESP32
Tx GPIO 18 (Rx)
Rx GPIO 05 (Tx)
CTS GPIO 19 (RTS)
RTS GPIO 22 (CTS)
  • 如果不使用硬件流控,RTSCTS 引脚设置可以写 -1

使用下面代码设置串口引脚

1
uart_set_pin(HCI_UART_PORT, HCI_UART_TXD, HCI_UART_RXD, HCI_UART_RTS, HCI_UART_CTS)

默认的波特率为 921600

使用自带的 USB 转 uart 接口作为 hci 接口

使用其他引脚作为串口链接到电脑需要额外链接一个串口设备,增加了成本还比较麻烦,所以我考虑使用 ESP 默认使用的 USB 串口,作为蓝牙链接串口。

但是由于 UART0 是默认配置的串口,用作系统信息的打印,所以默认没有打开作为 HCI 串口的选项,这里我们可以通过修改 esp_bt_controller_config 来设置 hci 使用串口 0

1
2
3
esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();
/* set hci use uart number*/
bt_cfg.hci_uart_no = HCI_UART_PORT;

同样由于 UART0 是系统信息打印的串口,引脚(TX->GPIO1,RX->GPIO3)已经默认配置好了,不需要再次设置引脚。但是 ESP32 DevKitCUSBUART 没有接 RTSCTS,所以需要使用 uart_set_hw_flow_ctrl 关闭硬件流控。

如果使用 uart_set_sw_flow_ctrl 开启软件流控,需要修改 XONXOFF的值,有些数据会被软件流控截断,不建议使用。

使用 Ubuntu 系统连接 ESP32 蓝牙适配器

将串口链接到电脑上,会出现对应串口的设备。如: /dev/ttyUSB1

  • 将串行设备 (serial devices) 连接到 BlueZ 蓝牙协议栈
    1
    sudo btattach -B /dev/ttyUSB1 -S 921600

    可以添加 -N 关闭 BlueZ 的硬件流控
    sudo btattach -N -B /dev/ttyUSB1 -S 921600

成功执行后会显示配置信息和连接设备的编号(index)

1
2
3
Attaching Primary controller to /dev/ttyUSB0
Switched line discipline from 0 to 15
Device index 1 attached

注意:这个窗口不要关闭!
到这里,系统就已经连接了 ESP32 的 adapter

我们还可以使用以下命令行工具进行调试。

  • 使用 BlueZ 管理工具 btmgmt

btmgmt: - A command-line interface of BlueZ for management Usage:

根据 btattach 连接上设备的 index,使用下面命令连接设备。

1
sudo btmgmt --index 1

测试命令

1
2
3
4
power on 打开电源
find 搜索设备
stop-find 停止搜索
power off 关闭电源
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
$ sudo btmgmt --index 1

[hci1]# power on
hci1 Set Powered complete, settings: powered bondable ssp br/edr le secure-conn
[hci1]# find
Discovery started
hci1 type 7 discovering on
hci1 dev_found: 6F:E6:68:BD:41:05 type LE Random rssi -94 flags 0x0000
AD flags 0x1a
eir_len 18
hci1 dev_found: 0C:E9:99:CE:F5:7D type LE Random rssi -69 flags 0x0004
AD flags 0x00
eir_len 31
[hci1]# stop-find
Discovery stopped
hci1 type 7 discovering off
[hci1]# power off
hci1 Set Powered complete, settings: bondable ssp br/edr le secure-conn
hci1 class of device changed: 0x000000
[hci1]#

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98

#include <stdio.h>
#include <string.h>
#include "nvs_flash.h"
#include "esp_bt.h"
#include "soc/uhci_periph.h"
#include "driver/uart.h"
#include "driver/periph_ctrl.h"
#include "esp_log.h"

static const char *tag = "CONTROLLER_UART_HCI";


#define HCI_UART_PORT (0)

#define BUF_SIZE (1024*4)

#if HCI_UART_PORT == 0

#define HCI_UART_TXD (1)
#define HCI_UART_RXD (3)
#define HCI_UART_RTS (-1)
#define HCI_UART_CTS (-1)

#elif HCI_UART_PORT == 1

#define HCI_UART_TXD (5)
#define HCI_UART_RXD (18)
#define HCI_UART_RTS (19)
#define HCI_UART_CTS (23)

#endif


void reconfig_hci_uart()
{
/* Configure parameters of an UART driver,
* communication pins and install the driver */
uart_config_t uart_config = {
.baud_rate = 115200,
.data_bits = UART_DATA_8_BITS,
.parity = UART_PARITY_DISABLE,
.stop_bits = UART_STOP_BITS_1,
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
.source_clk = UART_SCLK_APB,
};
int intr_alloc_flags = 0;

ESP_ERROR_CHECK(uart_driver_delete(HCI_UART_PORT));
ESP_ERROR_CHECK(uart_driver_install(HCI_UART_PORT, BUF_SIZE, 0, 0, NULL, intr_alloc_flags));
ESP_ERROR_CHECK(uart_param_config(HCI_UART_PORT, &uart_config));
ESP_ERROR_CHECK(uart_set_pin(HCI_UART_PORT, HCI_UART_TXD, HCI_UART_RXD, HCI_UART_RTS, HCI_UART_CTS));

#if ((HCI_UART_RTS == -1) || (HCI_UART_CTS == -1))
ESP_ERROR_CHECK(uart_set_hw_flow_ctrl(HCI_UART_PORT, UART_HW_FLOWCTRL_DISABLE, UART_FIFO_LEN - 8));
#endif

}


void app_main(void)
{
esp_err_t ret;

/* Initialize NVS — it is used to store PHY calibration data */
ret = nvs_flash_init();
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
ESP_ERROR_CHECK(nvs_flash_erase());
ret = nvs_flash_init();
}
ESP_ERROR_CHECK( ret );

// HCI_UART_PORT == 0 had been enabled
#if HCI_UART_PORT == 1
periph_module_enable(PERIPH_UART1_MODULE);
#elif HCI_UART_PORT == 2
periph_module_enable(PERIPH_UART2_MODULE);
#endif
periph_module_enable(PERIPH_UHCI0_MODULE);

esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();
/* Set the uart number used by hci*/
bt_cfg.hci_uart_no = HCI_UART_PORT;

ret = esp_bt_controller_init(&bt_cfg);
if (ret != ESP_OK) {
ESP_LOGE(tag, "Bluetooth Controller initialize failed: %s", esp_err_to_name(ret));
return;
}
reconfig_hci_uart();

ret = esp_bt_controller_enable(ESP_BT_MODE_BTDM);
if (ret != ESP_OK) {
ESP_LOGE(tag, "Bluetooth Controller initialize failed: %s", esp_err_to_name(ret));
return;
}

}

#

Comments

:D 一言句子获取中...

Loading...Wait a Minute!