本帖最后由 andery88 于 2020-2-25 17:30 编辑

各位伙伴们,距离我上次【智能全彩LED鱼缸灯】
的帖子已经有半月有余,受新型冠状病毒的影响,笔者虽已开工,但是单位为了降低办公的密集度,所以仍有一半时间是在家办公,为了充实宅在家里的时间,笔者又基于富芮坤BLE5.0开发板开发了一个新的应用:【智能环境监测仪】

首先,祝愿大家:身体健康!

好了,言归正传,上回说到:【智能全彩LED鱼缸灯】的应用其实是展示了富芮坤SOC芯片FR8016H核心功能:低功耗蓝牙的数据传输之peripheral端接收功能,即富芮坤SOC芯片作为蓝牙的外围端,由手机作为中央端,然后,由手机端软件单方向地向富芮坤SOC芯片端发送全彩LED鱼缸灯控制指令(数据:手机-->SOC),SOC端通过解析手机端发来的信息来控制全彩LED鱼缸灯的开、关及各颜色的度。


可是,如何能实现富芮坤SOC芯片端向手机端回传信息呢(数据:SOC-->手机),想着想着突然冒出个想法:即通过富芮坤BLE5.0开发板上原有的温湿度传感器获取环境的温度和湿度信息,通过MQ-135空气质量传感器获取空气质量信息,通过光传感器获取环境光照强度信息,这些环境信息组合在一起,然后通过低功耗蓝牙功能回传至手机端,并在手机端显示,达到环境数据的获取和监测功能,这也是本应用名称【智能环境监测仪】的初衷。


说干就干!


不过通过什么样的方式,才能使BLE外围端设备向中心端设备回传数据呢?
对此,分析了BLE协议中GATT服务操作的5种类型:
操作类型
功能说明
Write/
允许GATT客户端写入一个值到GATT服务器的一个特性中有应用层上的确认和回应。
Write without Response/没有回应的写
允许GATT客户端写入一个值到GATT服务器的一个特性中没有应用层上的确认和回应。
Read/
一个GATT客户端可以读取在GATT服务器中特性的值。
Notify/通知
允许GATT服务器在其某个特性改变的时候对GATT客户端进行提醒,无应用层上的确认
Indicate/指示
允许GATT服务器在其某个特性改变的时候对GATT客户端进行提醒,有应用层上的确认

当然,上述GATT服务的5种操作类型对应着GATT服务的5种权限,在富芮坤SOC的BLE5.0协议栈里定义了这5种权限:
权限类型
富芮坤SOCBLE5.0协议中的定义字符
Writable/可写
GATT_PROP_WRITEGATT_PROP_AUTHEN_WRITE
Readable/可读
GATT_PROP_READGATT_PROP_AUTHEN_READ
Can send Notification/可发通知
GATT_PROP_NOTI
Can send Indication/可发指示
GATT_PROP_INDI

据此,笔者梳理了富芮坤SOC的dev1.0\ble_simple_peripheral\simple_gatt_service.c里定义的GATT服务配置表(simple_profile_att_table)里所有特征值的权限:











特征值序号
对应特征的UUID
权限
SP_IDX_CHAR1_VALUE
0xfff1
GATT_PROP_READGATT_PROP_WRITE/可读、可写
SP_IDX_CHAR2_VALUE
0xfff2
GATT_PROP_READ/可读
SP_IDX_CHAR3_VALUE
0xfff3
GATT_PROP_WRITE/可写
SP_IDX_CHAR4_VALUE
0xfff4
GATT_PROP_WRITEGATT_PROP_NOTI/可写、可发通知
SP_IDX_CHAR5_VALUE
0xfff5
GATT_PROP_AUTHEN_READGATT_PROP_AUTHEN_WRITE/可读、可写

