极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 23573|回复: 9

ARDUINO MEGA2560 经过ESP8266 WIFI模块上传温湿度数据到中国移动OneNet服务器

[复制链接]
发表于 2016-8-3 20:44:27 | 显示全部楼层 |阅读模式
本帖最后由 迷你强 于 2016-8-3 21:54 编辑

简述
原来写了一个C++的wifi库但是发现用c++ arduino这小身板有点扛不住,代码比较大,使用String类型数据处理速度慢,而且很容易无缘无故跑飞。而且封装成库后使用还需要修改arduino的串口缓存大小才能使用。
今天抽空重新用c写了一下代码,运行速度明显加快,也不需要修改Arduino IDE了。本代码主要借鉴 中移物联-周家绪 的http头合成的库,和 DFRobot-Strictus 对AT指令数据处理的方法,在这里感谢两位发布的代码。
下面把测试成功的代码发布出来,供后来者使用。代码有不足之处欢迎指正。
最终效果
发布链接:http://open.iot.10086.cn/appview ... c1238237604f155e2db


硬件概述
1.主控:ARDUINO MEGA2560开发板
特点:多个串口,IO口丰富,内存比较大,使用方便


2.WIFI模块:使用ARDUINO MEGA2560的带ESP8266的扩展板
特点:带有贴片的ESP8266 WIFI模块,DHT11温湿度传感器,继电器等功能,和ARDUINO MEGA2560即插即用,扩展很多IO和电源接口方便后续扩展各种传感器。



3.温湿度传感器:DHT11单总线温湿度传感器(扩展板带的有这个传感器)
软件思路
1.使用DHT11温湿度传感器的库<dht11.h>,读取温湿度值。
2.使用定时器<TimerOne.h>库,监控AT指令发送和获取返回数据的时间。
3.使用OneNet提供的<HttpPacket.h>库,合成POST请求的HTTP头
4.使用<ArduinoJson.h>库,合成需要的JSON数据流
5.使用ESP8266连接路由器将数据发送到OneNet服务器
用到的库文件下载地址:
链接:http://pan.baidu.com/s/1miJEIFI 密码:y8ks
传感器和硬件的对应接口
ESP8266  --->  Serial3(TX3/RX3)    用户发送和读取WIFI指令
DHT11    --->  D8                    单总线读取温湿度数据值
DEBUG接口--->  Serial(D0/D1)       1.把发送给ESP8266的数据,也在DEBUG串口输出,观看指令运行到哪一步,2.ESP8266接收的数据,也通过DEBUG口转发出来,观看反馈数据是否正确。 3.错误跳转,观看错误发生的位置
串口反馈数据界面


