数码之家

 找回密码
 立即注册

QQ登录

只需一步,快速开始

微信登录

微信扫一扫,快速登录

搜索
查看: 395|回复: 9

[外设] ESP8266访问网页和NTP不定时会重启

[复制链接]
发表于 2020-2-10 12:24:59 | 显示全部楼层 |阅读模式
30M币
程序都是数码之家大神写的,我只是合并了一下。
程序设定的是10秒读取一次NTP时间,30分钟访问一次天气网页
但是,30分钟左右必定重启一次
麻烦大神分析一下
是不是一直访问网页,导致内存满了?负荷过重?该如何处理
2345截图20200209212739.png
代码如下
  1. /*
  2. 1,本人能力有限,程序存在BUG,目前问题是30分钟不到不定时重启。
  3. 2,程序为10秒获取一次时间,30分钟获取一次天气数据。
  4. 3,请登陆京东云【http://wx.jdcloud.com/market/datas/26/10610】获取APPKEY。
  5.   注意:未登陆直接“点击获取”APPKEY的“4ae4a2fcf405ce9beca0109018101d10”为无效APPKEY。
  6. 4,获取步骤:打开网址---点击立即测试---登陆(没注册的需要注册)---重新打开网址---点击立即测试即会出现APPKEY。
  7. */
  8. #include <ESP8266WiFi.h>
  9. #include <ESP8266HTTPClient.h>
  10. #include <WiFiUdp.h>
  11. #define PIN_LED 12
  12. #define KEY_FLASH 0

  13. char ssid[] = "TANG";  
  14. char pass[] = "12345678";      


  15. //NTP
  16. #define time_zone 8   //时区(要格林尼治时间加减的小时,北京为东八区,要将格林威治时间+8小时)
  17. unsigned int localPort = 2390;      // local port to listen for UDP packets
  18. IPAddress timeServerIP; // time.nist.gov NTP server address
  19. const char* ntpServerName = "ntp1.aliyun.com";
  20. const int NTP_PACKET_SIZE = 48; // NTP time stamp is in the first 48 bytes of the message
  21. byte packetBuffer[ NTP_PACKET_SIZE]; //buffer to hold incoming and outgoing packets
  22. WiFiUDP udp;

  23. String print_send2;
  24. int jisu;

  25. void setup()
  26. {
  27.   //初始化
  28.   Serial.begin(115200);//串口波特率115200
  29.   Serial.println();
  30.   Serial.println();
  31.   pinMode(PIN_LED, OUTPUT);
  32.   pinMode(KEY_FLASH, INPUT_PULLUP);
  33.   digitalWrite(PIN_LED, HIGH);
  34.   delay(1500);
  35.   Serial.print("Connecting to ");
  36.   Serial.println(ssid);
  37.   WiFi.begin(ssid, pass);
  38.   while (WiFi.status() != WL_CONNECTED) {
  39.     delay(500);
  40.     Serial.print(".");

  41.   }
  42.   Serial.println("");
  43.   Serial.println("WiFi connected");
  44.   Serial.println("IP address: ");
  45.   Serial.println(WiFi.localIP());
  46.   Serial.println("Starting UDP");
  47.   udp.begin(localPort);
  48.   Serial.print("Local port: ");
  49.   Serial.println(udp.localPort());
  50. }
  51. void loop()
  52. {
  53.   jisu++;
  54.   if (jisu > 180)jisu = 0;

  55.   if (WiFi.status() != WL_CONNECTED)
  56.   {
  57.     Serial.println("wifi连接失败");
  58.   }
  59.   else
  60.   {
  61.     digitalWrite(PIN_LED, LOW);//WiFi led
  62.     if (jisu == 3)
  63.     {
  64.       send2();
  65.       delay(10000);
  66.     }
  67.     else
  68.     {
  69.       NTP();             // 更新时间
  70.       delay(10000);
  71.     }
  72.   }
  73. }

  74. void send2()
  75. {
  76.   HTTPClient http;
  77.   Serial.print("[HTTP] begin...\n");
  78.   http.begin("http://way.jd.com/he/freeweather?city=CN101280304&appkey=**************");//API

  79.   Serial.print("[HTTP] GET...\n");
  80.   int httpCode = http.GET();
  81.   if (httpCode > 0)  {
  82.     Serial.printf("[HTTP] GET... code: %d\n", httpCode);
  83.     if (httpCode == HTTP_CODE_OK)
  84.     {
  85.       String payload1, payload2, payload3;
  86.       int chars1, chars2;
  87.       //解析
  88.       String payload = http.getString();
  89.       chars1 = payload.indexOf("code");
  90.       chars2 = payload.indexOf(""", chars1 + 7);
  91.       payload1 = payload.substring(chars1 + 7, chars2);
  92.       if (payload1 == "10000") //代码为1000是正确返回数据
  93.       {
  94.         // 查找地区
  95.         chars1 = payload.indexOf("basic");
  96.         chars2 = payload.indexOf(""", chars1 + 19);
  97.         payload2 = payload.substring(chars1 + 16, chars2);
  98.         print_send2 = payload2 + " 现在:";
  99.         //----------------------------------------------天气实况
  100.         chars1 = payload.indexOf("now");
  101.         chars2 = payload.indexOf("}", chars1 + 150);
  102.         payload1 = payload.substring(chars1, chars2);
  103.         //天气实况文字
  104.         chars1 = payload1.indexOf("txt");
  105.         chars2 = payload1.indexOf(""", chars1 + 6);
  106.         payload2 = payload1.substring(chars1 + 6, chars2);
  107.         print_send2 = print_send2 + payload2 + ",湿度:";
  108.         //体感温度
  109.         chars1 = payload1.indexOf("hum");
  110.         chars2 = payload1.indexOf(""", chars1 + 6);
  111.         payload2 = payload1.substring(chars1 + 6, chars2);
  112.         print_send2 = print_send2 + payload2 + "%,温度:";
  113.         //温度
  114.         chars1 = payload1.indexOf("tmp");
  115.         chars2 = payload1.indexOf(""", chars1 + 6);
  116.         payload2 = payload1.substring(chars1 + 6, chars2);
  117.         print_send2 = print_send2 + payload2 + "℃,";
  118.         //风向
  119.         chars1 = payload1.indexOf("dir");
  120.         chars2 = payload1.indexOf(""", chars1 + 6);
  121.         payload2 = payload1.substring(chars1 + 6, chars2);
  122.         print_send2 = print_send2 + payload2;
  123.         //风力
  124.         chars1 = payload1.indexOf("sc");
  125.         chars2 = payload1.indexOf(""", chars1 + 5);
  126.         payload2 = payload1.substring(chars1 + 5, chars2);
  127.         print_send2 = print_send2 + "/" + payload2 + "级,空气:";
  128.         //空气质量
  129.         chars1 = payload.indexOf("qlty");
  130.         chars2 = payload.indexOf(""", chars1 + 7);
  131.         payload2 = payload.substring(chars1 + 7, chars2);
  132.         print_send2 = print_send2 + payload2 + "。今天:";

  133.         //----------------------------------------------天气预报,今天
  134.         chars1 = payload.indexOf("daily_forecast");
  135.         chars2 = payload.indexOf("]");
  136.         payload1 = payload.substring(chars1, chars2);
  137.         //今天白天天气状况文字
  138.         chars1 = payload1.indexOf("txt_d");
  139.         chars2 = payload1.indexOf(""", chars1 + 8);
  140.         payload2 = payload1.substring(chars1 + 8, chars2);
  141.         //今天夜间天气状况文字
  142.         chars1 = payload1.indexOf("txt_n");
  143.         chars2 = payload1.indexOf(""", chars1 + 8);
  144.         payload3 = payload1.substring(chars1 + 8, chars2);
  145.         //今天天气状况文字一样就只显示一个
  146.         if (payload2 == payload3)
  147.           print_send2 = print_send2 + payload3 + " ";
  148.         else//不一样就转
  149.           print_send2 = print_send2 + payload2 + "转" + payload3 + " ";
  150.         //今天最高温度
  151.         chars1 = payload1.indexOf("max");
  152.         chars2 = payload1.indexOf(""", chars1 + 6);
  153.         payload2 = payload1.substring(chars1 + 6, chars2);
  154.         print_send2 = print_send2 + payload2 + "/";
  155.         //今天最低温度
  156.         chars1 = payload1.indexOf("min");
  157.         chars2 = payload1.indexOf(""", chars1 + 6);
  158.         payload2 = payload1.substring(chars1 + 6, chars2);
  159.         print_send2 = print_send2 + payload2 + "℃,";
  160.         //今天风向
  161.         chars1 = payload1.indexOf("dir");
  162.         chars2 = payload1.indexOf(""", chars1 + 6);
  163.         payload2 = payload1.substring(chars1 + 6, chars2);
  164.         print_send2 = print_send2 + payload2;
  165.         //今天风力
  166.         chars1 = payload1.indexOf("sc");
  167.         chars2 = payload1.indexOf(""", chars1 + 5);
  168.         payload2 = payload1.substring(chars1 + 5, chars2);
  169.         print_send2 = print_send2 + "/" + payload2 + "级。明天:";

  170.         //----------------------------------------------天气预报,明天
  171.         chars1 = payload.indexOf("daily_forecast");
  172.         chars1 = payload.indexOf("astro", chars1 + 150);
  173.         chars2 = payload.indexOf("astro", chars1 + 150);
  174.         payload1 = payload.substring(chars1, chars2);
  175.         //明天白天天气状况文字
  176.         chars1 = payload1.indexOf("txt_d");
  177.         chars2 = payload1.indexOf(""", chars1 + 8);
  178.         payload2 = payload1.substring(chars1 + 8, chars2);
  179.         //明天夜间天气状况文字
  180.         chars1 = payload1.indexOf("txt_n");
  181.         chars2 = payload1.indexOf(""", chars1 + 8);
  182.         payload3 = payload1.substring(chars1 + 8, chars2);
  183.         //明天天气状况文字一样就只显示一个
  184.         if (payload2 == payload3)
  185.           print_send2 = print_send2 + payload3 + " ";
  186.         else//不一样就转
  187.           print_send2 = print_send2 + payload2 + "转" + payload3 + " ";
  188.         //明天最高温度
  189.         chars1 = payload1.indexOf("max");
  190.         chars2 = payload1.indexOf(""", chars1 + 6);
  191.         payload2 = payload1.substring(chars1 + 6, chars2);
  192.         print_send2 = print_send2 + payload2 + "/";
  193.         //明天最低温度
  194.         chars1 = payload1.indexOf("min");
  195.         chars2 = payload1.indexOf(""", chars1 + 6);
  196.         payload2 = payload1.substring(chars1 + 6, chars2);
  197.         print_send2 = print_send2 + payload2 + "℃,";
  198.         //明天风向
  199.         chars1 = payload1.indexOf("dir");
  200.         chars2 = payload1.indexOf(""", chars1 + 6);
  201.         payload2 = payload1.substring(chars1 + 6, chars2);
  202.         print_send2 = print_send2 + payload2;
  203.         //明天风力
  204.         chars1 = payload1.indexOf("sc");
  205.         chars2 = payload1.indexOf(""", chars1 + 5);
  206.         payload2 = payload1.substring(chars1 + 5, chars2);
  207.         print_send2 = "[Timetianqi1] " + print_send2 + "/" + payload2 + "级。           **";

  208.         Serial.println(print_send2);//发送数据
  209.       }
  210.       else//接收数据出错
  211.         print_send2 = "**数据返回出错,请检查APPKEY接口***";
  212.     }
  213.     else//访问状态出错
  214.       print_send2 = "********数据接口访问出错********";
  215.   }
  216.   else//访问失败
  217.     print_send2 = "********数据接口访问失败********";
  218.   http.end();
  219. }



  220. void NTP() {
  221.   WiFi.hostByName(ntpServerName, timeServerIP);
  222.   sendNTPpacket(timeServerIP);
  223.   delay(5000);
  224.   int cb = udp.parsePacket();
  225.   if (!cb) {
  226.     Serial.println("无法连接阿里云时间服务器");
  227.     return;
  228.   }
  229.   else {
  230.     udp.read(packetBuffer, NTP_PACKET_SIZE);
  231.     unsigned long highWord = word(packetBuffer[40], packetBuffer[41]);
  232.     unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]);
  233.     unsigned long secsSince1900 = highWord << 16 | lowWord;
  234.     const unsigned long seventyYears = 2208988800UL;
  235.     unsigned long epoch = secsSince1900 - seventyYears;
  236.     unsigned long Time = time_zone * 3600 + epoch;
  237.     unsigned long Y2KTime = (Time - 946684800) / 86400;
  238.     unsigned long YTime;
  239.     unsigned int Year;
  240.     unsigned int Month = 0;
  241.     unsigned long Day;

  242.     //日期
  243.     if (Y2KTime % 146097 <= 36525)
  244.     {
  245.       Year = 2000 + Y2KTime / 146097 * 400 + Y2KTime % 146097 / 1461 * 4 + (Y2KTime % 146097 % 1461 - 1) / 365;
  246.       YTime = (Y2KTime % 146097 % 1461 - 1) % 365 + 1;
  247.     }
  248.     else
  249.     {
  250.       Year = 2000 + Y2KTime / 146097 * 400 + (Y2KTime % 146097 - 1) / 36524 * 100 + ((Y2KTime % 146097 - 1) % 36524 + 1) / 1461 * 4 + (((Y2KTime % 146097 - 1) % 36524 + 1) % 1461 - 1) / 365;
  251.       YTime = (((Y2KTime % 146097 - 1) % 36524 + 1) % 1461 - 1) % 365 + 1;
  252.     }
  253.     Day = YTime;
  254.     unsigned char f = 1; //循环标志
  255.     while (f)
  256.     {
  257.       switch (Month)
  258.       {
  259.         case 0:
  260.           if (Day < 31)
  261.             f = 0;
  262.           else
  263.             Day -= 31;
  264.           break;
  265.         case 1:
  266.           if (Day < 29)
  267.             f = 0;
  268.           else
  269.           {
  270.             if (LY(Year))
  271.             {
  272.               Day -= 29;
  273.             }
  274.             else
  275.             {
  276.               Day -= 28;
  277.             }
  278.           }
  279.           break;
  280.         case 2:
  281.           if (Day < 31)
  282.             f = 0;
  283.           else
  284.             Day -= 31;
  285.           break;
  286.         case 3:
  287.           if (Day < 30)
  288.             f = 0;
  289.           else
  290.             Day -= 30;
  291.           break;
  292.         case 4:
  293.           if (Day < 31)
  294.             f = 0;
  295.           else
  296.             Day -= 31;
  297.           break;
  298.         case 5:
  299.           if (Day < 30)
  300.             f = 0;
  301.           else
  302.             Day -= 30;
  303.           break;
  304.         case 6:
  305.           if (Day < 31)
  306.             f = 0;
  307.           else
  308.             Day -= 31;
  309.           break;
  310.         case 7:
  311.           if (Day < 31)
  312.             f = 0;
  313.           else
  314.             Day -= 31;
  315.           break;
  316.         case 8:
  317.           if (Day < 30)
  318.             f = 0;
  319.           else
  320.             Day -= 30;
  321.           break;
  322.         case 9:
  323.           if (Day < 31)
  324.             f = 0;
  325.           else
  326.             Day -= 31;
  327.           break;
  328.         case 10:
  329.           if (Day < 30)
  330.             f = 0;
  331.           else
  332.             Day -= 30;
  333.           break;
  334.         case 11:
  335.           if (Day < 31)
  336.             f = 0;
  337.           else
  338.             Day -= 31;
  339.           break;
  340.       }
  341.       Month += 1;
  342.     }
  343.     Day += 1;
  344.     Serial.print("[Timetianqi2] ");
  345.     Serial.print(Year);
  346.     Serial.print("-");
  347.     if (Month < 10) {
  348.       Serial.print('0');
  349.     }
  350.     Serial.print(Month);
  351.     Serial.print("-");
  352.     if (Day < 10) {
  353.       Serial.print('0');
  354.     }
  355.     Serial.print(Day);
  356.     Serial.print(" ");

  357.     //时间

  358.     if ((Time  % 86400L) / 3600 < 10)
  359.     {
  360.     }
  361.     Serial.print("");
  362.     if ( (Time  % 86400L) / 3600 < 10 ) {
  363.       Serial.print('0');
  364.     }
  365.     Serial.print((Time  % 86400L) / 3600);
  366.     Serial.print(':');
  367.     if ( ((Time % 3600) / 60) < 10 ) {
  368.       Serial.print('0');
  369.     }
  370.     Serial.print((Time  % 3600) / 60);
  371.     Serial.print(':');
  372.     if ( (Time % 60) < 10 ) {
  373.       Serial.print('0');
  374.     }
  375.     Serial.print(Time % 60);
  376.     Serial.print("**");
  377.     Serial.println();
  378.   }
  379. }


  380. unsigned long sendNTPpacket(IPAddress& address)
  381. {
  382.   Serial.println("sending NTP packet...");
  383.   memset(packetBuffer, 0, NTP_PACKET_SIZE);
  384.   packetBuffer[0] = 0b11100011;
  385.   packetBuffer[1] = 0;
  386.   packetBuffer[2] = 6;
  387.   packetBuffer[3] = 0xEC;
  388.   packetBuffer[12]  = 49;
  389.   packetBuffer[13]  = 0x4E;
  390.   packetBuffer[14]  = 49;
  391.   packetBuffer[15]  = 52;

  392.   udp.beginPacket(address, 123);
  393.   udp.write(packetBuffer, NTP_PACKET_SIZE);
  394.   udp.endPacket();
  395. }
  396. unsigned char LY(unsigned int y)//判断是否为闰年
  397. {
  398.   if (y % 400 == 0)
  399.     return 1;
  400.   if (y % 100 == 0)
  401.     return 0;
  402.   if (y % 4 == 0)
  403.     return 1;
  404. }