从上述表中可以清晰地看出在0xfff0服务下的各特征值的权限。
笔者上一篇【智能全彩LED鱼缸灯】的帖子中,控制全彩LED鱼缸灯的指令就是发送至0xfff0服务的0xfff3特征的特征值里,因其具有【可写】权限,所以,可以通过手机向该特征值写入控制指令数据,然后,在sp_gatt_write_cb()回调函数里对手机发来的指令数据进行解析,从而达到利用手机控制全彩LED鱼缸灯的目的。
有点扯远了,回到本帖的应用【智能环境监测仪】,其需要由SOC端向手机端不停地回传环境数据而不需手机端给其发任何指令,手机端则只需不断地接收并处理数据即可。
那么,上表中的0xfff4特征就是一个很好的选择,因其具有【Notify】功能,即GATT服务(SOC端)可向GATT客户端(手机端)发送数据而不需要确认或回应。
伙伴们一定会说:说了半天也看不明白,还不如直接上代码来的直接!
好勒!上代码!
首先,笔者在富芮坤SOC的dev1.0\ble_simple_peripheral\simple_gatt_service.c文件的sp_gatt_write_cb()函数里的if(uuid == GATT_CLIENT_CHAR_CFG_UUID)判断里增加如下代码:
NTF_Init.jpg
通过上述代码实现对BLE通知格式的初始化,当然这里的BLE通知数据结构ntf_att和通知使能标志位sp_svc_ntf_flag要定义为全局变量,以便应用层函数的调用。
然后,在应用层文件【ble_simple_peripheral.c】里的simple_peripheral_init()函数里增加如下代码:
System_Init.jpg
上图主要功能是定义了一个周期为1s的时钟,以便将富芮坤SOC获取的环境数据每隔1s向手机端发送一次,在其上几行代码是分别为【电池电压】、【空气质量】、【光照强度】而做的初始化工作。
这里需要重点说明一下,这里的adc_channel_DAQ赋值为8,对应的二进制为1000(ADC3, ADC2, ADC1, ADC0),所以,这里选择的就是ADC3通道,而我正是使用富芮坤SOC芯片FR8016HPD7引脚与MQ-135空气质量传感器的AOUT引脚相连,同时,根据要求,4个ADC通道中每次仅能选择一个,所以ADC通道的赋值与ADC通道直接的关系如下表:
ADC通道赋值
十进制(二进制)
ADC通道选择
对应SOC引脚
10001
ADC0
PD4
20010
ADC1
PD5
40100
ADC2
PD6
81000
ADC3
PD7

然后,在应用层文件【ble_simple_peripheral.c】里定义一个定时时钟回调函数:void ble_ntf_timer_refresh_fun(void *arg),函数里的代码如下:
app_1.jpg
app_2.jpg
app_3.jpg
好了,至此,所有码砖工作已经完毕。
看了上述应用程序的代码,伙伴们也许会注意到,在最后将环境数据打包时用到了几个函数:startValuePack()、putByte()、putFloat()、endValuePack(),这些函数是为了将环境数据打包而用的,手机端软件配套使用一款名为【蓝牙调试器】的免费APP,具体长什么样子可参考我上一个帖子【智能全彩LED鱼缸灯】,这里就不赘述了,经过简单的设置后就可以在手机端接收到来自富芮坤SOC端【通知】的环境数据了。
当然,这里为了方便伙伴们使用,特将这些打包函数所需要的驱动文件整理出来,供伙伴们使用,如下为打包驱动(valuepack.h和valuepack.c)下载地址:
https://pan.baidu.com/s/10aM9Z341zQIFkZpsIYJvEw
提取码:v35c
到这里,有伙伴问了,说了半天也没见到实物,硬件是啥样子啊!
好勒!马上上图:
智能环境监测仪硬件实物图:
微信图片_20200225153026.jpg
笔者怎么看怎么像一只小老鼠,在此也祝伙伴们鼠年大吉!身体健康!也愿新冠疫情早早结束!
再来一张正面的:
微信图片_20200225153122.jpg
再来一张内部照片:
微信图片_20200225153058.jpg
在上图富芮坤BLE5.0开发板下还有一块如下图所示的3.3V的可充电池模块:
bat.jpg
因为MQ-135空气质量传感器和光照强度传感器均需5V电压才能工作,所以,当外部5V USB供电断开时,这两个传感器就无法正常工作了,但温湿度传感器和SOC芯片均能够正常工作,且能够正常的回传温湿度和电池电压的数据。
接着放一张手机端接收环境数据的界面:
app_f.jpg
手机端界面由5个文本框和5个曲线图组成,分别用于显示富芮坤SOC端的温度、湿度、空气质量、光照强度和电池电压数据。
最后,贴个我体验此应用【智能环境监测仪】的视频吧!
<iframe height=498 width=510 src='http://player.youku.com/embed/XNDU2MTM0NzIwNA==' frameborder=0 'allowfullscreen'></iframe>
祝大家身体健康!万事如意!
__________________________