[UNO] Arduino+ESP8266使用EDP协议控制LED灯

[复制链接]
4770|10
 楼主 | 2016-11-29 08:57 | 显示全部楼层 |阅读模式
本帖最后由 hbzjt2011 于 2016-11-29 09:02 编辑

       Arduino是许多智能硬件爱好者的首选,使用简单快捷,而ESP8266模块也是当前最为热门的WIFI模块。本项目完成了Arduino使用EDP协议通过ESP8266 WIFI模块接入OneNET服务器,并通过在接入设备中创建的应用来实现远程控制LED灯。
【1】硬件连接:
准备元件:
  • Arduino UNO
  • ESP8266 WIFI模块
  • USB转TTL连接线

硬件连线:
Arduino UNO     USB转TTL
D2-----------------RX
D3-----------------TX
GND---------------GND

Arduino UNO     ESP8266
RX-----------------TX
TX-----------------RX
GND---------------GND
其中USB转TTL连接电脑用于调试打印输出,然后Arduino的串口连接ESP8266的串口。
实物连接如下如图所示:
745857785157534515.jpg       

【2】ESP8266配置和EDP上传数据介绍:

选用ESP8266串口WIFI模块,通过AT指令控制WIFI模块接入互联网,依次完成与接入互联网、与OneNet服务器建立TCP连接、传输数据等操作。
1)配置WIFI模块;
模块配置接入OneNet,依次发送如下几个命令到WIFI模块:
AT+CWMODE=3
AT+RST
AT+CIFSR
AT+CWJAP="your ssid","password"

2)和OneNet服务器建立TCP连接,依次发送命令:
AT+CIPSTART="TCP","183.230.40.39",876  //和服务器建立TCP连接
AT+CIPMODE=1    //进入透明传输模式
AT+CIPSEND  //开始传输
命令执行结果如下图所示:
2f7b8025c6c5b331623516b95c61eca0.png

关于如何使用WIFI方式接入可以详细查看:http://open.iot.10086.cn/doc/art76.html#29

【3】创建设备和应用:
添加产品并创建接入设备,详细创建步骤请查看:http://open.iot.10086.cn/doc/art243.html#66。其中数据传输协议选择EDP。
360截图20161111091855434.jpg 360截图20161111092202870.jpg

在设备中添加应用,创建一个开关控件,在右侧的属性中选择对应设备的switch0数据流 ·注意到属性中有开关开值和开关关值两个属性,分别默认为1,0,这里不做修改(因为代码中1为开,非1则为关) ·修改EDP命令内容为switch0:{v}(与代码对应,代码中会将冒号前的部分作为上传的数据流ID,而将冒号之后的部分作为上传是数据值) 这里的{v}是通配符当下发命令的时候,他将会被开关的开/关值取代,稍后我们将看到命令的内容。
360截图20161111092412108.jpg
360截图20161111092439495.jpg

360截图20161111092458078.jpg

编辑完成后点击保存应用。