复制代码


发表于 2020-2-10 14:34:13 | 显示全部楼层
有时候是模块的问题,我有一个模块,经常掉线,换了一个模块后好了
回复

使用道具 举报

发表于 2020-2-10 15:48:24 | 显示全部楼层
试试在void loop() 里面加一句  ESP.wdtFeed(); 喂下看门狗,极大可能是看门狗引发的复位,我以前也遇到过几个小时后莫名其妙重启的,加了就好了,还有delay延时一次不要太长,也容易引发看门狗复位
回复

使用道具 举报

 楼主| 发表于 2020-2-10 21:52:42 | 显示全部楼层
xlmttkl 发表于 2020-2-10 15:48
试试在void loop() 里面加一句  ESP.wdtFeed(); 喂下看门狗,极大可能是看门狗引发的复位,我以前也遇到过几 ...

通过打印返回空间堆大小,每次运行必定减少424,到最后不够减时,就重启了。
2345截图20200210214914.png
回复

使用道具 举报

发表于 2020-2-10 22:08:48 来自手机浏览器 | 显示全部楼层
28674500 发表于 2020-2-10 21:52
通过打印返回空间堆大小,每次运行必定减少424,到最后不够减时,就重启了。

...

厉害
回复

使用道具 举报

发表于 2020-2-11 02:34:18 来自手机浏览器 | 显示全部楼层
为何10秒就同步ntp?一个星期或启动时同步一下就好了。
回复

