使用 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 连接 BlueZ 和 ESP32 蓝牙的 controller。

使用 uart 串口作为 hci 接口

外部串口链接 uart 对应管脚

串口 ESP32
Tx GPIO 18 (Rx)
Rx GPIO 05 (Tx)
CTS GPIO 19 (RTS)
RTS GPIO 22 (CTS)
  • 如果不使用硬件流控,RTS 和 CTS 引脚设置可以写 -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 DevKitC 的 USB 转 UART 没有接 RTS 和 CTS,所以需要使用 uart_set_hw_flow_ctrl 关闭硬件流控。

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

使用 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!