【4】软件代码:
其中Arduino开发板的D13作为被控制的LED灯,在程序中添加设备ID和APIKey。
  1. [code]/*
  2.    采用外接电源单独供电,2 3口作为软串口接PC机作为调试端
  3.    1 0为串口,连接WIFI模块
  4. */
  5. #include <SoftwareSerial.h>
  6. #include "edp.c"

  7. #define KEY  "XpAhYrqhsZbk9eVqESnMJznDb3A="    //APIkey
  8. #define ID   "4051313"                          //设备ID
  9. //#define PUSH_ID "680788"
  10. #define PUSH_ID NULL

  11. // 串口
  12. #define _baudrate   115200
  13. #define _rxpin      3
  14. #define _txpin      2
  15. #define WIFI_UART   Serial
  16. #define DBG_UART    dbgSerial   //调试打印串口

  17. SoftwareSerial dbgSerial( _rxpin, _txpin ); // 软串口,调试打印
  18. edp_pkt *pkt;

  19. /*
  20. * doCmdOk
  21. * 发送命令至模块,从回复中获取期待的关键字
  22. * keyword: 所期待的关键字
  23. * 成功找到关键字返回true,否则返回false
  24. */
  25. bool doCmdOk(String data, char *keyword)
  26. {
  27.   bool result = false;
  28.   if (data != "")   //对于tcp连接命令,直接等待第二次回复
  29.   {
  30.     WIFI_UART.println(data);  //发送AT指令
  31.     DBG_UART.print("SEND: ");
  32.     DBG_UART.println(data);
  33.   }
  34.   if (data == "AT")   //检查模块存在
  35.     delay(2000);
  36.   else
  37.     while (!WIFI_UART.available());  // 等待模块回复

  38.   delay(200);
  39.   if (WIFI_UART.find(keyword))   //返回值判断
  40.   {
  41.     DBG_UART.println("do cmd OK");
  42.     result = true;
  43.   }
  44.   else
  45.   {
  46.     DBG_UART.println("do cmd ERROR");
  47.     result = false;
  48.   }
  49.   while (WIFI_UART.available()) WIFI_UART.read();   //清空串口接收缓存
  50.   delay(500); //指令时间间隔
  51.   return result;
  52. }


  53. void setup()
  54. {
  55.   char buf[100] = {0};
  56.   int tmp;

  57.   pinMode(13, OUTPUT);   //WIFI模块指示灯
  58.   pinMode(8, OUTPUT);    //用于连接EDP控制的发光二极管

  59.   WIFI_UART.begin( _baudrate );
  60.   DBG_UART.begin( _baudrate );
  61.   WIFI_UART.setTimeout(3000);    //设置find超时时间
  62.   delay(3000);
  63.   DBG_UART.println("hello world!");

  64.   delay(2000);
  65.   while (!doCmdOk("AT", "OK"));
  66.   digitalWrite(13, HIGH);   // 使Led亮

  67.   while (!doCmdOk("AT+CWMODE=3", "OK"));            //工作模式
  68.   while (!doCmdOk("AT+CWJAP=\"PDCN\",\"1234567890\"", "OK"));
  69.   while (!doCmdOk("AT+CIPSTART=\"TCP\",\"183.230.40.39\",876", "CONNECT"));
  70.   while (!doCmdOk("AT+CIPMODE=1", "OK"));           //透传模式
  71.   while (!doCmdOk("AT+CIPSEND", ">"));              //开始发送
  72. }

  73. void loop()
  74. {
  75.   static int edp_connect = 0;
  76.   bool trigger = false;
  77.   edp_pkt rcv_pkt;
  78.   unsigned char pkt_type;
  79.   int i, tmp;
  80.   char num[10];

  81.   /* EDP 连接 */
  82.   if (!edp_connect)
  83.   {
  84.     while (WIFI_UART.available()) WIFI_UART.read(); //清空串口接收缓存
  85.     packetSend(packetConnect(ID, KEY));             //发送EPD连接包
  86.     while (!WIFI_UART.available());                 //等待EDP连接应答
  87.     if ((tmp = WIFI_UART.readBytes(rcv_pkt.data, sizeof(rcv_pkt.data))) > 0 )
  88.     {
  89.       rcvDebug(rcv_pkt.data, tmp);
  90.       if (rcv_pkt.data[0] == 0x20 && rcv_pkt.data[2] == 0x00 && rcv_pkt.data[3] == 0x00)
  91.       {
  92.         edp_connect = 1;
  93.         DBG_UART.println("EDP connected.");
  94.       }
  95.       else
  96.         DBG_UART.println("EDP connect error.");
  97.     }
  98.     packetClear(&rcv_pkt);
  99.   }

  100.   while (WIFI_UART.available())
  101.   {
  102.     readEdpPkt(&rcv_pkt);
  103.     if (isEdpPkt(&rcv_pkt))
  104.     {
  105.       pkt_type = rcv_pkt.data[0];
  106.       switch (pkt_type)
  107.       {
  108.         case CMDREQ:
  109.           char edp_command[50];
  110.           char edp_cmd_id[40];
  111.           long id_len, cmd_len, rm_len;
  112.           char datastr[20];
  113.           char val[10];
  114.           memset(edp_command, 0, sizeof(edp_command));
  115.           memset(edp_cmd_id, 0, sizeof(edp_cmd_id));
  116.           edpCommandReqParse(&rcv_pkt, edp_cmd_id, edp_command, &rm_len, &id_len, &cmd_len);
  117.           DBG_UART.print("rm_len: ");
  118.           DBG_UART.println(rm_len, DEC);
  119.           delay(10);
  120.           DBG_UART.print("id_len: ");
  121.           DBG_UART.println(id_len, DEC);
  122.           delay(10);
  123.           DBG_UART.print("cmd_len: ");
  124.           DBG_UART.println(cmd_len, DEC);
  125.           delay(10);
  126.           DBG_UART.print("id: ");
  127.           DBG_UART.println(edp_cmd_id);
  128.           delay(10);
  129.           DBG_UART.print("cmd: ");
  130.           DBG_UART.println(edp_command);

  131.           //数据处理与应用中EDP命令内容对应
  132.           //本例中格式为  datastream:[1/0]
  133.           sscanf(edp_command, "%[^:]:%s", datastr, val);
  134.           if (atoi(val) == 1)
  135.             digitalWrite(13, HIGH);   // 使Led亮
  136.           else
  137.             digitalWrite(13, LOW);   // 使Led灭

  138.           packetSend(packetDataSaveTrans(NULL, datastr, val)); //将新数据值上传至数据流
  139.           break;
  140.         default:
  141.           DBG_UART.print("unknown type: ");
  142.           DBG_UART.println(pkt_type, HEX);
  143.           break;
  144.       }
  145.     }
  146.     //delay(4);
  147.   }
  148.   if (rcv_pkt.len > 0)
  149.     packetClear(&rcv_pkt);
  150.   delay(150);
  151. }

  152. /*
  153. * readEdpPkt
  154. * 从串口缓存中读数据到接收缓存
  155. */
  156. bool readEdpPkt(edp_pkt *p)
  157. {
  158.   int tmp;
  159.   if ((tmp = WIFI_UART.readBytes(p->data + p->len, sizeof(p->data))) > 0 )
  160.   {
  161.     rcvDebug(p->data + p->len, tmp);
  162.     p->len += tmp;
  163.   }
  164.   return true;
  165. }

  166. /*
  167. * packetSend
  168. * 将待发数据发送至串口,并释放到动态分配的内存
  169. */
  170. void packetSend(edp_pkt* pkt)
  171. {
  172.   if (pkt != NULL)
  173.   {
  174.     WIFI_UART.write(pkt->data, pkt->len);    //串口发送
  175.     WIFI_UART.flush();
  176.     free(pkt);              //回收内存
  177.   }
  178. }

  179. void rcvDebug(unsigned char *rcv, int len)
  180. {
  181.   int i;

  182.   DBG_UART.print("rcv len: ");
  183.   DBG_UART.println(len, DEC);
  184.   for (i = 0; i < len; i++)
  185.   {
  186.     DBG_UART.print(rcv[i], HEX);
  187.     DBG_UART.print(" ");
  188.   }
  189.   DBG_UART.println("");
  190. }
