AlexaZhou!

Here's my blog :)

从智能产品"防丢器"看中外差别

国外的StickNfind和国内的nut,我都使用过。发现其中有些不同很有意思,写出来和大家共享一下。

StickNfind

这是StickNfind

StickNfind一出世就在Indiegogo上面众筹超过90万美元,要知道这货众筹单价才20美元左右。可以看出来这货在国外很火。

StickNfind由一个小贴片和手机App组成,把贴片和自己的东西放在一起,就可以防丢了。

App中有两种模式:

  • 雷达

    比如把这货和钥匙挂在一起,然后如果钥匙找不到了,拿出手机一看,就大概知道钥匙离自己多远了。前后左右走两步,根据距离的变化,就能判断钥匙的方向。总之顺着App的指引,就可以很快找到钥匙啦~

  • 虚拟牵引绳

    比如去带小孩出去玩的时候,把贴片放在小孩身上,当小孩跑出一定范围的时候,手机就会发出报警。

stickNfind在App和各种宣传中都是强调雷达模式(上图手机画面即雷达模式)。

其实StickNfind的原理很简单,拆开发现贴片里面有个纽扣电池,和一个蓝牙4.0芯片。蓝牙芯片向外发出广播信号,手机通过接收到蓝牙信号的强度,就可以计算出贴片大概的距离,因为离的越远信号越弱嘛。同时由于蓝牙4.0的低功耗特性,一颗纽扣电池就能支持一年的运行时间,就基本省去了充电的烦恼,只要一年换一次电池就ok。使用体验还是比较好的。

nut

这是Nut,国内一家厂商做的兄弟产品。

StickNfind构造差不多,功能也一样,也就是这两种模式。

但是仔细体会这个App之后,发现它很强调StickNfind的第二种模式,也就是虚拟牵引绳。设计的应用场景是放在钱包里面,在钱包和手机之间建立虚拟牵引绳。一旦二者之间的距离超过一定值,手机和贴片就都会报警。重点是防止钱包或者手机被偷走。寻物模式反而是次要的。官方的宣传上也是这样的侧重。这点从上图右边的文字也能看到。第一条,第二条其实讲的都是虚拟牵引绳,最后一条才是雷达的变种。官方的宣传侧重点已经很明显了。

东西都是一样的,为什么有这样的区别呢?

因为中外环境不一样。StickNfind主要市场是美国,欧洲之类的国家。Nut的市场则是在国内。

神奇的点在于老外很多人都住着独栋房子(House),国内是公寓(Apartment)。

所以老外如果忘记东西放在哪儿了,需要楼上找,楼下找,房子这么大,到处找费功夫不说,还不一定找得到。而我们如果忘记了个东西,家就这么大,没几个房间,大概找找也就出来了。

如果把寻物看作一个算法的话,它的时间复杂度可能是O(n^2)。即随着房间的增多,所需要的时间按指数级别上升。很容易想象嘛,一般都是这里翻翻那里翻翻,那里翻不到再回到开始的地方翻。

明白了吧,这点差别就造成了国内市场对寻物的需求远比国外弱。

不过国内厂商也不是吃素的,估计想到国内人员密度大,小偷扒手多,防盗是个强需求。于是就开动脑筋,在这上面作文章。最后防丢贴片就主打“虚拟牵引绳”模式,以防盗为卖点作为宣传。

国内厂商这一步棋,走的够高明。

任何一个产品,都要经过深入的思考。哪怕是抄别人的,也要理解,并且加以改进来适应自己的情况。不然做出来的产品,就只能是一个笑话了。

同样的,国外Nest很火,是因为老外住大House。听说国内也团队在做类Nest产品的,我就不知道他们想干嘛了。

CC2540通过UART接收115200bps数据的方法

这个问题比较有意思,而且具有一定的普遍性,写出来和大家一起分享。

最近做了一个物联网项目,目的是为原有的一个只能通过UART接口控制的设备添加蓝牙功能。

采用的主体结构是把CC2540模块和设备通过UART连接,然后在CC2540上实现相应的Profile,手机通过Profile和CC2540通讯,而CC2540通过UART接口和设备通讯。这样子经过CC2540的转换,就可以实现用手机APP对设备进行控制了。

cc2540是TI的 蓝牙4.0(BLE)SOC芯片,特性如下:

  • 256KB FALSH
  • 16KB RAM
  • 32MHz的单周期增强型51 Core
  • 蓝牙协议栈和用户的应用程序可以在单芯片上运行
  • 极低的功耗

其实整个项目都很普通,没有什么难度。除了一个地方,就是用CC2540捕捉UART数据。这里的设备数据包大小不定,最大不超过1KB。

接收UART数据不是很简单嘛?单片机都能做,为嘛这个地方会有问题呢?

因为CC2540是一颗SOC芯片,也就是个System on chip。CC2540除了运行用户的应用程序以外,还运行蓝牙4.0的协议栈,收发无线数据包相关的事件都是由协议栈自动处理。

好的,问题来了。根据TI的资料,每次处理数据包相关事件可能需要占用CPU长达几个毫秒的时间,并且在这个时间中是完全关闭中断的。

