极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 23111|回复: 6

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

[复制链接]
发表于 2014-7-3 12:39:18 | 显示全部楼层 |阅读模式
本帖最后由 智能创客 于 2014-10-11 16:26 编辑

这篇开始,我们就真正做《网关》升级版教程了,采用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元
本帖隐藏的内容一共是235元,实现自己的arduino开源网关吧(自己有arduino和w5100是可以代替我们的arduino板的)。





第一部份: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软件和所有的库)



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


  1. #include <iBoardRF24Network.h>
  2. #include <iBoardRF24.h>
  3. #include <digitalWriteFast.h>
  4. #include <SPI.h>
  5. #include <Ethernet.h>
  6.   
  7.    
  8.   
  9. //请到m.znck007.com申请登陆-》家中环境-》网关,里可以看到!
  10. #define APIKEY "xxxxxxxxxxxxxxxx" //设置apikey

  11. uint16_t sid=001;//设置sid(设备号)
  12.   
  13.   

  14. //NRF24l01发送接收节点
  15. const uint16_t this_node = 0;
  16. const uint16_t other_node = 1;
  17.   
  18. //NRF24l01收发数据
  19. struct payload_t
  20. {
  21.   uint32_t ms;
  22.   uint32_t data;
  23.   char sendchar[20];
  24. };

  25. //NRF24l01脚针设置
  26. iBoardRF24 radioSend(3,8,5,6,7,2);
  27. iBoardRF24Network networkSend(radioSend);

  28. bool ispayload=false;//NRF24l01收发判断
  29. uint16_t sendChannel=1;//NRF24l01发送频道
  30. uint32_t sendCount=0;//NRF24l01发送次数

  31. char incomingData[20]={0};//NRF24l01接收到的字符(其它设置发过来)





  32. //设置MAC地址,如果有二个请改为不同(随意)
  33. static byte mymac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
  34.    
  35. EthernetClient client;//声明网关类

  36. char server[] = "api.znck007.com";//声明API网址
  37. //char urlBuf[] = "/index.php";

  38. static long timer;//用于规定时间间隔
  39. unsigned long last_http;//记录http时间,用于http超时判断,目前20秒无响应则重新GET。
  40. bool ishttpget=false;//标示http是否已经结束



  41. bool isUpdate=false;//成功则更新服务器数据为正常
  42. char updateData[20]={0};//更新的字符(服务器通过字符分析指定某个设备)

  43. //串口通信处理(主要用于zigbee通信)
  44. unsigned long serialnowlast;
  45. char serialbuff[80]={0};
  46. char serialData;
  47. int seriali=0;


  48.   
  49. void setup(void)
  50. {
  51.   //设置串口波特率
  52.   Serial.begin(115200);
  53.   Serial.println("IBOARD_GATEWAY_ZIGBEE/RF24Network");
  54.    
  55.   //NRF24l01初始化
  56.   SPI.begin();
  57.   radioSend.begin();
  58.    
  59.   //获取IP DNS等
  60.   Serial.println("\n[getDHCPandDNS]");
  61.   if (Ethernet.begin(mymac) == 0)
  62.   {
  63.         Serial.print(F("Failed to configure Ethernet using DHCP\n"));
  64.         while(1);
  65.    }
  66.    else
  67.    {
  68.         Serial.print("My IP address: ");
  69.         for (byte thisByte = 0; thisByte < 4; thisByte++) {
  70.        // print the value of each byte of the IP address:
  71.         Serial.print(Ethernet.localIP()[thisByte], DEC);
  72.         Serial.print("."); }
  73.         Serial.println("Ethernet configuration OK");
  74.   }
  75.   
  76.   //连接web服务器
  77.   // if you get a connection, report back via serial:
  78.   if (client.connect(server, 80)) {
  79.     Serial.println("connected");   
  80.     client.println("GET /index.php HTTP/1.1");
  81.     client.println("Host: api.znck007.com");
  82.     client.println("Connection: close");         
  83.     client.println();
  84.   }
  85.   else {
  86.     // kf you didn't get a connection to the server:
  87.     Serial.println("connection failed");
  88.     client.stop();
  89.   }
  90.    
  91.   //判断web服务器是否正常
  92.   timer=millis();
  93.   while ((!client.available()) && (millis()-timer)<2000);

  94.   if (client.available()) {
  95.     char c = client.read();
  96.     Serial.print(c);
  97.     client.stop();
  98.   }
  99.   timer = millis();  
  100.   
  101.   //完成setup
  102.   Serial.println("setup success");   
  103.    
  104. }


  105. void loop(void)
  106. {
  107. //  //NRF24l01检测接收数处理
  108. //  //如果使用NRF24l01,请启动这里(并删除ZIGBEE检测接收数据处理)
  109. //  networkSend.begin(/*channel*/ sid, /*node address*/ this_node);
  110. //  // Pump the network regularly
  111. //  networkSend.update();
  112. //
  113. //  // Is there anything ready for us?
  114. //  timer=millis();
  115. //  //while ((!networkSend.available())  && (millis()-timer)<2000);
  116. //  while(networkSend.available())
  117. //  {
  118. //    // If so, grab it and print it out
  119. //    RF24NetworkHeader header;
  120. //    payload_t payload;
  121. //    memset(payload.sendchar, 0, 20);
  122. //    networkSend.read(header,&payload,sizeof(payload));
  123. //    Serial.print("Received packet #");
  124. //    Serial.print(payload.data);
  125. //    Serial.print(" at ");
  126. //    Serial.print(payload.ms);
  127. //    Serial.print(" getchar ");
  128. //    Serial.println(payload.sendchar);
  129. //
  130. //    ispayload = true;
  131. //   
  132. //    get_html_body(payload.sendchar,incomingData);
  133. //    Serial.println(incomingData);
  134. //  }
  135. //  
  136. //  if(!ishttpget)
  137. //  {
  138. //        if(ispayload)
  139. //        {
  140. //          ispayload = false;
  141. //
  142. //      if(strstr(incomingData,"{ck") && strstr(incomingData,"}") )
  143. //        {
  144. //          last_http = millis();         
  145. //          ishttpget=true;  
  146. //                    
  147. //          Serial.println("\n>>> POST");
  148. //          static char buf[20]={0};
  149. //          sprintf(buf,"%s",incomingData);
  150. //
  151. //          client_post(server,APIKEY,buf);
  152. //          my_result_cb();
  153. //               
  154. //          return;
  155. //        }               
  156. //        
  157. //        }
  158. //  
  159. //  
  160. //  }


  161.   //ZIGBEE检测接收数据处理
  162.   if(!ishttpget)
  163.   {   
  164.       
  165.       unsigned long serialnow = millis();//获取现在的时间
  166.       if(serialnow - serialnowlast >= 5000)//如果数据间隔超过5秒而清空字符(为了防止数据错乱)
  167.       {
  168.         serialnowlast = millis();
  169.         memset(serialbuff, 0, 80);
  170.         seriali=0;
  171.       }
  172.       
  173.       bool isSerial=false;
  174.       while( Serial.available() )//如果串口有数据(ZIGBEE或电脑发过来的)
  175.       {
  176.         if(seriali==0)
  177.         {
  178.           Serial.println("Serial->");//打印出来方便调试
  179.         }      
  180.         serialData=(char)Serial.read();//读取串口数据
  181.         //Serial.print(serialData);////这里不打印,否则ZIGBEE检测到{ckxxxx}就认为是命令
  182.         serialbuff[seriali]=serialData;////保存到数组
  183.         seriali++;////数组长度+1
  184.         if(serialData=='}' || seriali>=80)//如果发现}而说明命令结束(并少于80个字符,太长会出错)
  185.         {
  186.           isSerial=true;
  187.           break;
  188.         }
  189.       }
  190.       
  191.       //开始处理{ckxxxxx}字符,如POST上传到web服务器
  192.       if(isSerial)
  193.       {
  194.         serialnowlast = millis(); //更新当前时间,不然5秒就超时了
  195.          
  196.         //Serial.println(serialbuff);
  197.         char body[81]={0};
  198.         get_html_body(serialbuff,body);//获取只是{ckxxxxxx}的字符,因为这是我们的命令格式
  199.         //Serial.println(body);   
  200.         
  201.         Serial.println("-------------------");
  202.         
  203.        //如果命令格式真确则POST到web服务器了
  204.         if(strstr(body,"{ck") && strstr(body,"}") )
  205.         {         
  206.           last_http = millis();
  207.           ishttpget=true;
  208.           timer = millis();
  209.            
  210.           Serial.println("\n>>> POST");
  211.           //static char buf[81]={0};
  212.           //sprintf(buf,"%s",body);
  213.            
  214.           client_post(server,APIKEY,body);//POST到网址,APIKEY,字符
  215.           my_result_cb();//接收web服务器返回的字符
  216.            
  217.         }
  218.         
  219.         memset(serialbuff, 0, 80);//清空字符
  220.         seriali=0;//字符长度为0
  221.          
  222.         return;
  223.       }
  224.   }
  225.   //delay(200);

  226.   //更新web服务器命令的状态(比如发送成功还是失败还是异常等,NRF24l01用到,ZIGBEE不用这里而是直接发送{ck00xxxxxxupdate}命令就行)
  227.   if( isUpdate )
  228.   {
  229.       isUpdate=false;
  230.      
  231.       last_http = millis();
  232.       ishttpget=true;      
  233.       
  234.       Serial.println("\n>>> UPDATE");

  235.       static char buf[20]={0};
  236.       sprintf(buf,"%s",updateData);
  237.       //Serial.println(buf);  
  238.    
  239.       client_post(server,APIKEY,buf);//POST到网址,APIKEY,字符
  240.       my_result_cb();//接收web服务器返回的字符        
  241.       isUpdate=false;
  242.       
  243.       return;
  244.   }

  245.   //每2秒钟查看web服务器是有命令数据
  246.   unsigned long now = millis();   
  247.   if(now - last_http >= 2000)
  248.   {
  249.     if(!ishttpget || (now - last_http) >= 20000)//20秒超时会执行,为了防卡死问题
  250.     {
  251.        last_http = millis();
  252.        ishttpget=true;      
  253.             
  254.          
  255.       Serial.println("\n>>> REQ");
  256.       static char buf[20]={0};
  257.       sprintf(buf,"{ck001000000000}"); //这个字符串代表获取新命令数据
  258.       client_post(server,APIKEY,buf);//POST到网址,APIKEY,字符
  259.       my_result_cb();//接收web服务器返回的字符        
  260.       
  261.       timer = millis();

  262.     }
  263.    
  264.   }   
  265.    

  266. }

  267. //接收web服务器返回的字符        
  268. static void my_result_cb(){
  269.   char eth_buffer[350];
  270.   timer=millis();
  271.   while ((!client.available()) && (millis()-timer)<1000);

  272.   if (client.available()) {
  273.    
  274.    for(int j=0;client.available()>0;j++)
  275.    {
  276.     char c = client.read();
  277.     eth_buffer[j]=c;
  278.     Serial.print(c);
  279.    }
  280.    client.stop();
  281.   }
  282.   Serial.println();
  283.    
  284.     char body[81]={0};
  285.     get_html_body(eth_buffer,body);//获取只是{ckxxxxxx}的字符,因为这是我们的命令格式
  286.     //Serial.println(body);
  287.          
  288.     sendChannel=get_channel(body);//获取是哪个sid,这是m.znck007.com手机客服端里的sid

  289. //  //如果使用NRF24l01,请启动这里
  290. //   if(  sendChannel>0 )
  291. //   {
  292. //      networkSend.begin(/*channel*/ sendChannel, /*node address*/ other_node);
  293. //         
  294. //      networkSend.update();
  295. //      Serial.println("");
  296. //      Serial.print("Sending...");
  297. //      if(sendCount>1000000) sendCount=0;
  298. //      payload_t payload = { sendChannel, sendCount++, "{ck000000000000}" };//millis()   
  299. //      sprintf(payload.sendchar,"%s",body);
  300. //      RF24NetworkHeader header(/*to node*/ this_node);
  301. //      bool ok = networkSend.write(header,&payload,sizeof(payload));
  302. //      if (ok)
  303. //      {
  304. //        Serial.println("ok.");  
  305. //        
  306. //        isUpdate=true;        
  307. //        char front[10]={0};
  308. //        memcpy(front,body,9);      
  309. //        sprintf(updateData,"%supdate}",front);
  310. //        Serial.println(updateData);
  311. //      
  312. //      }
  313. //      else
  314. //      {
  315. //        Serial.println("failed.");
  316. //      }
  317. //    }  
  318.      
  319.     ishttpget=false;   
  320.     last_http = millis();
  321.       

  322.     networkSend.begin(/*channel*/ sid, /*node address*/ this_node);         
  323.     networkSend.update();        
  324.          
  325. }


  326. //获取只是{ckxxxxxx}的字符,因为这是我们的命令格式
  327. void get_html_body(char *p,char *s){
  328.    
  329.   char rechar[81]={0};
  330.   int bufi=0;
  331.    
  332.   bool isend=false;
  333.   int charnum=0;   
  334.    
  335.   for(bufi=0;bufi<strlen(p);bufi++){
  336.     //Serial.print(p[bufi]);
  337.      
  338.     if(p[bufi]=='{'){
  339.       isend=true;
  340.     }
  341.     if(p[bufi]=='}' && isend==true){
  342.       isend=false;
  343.       rechar[charnum]=p[bufi];
  344.       break;
  345.     }
  346.     if(isend){
  347.       if(charnum<80)
  348.       {
  349.         rechar[charnum]=p[bufi];//Serial.print(rechar[charnum]);
  350.         charnum++;        
  351.       }
  352.     }
  353.      
  354.   }
  355.   Serial.println("");
  356.   //memcpy(s,rechar,17);
  357.   sprintf(s,"%s",rechar);
  358. }

  359. //获取是哪个sid,这是m.znck007.com手机客服端里的sid
  360. int get_channel(char *buff){
  361.      
  362.   if( strstr(buff,"{ck") && strstr(buff,"}") && strlen(buff)>10)
  363.     {
  364.       char charChannel[4]={0};
  365.       memcpy(charChannel,buff+3,3);
  366.       Serial.println(charChannel);
  367.       int intChannel=atoi(charChannel);
  368.       Serial.println(intChannel);
  369.       return intChannel;      
  370.     }
  371.     else
  372.     {
  373.       return 0;
  374.     }
  375.    
  376. }

  377. //W5100芯片POST字符数据到web服务器
  378. int client_post(char *server, char *apikey, char *buf){

  379.   if (client.connect(server, 80))
  380.   {
  381.       Serial.println("connecting...");
  382.       // send the HTTP PUT request:
  383.       client.print("POST /index.php");
  384.       client.println(" HTTP/1.1");
  385.       client.println("Host: api.znck007.com");
  386.       client.print("apikey: ");
  387.       client.println(APIKEY);
  388.       client.print("Accept: *");
  389.       client.print("/");
  390.       client.println("*");
  391.       client.print("Content-Length: ");
  392.       // calculate the length of the sensor reading in bytes:
  393.       // 8 bytes for {"value":} + number of digits of the data:
  394.       size_t thisLength = strlen(buf);
  395.       client.println(thisLength);
  396.       
  397.       client.println("Content-Type: application/x-www-form-urlencoded");
  398.       client.println("Connection: close");
  399.       client.println();
  400.       
  401.       client.println(buf);
  402.       client.println();
  403.   }
  404.   else
  405.   {
  406.       // kf you didn't get a connection to the server:
  407.       Serial.println("connection failed");
  408.       Serial.println();
  409.       Serial.println("disconnecting.");
  410.       client.stop();
  411.   }

  412. }
