找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 4558|回复: 8
打印 上一主题 下一主题
收起左侧

基于ESP8266网络天气时钟的OLED显示

  [复制链接]
跳转到指定楼层
楼主
注意修改 WiFi 名称和密码
需要申请【心知天气】API私钥

心知天气:wwwseniversecom
  1. /*
  2. 参考:
  3. https://blog.csdn.net/weixin_44668788/article/details/120643078
  4. OLED connect with ESP8266 NodeMCU
  5. SCL -- D1
  6. SDA -- D2
  7. */
  8. //引入必要的头文件
  9. #include <ArduinoJson.h>
  10. #include <ESP8266WiFi.h>
  11. #include <SPI.h>
  12. #include <U8g2lib.h>
  13. #include <WiFiUdp.h>
  14. #include <TimeLib.h>
  15. #include <DNSServer.h>
  16. #include <ESP8266WebServer.h>
  17. WiFiUDP Udp;
  18. unsigned int localPort = 8888; // 用于侦听UDP数据包的本地端口
  19. ​
  20. //网络校时的相关配置
  21. static const char ntpServerName[] = "ntp1.aliyun.com"; //NTP服务器,使用阿里云
  22. int timeZone = 8; //时区设置,采用东8区
  23. ​
  24. //保存断网前的最新数据
  25. int results_0_now_temperature_int_old;
  26. String results_0_now_text_str_old;
  27. int results_0_daily_1_high_int_old;
  28. int results_0_daily_1_low_int_old;
  29. String results_0_daily_1_text_day_str_old;
  30. ​
  31. //函数声明
  32. time_t getNtpTime();
  33. void sendNTPpacket(IPAddress &address);
  34. void oledClockDisplay();
  35. void sendCommand(int command, int value);
  36. void initdisplay();
  37. void connectWiFi();
  38. void parseInfo_now(WiFiClient client,int i);
  39. void parseInfo_fut(WiFiClient client,int i);
  40. //
  41. boolean isNTPConnected = false;
  42. ​
  43. const unsigned char xing[] U8X8_PROGMEM = {
  44.     0x00, 0x00, 0xF8, 0x0F, 0x08, 0x08, 0xF8, 0x0F, 0x08, 0x08, 0xF8, 0x0F, 0x80, 0x00, 0x88, 0x00,
  45.     0xF8, 0x1F, 0x84, 0x00, 0x82, 0x00, 0xF8, 0x0F, 0x80, 0x00, 0x80, 0x00, 0xFE, 0x3F, 0x00, 0x00}; /*星*/
  46. const unsigned char liu[] U8X8_PROGMEM = {
  47.     0x40, 0x00, 0x80, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00,
  48.     0x20, 0x02, 0x20, 0x04, 0x10, 0x08, 0x10, 0x10, 0x08, 0x10, 0x04, 0x20, 0x02, 0x20, 0x00, 0x00}; /*六*/
  49. ​
  50. typedef struct
  51. {                  //存储配置结构体
  52.     int tz;        //时间戳
  53. } config_type;
  54. config_type config;
  55. ​
  56. WiFiClient clientNULL;
  57. DNSServer dnsServer;
  58. ESP8266WebServer server(80);
  59. ​
  60. ​
  61. //----------WIFI连接配置----------
  62. const char* ssid     = "xxxxxxx";       // 连接WiFi名,需要修改
  63. const char* password = "xxxxxxxx";          // 连接WiFi密码,需要修改
  64.                                             // 请将您需要连接的WiFi密码填入引号中
  65. //----------天气API配置----------
  66. const char* host = "api.seniversecom";   // 将要连接的服务器地址  
  67. const int httpPort = 80;              // 将要连接的服务器端口      
  68. ​
  69. // 心知天气HTTP请求所需信息
  70. String reqUserKey = "xxxxxx";   // 私钥,需要修改
  71. String reqLocation = "Shanghai";            // 城市
  72. String reqUnit = "c";                      // 摄氏/华氏
  73. ​
  74. //----------设置屏幕----------
  75. U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/U8X8_PIN_NONE);
  76. int sta = 0;
  77. //----------初始化OLED----------
  78. void initdisplay()
  79. {
  80.     u8g2.begin();
  81.     u8g2.enableUTF8Print();
  82. }
  83. //----------用于获取实时天气的函数(0)----------
  84. void TandW(){
  85.   String reqRes = "/v3/weather/now.json?key=" + reqUserKey +
  86.                   + "&location=" + reqLocation +
  87.                   "&language=en&unit=" +reqUnit;
  88.   // 向心知天气服务器服务器请求信息并对信息进行解析
  89.   httpRequest(reqRes,0);
  90.   //延迟,需要低于20次/分钟
  91.   delay(5000);
  92. }
  93. void display_1(int results_0_now_temperature_int,String results_0_now_text_str);//声明函数,用于显示温度、天气
  94. ​
  95. ​
  96. //----------获取3天预报(1)----------
  97. void threeday(){
  98.   // 建立心知天气API当前天气请求资源地址
  99.   String reqRes = "/v3/weather/daily.json?key=" + reqUserKey +
  100.                   + "&location=" + reqLocation + "&language=en&unit=" +
  101.                   reqUnit + "&start=0&days=3";
  102. ​
  103.   // 向心知天气服务器服务器请求信息并对信息进行解析
  104.   httpRequest(reqRes,1);
  105.   delay(5000);
  106. }
  107. ​
  108. void clock_display(time_t prevDisplay){
  109.     server.handleClient();
  110.     dnsServer.processNextRequest();
  111.     if (timeStatus() != timeNotSet)
  112.     {
  113.         if (now() != prevDisplay)
  114.         { //时间改变时更新显示
  115.             prevDisplay = now();
  116.             oledClockDisplay();
  117.         }
  118.     }
  119. }
  120. ​
  121. ​
  122. void setup(){
  123.   Serial.begin(9600);         
  124.   Serial.println("");
  125.   initdisplay();
  126.   // 连接WiFi
  127. ​
  128.   
  129.   
  130.   u8g2.clearBuffer();
  131.   u8g2.setFont(u8g2_font_unifont_t_chinese2);
  132.   u8g2.setCursor(0, 14);
  133.   u8g2.print("Waiting for WiFi");
  134.   u8g2.setCursor(0, 30);
  135.   u8g2.print("connection...");
  136.   u8g2.sendBuffer();
  137.   connectWiFi();
  138.   Udp.begin(localPort);
  139.   setSyncProvider(getNtpTime);
  140.   setSyncInterval(300); //每300秒同步一次时间
  141. ​
  142.   
  143. }
  144. ​
  145. time_t prevDisplay = 0; //当时钟已经显示

  146. void loop(){
  147.     if (sta>=0 && sta<=250){
  148.       clock_display(prevDisplay);
  149.       
  150.     }else if(sta == 251){
  151.       TandW();
  152.       
  153.     }else{
  154.       threeday();
  155.       
  156.     }
  157. ​
  158.     ++sta;
  159. ​
  160.     if(sta==253){
  161.       sta = 0;
  162.     }
  163. }

  164. // 向心知天气服务器服务器请求信息并对信息进行解析
  165. void httpRequest(String reqRes,int stat){
  166.   WiFiClient client;
  167. ​
  168.   // 建立http请求信息
  169.   String httpRequest = String("GET ") + reqRes + " HTTP/1.1\r\n" +
  170.                               "Host: " + host + "\r\n" +
  171.                               "Connection: close\r\n\r\n";
  172.   Serial.println("");
  173.   Serial.print("Connecting to "); Serial.print(host);
  174. ​
  175.   // 尝试连接服务器
  176.   if (client.connect(host, 80)){
  177.     Serial.println(" Success!");

  178.     // 向服务器发送http请求信息
  179.     client.print(httpRequest);
  180.     Serial.println("Sending request: ");
  181.     Serial.println(httpRequest);  

  182.     // 获取并显示服务器响应状态行
  183.     String status_response = client.readStringUntil('\n');
  184.     Serial.print("status_response: ");
  185.     Serial.println(status_response);

  186.     // 使用find跳过HTTP响应头
  187.     if (client.find("\r\n\r\n")) {
  188.       Serial.println("Found Header End. Start Parsing.");
  189.     }
  190.     if (stat == 0){
  191.       
  192.       // 利用ArduinoJson库解析心知天气响应信息(实时数据)
  193.       parseInfo_now(client,1);
  194.     }else if(stat == 1){
  195.       parseInfo_fut(client,1);
  196.     }
  197.   }
  198.   else {
  199.     Serial.println(" connection failed!");
  200.     if (stat == 0){
  201.       
  202.       // 利用ArduinoJson库解析心知天气响应信息(实时数据)
  203.       parseInfo_now(clientNULL,0);
  204.     }else if(stat == 1){
  205.       parseInfo_fut(clientNULL,0);
  206.     }
  207.   }
  208.    
  209.   //断开客户端与服务器连接工作
  210.   client.stop();
  211. }
  212. ​
  213. // 连接WiFi
  214. void connectWiFi(){
  215.   WiFi.begin(ssid, password);                  // 启动网络连接
  216.   Serial.print("Connecting to ");              // 串口监视器输出网络连接信息
  217.   Serial.print(ssid); Serial.println(" ...");  // 告知用户NodeMCU正在尝试WiFi连接
  218.   
  219.   int i = 0;                                   // 这一段程序语句用于检查WiFi是否连接成功
  220.   while (WiFi.status() != WL_CONNECTED) {      // WiFi.status()函数的返回值是由NodeMCU的WiFi连接状态所决定的。
  221.     delay(1000);                               // 如果WiFi连接成功则返回值为WL_CONNECTED                       
  222.     Serial.print(i++); Serial.print(' ');      // 此处通过While循环让NodeMCU每隔一秒钟检查一次WiFi.status()函数返回值
  223.   }                                            // 同时NodeMCU将通过串口监视器输出连接时长读秒。
  224.                                                // 这个读秒是通过变量i每隔一秒自加1来实现的。                                             
  225.   Serial.println("");                          // WiFi连接成功后
  226.   Serial.println("Connection established!");   // NodeMCU将通过串口监视器输出"连接成功"信息。
  227.   Serial.print("IP address:    ");             // 同时还将输出NodeMCU的IP地址。这一功能是通过调用
  228.   Serial.println(WiFi.localIP());              // WiFi.localIP()函数来实现的。该函数的返回值即NodeMCU的IP地址。  
  229. }
  230. ​
  231. // 利用ArduinoJson库解析心知天气响应信息(实时)
  232. void parseInfo_now(WiFiClient client,int i){
  233. ​
  234.   if(i==1){
  235.   const size_t capacity = JSON_ARRAY_SIZE(1) + JSON_OBJECT_SIZE(1) + 2*JSON_OBJECT_SIZE(3) + JSON_OBJECT_SIZE(6) + 230;
  236.   DynamicJsonDocument doc(capacity);
  237.   
  238.   deserializeJson(doc, client);
  239.   
  240.   JsonObject results_0 = doc["results"][0];
  241.   
  242.   JsonObject results_0_now = results_0["now"];
  243.   const char* results_0_now_text = results_0_now["text"]; // "Sunny"
  244.   const char* results_0_now_code = results_0_now["code"]; // "0"
  245.   const char* results_0_now_temperature = results_0_now["temperature"]; // "32"
  246.   
  247.   const char* results_0_last_update = results_0["last_update"]; // "2020-06-02T14:40:00+08:00"

  248.   // 通过串口监视器显示以上信息
  249.   String results_0_now_text_str = results_0_now["text"].as<String>();
  250.   int results_0_now_code_int = results_0_now["code"].as<int>();
  251.   int results_0_now_temperature_int = results_0_now["temperature"].as<int>();
  252.   String results_0_last_update_str = results_0["last_update"].as<String>();   

  253.   Serial.println(F("======Weahter Now======="));
  254.   Serial.print(F("Weather Now: "));
  255.   Serial.print(results_0_now_text_str);
  256.   Serial.print(F(" "));
  257.   Serial.println(results_0_now_code_int);
  258.   Serial.print(F("Temperature: "));
  259.   Serial.println(results_0_now_temperature_int);
  260.   Serial.print(F("Last Update: "));
  261.   Serial.println(results_0_last_update_str);
  262.   Serial.println(F("========================"));
  263.   display_0(results_0_now_temperature_int,results_0_now_text_str);
  264.   results_0_now_text_str_old = results_0_now_text_str;
  265.   results_0_now_temperature_int_old = results_0_now_temperature_int;
  266.   }
  267.   else{
  268.     display_0(results_0_now_temperature_int_old,results_0_now_text_str_old);
  269.   }

  270. }
  271. //----------输出实时天气----------
  272. void display_0(int results_0_now_temperature_int,String results_0_now_text_str){
  273.   //显示输出
  274.   u8g2.clearBuffer();
  275.   u8g2.setFont(u8g2_font_wqy16_t_gb2312);
  276.   u8g2.setCursor(15, 14);
  277.   u8g2.print("上海实时天气");
  278.   u8g2.setFont(u8g2_font_logisoso24_tr);
  279.   u8g2.setCursor(45, 44);
  280.   u8g2.print(results_0_now_temperature_int);
  281.   u8g2.setCursor(15, 61);
  282.   u8g2.setFont(u8g2_font_unifont_t_chinese2);
  283.   u8g2.print(results_0_now_text_str);
  284.   u8g2.sendBuffer();
  285. }
  286. ​
  287. ​
  288. // 利用ArduinoJson库解析心知天气响应信息(预测)
  289. void parseInfo_fut(WiFiClient client,int i){
  290.   if(i==1){
  291.    
  292.   
  293.   const size_t capacity = JSON_ARRAY_SIZE(1) + JSON_ARRAY_SIZE(3) + JSON_OBJECT_SIZE(1) + JSON_OBJECT_SIZE(3) + JSON_OBJECT_SIZE(6) + 3*JSON_OBJECT_SIZE(14) + 860;
  294.   
  295.   DynamicJsonDocument doc(capacity);
  296.   
  297.   deserializeJson(doc, client);
  298.   
  299.   JsonObject results_0 = doc["results"][0];
  300.   
  301.   JsonArray results_0_daily = results_0["daily"];
  302.   
  303.   JsonObject results_0_daily_0 = results_0_daily[0];
  304.   const char* results_0_daily_0_date = results_0_daily_0["date"];
  305.   const char* results_0_daily_0_text_day = results_0_daily_0["text_day"];
  306.   const char* results_0_daily_0_code_day = results_0_daily_0["code_day"];
  307.   const char* results_0_daily_0_text_night = results_0_daily_0["text_night"];
  308.   const char* results_0_daily_0_code_night = results_0_daily_0["code_night"];
  309.   const char* results_0_daily_0_high = results_0_daily_0["high"];
  310.   const char* results_0_daily_0_low = results_0_daily_0["low"];
  311.   const char* results_0_daily_0_rainfall = results_0_daily_0["rainfall"];
  312.   const char* results_0_daily_0_precip = results_0_daily_0["precip"];
  313.   const char* results_0_daily_0_wind_direction = results_0_daily_0["wind_direction"];
  314.   const char* results_0_daily_0_wind_direction_degree = results_0_daily_0["wind_direction_degree"];
  315.   const char* results_0_daily_0_wind_speed = results_0_daily_0["wind_speed"];
  316.   const char* results_0_daily_0_wind_scale = results_0_daily_0["wind_scale"];
  317.   const char* results_0_daily_0_humidity = results_0_daily_0["humidity"];
  318.   
  319.   JsonObject results_0_daily_1 = results_0_daily[1];
  320.   const char* results_0_daily_1_date = results_0_daily_1["date"];
  321.   const char* results_0_daily_1_text_day = results_0_daily_1["text_day"];
  322.   const char* results_0_daily_1_code_day = results_0_daily_1["code_day"];
  323.   const char* results_0_daily_1_text_night = results_0_daily_1["text_night"];
  324.   const char* results_0_daily_1_code_night = results_0_daily_1["code_night"];
  325.   const char* results_0_daily_1_high = results_0_daily_1["high"];
  326.   const char* results_0_daily_1_low = results_0_daily_1["low"];
  327.   const char* results_0_daily_1_rainfall = results_0_daily_1["rainfall"];
  328.   const char* results_0_daily_1_precip = results_0_daily_1["precip"];
  329.   const char* results_0_daily_1_wind_direction = results_0_daily_1["wind_direction"];
  330.   const char* results_0_daily_1_wind_direction_degree = results_0_daily_1["wind_direction_degree"];
  331.   const char* results_0_daily_1_wind_speed = results_0_daily_1["wind_speed"];
  332.   const char* results_0_daily_1_wind_scale = results_0_daily_1["wind_scale"];
  333.   const char* results_0_daily_1_humidity = results_0_daily_1["humidity"];
  334.   
  335.   JsonObject results_0_daily_2 = results_0_daily[2];
  336.   const char* results_0_daily_2_date = results_0_daily_2["date"];
  337.   const char* results_0_daily_2_text_day = results_0_daily_2["text_day"];
  338.   const char* results_0_daily_2_code_day = results_0_daily_2["code_day"];
  339.   const char* results_0_daily_2_text_night = results_0_daily_2["text_night"];
  340.   const char* results_0_daily_2_code_night = results_0_daily_2["code_night"];
  341.   const char* results_0_daily_2_high = results_0_daily_2["high"];
  342.   const char* results_0_daily_2_low = results_0_daily_2["low"];
  343.   const char* results_0_daily_2_rainfall = results_0_daily_2["rainfall"];
  344.   const char* results_0_daily_2_precip = results_0_daily_2["precip"];
  345.   const char* results_0_daily_2_wind_direction = results_0_daily_2["wind_direction"];
  346.   const char* results_0_daily_2_wind_direction_degree = results_0_daily_2["wind_direction_degree"];
  347.   const char* results_0_daily_2_wind_speed = results_0_daily_2["wind_speed"];
  348.   const char* results_0_daily_2_wind_scale = results_0_daily_2["wind_scale"];
  349.   const char* results_0_daily_2_humidity = results_0_daily_2["humidity"];
  350.   
  351.   const char* results_0_last_update = results_0["last_update"];
  352.   
  353.   // 从以上信息中摘选几个通过串口监视器显示
  354.   String results_0_daily_0_date_str = results_0_daily_0["date"].as<String>();
  355.   String  results_0_daily_0_text_day_str = results_0_daily_0["text_day"].as<String>();
  356.   int results_0_daily_0_code_day_int = results_0_daily_0["code_day"].as<int>();
  357.   String results_0_daily_0_text_night_str = results_0_daily_0["text_night"].as<String>();
  358.   int results_0_daily_0_code_night_int = results_0_daily_0["code_night"].as<int>();
  359.   int results_0_daily_0_high_int = results_0_daily_0["high"].as<int>();
  360.   int results_0_daily_0_low_int = results_0_daily_0["low"].as<int>();
  361.   String results_0_last_update_str = results_0["last_update"].as<String>();
  362. ​
  363.   int results_0_daily_1_high_int = results_0_daily_1["high"].as<int>();
  364.   int results_0_daily_1_low_int = results_0_daily_1["low"].as<int>();
  365.   String results_0_daily_1_text_day_str = results_0_daily_1["text_day"].as<String>();

  366.   Serial.println(F("======Today Weahter ======="));
  367.   Serial.print(F("DATE: "));
  368.   Serial.println(results_0_daily_0_date_str);
  369.   Serial.print(F("Day Weather: "));
  370.   Serial.print(results_0_daily_0_text_day_str);
  371.   Serial.print(F(" "));
  372.   Serial.println(results_0_daily_0_code_day_int);
  373.   Serial.print(F("Night Weather: "));
  374.   Serial.print(results_0_daily_0_text_night_str);
  375.   Serial.print(F(" "));
  376.   Serial.println(results_0_daily_0_code_night_int);
  377.   Serial.print(F("High: "));
  378.   Serial.println(results_0_daily_0_high_int);
  379.   Serial.print(F("LOW: "));
  380.   Serial.println(results_0_daily_0_low_int);
  381.   Serial.print(F("Last Update: "));
  382.   Serial.println(results_0_last_update_str);
  383.   Serial.println(F("=============================="));
  384.   display_1(results_0_daily_1_high_int,results_0_daily_1_low_int,results_0_daily_1_text_day_str);
  385.   results_0_daily_1_high_int_old=results_0_daily_1_high_int;
  386.   results_0_daily_1_low_int_old=results_0_daily_1_low_int;
  387.   results_0_daily_1_text_day_str_old=results_0_daily_1_text_day_str;
  388. }else{
  389.   display_1(results_0_daily_1_high_int_old,results_0_daily_1_low_int_old,results_0_daily_1_text_day_str_old);
  390. }
  391. ​
  392. ​
  393.   
  394. }
  395. //----------预测明天天气----------
  396. void display_1(int results_0_daily_1_high_int,int results_0_daily_1_low_int,String results_0_daily_1_text_day_str){
  397.   //显示输出
  398.   u8g2.clearBuffer();
  399.   u8g2.setFont(u8g2_font_wqy16_t_gb2312);
  400.   u8g2.setCursor(15, 14);
  401.   u8g2.print("上海明天天气");
  402.   
  403.   u8g2.setFont(u8g2_font_logisoso24_tr);
  404.   u8g2.setCursor(20, 46);
  405.   u8g2.print(results_0_daily_1_low_int);
  406.   u8g2.setCursor(56, 46);
  407.   u8g2.print("~");
  408.   u8g2.setCursor(75, 46);
  409.   u8g2.print(results_0_daily_1_high_int);
  410.   
  411.   u8g2.setCursor(30, 62);
  412.   u8g2.setFont(u8g2_font_unifont_t_chinese2);
  413.   u8g2.print(results_0_daily_1_text_day_str);
  414.   u8g2.sendBuffer();
  415. }
  416. ​
  417. ​
  418. /*-------- NTP 代码 ----------*/
  419. ​
  420. const int NTP_PACKET_SIZE = 48;     // NTP时间在消息的前48个字节里
  421. byte packetBuffer[NTP_PACKET_SIZE]; // 输入输出包的缓冲区
  422. ​
  423. time_t getNtpTime()
  424. {
  425.     IPAddress ntpServerIP; // NTP服务器的地址
  426. ​
  427.     while (Udp.parsePacket() > 0)
  428.         ; // 丢弃以前接收的任何数据包
  429.     Serial.println("Transmit NTP Request");
  430.     // 从池中获取随机服务器
  431.     WiFi.hostByName(ntpServerName, ntpServerIP);
  432.     Serial.print(ntpServerName);
  433.     Serial.print(": ");
  434.     Serial.println(ntpServerIP);
  435.     sendNTPpacket(ntpServerIP);
  436.     uint32_t beginWait = millis();
  437.     while (millis() - beginWait < 1500)
  438.     {
  439.         int size = Udp.parsePacket();
  440.         if (size >= NTP_PACKET_SIZE)
  441.         {
  442.             Serial.println("Receive NTP Response");
  443.             isNTPConnected = true;
  444.             Udp.read(packetBuffer, NTP_PACKET_SIZE); // 将数据包读取到缓冲区
  445.             unsigned long secsSince1900;
  446.             // 将从位置40开始的四个字节转换为长整型,只取前32位整数部分
  447.             secsSince1900 = (unsigned long)packetBuffer[40] << 24;
  448.             secsSince1900 |= (unsigned long)packetBuffer[41] << 16;
  449.             secsSince1900 |= (unsigned long)packetBuffer[42] << 8;
  450.             secsSince1900 |= (unsigned long)packetBuffer[43];
  451.             Serial.println(secsSince1900);
  452.             Serial.println(secsSince1900 - 2208988800UL + timeZone * SECS_PER_HOUR);
  453.             return secsSince1900 - 2208988800UL + timeZone * SECS_PER_HOUR;
  454.         }
  455.     }
  456.     Serial.println("No NTP Response :-("); //无NTP响应
  457.     isNTPConnected = false;
  458.     return 0; //如果未得到时间则返回0
  459. }
  460. ​
  461. // 向给定地址的时间服务器发送NTP请求
  462. void sendNTPpacket(IPAddress &address)
  463. {
  464.     memset(packetBuffer, 0, NTP_PACKET_SIZE);
  465.     packetBuffer[0] = 0b11100011; // LI, Version, Mode
  466.     packetBuffer[1] = 0;          // Stratum, or type of clock
  467.     packetBuffer[2] = 6;          // Polling Interval
  468.     packetBuffer[3] = 0xEC;       // Peer Clock Precision
  469.     // 8 bytes of zero for Root Delay & Root Dispersion
  470.     packetBuffer[12] = 49;
  471.     packetBuffer[13] = 0x4E;
  472.     packetBuffer[14] = 49;
  473.     packetBuffer[15] = 52;
  474.     Udp.beginPacket(address, 123); //NTP需要使用的UDP端口号为123
  475.     Udp.write(packetBuffer, NTP_PACKET_SIZE);
  476.     Udp.endPacket();
  477. }
  478. ​
  479. void oledClockDisplay()
  480. {
  481.     int years, months, days, hours, minutes, seconds, weekdays;
  482.     years = year();
  483.     months = month();
  484.     days = day();
  485.     hours = hour();
  486.     minutes = minute();
  487.     seconds = second();
  488.     weekdays = weekday();
  489.     Serial.printf("%d/%d/%d %d:%d:%d Weekday:%d\n", years, months, days, hours, minutes, seconds, weekdays);
  490.     u8g2.clearBuffer();
  491.     u8g2.setFont(u8g2_font_unifont_t_chinese2);
  492.     u8g2.setCursor(0, 14);
  493.     if (isNTPConnected)
  494.     {
  495.         if(timeZone>=0)
  496.         {
  497.             u8g2.print("当前时间(UTC+");
  498.             u8g2.print(timeZone);
  499.             u8g2.print(")");
  500.         }
  501.         else
  502.         {
  503.             u8g2.print("当前时间(UTC");
  504.             u8g2.print(timeZone);
  505.             u8g2.print(")");
  506.         }
  507.     }
  508.     else
  509.         u8g2.print("无网络!"); //如果上次对时失败,则会显示无网络
  510.     String currentTime = "";
  511.     if (hours < 10)
  512.         currentTime += 0;
  513.     currentTime += hours;
  514.     currentTime += ":";
  515.     if (minutes < 10)
  516.         currentTime += 0;
  517.     currentTime += minutes;
  518.     currentTime += ":";
  519.     if (seconds < 10)
  520.         currentTime += 0;
  521.     currentTime += seconds;
  522.     String currentDay = "";
  523.     currentDay += years;
  524.     currentDay += "/";
  525.     if (months < 10)
  526.         currentDay += 0;
  527.     currentDay += months;
  528.     currentDay += "/";
  529.     if (days < 10)
  530.         currentDay += 0;
  531.     currentDay += days;
  532. ​
  533.     u8g2.setFont(u8g2_font_logisoso24_tr);
  534.     u8g2.setCursor(0, 44);
  535.     u8g2.print(currentTime);
  536.     u8g2.setCursor(0, 61);
  537.     u8g2.setFont(u8g2_font_unifont_t_chinese2);
  538.     u8g2.print(currentDay);
  539.     u8g2.drawXBM(80, 48, 16, 16, xing);
  540.     u8g2.setCursor(95, 62);
  541.     u8g2.print("期");
  542.     if (weekdays == 1)
  543.         u8g2.print("日");
  544.     else if (weekdays == 2)
  545.         u8g2.print("一");
  546.     else if (weekdays == 3)
  547.         u8g2.print("二");
  548.     else if (weekdays == 4)
  549.         u8g2.print("三");
  550.     else if (weekdays == 5)
  551.         u8g2.print("四");
  552.     else if (weekdays == 6)
  553.         u8g2.print("五");
  554.     else if (weekdays == 7)
  555.         u8g2.drawXBM(111, 49, 16, 16, liu);
  556.     u8g2.sendBuffer();
  557. }
