Linknode开发板评测
一、开箱与三个sensortag对比
拿到LinkNode,看了看包装,Mbed BLE sensors Tag,那咱也当他是一个sensortag吧,正好手头还有两颗Ti的sensortag,一起比较以下哦。先看看三个小家伙的包装对比,咱们的LinkNode是最小的。
然后是板子对比,也是linknode最小,而且已经自带了下载器,还是mbed的哦。而Ti的还是需要另找调试器的,关键调试器接口还是1.27间距的,相当的难弄。不过Linknode用的是2.0mm间距的口子,所以附送了2.0转2.54的杜邦线,以及2.0mm的排针,也算细心了。可是调试口明明只用了4个,为啥要来6孔2.0mm呢,变成4孔2.54mm的不是挺好?
LinkNode尺寸的减小,主要是两个方面造成的,首先,Ti全部使用PCB天线,而LinkNode使用了陶瓷天线,就是照片上那颗蓝色的,这个差别很大。另外,T1使用的传感器众多(在后面表格中有比较),而LinkNode只是板载了加速度和大气压,还是比较简单的。不过LinkNode比较有特色的是板载了一颗buzzer,就是蜂鸣器了,非常适合来做一个随身的提醒功能,多了一样用户交互方式。
最后是三个家伙的比对,可以看到nRF51822的性能功耗在三者中处于中档的样子。
二、开发环境与第一个mbed程序
概要:按照官方wiki做就行,注意事项:开发板自带的flash盘的链接添加的是nRF51-DK,用这个是不行的,必须用nRF51822,原因未知。具体过程如下。
将开发板插入电脑后,会看到一个名字叫JLINK的flash盘,里面有4个文件,从readme的文档中可以知道,这个就是用来更新目标板程序用的flash盘,只要把hex文件拖进去,就可以完成程序的下载。
在浏览器中打开其中的MBED.HTM,则会自动连接到mbed网站,并将对应的开发板加入到自己账户名下,很是方便。同时也说明了我们的开发板其实对应的就是Nordic nRF51-DK,至少在编程器部分是相同的。
写到这里发现忽然有点问题,就是官方的wiki上说选用的是Nordic nRF51822,到底应该用哪个?还得后续试用才知道。
所以就让我们从点亮LED开始吧,原理图显示,低电平点亮,R连P020,蓝色P019
mbed的代码组织和开发过程倒是和常见的IDE相似,原始界面如下图,workshop下面就是自己的各个program了。可以新建,也可以导入,最右边是帮助。
点新建可以出来界面,我们来一个LinkNode_blink
然后增加一个main.cpp文件,并在里面添加官网代码
#include<mbed.h>
DigitalOut LED_R(P0_20);
DigitalOut LED_B(P0_19);
int main()
{
while(1)
{
LED_R=0;
LED_B=1;
wait(0.5);
LED_R=1;
LED_B=0;
wait(0.5);
}
}
复制代码
如果忘记导入mbed库,会有错误提示,
点击fix it可以自动跳出lib的搜寻结果,找到合适添加一下就好了,添加完以后会自动重新编译(也可以编译前手动导入)。
编译成功就可以下载hex文件到本地啦,不过不能直接下载到那个jlink盘里面,要下载到本地,然后再拖进去。复制进去以后会自动重启,可是,并没有看到什么blink!!试了很多次还是这样,最后忽然想到,要不换一块板?从nRF51DK换成nRF51822,成功闪烁!!看来有时盘里的东西也不一定靠谱啊,还是看官网的说明比较靠谱。
三、mbed之用户交互-串口
LinkNode上的用户交互主要有按键、LED、buzzer,但是更重要的是uart,一般mbed除了虚拟U盘(MSD programmer) 外,还有两个设备,分别是CMSIS-DAP Debug和虚拟串口。
不过虚拟串口和debug这两个不能默认使用,必须先装驱动。串口界面在此,可是并不能装
https://developer.mbed.org/handbook/Windows-serial-configuration
只好求助于nordic的官网。可惜是51822mDK是一个discontinued的产品,也没找到合适的驱动。论坛求助以后给了一个新的固件,可能目前并不是标准的mbed?不过考虑到后面要退回的,暂时也不影响评测,那就先对付着用着吧。串口就先使用另外引出的P023和P025。
so,我们先通过串口来采集一下bmp180的大气压和温度。mbed的一个优势是有大量共享的库可以用,比如这个bmp180在mbed上就能搜到,我们直接使用lib方式就好了。会有很多,选一个介绍比较全面一点的
比如上面这个,里面有class reference
还有具体使用示例,节省空间,帖个部分
只要复制这个代码就行,唯一需要修改的就是I2C的具体管脚(sda,scl),
I2C i2c(P0_17, P0_18);
复制代码
并增加一个串口界面,示例中直接使用了printf,应该是打印到了默认的串口上了吧。如果删除下面这行,编译没有问题,但是串口上就没有任何东西啦。
Serial pc(P0_23,P0_25);
复制代码
剩下就没有剩下了,编译下载,顺利看到现象。
顺便总结下bmp180的使用过程(以温度为例):
bmp180.init(); //返回0表示成功
bmp180.startTemperature();
wait_ms(5);
bmp180.getTemperature(&temp);//返回0表示成功
复制代码
四、BLE双向数据传输
mbed上有不少关于ble的例子,用BLE搜索到的项目有43页,其中很多都是针对nRF51822的,可以直接拿来用。
那我们就先选用那个simplechat好了,看说明应该是配合某个app来实现双向数据传输的,BLE的显示终端是串口,而手机的显示终端就是某个app。
不过这个app上的uart和LinkNode的定义是不一样的,因此我们需要来做一下改造。在OOP下,这个也很容易,只要把main里面的//Serial pc(USBTX, USBRX);改为Serial pc(P0_23,P0_25);就可以了。初始打印串口上有些问题,主要体现在计数值的输出上,会出现乱码,其实主要是在调用串口的putc方法的问题,本来应该显示对应数值的ascii码,结果实际将byte值直接输出了。
所以只要将putc直接用printf的%d代替就可以了,修改前代码
pc.printf("Length: ");
pc.putc(bytesRead);
pc.printf("\r\n");
复制代码
修改后代码
pc.printf("Length: %d\r\n",bytesRead);
复制代码
这样就可以完美实现LinkNode和手机通过BLE的双向数据传输了。没有安装例子上说的app,直接用了一个通用的调试工具,lightblue。具体效果看视频。需要注意的是,LinkNode串口收到数据后,会把\r\n都算成字符数目,所以看到的是6,而实际可见字符只有4个。
flash视频请点击阅读原文。
另外有一个隐藏的问题,就是长UUID和短UUID的问题,前面用长uuid有问题,
static const uint8_t uart_tx_uuid[] = {0x71, 0x3D, 0, 3, 0x50, 0x3E, 0x4C, 0x75, 0xBA, 0x94, 0x31, 0x48, 0xF1, 0x8D, 0x94, 0x1E};
复制代码
换了短的UUID就行。
#define BLE_UUID_TX_CHARACTERISTIC 0x0002
复制代码
但是这个问题没法复现,对应一个char的问题,研究一下另开贴讨论。
五、LinkNode玩呼吸灯
这个其实就是利用PWM的占空比来控制LED的亮度,对于单片机来说是很普通的功能,但在mbed下会发现更加无法想象的简单。在没有看官方例子前,总觉得该配置点定时器什么的,然后再得到PWM。结果并非如此。因为已经定义了PwmOut这个类了!!官方例子是控制蜂鸣器演奏一首歌曲,那我们就改造成呼吸灯吧。不够在pwm的duty-cycle设置中有个小坑,跟大家分享一下。
编程环境,mbed,添加mbed库即可。在库中可以找到pwm类的说明,还是比较简单的。下图所示的方法用用就够了
另外write和read可以简单的用实例=和=实例来完成。废话少说,先来试试这个duty-cycle到底是数字大亮还是数字小亮。既然是百分比,那么肯定在0-1.0之间取值。我们给两盏LED都点上
#include <mbed.h>
PwmOut L_red(P0_20);
PwmOut L_blue(P0_19);
int main(void){
L_red=0.1;
L_blue=0.9;
while(1){
}
}
复制代码
实验结果:红灯很亮,蓝灯比较暗。但是因为IO口接的是LED灯的阴极,所以这个duty-cycle数字表示的是高电平的比例。然后就是咱们的呼吸灯了,定时改变占空比咯。蓝色比较优雅,就选它了。不过很奇怪 ,现象并不乐观,首先使用这段代码,预期是灯从最暗变到最亮,然后再回到最暗。
#include <mbed.h>
PwmOut L_blue(P0_19);
int main(void){
L_blue=1.0;
while(1){
wait(1);
L_blue=L_blue-0.2;
if (L_blue==0) {
L_blue=1.0;
}
}
}
复制代码
结果实际情况是:从暗变到最亮,然后就停在最亮状态不变了!!开始以为是0值比较问题,可是把第三行变成L_blue<0也没戏。参考了下mbed的PWM例程。也是失败。
但是while(1)中,使用这段代码可以。
wait(1);
L_blue=1.0;
wait(1);
L_blue=0.8;
wait(1);
L_blue=0.6;
wait(1);
L_blue=0.4;
wait(1);
L_blue=0.2;
wait(1);
L_blue=0.0;
复制代码
想了半天,最后使用了一个中间变量dc,严格保证给到L_blue的值一定在0和1之间。于是就成功了。最终完整代码如下:
#include <mbed.h>
PwmOut L_blue(P0_19);
int main(void){
float dc=0.0;
L_blue=dc;
L_blue.period_us(10);
while(1){
wait(1);
dc=dc+0.2;
if (dc>1.1) {
dc=0.0;
}
L_blue=dc;
}
}
复制代码
看来mbed也是有坑的啊,官方例程也靠不住。当然也许在底层实现中,有些mcu会自动检查duty-cycle的范围,有些就没有?如果误写入了不合理的数值,可能就引起单片机的奇怪状态了。库的源文件并不可见,所以也不追究了。
六、并不成功的LinkNode的三轴加速度计
概要:按照官方代码,读不到正常数据。初步估计原因可能有以下几个:1、SPI驱动有问题。可是呢IO口没有引出,没法测试。2、主芯片和LIS3DH之间的连接有问题,导致不能正常通信。看了看引脚太小,没法测试。具体过程描述如下。
LinkNode上有一个LIS3DH,可是官方手册上并没有给出参考代码。就连SPI的参考代码都没有。不过linksprite的wiki上有,可以在以下网址找到(http://linksprite.com/wiki/index ... IS3DH_accelerometer)。
本来想利用mbed的库从头建个工程看看,但是搜索了以下,发现LIS3DH的库和项目都只有2个,而且都是i2c接口的。虽然芯片CS拉高就是i2c模式,但是看原理图,并没有看到有接i2c上拉电阻,所以还是乖乖用SPI,参考官方代码来写吧。有时间再转换一下i2c驱动到SPI吧。
官方代码比较简单,就是写了一个SPI的初始化,读写寄存区的子函数,然后调用。结果烧写以后满屏的“device err”。这又是什么鬼??!!
看了下代码,每次读数都会查看下芯片的ID,如果是0x33,表示有芯片,如果不是,则显示上图的出错信息。
打印了一下收到的who am i,发现都是255。这说明MI上全是高电平啊。
绕过who am I检测,强制读取三轴的值就是这么个死相
改造下显示代码,其实是以下这么回事,也就是说,读到的全是1。和读who am I的结果一致。真是醉了
可怜的SPI引脚也没有引出,无法测试。有没有人可以跑动这个例程的呢?
七、BLE light
尝试使用手机控制两个LED灯的亮度。本次是在nRF51822_SimpleControls基础上修改的。因为redbear的app只能控制一个LED,所以手机上配合通用的BLE调试工具完成。不求功能复杂,只要控制亮度就行,玩转整个流程。
删除servo.cpp和servo.h
service只留下一个可写的LIGHT_CHAR
#define BLE_UUID_LIGHT_SERVICE 0x0000 /**< The UUID of the Nordic UART Service. */
#define BLE_UUID_LIGHT_CHARACTERISTIC 0x0002 /**< The UUID of the TX Characteristic. */
复制代码
控制单元只留下两个灯,都是PwmOut
PwmOut LEDR(LIGHT_R);
PwmOut LEDB(LIGHT_B);
复制代码
修改串口Pin,显示调试信息。
Serial pc(P0_23,P0_25);
复制代码
注释掉所有的长UUID,测试只用短的UUID是否可行。
手机发送控制命令2个字节,第一字节指定控制哪个LED,1 for LEDR,2 forLEDB。第二个字节表示灯的亮度,0是熄灭,0xff是最亮。对应的代码也要修改,因为PWM接的是LED的阴极。
float value = 1.0-(buf[1]/255.0);
LEDR = value;
复制代码
效果看视频。控制命令格式如上所述,测试结果,短UUID是可以的。用通用app控制还是有点慢啊,其他七七八八修改的东西都是细节,一并附在附件里面吧。
未完,待续……