复制代码










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





第二部份:刷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图文视频教程

《智能创客DIY交流论坛》成立了
欢迎大家来提问题、交流、学习,共同建立智能的创客平台!
http://www.znck007.com注册有机会送板子哇!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
回复

使用道具 举报

发表于 2014-7-3 13:38:58 | 显示全部楼层
哇,都做出一整套了。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-7-4 09:54:13 | 显示全部楼层
Cupid 发表于 2014-7-3 13:38
哇,都做出一整套了。

是呀。
回复 支持 反对

使用道具 举报

发表于 2014-9-23 22:09:04 | 显示全部楼层
没看明白,楼主为什么同时会有ZIGBEE 和NRF24l01 的代码呢?
回复 支持 反对

使用道具 举报

发表于 2015-1-26 14:37:11 | 显示全部楼层
想知道怎么用wifi把数据传到internet上,然后像这样用手机查看?这里的zigbee能换成wifi吗?能的话需要改哪些硬件连接(引脚什么的),程序改哪些地方?好期待那个wifi产品,什么时候能出啊?
回复 支持 反对

使用道具 举报

发表于 2015-8-28 16:40:13 | 显示全部楼层
我想请问一下你有没有这个安卓应用的apk源码
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-9-15 14:23:19 | 显示全部楼层
无痕47 发表于 2015-8-28 16:40
我想请问一下你有没有这个安卓应用的apk源码

有了。有了。有了。有了。有了。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则 需要先绑定手机号

Archiver|联系我们|极客工坊

GMT+8, 2024-3-29 10:14 , Processed in 0.054285 second(s), 23 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表