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 //开始传输
命令执行结果如下图所示:
【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
#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[100] = {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[10];
/* 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[0] == 0x20 && rcv_pkt.data[2] == 0x00 && rcv_pkt.data[3] == 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[0];
switch (pkt_type)
{
case cmdreq:
char edp_command[50];
char edp_cmd_id[40];
long id_len, cmd_len, rm_len;
char datastr[20];
char val[10];
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:[1/0]
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[i], hex);
dbg_uart.print( );
}
dbg_uart.println();
}
【5】功能测试:
设备上电后,可以看到电脑串口打印输出的内容,首先连接onenet服务器:
连接成功后,可以看到设备在线状态:
点击设备应用中的开关按钮,发送开关命令给设备:
设备接收命令后进行解析,并在串口打印输出:
当解析到数据流switch0的值为1时设备开灯,arduino 开发板的d13被点亮,相反为0时灯灭。
获得可靠的传感器数据:电子、光学和机械设计之间的相互作用
更新IoT设备OTA的方法
全球最快电池摩托车
Linux驱动高精度定时器hrtimer
德州仪器针对HDMI与DisplayPort推出高灵活、八通
远程控制通讯--基于Arduino + ESP8266控制LED灯
纳米材料及纳米技术在各领域的发展趋势介绍
Mark Levinson No.33XL後級
液晶面板为什么下滑_液晶面板行业前景如何
L-com新型GPS定时天线和UHF天线 支持先进网络应用的卫星定时信号精确接收
新加坡央行计划利用区块链来提高国际支付的效率
电动牙刷气如何进行密性防水测试
厉害了!通用电气将AR增强现实技术用于机械组装
锐龙7 2700对比 i5-9600KF测评
柔性多孔聚合物材料拉伸试验详解:利用电子万能试验机测量拉伸强度,标准流程解析
工业4.0制造的自动化和信息化正在逐步布局
比特币中国被收购 美元现货交易平台将会是以后重心
英特尔立足于物联网领域不断开创新技术的三大战略
海信舒适家空调亮相北京 增氧换气畅享鲜呼吸
企业仍信赖微软产品,Cortana未来端视企业市场外溢效应