面包板社区的各位伙伴,大家春节好!


在这个本该喜庆的日子里,大家不免被新型冠状病毒的阴影笼罩着,为奋斗在一线的医护人员点赞!
各位伙伴也都在家为社会做着贡献!
我也和大家伙一样在家待着,实在闲来无趣,我就一直盯着我们家的鱼缸看,回想起去年元旦新购的10余条金鱼,由于刚开始养金鱼,没有什么经验,现在的鱼缸就只剩下两条较大个的金鱼了,来上图。

微信图片_20200206202907.jpg


而沉在鱼缸底部的全彩LED灯由于红外遥控器丢失(遥控器太小)一直无法打开,没了灯光的陪衬,夜晚的鱼缸暗淡了许多。
就在这时,突然想到春节前刚刚收到的来自面包板社区的【富芮坤物联网开发板BLE5.0】评测活动而获得的低功耗蓝牙V5BLE5.0)开发板,想利用此开发板来作为控制板,对原有的采用红外线+解码器的全彩LED灯控制方案改为【富芮坤BLE5.0开发板】+全彩LED驱动板的控制方案,此应用场景取名为:【智能全彩LED鱼缸灯】。
说干就干!
俗话说:知己知彼,百战不殆!

首先,先弄清楚【富芮坤物联网BLE5.0开发板】上都有什么硬件,这决定着我用那些端口去驱动全彩LED灯。

首先,查看【富芮坤开发板】文件夹里的【开发板 使用手册】/【BLE5.0开发板】/【FR8016HA开发板使用手册V1.1.pdf】。

开发板使用手册具体文件下载地址可参考:https://pan.baidu.com/share/init?surl=91JY-x2G7rWIVebdVoafww,提取码:zdov

经过学习开发板使用手册,获得【富芮坤物联网BLE5.0开发板】的硬件与软件相关信息如下:

(由于个人能力有限,下面也是根据笔者自己的理解对此芯片进行评估,有不对的地方还请伙伴们批准指正,共同学习!)

【芯片型号】:FR8016H

该芯片为SOC芯片(system on chip),芯片内含有ARM主控芯片、电源管理芯片、音频解码芯片、低功耗蓝牙5.0通信芯片等。

在软件上,该芯片的蓝牙协议栈建立在一个微型嵌入式操作系统上,也许是uCOSII,笔者在之前的小型嵌入式系统中曾在基于STM32F103芯片上移植成功过uCOSII,只记得uCOSII可同时处理多个并行任务,但对于ROM存储容量受限的普通MCU芯片来说,uCOSII程序本身占用的存储空间比较大,这就造成移植后真正留给应用程序的空间会很小,但反观此款SOC芯片,掉电不丢失存储部件由两部分构成:ROM和Flash,其中,ROM的大小为:128kB,主要用于存储启动代码、BLE controller部分协议栈等,这部分存储容量软件开发者是无法使用的,而开发者可以使用的为Flash,主要用于存储用户程序、用户数据等,其大小为:512kB或者1MB之多,由于存储空间大,所以对开发者来说不用担心芯片程序容量不够的情况发生。

程序在运行时使用的内存即RAM,用于存储程序运行时的各种变量、堆栈等,也是在运行OS时容易饱和的地方,此SOC芯片的RAM容量为48kB,较常规的20kB的容量大了一倍多,由于笔者此次开发的程序比较简单,还无法遇到RAM的瓶颈,不过笔者从此开发板自带的名为【ble_simple_peripheral】例子来看,其具有音频(.wav)解码的功能,众所周知,音频解码的过程是需要较大RAM的,其能够顺利完成音频解码说明其内部RAM足够常规程序使用。

SDK具体文件下载地址可参考:https://gitee.com/freqchip/FR801xH-SDK

说完了存储空间,再说一下主频,此SOC支持的最大主频为:48MHz,其它可设置的主频为:6MHz、12MHz、24MHz,说实话此SOC主频与常规MCU的72MHz主频相比并不高,但是如果从此SOC的定位来看就很容易理解了:BLE(Bluetooth Low Energy,低功耗蓝牙),内含电源管理芯片,且协议栈中具有单独电源管理的驱动函数,所有的这一切都是为了节能,直接对标智能移动物联网终端领域,例如:血压计、温湿度传感器、门禁开关、红外线传感器、儿童智能积木玩具、烟雾传感器等,而这些领域也都是BLE的优势领域,况且48MHz的主频已经能够满足绝大部分的需求场合。

