hbzjt2011 发表于 2016-11-29 08:57

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

本帖最后由 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的串口。
实物连接如下如图所示:
   

【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//开始传输命令执行结果如下图所示:

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

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


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





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

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

#define KEY"XpAhYrqhsZbk9eVqESnMJznDb3A="    //APIkey
#define ID   "4051313"                        //设备ID
//#define PUSH_ID "680788"
#define PUSH_ID NULL

// 串口
#define _baudrate   115200
#define _rxpin      3
#define _txpin      2
#define WIFI_UART   Serial
#define DBG_UART    dbgSerial   //调试打印串口

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

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

delay(200);
if (WIFI_UART.find(keyword))   //返回值判断
{
    DBG_UART.println("do cmd OK");
    result = true;
}
else
{
    DBG_UART.println("do cmd ERROR");
    result = false;
}
while (WIFI_UART.available()) WIFI_UART.read();   //清空串口接收缓存
delay(500); //指令时间间隔
return result;
}


void setup()
{
char buf = {0};
int tmp;

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

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

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

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

void loop()
{
static int edp_connect = 0;
bool trigger = false;
edp_pkt rcv_pkt;
unsigned char pkt_type;
int i, tmp;
char num;

/* EDP 连接 */
if (!edp_connect)
{
    while (WIFI_UART.available()) WIFI_UART.read(); //清空串口接收缓存
    packetSend(packetConnect(ID, KEY));             //发送EPD连接包
    while (!WIFI_UART.available());               //等待EDP连接应答
    if ((tmp = WIFI_UART.readBytes(rcv_pkt.data, sizeof(rcv_pkt.data))) > 0 )
    {
      rcvDebug(rcv_pkt.data, tmp);
      if (rcv_pkt.data == 0x20 && rcv_pkt.data == 0x00 && rcv_pkt.data == 0x00)
      {
      edp_connect = 1;
      DBG_UART.println("EDP connected.");
      }
      else
      DBG_UART.println("EDP connect error.");
    }
    packetClear(&rcv_pkt);
}

while (WIFI_UART.available())
{
    readEdpPkt(&rcv_pkt);
    if (isEdpPkt(&rcv_pkt))
    {
      pkt_type = rcv_pkt.data;
      switch (pkt_type)
      {
      case CMDREQ:
          char edp_command;
          char edp_cmd_id;
          long id_len, cmd_len, rm_len;
          char datastr;
          char val;
          memset(edp_command, 0, sizeof(edp_command));
          memset(edp_cmd_id, 0, sizeof(edp_cmd_id));
          edpCommandReqParse(&rcv_pkt, edp_cmd_id, edp_command, &rm_len, &id_len, &cmd_len);
          DBG_UART.print("rm_len: ");
          DBG_UART.println(rm_len, DEC);
          delay(10);
          DBG_UART.print("id_len: ");
          DBG_UART.println(id_len, DEC);
          delay(10);
          DBG_UART.print("cmd_len: ");
          DBG_UART.println(cmd_len, DEC);
          delay(10);
          DBG_UART.print("id: ");
          DBG_UART.println(edp_cmd_id);
          delay(10);
          DBG_UART.print("cmd: ");
          DBG_UART.println(edp_command);

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

          packetSend(packetDataSaveTrans(NULL, datastr, val)); //将新数据值上传至数据流
          break;
      default:
          DBG_UART.print("unknown type: ");
          DBG_UART.println(pkt_type, HEX);
          break;
      }
    }
    //delay(4);
}
if (rcv_pkt.len > 0)
    packetClear(&rcv_pkt);
delay(150);
}

/*
* readEdpPkt
* 从串口缓存中读数据到接收缓存
*/
bool readEdpPkt(edp_pkt *p)
{
int tmp;
if ((tmp = WIFI_UART.readBytes(p->data + p->len, sizeof(p->data))) > 0 )
{
    rcvDebug(p->data + p->len, tmp);
    p->len += tmp;
}
return true;
}

/*
* packetSend
* 将待发数据发送至串口,并释放到动态分配的内存
*/
void packetSend(edp_pkt* pkt)
{
if (pkt != NULL)
{
    WIFI_UART.write(pkt->data, pkt->len);    //串口发送
    WIFI_UART.flush();
    free(pkt);            //回收内存
}
}

void rcvDebug(unsigned char *rcv, int len)
{
int i;

DBG_UART.print("rcv len: ");
DBG_UART.println(len, DEC);
for (i = 0; i < len; i++)
{
    DBG_UART.print(rcv, HEX);
    DBG_UART.print(" ");
}
DBG_UART.println("");
}


【5】功能测试:
设备上电后,可以看到电脑串口打印输出的内容,首先连接OneNET服务器:


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


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


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


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

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

colin2135 发表于 2016-11-29 11:21

可以,非常帅!!!!!!!!!!!!!

巧克力娃娃 发表于 2016-11-29 15:13

帅爆了,给lz加精!

小曾1220 发表于 2017-3-6 10:34

{:hug:}

洲际导弹 发表于 2017-5-16 11:11

嗨喽,大神,我想问下:#include "edp.c"   怎么编译不过去,谢了{:smile:}

matrix3301 发表于 2017-7-9 18:55

#include "edp.c"   请问这个文件去哪里下载呢

m.y 发表于 2017-8-31 11:54

学习了,顶顶

嘚瑟的小孩 发表于 2017-12-9 15:49

遇到了一些问题,你能帮忙解答一下吗??

nclzz 发表于 2018-7-4 16:27

谢谢,正在查找中

acktomas 发表于 2018-12-14 14:49

不错,学习了

cyzchenyongzhi 发表于 2020-3-3 15:21

赞!

gaochy1126 发表于 2020-7-11 08:52

ESP8266模块确实是当前最为热门的WIFI模块,zigbee也研究起来

gaochy1126 发表于 2020-8-1 18:48

one net通信协议有没有呢?                        

jeoge 发表于 2021-3-1 18:34

了解了一下,这个平台只提供了ARM的SDK,当下ARM芯片的价格这么高,用这个做产品不现实.如果有51的开发包选择性就强了.成本也就下来了.

gaochy1126 发表于 2021-8-23 18:54

Arduino做这个http或者mqtt还是容易很多的。            

gaochy1126 发表于 2021-8-23 18:54

为什么不直接使用esp8266做编程设计呢?还需要esp8266做外设   

帅气的小柿子 发表于 2021-12-2 10:43

非常棒,受益匪浅呀

gaochy1126 发表于 2022-8-30 21:32

OneNET服务器的发送命令不是很好弄呢。               

gaochy1126 发表于 2022-8-30 21:32

OneNET的物联网平台的,数据解析有相关的教程吗?   

suncat0504 发表于 2022-10-24 18:01

挺好的,值得学习
页: [1] 2
查看完整版本: Arduino+ESP8266使用EDP协议控制LED灯