源代码(使用ARDUINO IDE 1.06版本测试)
  1. #include <TimerOne.h>
  2. #include <HttpPacket.h>
  3. #include <ArduinoJson.h>
  4. #include <dht11.h>
  5. dht11 DHT11;
  6. #define DHT11PIN 8 //DHT11 连接ARDUINO 8


  7. HttpPacketHead packet;


  8. #define DebugSerial Serial
  9. #define ESP8266Serail Serial3

  10. #define Success 1U
  11. #define Failure 0U

  12. int L = 13; //LED指示灯引脚

  13. unsigned long  Time_Cont = 0;       //定时器计数器

  14. const unsigned int esp8266RxBufferLength = 600;
  15. char esp8266RxBuffer[esp8266RxBufferLength];
  16. unsigned int ii = 0;
  17. char OneNetServer[] = "api.heclouds.com";     //不需要修改

  18. const char ssid[] = "PushPull";     //修改为自己的路由器用户名
  19. const char password[] = "********"; //修改为自己的路由器密码



  20. char device_id[] = "600911";    //修改为自己的设备ID
  21. char API_KEY[] = "R9xO5NZm6oVI4YBHvCPKEqtwYtMA";    //修改为自己的API_KEY
  22. char sensor_id1[] = "TEMP";
  23. char sensor_id2[] = "HUMI";



  24. void setup() {
  25.     pinMode(L, OUTPUT);
  26.     digitalWrite(L, LOW);
  27.     DebugSerial.begin(9600);
  28.     ESP8266Serail.begin(115200);

  29.     Timer1.initialize(1000);
  30.     Timer1.attachInterrupt(Timer1_handler);

  31.     initEsp8266();


  32.     DebugSerial.println("setup end!");
  33. }

  34. void loop() {
  35.     //获取温湿度数据
  36.     int chk = DHT11.read(DHT11PIN);                             //读取温湿度值

  37.       //串口调试DHT11输出信息
  38.       DebugSerial.print("Read sensor: ");
  39.       switch (chk)
  40.       {
  41.       case DHTLIB_OK:
  42.         DebugSerial.println("OK");
  43.         break;
  44.       case DHTLIB_ERROR_CHECKSUM:
  45.         DebugSerial.println("Checksum error");
  46.         break;
  47.       case DHTLIB_ERROR_TIMEOUT:
  48.         DebugSerial.println("Time out error");
  49.         break;
  50.       default:
  51.         DebugSerial.println("Unknown error");
  52.         break;
  53.       }

  54.       //发送数据到Onenet
  55.       postDataToOneNet(API_KEY,device_id,sensor_id1,DHT11.temperature);     
  56.       postDataToOneNet(API_KEY,device_id,sensor_id2,DHT11.humidity);

  57.       delay(5000);
  58. }

  59. void postDataToOneNet(char* API_VALUE_temp,char* device_id_temp,char* sensor_id_temp,double thisData)
  60. {
  61.         //合成POST请求
  62.     StaticJsonBuffer<200> jsonBuffer;



  63.     JsonObject& value = jsonBuffer.createObject();
  64.     value["value"] = thisData;

  65.     JsonObject& id_datapoints = jsonBuffer.createObject();
  66.     id_datapoints["id"] = sensor_id_temp;
  67.     JsonArray& datapoints = id_datapoints.createNestedArray("datapoints");
  68.     datapoints.add(value);

  69.     JsonObject& myJson = jsonBuffer.createObject();
  70.     JsonArray& datastreams = myJson.createNestedArray("datastreams");
  71.     datastreams.add(id_datapoints);

  72.     char p[200];
  73.     int num = myJson.printTo(p, sizeof(p));


  74.     packet.setHostAddress(OneNetServer);
  75.     packet.setDevId(device_id_temp);   //device_id
  76.     packet.setAccessKey(API_VALUE_temp);  //API_KEY
  77.     // packet.setDataStreamId("<datastream_id>");    //datastream_id
  78.     // packet.setTriggerId("<trigger_id>");
  79.     // packet.setBinIdx("<bin_index>");

  80.     /*create the http message about add datapoint */
  81.     packet.createCmdPacket(POST, TYPE_DATAPOINT, p);
  82.     // if (strlen(packet.content))
  83.     //  Serial.print(packet.content);
  84.     // Serial.print(p);
  85.     int httpLength = strlen(packet.content) + num;

  86.    

  87.         //连接服务器
  88.     char cmd[400];
  89.     memset(cmd, 0, 400);    //清空cmd
  90.     strcpy(cmd, "AT+CIPSTART="TCP","");
  91.     strcat(cmd, OneNetServer);
  92.     strcat(cmd, "",80\r\n");
  93.     if (sendCommand(cmd, "CONNECT", 7, 10000, 5) == Success);
  94.     else ESP8266_ERROR(1);

  95.     //发送数据
  96.     memset(cmd, 0, 400);    //清空cmd
  97.     sprintf(cmd, "AT+CIPSEND=%d\r\n", httpLength);
  98.     if (sendCommand(cmd, ">", 1, 3000, 1) == Success);
  99.     else ESP8266_ERROR(2);

  100.     memset(cmd, 0, 400);    //清空cmd
  101.     strcpy(cmd, packet.content);
  102.     strcat(cmd, p);
  103.     if (sendCommand(cmd, ""succ"}", 7, 3000, 1) == Success);
  104.     else ESP8266_ERROR(3);

  105.     if (sendCommand("AT+CIPCLOSE\r\n", "CLOSED", 6, 3000, 1) == Success);
  106.     else ESP8266_ERROR(4);
  107. }

  108. void initEsp8266()
  109. {
  110.     if (sendCommand("AT\r\n", "OK", 2, 3000, 10) == Success);
  111.     else ESP8266_ERROR(5);

  112.     if (sendCommand("AT+RST\r\n", "ready", 5, 10000, 10) == Success);
  113.     else ESP8266_ERROR(6);

  114.     if (sendCommand("AT+CWMODE=1\r\n", "OK", 2, 3000, 10) == Success);
  115.     else ESP8266_ERROR(7);

  116.     char cmd[50];
  117.     strcpy(cmd, "AT+CWJAP="");
  118.     strcat(cmd, ssid);
  119.     strcat(cmd, "","");
  120.     strcat(cmd, password);
  121.     strcat(cmd, ""\r\n");

  122.     if (sendCommand(cmd, "OK", 2, 20000, 10) == Success);
  123.     else ESP8266_ERROR(8);

  124.     if (sendCommand("AT+CIPMUX=0\r\n", "OK", 2, 3000, 10) == Success);
  125.     else ESP8266_ERROR(9);

  126.     if (sendCommand("AT+CIFSR\r\n", "OK", 2, 20000, 10) == Success);
  127.     else ESP8266_ERROR(10);
  128. }

  129. void ESP8266_ERROR(int num)
  130. {
  131.     DebugSerial.print("ERROR");
  132.     DebugSerial.println(num);
  133.     while (1)
  134.     {
  135.         digitalWrite(L, HIGH);
  136.         delay(300);
  137.         digitalWrite(L, LOW);
  138.         delay(300);
  139.     }
  140. }



  141. unsigned int sendCommand(char *Command, char *Response, unsigned int Res_Length, unsigned long Timeout, unsigned char Retry)
  142. {
  143.     clrEsp8266RxBuffer();
  144.     for (unsigned char n = 0; n < Retry; n++)
  145.     {
  146.         DebugSerial.print("\r\nsend AT Command:\r\n----------\r\n");
  147.         DebugSerial.write(Command);

  148.         ESP8266Serail.write(Command);

  149.         Time_Cont = 0;
  150.         while (Time_Cont < Timeout)
  151.         {
  152.             esp8266ReadBuffer();
  153.             if ((mystrstr(esp8266RxBuffer, Response, ii, Res_Length)) != NULL)
  154.             {
  155.                 DebugSerial.print("\r\nreceive AT Command:\r\n==========\r\n");
  156.                 DebugSerial.print(esp8266RxBuffer); //输出接收到的信息
  157.                 clrEsp8266RxBuffer();
  158.                 return Success;
  159.             }
  160.         }
  161.         Time_Cont = 0;
  162.     }
  163.     DebugSerial.print("\r\nreceive AT Command:\r\n==========\r\n");
  164.     DebugSerial.print(esp8266RxBuffer);//输出接收到的信息
  165.     clrEsp8266RxBuffer();
  166.     return Failure;
  167. }

  168. unsigned char mystrstr(char *s, char *t, unsigned int Length_s, unsigned int Length_t)
  169. {   char x = 0; char *p; p = t;
  170.     int i = 0, j = 0;
  171.     for (; i < Length_s; s++, i++)
  172.     {
  173.         while (*t == *s)
  174.         {   s++; t++; i++; j++;
  175.             if (j >= Length_t) return 1;
  176.         }
  177.         s -= j;
  178.         t = p; j = 0;
  179.     }
  180.     return NULL;
  181. }


  182. void Timer1_handler(void)
  183. {
  184.     Time_Cont++;
  185. }



  186. void esp8266ReadBuffer() {
  187.     while (ESP8266Serail.available())
  188.     {
  189.         esp8266RxBuffer[ii++] = ESP8266Serail.read();
  190.         if (ii == esp8266RxBufferLength)clrEsp8266RxBuffer();
  191.     }
  192. }

  193. void clrEsp8266RxBuffer(void)
  194. {
  195.     memset(esp8266RxBuffer, 0, esp8266RxBufferLength);      //清空
  196.     ii = 0;
  197. }
复制代码

本帖子中包含更多资源

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

x
回复

使用道具 举报

发表于 2016-8-3 20:56:10 | 显示全部楼层
做得不错。
回复 支持 反对

使用道具 举报

发表于 2016-8-3 21:48:37 | 显示全部楼层
先收藏,慢慢看
回复 支持 反对

使用道具 举报

发表于 2016-8-4 13:38:23 | 显示全部楼层
LZ不知道 一颗8266带个温感就能完成任务了吗?
2560都用不着。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-8-4 19:08:15 | 显示全部楼层
wxws 发表于 2016-8-4 13:38
LZ不知道 一颗8266带个温感就能完成任务了吗?
2560都用不着。

一路是可以直接用8266,那如果50路温湿度呢,或者有很多其他的传感器呢,8266才有几个IO啊。2560有他的好处,引脚多。
回复 支持 反对

使用道具 举报

发表于 2016-8-5 00:54:07 | 显示全部楼层
用来开发还可以。做产品还是要自己画图的。。。
回复 支持 反对

使用道具 举报

发表于 2016-8-5 00:57:56 | 显示全部楼层
wxws 发表于 2016-8-4 13:38
LZ不知道 一颗8266带个温感就能完成任务了吗?
2560都用不着。

楼主这个实际上是提供了扩展性
另外,2560能处理的东西还是不少的。可以结合很多

当然 你提的也没错,做产品的时候要考虑如何用最便宜最简单的硬件架构
毕竟硬件多了故障率和成本都会随之升高。
目的不同,采用的硬件方案不同,在研发阶段 可以用这种盾 实际产出不可能如此 成本账就算不过来。。。
而且实际产品用UNO 或者MEGA的不多 一般都是自己改的AVR。甚至可能会用51来做,成本或许还能再降
回复 支持 反对

使用道具 举报

发表于 2017-3-15 18:52:45 | 显示全部楼层
请问onenet上需要相应做啥工作才能接收这个程序上传的数据啊?本来菜鸟一枚,求教。
回复 支持 反对

使用道具 举报

发表于 2017-4-9 22:04:07 | 显示全部楼层
楼主用得是EDP模式?
回复 支持 反对

使用道具 举报

发表于 2017-4-30 13:57:24 | 显示全部楼层
弱弱的问一下,DEBUG接口是哪个接口?
回复 支持 反对

使用道具 举报

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

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

Archiver|联系我们|极客工坊

GMT+8, 2024-3-29 03:46 , Processed in 0.050862 second(s), 26 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2021, Tencent Cloud.

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