复制代码

[/code]

【5】功能测试:

设备上电后,可以看到电脑串口打印输出的内容,首先连接OneNET服务器:
Screenshot_3.png

连接成功后,可以看到设备在线状态:
Screenshot_1.png

点击设备应用中的开关按钮,发送开关命令给设备:
Screenshot_2.png

设备接收命令后进行解析,并在串口打印输出:
Screenshot_4.png

当解析到数据流switch0的值为1时设备开灯,Arduino 开发板的D13被点亮,相反为0时灯灭。

【6】效果演示:
Arduino+ESP8266接入OneNET

评分

参与人数 1威望 +15 收起 理由
巧克力娃娃 + 15
| 2016-11-29 11:21 | 显示全部楼层
可以,非常帅!!!!!!!!!!!!!

使用特权

评论回复
| 2016-11-29 15:13 | 显示全部楼层
帅爆了,给lz加精!

使用特权

评论回复
| 2017-3-6 10:34 | 显示全部楼层

使用特权

评论回复
| 2017-5-16 11:11 | 显示全部楼层
嗨喽,大神,我想问下:#include "edp.c"   怎么编译不过去,谢了

使用特权

评论回复
| 2017-7-9 18:55 | 显示全部楼层
#include "edp.c"   请问这个文件去哪里下载呢

使用特权

评论回复

评论

newphj 2018-11-16 16:42 回复TA
我也想知道 
| 2017-8-31 11:54 | 显示全部楼层
学习了,顶顶

使用特权

评论回复
| 2017-12-9 15:49 | 显示全部楼层
遇到了一些问题,你能帮忙解答一下吗??

使用特权

评论回复
| 2018-7-4 16:27 | 显示全部楼层
谢谢,正在查找中

使用特权

评论回复
| 2018-12-14 14:49 | 显示全部楼层
不错,学习了

使用特权

评论回复
扫描二维码,随时随地手机跟帖
您需要登录后才可以回帖 登录 | 注册

本版积分规则

我要发帖 投诉建议 创建版块 申请版主

快速回复

您需要登录后才可以回帖
登录 | 注册
高级模式

论坛热帖

关闭

热门推荐上一条 /5 下一条

在线客服 快速回复 返回顶部 返回列表