复制代码

实现效果如下

实时天气.JPG (228.87 KB, 下载次数: 19)

实时天气.JPG

当前时间.JPG (236.46 KB, 下载次数: 21)

当前时间.JPG

明天天气.JPG (230.48 KB, 下载次数: 21)

明天天气.JPG

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏7 分享淘帖 顶顶1 踩踩
回复

使用道具 举报

沙发
ID:1130053 发表于 2024-8-15 13:25 | 只看该作者
谢谢分享,学习学习
回复

使用道具 举报

板凳
ID:1009314 发表于 2025-6-7 20:47 | 只看该作者
有没有换个大屏,显示东西多一点的代码
回复

使用道具 举报

地板
ID:88256 发表于 2025-6-8 12:57 | 只看该作者
qq869240666 发表于 2025-6-7 20:47
有没有换个大屏,显示东西多一点的代码

他这是12864的屏幕,你能换多大的?除非换成墨水屏或者彩屏,况且完整程序也放出来了,显示部分完全可以自己换用别的屏幕并更改布局。墨水屏刷新慢,一般来说没有秒显,会习惯的话就可以DIY一个用。



回复

使用道具 举报

5#
ID:16255 发表于 2025-6-8 23:13 | 只看该作者
hhdsdy 发表于 2025-6-8 12:57
他这是12864的屏幕,你能换多大的?除非换成墨水屏或者彩屏,况且完整程序也放出来了,显示部分完全可以 ...