而平时我们从UART接收数据,最常用就是通过中断。配置好设备的寄存器,使得每次UART收到数据就产生一次中断,然后在中断中对数据进行读取。

115200bps的速率下1秒大约有 115200/8=14400Byte的数据发送,1ms也就是14Byte。如果通过中断的方式来接收数据,假设CPU处理运行协议栈花了1ms时间,而这时恰好有数据过来。就会丢失14Byte,这肯定是没法用的。so,此路不通。

幸好还有更好的方法,也就是通过DMA接收数据

DMA(Direct Memory Access,直接内存存取) 是所有现代电脑的重要特色,它允许不同速度的硬件装置来沟通,而不需要依于 CPU 的大量中断负载。否则,CPU 需要从来源把每一片段的资料复制到暂存器,然后把它们再次写回到新的地方。在这个时间中,CPU 对于其他的工作来说就无法使用。

DMA的特色就是可以不经过CPU来传输数据,正适合当前这种CPU分身乏术的情况。经查DataSheet,CC2540一共有4个DMA通道,无线协议栈用掉了一个。

通过把DMA的触发源设置为UART接收到数据,传输源地址设置为UART数据寄存器,传输目的地址设置为一片Buf,并设置为每次传输源地址不变,目的地址自增。就可以在DMA实现DMA自动搬运UART数据了。

不过不管开辟多大的DMA接收Buf,也总有满的时候。当DMA Buf满了,或者需要对DMA Buf中数据进行处理的时候,就需要暂停DMA传输。而这时如果有数据进入,就会丢失。

为了解决这个问题,这里使用经典的Ping-Pang DMA操作方法。

Ping-Pang通过开启双DMA通道,实现任意时刻都有一个DMA通道在接受数据中,不会丢数据。而且通过Ping-Pang切换,DMA Buf不会满,也就可以持续接收。

这里具体实现上先开辟两次要(a,b)一主要(x)三个缓冲区,并建立两个DMA通道,分别把DMA数据传输到两个次要缓冲区ab中。通过一个定时器在两个DMA通道之间来进行切换。每次切换到新的次要缓冲区之后,就把旧的次要缓冲区中的数据导出到主要接收缓冲x中。这样就可以在x中对数据进行处理,并且过程中不会丢失数据。

不过这里还有一个坑,那就是怎样获得DMA传输数据的长度

使用Ping-Pang 方法操作DMA时,需要不断导出已经保存在DMA Buf中的数据。这时就需要知道DMA Buf中数据的长度。有些芯片的DMA控制器有相关接口,可以直接从寄存器中读取到传输计数值。不过CC2540没有这个功能。。。TI啊TI,你这样做事情做一半,真的好么-_-#

这里显然不可以通过把DMA接收缓冲初始化为0,然后判断非0数据的长度来实现,因为UART接收到的数据可能是0。

后来想了个方法来解决。思路就是开始每一轮DMA传输之前把DMA接收缓冲区的数据初始化为固定值,比如0x00。然后把DMA控制器配置为每次传输双字节数据^1。通过查询DataSheet,UART控制器的数据寄存器后面一字节是波特率寄存器的一部分,这是一个固定值而且不为零。这样DMA每次传输会传输1字节UART接收的数据+1字节固定数据到接收Buf中。通过分析收到固定数据的长度,就可以知道DMA收到数据的长度。

这里一共有三个地方需要注意的:

  • 通过DMA接收数据
  • DMA Ping-Pong操作
  • 通过给数据添加"尾巴"来实现DMA传输计数

通过以上方法,就完美的解决了UART接收数据的问题。现在带无线协议栈的Soc芯片被广泛使用,这一类芯片的接收数据问题,都可以通过这样的思路来解决。

Versions软件让我学会SVN命令行

Versions是Mac下的一款svn客户端。Mac下面还有其他svn客户端软件,不过都差不太多,各有各的脾气,嗯,明白了吧。没有哪个象windows下乌龟牌svn那么乖的。

Versions是这一堆里面相对比较好用的。不过用的时间长了,就发现很多地方确实不能忍。

之前Versions看commit log经常cpu占用很高,有时候还干脆卡死。。。卡死了不说,关也关不掉,得kill PID才行。

有两次居然把本地的svn工作副本搞坏掉了,尼玛上G的副本,重新checkout真的要一次很长时间的。

-----------------------------------我是分割线---------------------------------

在这种情况下我尝试使用命令行来工作。发现其实SVN的CLI及其好用,简单明了。区区几个命令就把事情给干的漂漂亮亮。我玩转SVN CLI之后,也不再需要图形化工具了。

同样是版本控制系统的Git,因为Mac下有好用的SourceTree软件,我基本都是在图形界面下操作,也就不记得命令了,要用都是先查help。

好吧,其实我是想说,让我们变强的恰恰是这些...这些让我们不爽的东西。

后记: 现在好了,升级了OS X 10.10 之后,Versions貌似由于兼容问题,已经打不开了。。。我继续命令行使用中。