- 积分
- 282
- 金钱
- 204
- 威望
- 0
- 贡献
- 0
- HASS币
- 0
中级会员
- 积分
- 282
- 金钱
- 204
- HASS币
- 0
|
本帖最后由 zigbee_luo 于 2021-9-1 20:23 编辑
做zigbee gateway做了这么久,想把一些东西开放出来。
看了市面上的zigbee gateway,要么基于TI的ZNP,要么基于silicon labs的NCP,还有基于泰凌微的ZGC的方案。以上几种方案,都是所谓的“网络处理器”,网络处理器都存在以下缺陷。
首先,有一部分网络处理器的UART都沿用了485总线的半双工协议,其实本来zigbee是一种无线传输,凡是无线传输都是半双工。但是如果无线和UART搭配起来使用的时候,数据从无线到UART,还是从UART到无线,都有一个转换过程。从UART到无线的数据,是从UART先到MCU的RAM,再从RAM到无线。当UART把一包数据送到RAM中,在RAM中的数据等着无线一个bit一个bit的传到空气中,这个时候UART可以休息了么?如果UART休息了,那么gateway的整体效率就拖垮了。因此这个时候要合理利用UART的资源,比如gateway在同时控制多个设备(这个时候千万不能用广播,比如需要同时控制多个不同设备的时候你敢用广播么?),UART就应该把控制指令全部堆到zigbee MCU的RAM里面,然后RAM再以队列的形式一包一包的发出去。zigbee的传输速率250kbps,加上CSMA机制带来的延迟时间,平均一个数据包从UART送到RAM中,再从RAM中发到空气中,平均时间约5~10ms。即使加上各个设备的反馈消息,在好的情况下gateway至少1秒钟内可以连续控制20~50个设备。
因此zigbee MCU的并发控制非常重要,提高并发效率可以很好的解决用户体验。但是按照原厂的ZNP或者NCP或者ZGC的建议,gateway向设备发送了Request后,需要收到设备返回来的Response,再给下一个设备发送Request。如果按照原厂(包括TI,Silicon Labs,泰凌微等)的建议,gateway的效率是很低的。这时候我们可以借鉴一下牙膏厂英特尔的一些脑洞,把超线程,乱序执行,流水线这些概念全部搬到zigbee gateway上面。假设gateway控制甲乙丙三个设备,gateway给甲发送Request,等待甲返回Response的同时又给乙和丙发送Request。反正对于gateway来说,Request都是发到zigbee MCU的RAM里面,然后RAM里面的数据包按照250kb/s加上CSMA的延迟,一个bit一个bit的送到空气中。这样的话,效率是不是变高了?
但是,这么做的话,首先要解决一个问题,就是gateway发送给甲乙丙的Request是按照甲乙丙的顺序发的,但是甲乙丙返回来的Response有可能是乱序的。而且,在zigbee应用层,一个硬件节点可以支持多个功能,比如一个zigbee设备既有照明灯的功能又有传感器的功能,如果gateway先控制这个设备的灯开关,再读取它上面的传感器,但是传感器的Response先返回来,控灯结果的Response后返回来,那么gateway的程序里面就必须处理灯的逻辑和传感器的逻辑,并把消息状态返回给对应的APP用户。但是如果给Request和Response加上设备地址和帧序号,gateway只需要根据设备地址和帧序号,就能判断Response对应的是哪个Request。这个时候,gateway就不需要对控制灯,解析传感器这些具体的应用操作进行解析了,完全就是一个数据转发。
为什么要把gateway设计成单纯的数据转发?首先gateway不会无缘无故控制设备,肯定背后有APP或者云平台或者应用程序对其进行操作。比如APP控制把某个灯开到80%亮度,gateway不需要去理解80%亮度是什么意思,只需要把80%这个数据发到目标设备就行了。而gateway收到了Response或者Report(Notify)之类的消息,收到Response了肯定有对应的Request,gateway直接把Response丢给发起Request的APP或其它应用程序,不需要知道Response里面是什么意思。哪怕Response里面通知的是目标设备要爆炸了都与Gateway无关,都是APP或其它应用程序的事。收到Report或者Notify了则可以放在消息池里面,APP或其它应用程序根据需要来处理消息池里面的消息。
gateway和zigbee MCU千万不要做任何应用层的解析。因为这个解析是无穷尽的,zigbee的cluster就有65535种,每个cluster下又有65535种Attribute,尽管现在zigbee的cluster还没用完,但是gateway和zigbee MCU的更新程序都是bin文件,仅仅是简单的在bin文件里面增加一两个cluster的支持,bin文件的内容都变化很大,目前很多zigbee MUC的bin文件更新都不支持部分更新,而且需要重新刷整个bin文件。但是如果把这一部分丢给APP或者应用程序,仅仅是增加cluster的支持,完全可以使用插件文件的形式,APP或者应用程序的主程序都不用更新,只需要添加对应的插件就行了。
再回到UART传输上来,在设计zigbee MCU程序时,UART发送到zigbee MCU的RAM中的数据,除了发到空气中以外,还有几种结果。一种是目标设备根本不存在,数据都发不出去。还有就是信号冲突,数据根本没有传出去。特别是在gateway接入的设备很多的情况下,很多设备都在周期广播链接信号,导致CSMA的延迟加大,UART到RAM可能1~2毫秒就搞定,但是RAM到空气要20ms~30ms。这个时候可以利用zigbee MCU提供的Send Confirm接口来查看数据包有没有发出去,什么时候发出去。但是像ZNP,NCP,ZGC之类的模块,并未提供Send Confirm机制,或者提供的Send Confirm接口不能回溯对应发送的数据包。比如ZNP就没有提供ZDP命令的Send Confirm接口,通常ZDP命令在设备入网的时候,用于判断入网设备是个什么东西,需要连续对一个设备发送ZDP Active EP指令和ZDP Simple Descriptor指令,通常这个动作是在设备入网的瞬间进行。但是如果遇到多个设备同时入网时,UART向zigbee MCU的RAM中连续写入多个设备的ZDP命令,如果其中某个设备入网不稳定(以zigbee 3.0设备为例,如果入网的时候握手未完成会自动失效),RAM中发给这个设备的命令会卡在RAM中一段时间。如果出现多个设备都不稳定,那么zigbee MCU的RAM中卡的数据包就越多,影响了正常设备的访问控制。因此gateway可以这样做:发任何消息给任何设备时,都要验证Send Confirm。gateway收到对应的Send Confirm了再发送下一条消息,避免MCU的RAM堵死。
综合以上因素,我们选用了TI的CC2652P芯片,重新自定义一套UART指令。这套UART指令借鉴了ZNP的原理,但是彻底抛弃了ZNP的一些落后设计,是在假设入网设备达到200个,并且对部分设备需要实时控制和并发控制的思想上完全重新开发的。模块暂时选用信驰达的CC2652P模块,亿百特的CC2652P模块的固件还在测试中。
选用的模块
下载固件
coord_cc2652P.zip
(190.35 KB, 下载次数: 18)
命令文档
TI ZIGBEE串口命令.pdf
(1.21 MB, 下载次数: 32)
总之一句话,gateway在对多个目标控制的时候,把等待设备返回的延迟时间充分利用起来,可以极大的提高设备控制效率。典型的场景就是控制100个灯,其中20个断电,剩余80个可控,用我的方法明显效率会高很多。
|
评分
-
查看全部评分
|