Alexie 发表于 2013-5-15 10:32:21

智能开关的无线协议详解

本帖最后由 Alexie 于 2013-5-17 14:42 编辑

ITEAD智能开关使用的是433MHz无线频段进行数据通讯,采用的是OOK的调制,通过占空比做简单的编码表示0和1。我们知道这样做确实不太稳定和可靠,不过因为单火线的供电方式只能提供不到100uA的持续电流,我们是在无法使用蓝牙,wifi等稳定可靠的通讯方式,433MHz的简单调制通讯是综合了供电问题和距离问题后的一个妥协选择,使用这个方法我们可以让开关直接的通讯距离达到30米,普通的房间之间穿墙传输都可以轻松完成。

下面我们详细介绍下智能开关的数据传输格式。开关间的每一次数据传输都是由4段数据流+结束码组成,而每段数据流又由引导码+32位数据组成,如下图所示。



从图上的时序可以看出,引导码是由一段400us的高电平加上一段10ms的低电平信号而构成。紧接着的32位数据是由一个8位的命令加上24位的IDKEY而构成的,对于智能开关的按键来说,每一个IDKEY都是独一无二的。其中,数据0是由一段400us的高电平加上一段400us的低电平而构成;而数据1是由一段400us的高电平加上一段1.2ms的低电平而构成。引导码和32位数据会被重复发送四次,以免数据接收终端由于恶劣的环境而不能有效地接收到首次数据。最后,结束码是由一段400us的高电平,一段10ms的低电平再加上一段400us的高电平而构成。这样就完整地发送了一次命令。

我们知道你们肯定要吐槽为什么使用的不是定长的编码,而是非等长的。其实,我们原先的设计是400us高电平加上1.2ms低电平表示数据1,1.2ms的高电平加上400us的低电平表示数据0,这样每个数据都是等长的1.6ms。 不过最后因为一言难尽的原因,最后协议被修改为以上的格式,这也是综合了各种情况后的妥协结果。

智能开关的固件里现在支持下面的几种命令:

控制开:0x02+ 24位IDKEY
控制关:0x03+ 24位IDKEY
控制反转状态:        0x01+ 24位IDKEY
请求配对指令:        0x40000000
开状态: 0x06+ 24位IDKEY
关状态: 0x07+ 24位IDKEY
配对成功指令:        0x50+ 24位IDKEY

若智能开关上的某一个按键被你的设备,遥控器,手动触摸中任意一种方式控制改变了状态,它将在改变状态后的0.4s左右发送自身当前状态信息。捕捉此信息即可得到相应按键的当前状态。

上面的内容是智能开关使用的通讯方式,我们知道,通过433MHz的方式我们是无法直接通过手机来直接控制它的,因为手机不支持433MHz频段的无线通讯。所以,我们就做了一个智能中转盒来完成这个从手机到433MHz的无线中转。那么,为了支持这些控制指令,我们必须为手机也建立一个简单的命令协议,以便手机或者其他终端通过蓝牙发送指令来控制开关。

下面就是我们为手机蓝牙通讯部分建立的一个简单控制协议:

注*   奇偶校验位为字节2到字节5的奇偶校验和。

手机通过蓝牙发送对应的指令,中转盒即可给转换成对应的智能开关指令,并通过433MHz的无线通讯协议方式发送给智能开关。
当然除了使用智能中转盒外,你也可以使用其他任何设备加上433MHz的无线通讯模块来控制智能开关,为了方便大家DIY,我们提供了一个专门的智能开关通讯库(Arduino版本),让你可以通过Arduino控制板加上433MHz的无线模块,简单调用433MHz发送和接收函数来控制智能开关了。


接下来我们简单介绍一下“ITEAD Intelligent Switch Protocol”库中的一些函数:

Switch.Init(baud)
函数功能:初始化智能中转盒,包括串口的波特率、设置发射引脚为输出、初始化接收中断等。
函数参数:
baud:串口的波特率
Switch.PAIR()
函数功能:发送请求配对命令0x40000000
Switch.ON(IDKEY)
函数功能:开启ID地址为IDKEY的智能开关。
函数参数:
IDKEY:此参数为32位,因为智能开关对应的IDKEY只有24位,高8位为无效位,后24位才是真正的有效IDKEY。
Switch.OFF(IDKEY)
函数功能:关闭ID地址为IDKEY的智能开关。
函数参数:
IDKEY:此参数为32位,因为智能开关对应的IDKEY只有24位,高8位为无效位,后24位才是真正的有效IDKEY。
Switch.INVERT(IDKEY)
函数功能:反转ID地址为IDKEY的智能开关的当前状态。
函数参数:
IDKEY:此参数为32位,因为智能开关对应的IDKEY只有24位,高8位为无效位,后24位才是真正的有效IDKEY。
Switch.QUERY(IDKEY)
函数功能:查询ID地址为IDKEY的智能开关当前的状态。
函数参数:
IDKEY:此参数为32位,因为智能开关对应的IDKEY只有24位,高8位为无效位,后24位才是真正的有效IDKEY。
Switch.Available()
函数功能:433接收到开关返回给串口的数据的字节总数。
Switch.Read()
函数功能:读取433接收到开关返回给串口的数据。

库里面带有一个demo的例程,如下:
#include <CloudSwitch.h>
void setup(){
       Switch.Init(115200);
       Switch.ON(0x000002C2); //Turn on the switch with 0x0002C2 IDKEY.
}

void loop(){
       while(1)
{   
       if(Switch.Available())
       {
            unsigned char value = Switch.Read();
            Serial.write(value);
       }
}   
}
把上面的demo程序下载到智能中转盒或者Arduio开发板中,就可以实现开启IDKEY为0x0002C2的智能开关,并且通过串口可看到智能开关以HEX形式返回的32位数据(8位状态位+24位IDKEY)。如果开关通过遥控或触摸改变开关状态,在串口上也会打印出相应的状态。

u8500 发表于 2013-5-17 20:30:57

mark{:soso_e179:}

幻生幻灭 发表于 2013-5-18 14:59:12

好像可以直接用来控制我们的BOXZ机器人了吧

幻生幻灭 发表于 2013-5-18 15:05:54

手里还没有433模块,这个用的是软串口?
看到“这样每个数据都是等长的1.6ms”让我想起了红外的NEC协议:lol

Alexie 发表于 2013-5-18 20:31:01

幻生幻灭 发表于 2013-5-18 15:05 static/image/common/back.gif
手里还没有433模块,这个用的是软串口?
看到“这样每个数据都是等长的1.6ms”让我想起了红外的NEC协议:lo ...

不是串口哦 就是用一个普通IO口而已~ 加了个定时器做计时

433MHz的穿透性强点 如果2.4G这种功耗下根本无法工作..就算有低功耗的距离也成问题

问题不大 发表于 2013-8-16 09:44:36

:lol非常棒的开源开关

飞翔的红猪 发表于 2013-11-20 07:55:47

好贴要果断mark!:lol

小辛同学 发表于 2014-1-7 10:51:31

Alexie 发表于 2013-5-18 20:31 static/image/common/back.gif
不是串口哦 就是用一个普通IO口而已~ 加了个定时器做计时

433MHz的穿透性强点 如果2.4G这种功耗下根本 ...

在吗。。。为啥我用的上边的方法怎么不能调试呢

霸菱工程部 发表于 2014-6-2 15:18:35

不错,谢谢啦!

Jxp891025 发表于 2014-8-26 11:59:42

好帖子,赞一个!

hhl0910 发表于 2014-9-18 15:19:27

深受启发!好!

arduinook 发表于 2014-9-19 09:50:18

好帖子,赞一个!:D:D:D:D

arduinook 发表于 2014-9-19 10:38:05

:):):):):):)好帖子,赞一个

woaijike12 发表于 2018-10-12 15:43:40

太厉害了,可以留个联系方式吗?:)
页: [1]
查看完整版本: 智能开关的无线协议详解