使用道具 举报

发表于 2020-2-11 12:45:06 | 显示全部楼层
NTP用官方的就好了,不要自己写,还有时间,日期,星期也不用自己算,直接调用time.h,然后用hour()之类的取就行。
  1. /*-------- NTP code ----------*/

  2. const int NTP_PACKET_SIZE = 48; // NTP time is in the first 48 bytes of message
  3. byte packetBuffer[NTP_PACKET_SIZE]; //buffer to hold incoming & outgoing packets

  4. time_t getNtpTime()
  5. {
  6.   IPAddress ntpServerIP; // NTP server's ip address

  7.   while (Udp.parsePacket() > 0) ; // discard any previously received packets
  8.   // Serial.println("Transmit NTP Request");
  9.   // get a random server from the pool
  10.   WiFi.hostByName(ntpServerName, ntpServerIP);
  11.   // Serial.print(ntpServerName);
  12.   // Serial.print(": ");
  13.   // Serial.println(ntpServerIP);
  14.   sendNTPpacket(ntpServerIP);
  15.   uint32_t beginWait = millis();
  16.   while (millis() - beginWait < 1500) {
  17.     int size = Udp.parsePacket();
  18.     if (size >= NTP_PACKET_SIZE) {
  19.       //   Serial.println("Receive NTP Response");
  20.       Udp.read(packetBuffer, NTP_PACKET_SIZE);  // read packet into the buffer
  21.       unsigned long secsSince1900;
  22.       // convert four bytes starting at location 40 to a long integer
  23.       secsSince1900 =  (unsigned long)packetBuffer[40] << 24;
  24.       secsSince1900 |= (unsigned long)packetBuffer[41] << 16;
  25.       secsSince1900 |= (unsigned long)packetBuffer[42] << 8;
  26.       secsSince1900 |= (unsigned long)packetBuffer[43];
  27.       return secsSince1900 - 2208988800UL + timeZone * SECS_PER_HOUR;
  28.     }
  29.   }
  30.   //Serial.println("No NTP Response :-(");
  31.   return 0; // return 0 if unable to get the time
  32. }

  33. // send an NTP request to the time server at the given address
  34. void sendNTPpacket(IPAddress & address)
  35. {
  36.   // set all bytes in the buffer to 0
  37.   memset(packetBuffer, 0, NTP_PACKET_SIZE);
  38.   // Initialize values needed to form NTP request
  39.   // (see URL above for details on the packets)
  40.   packetBuffer[0] = 0b11100011;   // LI, Version, Mode
  41.   packetBuffer[1] = 0;     // Stratum, or type of clock
  42.   packetBuffer[2] = 6;     // Polling Interval
  43.   packetBuffer[3] = 0xEC;  // Peer Clock Precision
  44.   // 8 bytes of zero for Root Delay & Root Dispersion
  45.   packetBuffer[12] = 49;
  46.   packetBuffer[13] = 0x4E;
  47.   packetBuffer[14] = 49;
  48.   packetBuffer[15] = 52;
  49.   // all NTP fields have been given values, now
  50.   // you can send a packet requesting a timestamp:
  51.   Udp.beginPacket(address, 123); //NTP requests are to port 123
  52.   Udp.write(packetBuffer, NTP_PACKET_SIZE);
  53.   Udp.endPacket();
  54. }
复制代码

setup里加入
  1.     setSyncProvider(getNtpTime);//从NTP同步
  2.     setSyncInterval(600);//同步间隔秒数
  3.     while (!getNtpTime) {
  4.       delay(500);
  5.       server.handleClient();
  6.     }
复制代码
回复

使用道具 举报

发表于 2020-2-11 14:36:18 | 显示全部楼层
还没仔细看代码,总之每次跑完把该释放的都释放掉。
回复

使用道具 举报

发表于 2020-2-11 15:03:00 | 显示全部楼层
代码过于冗余,有自己的云的话可以写个web服务作为中间层来处理数据,8266只负责定时查询和展示就行,另外ntp几天或者一周同步一次就行
回复

使用道具 举报

发表于 2020-2-11 23:29:52 | 显示全部楼层
8266真正想稳定使用要用sdk开发,比较麻烦。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册 微信登录

本版积分规则

Archiver|手机版|小黑屋|关于我们|联系我们|网站条款|数码之家 ( 闽ICP备05031405号 )

GMT+8, 2020-4-7 14:27 , Processed in 0.124800 second(s), 15 queries , Redis On.

Powered by Discuz!

© 2001-2019 Comsenz Inc.

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