不知为什么,我用8266驱动墨水屏来做天气屏,就是不成功。
初步归结为以下几个原因:⒈本人功力太菜。⒉8266空间/算力有限。⒊还是本人太菜。
回复

使用道具 举报

6#
ID:123917 发表于 2025-6-9 08:06 | 只看该作者
谢谢,学习
回复

使用道具 举报

7#
ID:88256 发表于 2025-6-9 09:09 | 只看该作者
mengsiu 发表于 2025-6-8 23:13
不知为什么,我用8266驱动墨水屏来做天气屏,就是不成功。
初步归结为以下几个原因:⒈本人功力太菜。⒉ ...

首先是要排除硬件上的问题,焊接FPC插座容易焊锡粘连或者虚焊,不容易观察到,可以在焊接后插接一条FPC用于测试是否短路和开路;墨水屏驱动一定要对,先使用别人点亮过(和自己的屏一摸一样的)的程序刷入点亮,排除硬件问题;墨水屏需要负压用于刷新,可以先搭好万用表测量一下刷新时是否有该负压出现。
8266的算力肯定够,我一直都是用8266的,舍不得用ESP32,所以不用怀疑,至于空间,一般来说也不会用到满,况且下载的时候还有提示。
回复

使用道具 举报

8#
ID:71977 发表于 2025-9-2 14:55 | 只看该作者
谢谢楼主分享啊
回复

使用道具 举报

9#
ID:597949 发表于 2026-10-1 18:32 | 只看该作者
用的esp01s一直出问题,好像是说内存太小了
回复

使用道具 举报

10#
无效楼层,该帖已经被删除
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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