废话不多说,直接上我整理的FR8016H芯片外围管脚及功能表:
管脚功能.png


上表是我刚开时由于对此SOC硬件结构不太理解整理的,后来发现每个管脚的硬件功能是可配置的,例如上表中的PD4、PD5、PD6、PD7可以配置成PWM功能、IIC功能、SPI功能、UART功能、PDM功能等,硬件管脚与端口功能之间在硬件上是通过一个矩阵表进行映射的,此表可在此SOC配套的SDK的【driver_iomux.h】中找到,程序开发者可根据应用需求自由支配。

上表中凡带有颜色的均表示此管脚已在此开发板有用途,为了给此应用后续的升级(例如:增加鱼缸周围环境的温湿度监测、大气压监测通过蓝牙回传至手机并存储等功能)留有余地,经过分析,采用PD4、PD5、PD7(后来深入了解发现,温湿度传感器并未使用此管脚作为SHTR,所以这里可以放心使用,而且还不用担心后续应用升级时的温湿度读取)作为外部控制功能引脚,用于控制全彩LED鱼缸灯,以实现智能全彩LED鱼缸灯的设计。

这里首先将本应用的原理框图画一下:

(原理图是我用画图自己手绘的,仅用说明原理,驱动电路仍沿用原来全彩LED鱼缸灯的,不专业,不喜勿喷!)
原理图.png

上图中间红色虚框处即为全彩LED驱动电路。

在这里说明一下,全彩LED的类型有许多种,我所知道的大致有两大类,一类是接口有三个引脚:GND、VCC、Din(Dout作为输出引脚,暂且不计算在内),控制时仅需要1个I/O引脚即可,另一类是接口有四个引脚:共阴类则是GND、G、R、B,共阳类则是:VCC、G、R、B,经过反复测试发现我鱼缸里原有全彩LED灯的类型属于:共阳GRB类,如上图所示有四个引脚:VCC、G、R、B来驱动。

全彩LED灯带的每个灯泡里分别含有红灯、绿灯、蓝灯各一个,每个子灯分别由R、G、B三个引脚分别控制亮度,又有不同亮度的红、绿、蓝灯同时点亮而形成五颜六色的颜色。

为了能够控制每个子灯的亮度,这里采用PWM波输出的方式,通过实时调节PWM波占空比的大小来控制BLE芯片I/O管脚输出电压有效值的大小,进而可以近似连续地控制全彩LED灯子灯的亮度,G、R、B三路同时控制,进而实现LED的全彩点亮。

接下来我将用于配置G(PD4)、R(PD5)、B(PD7)各管脚的程序代码粘贴如下:
PWM使能.png


上述PWM使能及初始化程序是写在了【proj_main.c】的【user_entry_before_ble_init(void)】函数里,建议伙伴们把硬件赋能、初始化等程序都放在这里哦!

说到这里,我在编写此PWM初始化代码时死活找不到pwm_init()函数,后来发现SDK文件下的components里包含所有的库函数,包括:driver_pwm.h,后来在proj_main.c及其他程序文件中添加driver_pwm.h头文件,并且在uV5里将driver_pwm.c添加到driver组里后,pwm相关函数就可以随意使用了。

对了,在调用常规PWM驱动函数的时候,我还发现一类pmu_pwm的函数,按照官方的说法,这叫【低功耗PWM接口】,后来发现不仅仅是PWM接口,任何其他通信接口均对应一个低功耗函数,这也印证了前面所说的该SOC是面向低功耗领域的移动终端应用领域的智能控制芯片。不过我的智能全彩LED鱼缸灯由于需要的电量比较大,需要通过市电经变压器实时供电,所以,这里我也就没必要采用低功耗函数了,但是这里给伙伴们提个建议,如果您将该SOC运行到移动终端等需要低功耗的领域的应用,建议每个端口均采用的对应的低功耗接口,只有这样,系统中定义低功耗模式才会真正起作用,由于时间原因,我也没有对其中的低功耗函数做过多研究,在这里抛砖引玉,希望看到伙伴们在低功耗方面的更好的作品。

