查看: 55662|回复: 273
打印 上一主题 下一主题

Arduino开源智能家居01《网关》升级版网关正式教程(zigbee)

? [复制链接]
  • TA的每日心情

    2015-9-22 09:41
  • 签到天数: 9 天

    [LV.3]偶尔看看II

    跳转到指定楼层
    楼主
    发表于 2014-7-2 23:36 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
    本帖最后由 智能创客 于 2014-10-11 16:31 编辑

    这篇开始,我们就真正做《网关》升级版教程了,采用arduino+zigbee哦。
    arduino简单易学,zigbee自组网(如果不懂c语言,直接用就好,我们已经刷好自组网代码)!

    这次我们的教程是通过以下配件实现《网关》功能,并在手机端点击按钮,使zigbee模块上的灯闪亮(实现是发送真正的命令了{ckxxxxxxxxx}的格式)!
    通过不同的格式命令就可以操作开、关、接收、发送数据!之后《温湿传感器》《zigbee插座》等就可以直接连上了!


    上面就是arduino开源网关的配件。

    1、SMARTRF04EB(ZIGBEE下载器)35元
    2、CP2102(arduino下载器)15元
    3、电源供电 10元
    4、arduino板(含w5100、zigbee插槽、SD卡座)100元
    5、zigbee开发板 30元 (如果只想学zigbee只需要两块开发板和zigbee模块,自组网学习哦)
    6、zigbee模块 45元
    游客,如果您要查看本帖隐藏内容请回复




    第一部份:arduino板刷上代码。

    一、安装CP2102驱动(USB驱动)
    http://pan.baidu.com/s/1o6iDLcm(下载后直接安装或发现有新硬件就更新驱动)。


    二、将CP2102连上arduino板底下的插槽的一定要一一对应哦。
    DTR->DTR
    GND->GND
    TX->RXI
    RX->TXO
    VDD3.3->VCC









    三、刷arduino代码
    大家可以直接在这里下载源代码:
    http://pan.baidu.com/s/1i386zPV(包含arduino软件和所有的库)


    [size=0.83em]
    [color=rgb(153, 153, 153) !important]





    下面我们就贴上代码(都有注释哦)

    kittenblock中小学创客名师推荐的图形化编程软件

    #include 
    #include 
    #include 
    #include 
    #include 
    ??
    ? ?
    ??
    //请到m.znck007.com申请登陆-》家中环境-》网关,里可以看到!
    #define APIKEY "xxxxxxxxxxxxxxxx" //设置apikey 
     
    uint16_t sid=001;//设置sid(设备号)
    ??
    ??
     
    //NRF24l01发送接收节点
    const uint16_t this_node = 0; 
    const uint16_t other_node = 1;
    ??
    //NRF24l01收发数据
    struct payload_t
    {
    ??uint32_t ms;
    ??uint32_t data;
    ??char sendchar[20];
    };
     
    //NRF24l01脚针设置
    iBoardRF24 radioSend(3,8,5,6,7,2);
    iBoardRF24Network networkSend(radioSend);
     
    bool ispayload=false;//NRF24l01收发判断
    uint16_t sendChannel=1;//NRF24l01发送频道
    uint32_t sendCount=0;//NRF24l01发送次数
     
    char incomingData[20]={0};//NRF24l01接收到的字符(其它设置发过来)
     
     
     
     
     
    //设置MAC地址,如果有二个请改为不同(随意)
    static byte mymac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
    ? ?
    EthernetClient client;//声明网关类
     
    char server[] = "api.znck007.com";//声明API网址
    //char urlBuf[] = "/index.php";
     
    static long timer;//用于规定时间间隔
    unsigned long last_http;//记录http时间,用于http超时判断,目前20秒无响应则重新GET。
    bool ishttpget=false;//标示http是否已经结束
     
     
     
    bool isUpdate=false;//成功则更新服务器数据为正常
    char updateData[20]={0};//更新的字符(服务器通过字符分析指定某个设备)
     
    //串口通信处理(主要用于zigbee通信)
    unsigned long serialnowlast;
    char serialbuff[80]={0};
    char serialData;
    int seriali=0;
     
     
    ??
    void setup(void)
    {
    ??//设置串口波特率
    ??Serial.begin(115200);
    ??Serial.println("IBOARD_GATEWAY_ZIGBEE/RF24Network");
    ? ?
    ??//NRF24l01初始化
    ??SPI.begin();
    ??radioSend.begin();
    ? ?
    ??//获取IP DNS等
    ??Serial.println("\n[getDHCPandDNS]"); 
    ??if (Ethernet.begin(mymac) == 0)
    ??{
    ? ?? ???Serial.print(F("Failed to configure Ethernet using DHCP\n"));
    ? ?? ???while(1);
    ? ?}
    ? ?else
    ? ?{
    ? ?? ???Serial.print("My IP address: ");
    ? ?? ???for (byte thisByte = 0; thisByte < 4; thisByte++) {
    ? ?? ? // print the value of each byte of the IP address:
    ? ?? ???Serial.print(Ethernet.localIP()[thisByte], DEC);
    ? ?? ???Serial.print("."); }
    ? ?? ???Serial.println("Ethernet configuration OK");
    ??}
    ??
    ??//连接web服务器
    ??// if you get a connection, report back via serial:
    ??if (client.connect(server, 80)) {
    ? ? Serial.println("connected");? ? 
    ? ? client.println("GET /index.php HTTP/1.1");
    ? ? client.println("Host: api.znck007.com");
    ? ? client.println("Connection: close");? ?? ?? ? 
    ? ? client.println();
    ??} 
    ??else {
    ? ? // kf you didn't get a connection to the server:
    ? ? Serial.println("connection failed");
    ? ? client.stop();
    ??}
    ? ?
    ??//判断web服务器是否正常
    ??timer=millis();
    ??while ((!client.available()) && (millis()-timer)<2000);
     
    ??if (client.available()) {
    ? ? char c = client.read();
    ? ? Serial.print(c);
    ? ? client.stop();
    ??}
    ??timer = millis();??
    ??
    ??//完成setup
    ??Serial.println("setup success");? ? 
    ? ?
    }
     
     
    void loop(void)
    {
    //??//NRF24l01检测接收数处理
    //??//如果使用NRF24l01,请启动这里(并删除ZIGBEE检测接收数据处理)
    //??networkSend.begin(/*channel*/ sid, /*node address*/ this_node);
    //??// Pump the network regularly
    //??networkSend.update();
    //
    //??// Is there anything ready for us?
    //??timer=millis();
    //??//while ((!networkSend.available())??&& (millis()-timer)<2000);
    //??while(networkSend.available())
    //??{
    //? ? // If so, grab it and print it out
    //? ? RF24NetworkHeader header;
    //? ? payload_t payload;
    //? ? memset(payload.sendchar, 0, 20);
    //? ? networkSend.read(header,&payload,sizeof(payload));
    //? ? Serial.print("Received packet #");
    //? ? Serial.print(payload.data);
    //? ? Serial.print(" at ");
    //? ? Serial.print(payload.ms);
    //? ? Serial.print(" getchar ");
    //? ? Serial.println(payload.sendchar); 
    //
    //? ? ispayload = true;
    //? ? 
    //? ? get_html_body(payload.sendchar,incomingData);
    //? ? Serial.println(incomingData);
    //??}
    //??
    //??if(!ishttpget)
    //??{
    //? ?? ???if(ispayload)
    //? ?? ???{
    //? ?? ?? ? ispayload = false;
    //
    //? ?? ?if(strstr(incomingData,"{ck") && strstr(incomingData,"}") )
    //? ?? ???{
    //? ?? ?? ? last_http = millis();? ?? ?? ? 
    //? ?? ?? ? ishttpget=true;??
    //? ?? ?? ?? ?? ?? ???
    //? ?? ?? ? Serial.println("\n>>> POST");
    //? ?? ?? ? static char buf[20]={0};
    //? ?? ?? ? sprintf(buf,"%s",incomingData);
    //
    //? ?? ?? ? client_post(server,APIKEY,buf);
    //? ?? ?? ? my_result_cb();
    //? ?? ?? ?? ?? ? 
    //? ?? ?? ? return;
    //? ?? ???}? ?? ?? ?? ?? ? 
    //? ?? ???
    //? ?? ???}
    //??
    //??
    //??}
     
     
    ??//ZIGBEE检测接收数据处理
    ??if(!ishttpget)
    ??{? ?
    ? ?? ? 
    ? ?? ?unsigned long serialnow = millis();//获取现在的时间
    ? ?? ?if(serialnow - serialnowlast >= 5000)//如果数据间隔超过5秒而清空字符(为了防止数据错乱)
    ? ?? ?{ 
    ? ?? ???serialnowlast = millis(); 
    ? ?? ???memset(serialbuff, 0, 80);
    ? ?? ???seriali=0;
    ? ?? ?} 
    ? ?? ? 
    ? ?? ?bool isSerial=false;
    ? ?? ?while( Serial.available() )//如果串口有数据(ZIGBEE或电脑发过来的)
    ? ?? ?{
    ? ?? ???if(seriali==0)
    ? ?? ???{
    ? ?? ?? ? Serial.println("Serial->");//打印出来方便调试
    ? ?? ???}? ?? ? 
    ? ?? ???serialData=(char)Serial.read();//读取串口数据
    ? ?? ???//Serial.print(serialData);////这里不打印,否则ZIGBEE检测到{ckxxxx}就认为是命令
    ? ?? ???serialbuff[seriali]=serialData;////保存到数组
    ? ?? ???seriali++;////数组长度+1
    ? ?? ???if(serialData=='}' || seriali>=80)//如果发现}而说明命令结束(并少于80个字符,太长会出错)
    ? ?? ???{
    ? ?? ?? ? isSerial=true;
    ? ?? ?? ? break;
    ? ?? ???}
    ? ?? ?}
    ? ?? ? 
    ? ?? ?//开始处理{ckxxxxx}字符,如POST上传到web服务器
    ? ?? ?if(isSerial)
    ? ?? ?{
    ? ?? ???serialnowlast = millis(); //更新当前时间,不然5秒就超时了
    ? ?? ?? ?
    ? ?? ???//Serial.println(serialbuff);
    ? ?? ???char body[81]={0};
    ? ?? ???get_html_body(serialbuff,body);//获取只是{ckxxxxxx}的字符,因为这是我们的命令格式 
    ? ?? ???//Serial.println(body);? ? 
    ? ?? ???
    ? ?? ???Serial.println("-------------------");
    ? ?? ???
    ? ?? ? //如果命令格式真确则POST到web服务器了
    ? ?? ???if(strstr(body,"{ck") && strstr(body,"}") )
    ? ?? ???{? ?? ?? ? 
    ? ?? ?? ? last_http = millis();
    ? ?? ?? ? ishttpget=true;
    ? ?? ?? ? timer = millis();
    ? ?? ?? ???
    ? ?? ?? ? Serial.println("\n>>> POST");
    ? ?? ?? ? //static char buf[81]={0};
    ? ?? ?? ? //sprintf(buf,"%s",body);
    ? ?? ?? ???
    ? ?? ?? ? client_post(server,APIKEY,body);//POST到网址,APIKEY,字符
    ? ?? ?? ? my_result_cb();//接收web服务器返回的字符
    ? ?? ?? ???
    ? ?? ???}
    ? ?? ???
    ? ?? ???memset(serialbuff, 0, 80);//清空字符
    ? ?? ???seriali=0;//字符长度为0
    ? ?? ?? ?
    ? ?? ???return;
    ? ?? ?}
    ??}
    ??//delay(200);
     
    ??//更新web服务器命令的状态(比如发送成功还是失败还是异常等,NRF24l01用到,ZIGBEE不用这里而是直接发送{ck00xxxxxxupdate}命令就行)
    ??if( isUpdate )
    ??{
    ? ?? ?isUpdate=false;
    ? ???
    ? ?? ?last_http = millis(); 
    ? ?? ?ishttpget=true;? ?? ?
    ? ?? ? 
    ? ?? ?Serial.println("\n>>> UPDATE");
     
    ? ?? ?static char buf[20]={0};
    ? ?? ?sprintf(buf,"%s",updateData); 
    ? ?? ?//Serial.println(buf);??
    ? ? 
    ? ?? ?client_post(server,APIKEY,buf);//POST到网址,APIKEY,字符
    ? ?? ?my_result_cb();//接收web服务器返回的字符? ?? ???
    ? ?? ?isUpdate=false;
    ? ?? ? 
    ? ?? ?return;
    ??}
     
    ??//每2秒钟查看web服务器是有命令数据
    ??unsigned long now = millis();? ?
    ??if(now - last_http >= 2000)
    ??{ 
    ? ? if(!ishttpget || (now - last_http) >= 20000)//20秒超时会执行,为了防卡死问题
    ? ? {
    ? ?? ? last_http = millis(); 
    ? ?? ? ishttpget=true;? ?? ?
    ? ?? ?? ?? ? 
    ? ?? ?? ?
    ? ?? ?Serial.println("\n>>> REQ");
    ? ?? ?static char buf[20]={0};
    ? ?? ?sprintf(buf,"{ck001000000000}"); //这个字符串代表获取新命令数据
    ? ?? ?client_post(server,APIKEY,buf);//POST到网址,APIKEY,字符
    ? ?? ?my_result_cb();//接收web服务器返回的字符? ?? ???
    ? ?? ? 
    ? ?? ?timer = millis();
     
    ? ? } 
    ? ? 
    ??}? ?
    ? ?
     
    }
     
    //接收web服务器返回的字符? ?? ???
    static void my_result_cb(){
    ??char eth_buffer[350];
    ??timer=millis();
    ??while ((!client.available()) && (millis()-timer)<1000);
     
    ??if (client.available()) {
    ? ?
    ? ?for(int j=0;client.available()>0;j++)
    ? ?{
    ? ? char c = client.read();
    ? ? eth_buffer[j]=c;
    ? ? Serial.print(c);
    ? ?}
    ? ?client.stop(); 
    ??}
    ??Serial.println();
    ? ?
    ? ? char body[81]={0};
    ? ? get_html_body(eth_buffer,body);//获取只是{ckxxxxxx}的字符,因为这是我们的命令格式 
    ? ? //Serial.println(body);
    ? ?? ?? ?
    ? ? sendChannel=get_channel(body);//获取是哪个sid,这是m.znck007.com手机客服端里的sid
     
    //??//如果使用NRF24l01,请启动这里
    //? ?if(??sendChannel>0 )
    //? ?{
    //? ?? ?networkSend.begin(/*channel*/ sendChannel, /*node address*/ other_node);
    //? ?? ?? ?
    //? ?? ?networkSend.update();
    //? ?? ?Serial.println("");
    //? ?? ?Serial.print("Sending...");
    //? ?? ?if(sendCount>1000000) sendCount=0;
    //? ?? ?payload_t payload = { sendChannel, sendCount++, "{ck000000000000}" };//millis()? ? 
    //? ?? ?sprintf(payload.sendchar,"%s",body);
    //? ?? ?RF24NetworkHeader header(/*to node*/ this_node);
    //? ?? ?bool ok = networkSend.write(header,&payload,sizeof(payload));
    //? ?? ?if (ok)
    //? ?? ?{
    //? ?? ???Serial.println("ok.");??
    //? ?? ???
    //? ?? ???isUpdate=true;? ?? ???
    //? ?? ???char front[10]={0};
    //? ?? ???memcpy(front,body,9);? ?? ? 
    //? ?? ???sprintf(updateData,"%supdate}",front);
    //? ?? ???Serial.println(updateData);
    //? ?? ? 
    //? ?? ?}
    //? ?? ?else
    //? ?? ?{
    //? ?? ???Serial.println("failed."); 
    //? ?? ?}
    //? ? }??
    ? ???
    ? ? ishttpget=false;? ? 
    ? ? last_http = millis();
    ? ?? ? 
     
    ? ? networkSend.begin(/*channel*/ sid, /*node address*/ this_node);? ?? ?? ?
    ? ? networkSend.update();? ?? ???
    ? ?? ?? ?
    }
     
     
    //获取只是{ckxxxxxx}的字符,因为这是我们的命令格式 
    void get_html_body(char *p,char *s){
    ? ?
    ??char rechar[81]={0};
    ??int bufi=0;
    ? ?
    ??bool isend=false;
    ??int charnum=0;? ? 
    ? ?
    ??for(bufi=0;bufi10)
    ? ? {
    ? ?? ?char charChannel[4]={0};
    ? ?? ?memcpy(charChannel,buff+3,3);
    ? ?? ?Serial.println(charChannel);
    ? ?? ?int intChannel=atoi(charChannel);
    ? ?? ?Serial.println(intChannel);
    ? ?? ?return intChannel;? ?? ?
    ? ? }
    ? ? else
    ? ? {
    ? ?? ?return 0;
    ? ? }
    ? ?
    }
     
    //W5100芯片POST字符数据到web服务器
    int client_post(char *server, char *apikey, char *buf){
     
    ??if (client.connect(server, 80)) 
    ??{
    ? ?? ?Serial.println("connecting...");
    ? ?? ?// send the HTTP PUT request:
    ? ?? ?client.print("POST /index.php");
    ? ?? ?client.println(" HTTP/1.1");
    ? ?? ?client.println("Host: api.znck007.com");
    ? ?? ?client.print("apikey: ");
    ? ?? ?client.println(APIKEY);
    ? ?? ?client.print("Accept: *");
    ? ?? ?client.print("/");
    ? ?? ?client.println("*");
    ? ?? ?client.print("Content-Length: ");
    ? ?? ?// calculate the length of the sensor reading in bytes:
    ? ?? ?// 8 bytes for {"value":} + number of digits of the data:
    ? ?? ?size_t thisLength = strlen(buf);
    ? ?? ?client.println(thisLength);
    ? ?? ? 
    ? ?? ?client.println("Content-Type: application/x-www-form-urlencoded");
    ? ?? ?client.println("Connection: close");
    ? ?? ?client.println();
    ? ?? ? 
    ? ?? ?client.println(buf);
    ? ?? ?client.println();
    ??} 
    ??else
    ??{
    ? ?? ?// kf you didn't get a connection to the server:
    ? ?? ?Serial.println("connection failed");
    ? ?? ?Serial.println();
    ? ?? ?Serial.println("disconnecting.");
    ? ?? ?client.stop();
    ??}
     
    }











    四、插上网线,打开串口就可以测试联网是否成功了!






    第二部份:刷zigbee模块代码


    一、将zigbee模块插到zigbee开发板上





    二、连上SMARTRF04EB下载器。
    将一边有凸出来的一端与(VDD、RES、NC、DC、GND的NC对应就正确了!


    三、安装SMARTRF04EB驱动
    http://pan.baidu.com/s/1dDH1ZX3(安装SmartRFStudio后里面包含有驱动)
    提示:如果刷不成功,点击一下SMARTRF04EB上的RESET(凹进去就用笔撮)。


    四、安装IAR 8.1,软件比较大,安装后看说明破解就好。
    http://pan.baidu.com/s/1c0b69Ra(下载解压里面有安装说明)

    五、下载zigbee自组网代码。
    http://pan.baidu.com/s/1COxT8(最新ZStack-CC2530-2.5.1自组网代码,已经写好了按键、LED灯功能)

    六、点击编译并下载。

    七、插个LED到zigbee开发板的P1.0和-。

    八、安到arduino板上。






    第三步:使用手机测试



    一、手机打开m.znck007.com手机控制端。



    二、新建一个开关。


    三、点击开关,如果发现LED灯闪,说明《网关工作正常了》!



    OK,《网关》部份已经搞定了,下期我们就来上《温湿传感器》《Zigbee插座》《红外控制》!
    因为我们还未使用Wifi,所以都需要与《网关》交互数据哦!
    等我们Wifi产品出来就可以单独使用了!



    《WIFI作品DIY教程》
    WIFI作品DIY教程01-《Z WIFI开发板》介绍和联网等配置教程


    《Arduino开源智能家居DIY教程系列》
    Arduino开源智能家居《花絮1》zigbee小底板DIY成功
    Arduino开源智能家居《认识Zigbee》zigbee功能和自组网介绍
    Arduino开源智能家居《zigbee开发板》手机/按键点亮LED
    Arduino开源智能家居01《网关》升级版网关正式教程(zigbee)
    Arduino开源智能家居02《温湿传感器》什么样温湿度才适居
    Arduino开源智能家居03《开发板套件》学习zigbee家居-性价比高
    Arduino开源智能家居04《插座开关》手机控制:网扇、空调...
    Arduino开源智能家居05《红外线》手机红外线控制电器


    《百元智能家居DIY教程系列》
    arduino教程【实战篇】01《家居网关》DIY图文视频教程
    arduino教程【实战篇】02《温湿度》DIY图文视频教程
    arduino教程【实战篇】03《智能插座》DIY图文视频教程
    arduino教程【实战篇】04《电灯开关》DIY图文视频教程
    arduino教程【实战篇】05《手机红外线》DIY图文视频教程
    关注@智能创客http://www.znck007.com(打造DIY创客平台)

  • TA的每日心情
    奋斗
    2019-9-20 09:57
  • 签到天数: 1669 天

    [LV.Master]伴坛终老

    推荐
    发表于 2014-7-3 15:01 | 只看该作者
    我要好好学习!

    该用户从未签到

    板凳
    发表于 2014-7-3 09:22 | 只看该作者
    不错,真是需要的
  • TA的每日心情
    慵懒
    2019-6-11 14:24
  • 签到天数: 101 天

    [LV.6]常住居民II

    5#
    发表于 2014-7-3 16:11 | 只看该作者

    不错,真是需要的
  • TA的每日心情
    开心
    2015-5-25 09:37
  • 签到天数: 2 天

    [LV.1]初来乍到

    6#
    发表于 2014-7-3 17:26 | 只看该作者
    看看怎么样.

    该用户从未签到

    7#
    发表于 2014-7-7 17:18 | 只看该作者
    想学学突然看到了这么好的贴
  • TA的每日心情

    2015-9-22 09:41
  • 签到天数: 9 天

    [LV.3]偶尔看看II

    8#
    ?楼主| 发表于 2014-7-7 20:15 | 只看该作者
    fever1985 发表于 2014-7-7 17:18
    想学学突然看到了这么好的贴

    哈哈,一起加油……

    该用户从未签到

    9#
    发表于 2014-7-8 09:24 | 只看该作者
    灰常酷 喜欢额
  • TA的每日心情
    开心
    2016-1-27 11:13
  • 签到天数: 1 天

    [LV.1]初来乍到

    10#
    发表于 2014-7-8 09:53 | 只看该作者
    恭喜升级!IBoard+zigbee真心不错!{:soso_e179:}
    您需要登录后才可以回帖 登录 | 立即注册 ?

    本版积分规则

    热门推荐

    关于温湿度传感器在LCD显示上的问题
    关于温湿度传感器在LCD显
    我建立了一个程序,想要将dht11传感器得到的数据显示在LCD1602上,但是LCD显的都是乱
    【原创】全球最小口袋3D打印机mini one直播教程贴
    【原创】全球最小口袋3D打
    最近闲得蛋疼,没事搞个掌上3D打印机,先放效果图吧。 搞了半天,终于能正常打印,
    【Arduino】108种传感器模块系列实验(74)--- 4位LED数码管模块
    【Arduino】108种传感器模
    37款传感器与模块的提法,在网络上广泛流传,其实Arduino能够兼容的传感器模块肯定是
    (开源)ESP8266改装小风扇,app远程控制+天猫精灵控制
    (开源)ESP8266改装小风
    材料准备 [*]USB风扇一个 [*]ESP8266一块 [*]3.3继电器一块 拆解风扇 第一次,没有
    基于机器视觉的智能分拣机械臂
    基于机器视觉的智能分拣机
    本作品是一个基于机器视觉的智能机械臂操作平台,其采用atmega32单片机作为主控制系统
    Copyright ???2015-2016??Arduino中文社区??Powered by?Discuz! ??( 蜀ICP备14017632号-3 )
    快速回复 返回顶部 返回列表