随着健身手环,智能手表和其他可穿戴设备的普及,蓝牙5 /低功耗蓝牙的使用通信标准被广泛采用。 BLE帮助我们以很少的功率在短距离内交换数据,这对于电池供电的设备(如可穿戴设备)至关重要。它还帮助我们建立无线BLE网状网络,此功能对于家庭自动化设备非常有用,在该设备中,多个设备必须在封闭环境中相互通信。我们已经在Raspberry Pi中使用了BLE,在ESP32中使用了BLE,以执行一些基本的BLE功能。工程师正在尝试使用BLE设计便携式无线设备,这些设备可以使用小电池长时间运行,并且有多种开发套件可用于BLE。在我们最近对Arduino Nano 33的评论中,我们还注意到开发板具有带BLE功能的nRF52840。
在本教程中,我们将探索另一个令人兴奋且流行的开发板,称为nRF52 DK,它可以使用BLE测量温度和湿度。默认情况下,BLE环境传感配置文件支持各种环境参数,但本教程仅限于温度和湿度值。该解决方案通过蓝牙低功耗与智能手机连接,并提供有关环境参数(例如温度,湿度)的频繁更新。我们将使用DHT1传感器,温度测量的分辨率为0.01摄氏度,湿度测量的分辨率为0.01%。
nRF52开发套件:
nRF52DK 是用于蓝牙低功耗和2.4 GHz无线物联网应用的完整原型平台。该开发套件支持各种标准的Nordic工具链(例如开源,GCC和商业集成开发环境,例如 Keil,IAR和Segger Embedded Studio 等)。Nordic还为nRF52提供了完整的软件开发套件,其中包括对nRF52DK的完整支持。
nRF52DK配备了nRF52832 ARM Cortex-M4F微控制器,该控制器集成了 512 KB的闪存和64 KB的SRAM。 nRF52DK具有集成的Segger J-Link On Board调试器,该调试器无需外部/其他jtag调试设备即可提供更轻松,更快速的调试。它还包括与 Arduino Uno Rev3兼容的连接器支持模拟和数字输入与微处理器的接口,并且还包括标准通信协议,例如I2C(内部集成电路),SPI(串行外围设备接口)和UART(通用异步接收器和发送器)。该开发套件采用集成的内置PCB天线进行设计,该天线可使用低功耗蓝牙与智能手机,笔记本电脑和平板电脑连接,提供短距离无线通信。
Segger嵌入式工作室
要对开发板进行编程,我们将使用 带有nRF52的Segger Embedded Studio。Segger Embedded Studio是一个功能强大的C / C ++集成开发环境(IDE),专门用于嵌入式系统开发。这提供了一个完整的一体化解决方案,其中包含嵌入式C编程,开发和调试所需的一切。这包括用于嵌入式系统编程和开发的完整工作流,具有支持ARM Cortex设备的项目管理,编辑器和调试器。对于拥有完整许可证的北欧客户,此功能强大且易于使用的IDE是完全免费的,没有任何代码大小限制。可以从下面给出的链接下载IDE,
下载Segger Embedded Studio
带nRF52DK的DHT11
DHT11是具有电阻型湿度测量组件和NTC型温度测量组件的功能齐全的温度和湿度传感器。它提供了卓越的质量,更快的响应速度和成本效益。默认情况下,所有DHT11传感器都在实验室中进行了校准,因此具有极高的准确性和可靠性。它使用单线串行接口系统进行通信,其他规格如下
DHT11的规格:
- 湿度范围:20 – 90%RH
- 温度范围:0 – 50摄氏度
- 湿度精度:±5%RH
- 温度精度:±2℃
DHT11的时序图:
使用上面显示的时序图从DHT11传感器读取数据相对简单。该过程类似于任何控制器,我们已经将该传感器与其他开发平台一起使用,例如
- 带树莓派的DHT11传感器
- 具有PIC16F877A的DHT11传感器
- 具有STM32F103C8的DHT11传感器
- 带NodeMCU的DHT11传感器
要将DHT11温湿度传感器与nRF52开发套件连接,请遵循以下给出的连接图。
我正在使用连接器模块将传感器连接到板上,所以我的最终设置如下所示
与DHT11通信的流程图:
下面的流程图说明了我们将用于在nRF52DK和DHT11之间进行通信的程序逻辑流程
资料格式:
如何使用低功耗蓝牙(BLE)?
为了了解如何使用BLE功能,我们必须了解以下解释的一些基本术语,您也可以阅读ESP32 BLE文章以了解有关BLE的更多信息
通用访问配置文件(GAP)
通用访问配置文件完全负责建立BLE外围设备 与 中央 设备之间的通信连接 。GAP还提供各种程序,包括设备扫描/发现,链路层连接建立,链路终止,安全功能握手和完整的设备配置。GAP在以下设备状态下工作
GAP国家 |
描述 |
支持 |
重置后的设备初始状态 |
广告商 |
使用有助于发起者扫描的数据进行设备广告 |
扫描器 |
接收并将扫描请求发送给广告商 |
启动器 |
发送连接请求以建立链接 |
从/主 |
连接时,如果是广告客户,则设备将作为从属设备;如果是发起方,则将设备作为主设备 |
通用属性配置文件层(GATT)
GATT代表通用属性配置文件层,它负责两个BLE设备(外围设备和中央设备)之间的数据通信。数据通信以特征的形式进行特征化,可以通信和存储数据。BLE设备在以下设备通信中扮演两个不同的角色,
- GATT服务器包含将用于读取和写入的特征信息。在我们的教程中,介绍DHT11传感器和开发人员。该套件是我们的GATT服务器。
- GATT客户端从GATT服务器读取数据或向GATT服务器写入数据。智能手机是一个GATT客户端,可以将数据读写到我们的传感器板上。
蓝牙SIG
蓝牙特殊利益组织(Bluetooth Special Interest Group,简称SIG)是负责监视蓝牙标准的发展和蓝牙技术许可的标准组织。SIG集团不生产或销售任何蓝牙产品。它定义了蓝牙规范和标准化。它们为蓝牙低功耗配置文件和各自的特性定义了唯一标识符。GATT配置文件规范可以在下面的链接中找到
GATT配置文件规格
根据以上链接中给出的GATT规范,我们收集了项目所需的唯一标识符,下表列出了这些标识符。
简介/特征 |
UUID |
GAP(通用访问权限) |
0x1800 |
GATT(通用属性) |
0x1801 |
ESS(环境感应) |
0x181A |
温度 |
0x2A6E |
湿度 |
0x2A6F |
BLE服务/特性图
BLE UUID
UUID |
16位值 |
128位UUID |
ESS服务 |
0x181A |
0000181A-0000-0000-0000-00000000000 |
临时炭 |
0x2A6E |
00002A6E-0000-0000-0000-00000000000 |
湿度炭 |
0x2A6F |
00002A6F-0000-0000-0000-00000000000 |
温度特性
属性 |
描述 |
单元 |
摄氏度,分辨率为0.01度 |
格式 |
sint16 |
UUID |
0x2A6E |
小数指数 |
2 |
读 |
强制性的 |
湿度特性
属性 |
描述 |
单元 |
分辨率为0.01%的百分比 |
格式 |
uint16 |
UUID |
0x2A6F |
小数指数 |
2 |
读 |
强制性的 |
nRF52 BLE程序说明
我们将使用 nRF5 SDK 来对nRF52开发套件进行编程。nRF5 SDK是一个完整的软件开发套件,与nRF5系列SoC上的所有外设集成了众多蓝牙低功耗配置文件,GATT串行器和驱动程序支持。该SDK可帮助开发人员使用nRF52和nRF51系列微控制器构建功能齐全,可靠且安全的蓝牙低功耗应用。完整的程序可以从这里下载,代码说明如下。
通过上拉使能将DHT11 DATA引脚配置为nrf52的输入。引脚状态应为高,以确认nRF52为DHT11数据引脚提供正确的上拉
/ *设置为输入并检查信号是否上拉* / Data_SetInput(); DelayUSec(50); if(Data_GetVal()== 0){返回DHT11_NO_PULLUP; }
从nRF52单片机生成START信号并检查确认信号。
/ *发送开始信号* / Data_SetOutput(); Data_ClrVal(); DelayMSec(20); / *将信号保持低电平至少18 ms * / Data_SetInput(); DelayUSec(50); / *检查确认信号* /如果(Data_GetVal()!= 0){/ *信号必须被传感器拉低* /返回DHT11_NO_ACK_0; } / *等待最多100 us,等待来自传感器的ack信号* / cntr = 18; while(Data_GetVal()== 0){/ *等待信号上升* / DelayUSec(5); 如果(--cntr == 0){返回DHT11_NO_ACK_1; / *信号应在此处用于ACK * /}} / *等待直到再次下降,ACK序列结束* / cntr = 18; while(Data_GetVal()!= 0){/ *等待信号下降* / DelayUSec(5); 如果(--cntr == 0){返回DHT11_NO_ACK_0; / *信号应在此处再次降至零* /}}
现在读取40位数据,其中包含2个字节的温度,2个字节的湿度和1个字节的校验和。
/ *现在读取40位数据* / i = 0; 数据= 0; loopBits = 40; 做{cntr = 11; / *等待最多55 us * / while(Data_GetVal()== 0){DelayUSec(5); 如果(--cntr == 0){返回DHT11_NO_DATA_0; cntr = 15; / *最大等待75 us * / while(Data_GetVal()!= 0){DelayUSec(5); 如果(--cntr == 0){返回DHT11_NO_DATA_1; }} data << = 1; / *下一个数据位* /如果(cntr <10){/ *数据信号高> 30 us ==>数据位1 * / data-= 1; } if(((loopBits&0x7)== 1){/ *下一个字节* / buffer = data; i ++; 数据= 0; }} while(-loopBits!= 0);
借助Checksum验证数据。
/ *测试CRC * /如果((uint8_t)((缓冲区+缓冲区+缓冲区+缓冲区)!=缓冲区){返回DHT11_BAD_CRC; }
操作并存储温度和湿度
/ *存储调用者的数据值* /湿度=((int)buffer)* 100 + buffer; 温度=((int)buffer)* 100 + buffer;
初始化nRF5 SDK记录器服务。nRF52 SDK具有称为 nrf_log 的日志记录控制接口, 并使用默认后端记录信息。默认后端将是一个串行端口。在这里,我们同时初始化了 nrf_log 控制接口和 nrf_log 默认后端。
ret_code_t err_code = NRF_LOG_INIT(NULL); APP_ERROR_CHECK(错误代码); NRF_LOG_DEFAULT_BACKENDS_INIT();
nRF52 SDK具有应用程序计时器功能。应用程序定时器模块可基于RTC1外设创建多个定时器实例。在这里,我们初始化nRF5应用程序计时器模块。在此解决方案中,两个应用程序计时器用于和数据更新间隔。
ret_code_t err_code = app_timer_init(); APP_ERROR_CHECK(错误代码);
nRF52 SDK具有完整功能的 电源管理模块, 因为BLE设备需要在纽扣电池上工作数月。电源管理在BLE应用中起着至关重要的作用。nRF52电源管理模块完全可以处理。在这里,我们初始化nRF5 SDK的电源管理模块
ret_code_t err_code; err_code = nrf_pwr_mgmt_init(); APP_ERROR_CHECK(错误代码);
nRF52 SDK具有内置的 Nordic Soft Device固件hex文件,该文件具有蓝牙低功耗中央和外围堆栈。此高质量协议栈包括GATT,GAP,ATT,SM,L2CAP和链路层。在这里,我们遵循初始化顺序,即初始化nRF5 BLE无线电堆栈(Nordic Soft Device)
ret_code_t err_code; err_code = nrf_sdh_enable_request(); APP_ERROR_CHECK(错误代码); //使用默认设置配置BLE堆栈。 //获取应用程序RAM的起始地址。 uint32_t ram_start = 0; err_code = nrf_sdh_ble_default_cfg_set(APP_BLE_CONN_CFG_TAG,&ram_start); APP_ERROR_CHECK(错误代码); //启用BLE堆栈。 err_code = nrf_sdh_ble_enable(&ram_start); APP_ERROR_CHECK(错误代码); //注册BLE事件的处理程序。 NRF_SDH_BLE_OBSERVER(m_ble_observer,APP_BLE_OBSERVER_PRIO,ble_evt_handler,NULL);
GAP负责设备扫描/发现,链接建立,链接终止,安全功能和配置的启动。 GAP具有关键的连接参数,例如连接间隔,从属延迟,监督超时等。在此初始化通用访问配置文件连接参数
ret_code_terr_code; ble_gap_conn_params_tgap_conn_params; ble_gap_conn_sec_mode_t sec_mode; BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode); err_code = sd_ble_gap_device_name_set(&sec_mode, (const uint8_t *)DEVICE_NAME, strlen(DEVICE_NAME)); APP_ERROR_CHECK(错误代码); memset(&gap_conn_params,0,sizeof(gap_conn_params)); gap_conn_params.min_conn_interval = MIN_CONN_INTERVAL; gap_conn_params.max_conn_interval = MAX_CONN_INTERVAL; gap_conn_params.slave_latency = SLAVE_LATENCY; gap_conn_params.conn_sup_timeout = CONN_SUP_TIMEOUT; err_code = sd_ble_gap_ppcp_set(&gap_conn_params); APP_ERROR_CHECK(错误代码);
GATT负责BLE外围设备与中央设备之间的数据通信。nRF52 GATT模块有助于协商和跟踪最大ATT_MTU大小。在这里,我们初始化nRF52 SDK通用属性模块,
ret_code_t err_code = nrf_ble_gatt_init(&m_gatt,NULL); APP_ERROR_CHECK(错误代码);
关贸总协定以服务和特征的形式进行数据通信。在这里,我们初始化GATT环境传感服务,其中包括温度和湿度等特性的初始化。
ret_code_terr_code; nrf_ble_qwr_init_t qwr_init = {0}; //初始化排队写模块。 qwr_init.error_handler = nrf_qwr_error_handler; err_code = nrf_ble_qwr_init(&m_qwr,&qwr_init); APP_ERROR_CHECK(错误代码); m_ess.notif_write_handler = ble_ess_notif_write_handler; err_code = ble_ess_init(&m_ess); APP_ERROR_CHECK(错误代码);
广告在BLE应用环境中起着至关重要的作用。数据包包括地址类型,广告类型,广告数据,设备制造商特定数据和扫描响应数据的信息。nRF52 SDK带有广告模块。在这里,我们使用参数对广告模块进行初始化。
ret_code_terr_code; ble_advdata_t advdata; ble_advdata_t srdata; ble_uuid_t adv_uuids = {{ESS_UUID_SERVICE,BLE_UUID_TYPE_BLE}}; //构建和设置广告数据。 memset(&advdata,0,sizeof(advdata)); advdata.name_type = BLE_ADVDATA_FULL_NAME; advdata.include_appearance = true; advdata.flags = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE; memset(&srdata,0,sizeof(srdata)); srdata.uuids_complete.uuid_cnt = sizeof(adv_uuids)/ sizeof(adv_uuids); srdata.uuids_complete.p_uuids = adv_uuids; err_code = ble_advdata_encode(&advdata,m_adv_data.adv_data.p_data,&m_adv_data.adv_data.len); APP_ERROR_CHECK(错误代码); err_code = ble_advdata_encode(&srdata,m_adv_data.scan_rsp_data.p_data,&m_adv_data.scan_rsp_data.len); APP_ERROR_CHECK(错误代码); ble_gap_adv_params_t adv_params; //设置广告参数。 memset(&adv_params,0,sizeof(adv_params)); adv_params.primary_phy = BLE_GAP_PHY_1MBPS; adv_params.duration = APP_ADV_DURATION; adv_params.properties.type = BLE_GAP_ADV_TYPE_CONNECTABLE_SCANNABLE_UNDIRECTED; adv_params.p_peer_addr = NULL; adv_params.filter_policy = BLE_GAP_ADV_FP_ANY; adv_params.interval = APP_ADV_INTERVAL; err_code = sd_ble_gap_adv_set_configure(&m_adv_handle,&m_adv_data,&adv_params); APP_ERROR_CHECK(错误代码);
将使用各种连接参数来处理和监视BLE连接,例如第一个连接参数更新延迟,下一个连续延迟,更新计数,连接事件处理程序回调函数和连接错误回调事件处理程序。在这里,我们进行初始化BLE连接建立参数以及用于连接事件和错误事件的回调事件处理程序。
ret_code_terr_code; ble_conn_params_init_t cp_init; memset(&cp_init,0,sizeof(cp_init)); cp_init.p_conn_params = NULL; cp_init.first_conn_params_update_delay = FIRST_CONN_PARAMS_UPDATE_DELAY; cp_init.next_conn_params_update_delay = NEXT_CONN_PARAMS_UPDATE_DELAY; cp_init.max_conn_params_update_count = MAX_CONN_PARAMS_UPDATE_COUNT; t_on_notify_cccd_handle = BLE_GATT_HANDLE_INVALID; cp_init.disconnect_on_fail = false; cp_init.evt_handler = on_conn_params_evt; cp_init.error_handler = conn_params_error_handler; err_code = ble_conn_params_init(&cp_init); APP_ERROR_CHECK(错误代码);
系统初始化完成后,我们从公告BLE设备名称和功能信息开始。从这里,可以在智能手机的Ble扫描列表上看到此外围设备。
ret_code_terr_code; err_code = sd_ble_gap_adv_start(m_adv_handle,APP_BLE_CONN_CFG_TAG); APP_ERROR_CHECK(错误代码);
主循环运行2秒钟,读取温度和湿度,并使用读取或通知更新到连接的智能设备
对于(;;) { uint16_t温度,湿度; DHTxx_ErrorCode dhtErrCode; idle_state_handle(); if(updtmrexp){ dhtErrCode = DHTxx_Read(&temperature,&湿度); if(dhtErrCode == DHT11_OK){ NRF_LOG_INFO(“温度:%d湿度:%d \ n”,温度,湿度); if(temp_notif_enabled){ ble_ess_notify_temp(m_conn_handle,&m_ess,温度); }其他{ ble_ess_update_temp(&m_ess,温度); } if(humid_notif_enabled){ ble_ess_notify_humid(m_conn_handle,&m_ess,湿度); }其他{ ble_ess_update_humid(&m_ess,湿度); } } updtmrexp = false; } }
使用nRF Connect测试我们的程序
nRF Connect是功能强大的低功耗蓝牙工具,可用于扫描和探索启用BLE的外围设备。 nRF Connect for mobile支持广泛的Bluetooth SIG采用的标准配置文件。我们可以使用此工具来验证程序,在安装应用程序后,我们可以通过扫描应用程序上的BLE设备将nRF52板与手机配对。在环境感应属性中,我们可以注意到温度和湿度值正在更新,如下图所示。
Hariharan Veerappan 是一位独立顾问,在嵌入式产品开发方面拥有超过15年的经验。他提供嵌入式固件/ Linux开发方面的咨询服务,还提供公司和在线培训。Hariharan拥有电子与通信工程专业的工程学士学位,他通过其文章和教程与Circuit Digest的读者分享了他的经验和想法。