PWM使能和初始化完毕之后,我又写了一个全彩LED灯上电后红、绿、蓝三颜色灯自动依次点亮后熄灭的程序,目的是在上电时监测全彩LED的每个子灯是否完好,这部门程序的代码我写在了【ble_simple_peripheral.c】的【simple_peripheral_init(void)】函数里,建议伙伴们把应用级别的初始化程序都放在这里哦!当然,这里我还是偷懒了,其实应该把ble_simple_peripheral.c给替换掉,替换成例如【Intelligent_Fullcolor_Fishbowl_LED】,说到这里的意思是这里的ble_simple_peripheral.c文件属于应用层文件,当然应用程序文件名也应该与应用相匹配吧!所以这里建议伙伴们把应用程序都放在ble_simple_peripheral.c或者伙伴们自己新建的应用程序文件里。

上述全彩LED灯自检程序如下:
全彩LED自检.png

哈哈,刚刚发现上述程序中的备注写错了,不应是3s,应该是1s,刚开始写程序时的确是3s,后来发现程序在初始化的过程中时间太长,要等待9s以上,如此,也将降低智能全彩LED鱼缸灯的用户体验,所以后来就改为了1s,绿、红、蓝各点亮1s后熄灭,整个初始化过程3s多一点,不仅完成了自检,而且用户等待时间也不会太长。

全彩LED自检完后,该干什么了呢?

当然是去响应接收来自手机端的蓝牙指令了!

响应接收来自手机端的蓝牙指令程序我放在了【simple_gatt_service.c】的【sp_gatt_write_cb(...)】函数里了,当蓝牙模块接收到来自手机端的控制指令后,此SOC软件系统会自动调用该函数,接收到来自手机端的控制指令就存储在指针write_buf所指向的RAM里,程序会根据蓝牙UUID的不同,自动将其copy到对应的变量里,在BLE协议栈里,有服务、特征的概念,每个服务都有一个UUID,每个特征也有一个UUID,一个服务下可以有多个特征,我这里选择了具有【写功能】(对手机端(central端)而言)的特征3的值:sp_char3_value,BLE接收到的控制指令均存放在sp_char3_value数组里。

对于服务和特征等的概念伙伴们可能不太理解,这里贴一张笔者整理的【simple_gatt_service】服务里的【Attribute(属性)表】的其中一部分:

(这里先声明一下,我是个BLE新手,因为此活动才临时学习的BLE协议栈的,理解有不对的地方还请伙伴们批评指正!)
属性表.png


上图中,红颜色的部分代表的就是服务:SP_IDX_SERVICE(16位UUID=0xfff0),紧接着绿色、蓝色和黄色这三个部分共同组成了UUID=0xfff0的服务下的一个特征,而一个特征又有三部分组成:绿色部分的特征声明(SP_IDX_CHAR1_DECLARATION)、蓝色部分的特征值(SP_IDX_CHAR1_VALUE)以及黄色部分的特征描述(SP_IDX_CHAR1_USER_DESCRIPTION),其中的特征值就是GATT服务所提供的通信数据内容,此次【智能全彩LED鱼缸灯】应用所使用的是UUID=0xfff0服务下的UUID=0xfff3的特征,其值对应于【SP_IDX_CHAR3_VALUE】所对应的数组变量【sp_char3_value】,也就是上面所说的特征3的值。

我刚开始直接读BLE协议栈理论的时候更难理解,这里我通过解析【属性表】并以表格的形式向伙伴们展示BLE协议栈中服务与特征之间的关系,希望对伙伴们加快理解BLE协议有所帮助。

好了,关于GATT服务就先说到这里,下面我将解析来自手机端发来的控制指令的程序贴出来,供伙伴们参考:
包解析.png

至此,所有需要我在peripheral端(此SOC端)编写的程序编写完毕,伙伴们一定惊讶此应用程序如此之短。

是啊,我还特地数了一下,此应用程序需要开发者编写的程序有效行仅36行,就这36行就实现了一个比较复杂的蓝牙通信控制终端。

当然,其实如果从头至尾程序都要开发者自己编写这样功能的程序,估计至少要成百上千行代码吧,之所以我用了极少的代码编写出了一个功能相对完备的BLE peripheral端应用程序,是建立在富芮坤完备的SDK基础之上,官方提供了完备的库函数供开发者调用,完全不用将大把时间花在具体驱动细节上,这样的开发模式我喜欢!

对了,看到这里,伙伴们也许会说我忽悠的吧,没看到实物啊!

接下来,我逐一秀一下我的作品细节:

作品整体图:
微信图片_202002070040021.jpg

来,给控制盒一个特写:
微信图片_202002070040022.jpg

哈哈,这是我翻箱倒柜找到的一个还算比较合适的旧手机包装盒做的,我是业余的,伙伴们凑合着看吧!不喜勿喷!

来,打开盒子看看都有什么:
微信图片_20200207004002.jpg

嗨!我本来想让此图片横放,但设置了半天也没弄过来,就这样凑合着看吧!

图中最核心的就是富芮坤提供的BLE5.0开发板了,开发板的上边是一个AC220V/50Hz转DC26.5V的电源模块,还有一个全彩LED驱动模块,当初只顾安装了,忘了给它拍照了o(╥﹏╥)o。具体原理呢就请伙伴们参考我上边手绘的原理图吧!

对了,BLE5.0的开发板也是由全彩LED驱动模块里的一个DC5V电源供通过电池接口供电的,此时,【BT蓝牙芯片电源供电】跳帽应该选择【BAT】(外部电池供电),当然了我这里不是电池,而是DC5V电源模块o(* ̄︶ ̄*)o。

说了半天BLE的peripheral端,那么central端我是如何实现的呢?

手机下载“蓝牙调试器”,APP的Logo长这个样子:
蓝牙调试器.png


这是一个免费软件,除了打开APP时有一次广告推送外,其它都十分好用,真心感谢此APP的开发者,可以让蓝牙(BLE版)初学者不写一行代码就可以控制蓝牙模块,赞!在这里也推荐伙伴们调试用哦!

此软件进入后先设置拟用蓝牙模块数传的UUID,我设置的如下图所示:
UUID配置.jpg

伙伴们,看到了吗?这里第一UUID就是服务UUID=0xfff0,这里说一下,UUID是一个128bits长的二进制数,全球唯一,但对于蓝牙协议数据来说,其余位数的数字均一致,变的部分就这16位(也不绝对哦,如果用户自己闭环使用,UUID的128bits数值任君使用,但通用性就荡然无存了,这也就失去了UUID的意义)。0xfff0服务就是上面所说到的SP_IDX_SERVICE服务(即:simple_gatt_service服务)。UUID=0xfff3的特征存储有此应用要使用到的控制命令。UUID=0xfff2是用于手机端接收peripheral端发回的命令的,目前暂未使用,主要是由于笔者能力有限、时间有限,还没搞明白如何使peripheral端主动发送命令(Notification方式或者是Indication方式,前者无需central端应答,而后者需要),希望后续的伙伴们加油能给我以启发。

下面上图——控制主界面:
控制界面.jpg


至于此APP如何使用我在这里就不详述了,否则就跑题了,感兴趣的伙伴可以自己看其帮助,里面有很详细的指导步骤,而且也不复杂。

最后,贴个我体验此应用:【智能全彩LED鱼缸灯】的视频吧!



最后的最后,奉上笔者鱼缸七彩图(无美颜,不喜勿喷O(∩_∩)O哈哈~):
微信图片_202002062029461.jpg
微信图片_202002062029467.jpg
微信图片_202002062029466.jpg
微信图片_202002062029462.jpg
微信图片_202002062029465.jpg
微信图片_202002062029463.jpg
微信图片_202002062029464.jpg

好了,集齐7张彩图就可以...分享啦!

对了,还没结束,末了,我还要分享一下我在制作此应用中发现的此开发板设计不合理的地方:

此开发板的蓝牙天线旁边设计了一个安装孔,手里有开发板的伙伴们估计也都看到了,起初我是用四个螺丝通过四个金属杆固定在外壳上的,但在安装后发现蓝牙信号变得十分微弱,有时手机与蓝牙模块距离很近也连接不上,后来试着将靠近蓝牙天线的螺母拧掉,信号明细好了些,但感觉仍没有单板是信号强,搜索时仍不容易搜索到,后来索性把该定位孔下的金属杆也撤了,再试发现蓝牙信号钢钢的,连接无阻,测试了20米的距离仍能正常通信,不错!不错!

后续的伙伴们一定要注意哦!此定位孔不要使用,及时要用也要用绝缘材料滴!

笔者是一个标准化工作者,文章末尾以标准的结束符结尾吧!

祝大家身体健康!万事如意!