Arduino网络编程实战-OLED显示天气信息 OLED显示天气信息 Arduino Ethernet Shield V1 允许 Arduino 板连接到互联网。 它基于 Wiznet W5100ethernet 芯片(数据表)。 Wiznet W5100 提供支持 TCP 和 UDP 的网络 (IP) 堆栈。 它最多支持四个同时套接字连接。
本实例将演示获取天气JSON数据、数据解析、并在OLED中显示天气。
通过使用OLED显示天气信息主要由以下步骤组成:
1)请求天气信息,请参考:
2)解析天气JSON信息,请参考:
3)根据天气代码显示天气图片、城市名称、温度信息,请参考:
1、硬件准备
Arduino Mega2560 开发板一块
SD卡模块一个及SD卡一个
SSD1306 OLED屏幕一块
数据线一条
杜邦线若干
硬件接线,请关于前面相关文章,在这里不再做描述。
2、软件准备
3、代码实现 3.1 导入相关头文件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 #include <SPI.h> #include <Wire.h> #include <Adafruit\_GFX.h> #include <Adafruit\_SSD1306.h> #include <SdFat.h> #include <ArduinoJson.h> #include <Ethernet.h> #define SCREEN\_WIDTH 128 // OLED display width, in pixels #define SCREEN\_HEIGHT 64 // OLED display height, in pixels #define OLED\_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin) #define SCREEN\_ADDRESS 0x3C ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32 Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET); // SD\_FAT\_TYPE = 0 for SdFat/File as defined in SdFatConfig.h, // 1 for FAT16/FAT32, 2 for exFAT, 3 for FAT16/FAT32 and exFAT. // SD卡文件系统格式类型 #define SD\_FAT\_TYPE 0 #define SD\_CS\_PIN 4 #define SPI\_CLOCK SD\_SCK\_MHZ(50) #define SD\_CONFIG SdSpiConfig(SD\_CS\_PIN, DEDICATED\_SPI, SPI\_QUARTER\_SPEED) #if SD\_FAT\_TYPE == 0 SdFat sd; File file; #elif SD\_FAT\_TYPE == 1 SdFat32 sd; File32 file; #elif SD\_FAT\_TYPE == 2 SdExFat sd; ExFile file; #elif SD\_FAT\_TYPE == 3 SdFs sd; FsFile file; #else // SD\_FAT\_TYPE #error Invalid SD\_FAT\_TYPE #endif // SD\_FAT\_TYPE #define USE\_STATIC 1 byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; #if USE\_STATIC IPAddress ip(192, 168, 0, 116); #endif unsigned char img_datas [1024] = {0}; const String beijing_fonts[] = {"fonts/cn\_bei.json","fonts/cn\_jing.json"}; const String weather_code_0 = "weather\_image\_configs/files/0@2x.json"; const String weather_temp_icon = "weather\_image\_configs/files/170@1x.json"; DeserializationError error; int width,height,len;
3.2 OLED初始化 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 // 串口初始化 Serial.begin(9600); // OLED初始化 if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) { Serial.println(F("SSD1306 allocation failed")); for(;;); // Don't proceed, loop forever } // 显示欢迎屏幕 display.display(); // 清屏 display.clearDisplay(); // 设置字体 display.setTextSize(1); // Normal 1:1 pixel scale display.setTextColor(SSD1306_WHITE); // Draw white text display.setCursor(0, 0); // Start at top-left corner display.cp437(true); // Use full 256 char 'Code Page 437' font
3.3 网卡初始化 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 // 初始化网卡 selectEthernet(); #if USE\_STATIC Ethernet.begin(mac,ip); #else Ethernet.begin(mac); #endif if (Ethernet.hardwareStatus() == EthernetNoHardware) { Serial.println("Ethernet shield was not found. Sorry, can't run without hardware. :("); display.setCursor(0,0); display.println("Ethernet Failed"); display.display(); while (true) { delay(1); } } if (Ethernet.linkStatus() == LinkOFF) { Serial.println("Ethernet cable is not connected."); display.clearDisplay(); display.setCursor(0,0); display.println("Ethernet LinkOFF"); display.display(); while(true){ delay(1); } } Serial.print("IP:"); Serial.println(Ethernet.localIP()); Serial.print("Subnet Mask:"); Serial.println(Ethernet.subnetMask()); Serial.print("Gateway:"); Serial.println(Ethernet.gatewayIP()); Serial.print("DNS Server:"); Serial.println(Ethernet.dnsServerIP()); display.clearDisplay(); display.setCursor(0,0); display.print("IP:"); display.print(Ethernet.localIP()); display.display();
3.4 SD卡初始化 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 // SD卡初始化 selectSdcard(); // Initialize the SD. if (!sd.begin(SD_CONFIG)) { display.clearDisplay(); display.setCursor(0,16); display.print("SDCard failed"); display.display(); sd.initErrorHalt(&Serial); return; } //display.clearDisplay(); display.setCursor(0,16); display.print("SDCard Inited"); display.display(); Serial.println("Initialized SD card...");
3.5 请求天气信息 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 selectEthernet(); // Connect to HTTP server EthernetClient client; client.setTimeout(10000); Serial.println("Connecting...."); if (!client.connect("api.seniverse.com", 80)) { Serial.println("Connection failed"); return; } Serial.println(F("Connected!")); // Send HTTP request client.println(F("GET /v3/weather/now.json?key=【你的API Key】&location=beijing&language=zh-Hans&unit=c HTTP/1.0")); client.println(F("Host: api.seniverse.com")); client.println("Content-Type: application/json"); client.println("Connection: close"); // or close client.println("User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.82 Safari/537.36"); //client.print("Content-Length: "); client.println("Connection: close"); client.println(F("Connection: close")); if (client.println() == 0) { Serial.println(F("Failed to send request")); client.stop(); return; } // Check HTTP status char status[32] = {0}; client.readBytesUntil('\r', status, sizeof(status)); if (strcmp(status, "HTTP/1.1 200 OK") != 0) { Serial.print(F("Unexpected response: ")); Serial.println(status); client.stop(); return; } // Skip HTTP headers char endOfHeaders[] = "\r\n\r\n"; if (!client.find(endOfHeaders)) { Serial.println(F("Invalid response")); client.stop(); return; } // Allocate the JSON document // Use arduinojson.org/v6/assistant to compute the capacity. //const size\_t capacity = 1024;//JSON\_OBJECT\_SIZE(3) + JSON\_ARRAY\_SIZE(2) + 60; DynamicJsonDocument doc(2048); // Parse JSON object error = deserializeJson(doc, client); if (error) { Serial.print(F("deserializeJson() failed: ")); Serial.println(error.f\_str()); client.stop(); return; } // Disconnect client.stop();
3.6 解析天气信息 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 // 解析天气信息 serializeJson(doc, Serial); Serial.println(); // Extract values String id = doc["results"][0]["location"]["id"].as<String>(); String temp = doc["results"][0]["now"]["temperature"].as<String>(); String code = doc["results"][0]["now"]["code"].as<String>(); Serial.println(id); Serial.println(temp); Serial.println(code); display.setCursor(0,0); display.setTextSize(1); //设置字体大小 display.setTextColor(SSD1306_WHITE);//开像素点发光
3.7 显示天气城市名 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 display.clearDisplay(); display.display(); selectSdcard(); // 解析并显示城市名称 if(id == "WX4FBXXFKE4F"){ for(int j = 0;j < 2;j++){ Serial.println(beijing_fonts[j].c\_str()); if (!file.open(beijing_fonts[j].c\_str(), O_RDWR)) { Serial.println("open failed"); while(true); } error = deserializeJson(doc, file); int width = doc["width"].as<int>(); int height = doc["height"].as<int>(); int len; //serializeJson(doc, Serial); memset(img_datas,0,1024); Serial.print("data len:"); Serial.println(doc["datas"].as<JsonArray>().size()); len = doc["datas"].as<JsonArray>().size(); if(len > 0){ for(int i = 0;i < len;i++){ img_datas[i] = doc["datas"][i].as<unsigned char>(); } display.drawBitmap(j \* 16, 0, img_datas, 16, 16, 1); } file.close(); // 绘制字符 } }
3.8 显示天气温度 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 // 解析并显示温度值及图标 display.setTextSize(4); // Normal 1:1 pixel scale display.setTextColor(SSD1306_WHITE); // Draw white text display.setCursor(32, 24); // Start at top-left corner display.cp437(true); // Use full 256 char 'Code Page 437' font display.print(temp.c\_str()); doc.clear(); Serial.println(weather_temp_icon.c\_str()); if (!file.open(weather_temp_icon.c\_str(), O_RDWR)) { Serial.println("open failed"); while(true); } error = deserializeJson(doc, file); width = doc["width"].as<int>(); height = doc["height"].as<int>(); memset(img_datas,0,1024); Serial.print("data len:"); Serial.println(doc["datas"].as<JsonArray>().size()); len = doc["datas"].as<JsonArray>().size(); if(len > 0){ for(int i = 0;i < len;i++){ img_datas[i] = doc["datas"][i].as<unsigned char>(); } file.close(); display.drawBitmap(64, 24, img_datas, 32, 32, 1); }
3.9 显示天气代码图标 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 // 解析并显示天气图标 if(code == "0"){ doc.clear(); Serial.println(weather_code_0.c\_str()); if (!file.open(weather_code_0.c\_str(), O_RDWR)) { Serial.println("open failed"); while(true); } error = deserializeJson(doc, file); width = doc["width"].as<int>(); height = doc["height"].as<int>(); //serializeJson(doc, Serial); memset(img_datas,0,1024); Serial.print("data len:"); Serial.println(doc["datas"].as<JsonArray>().size()); len = doc["datas"].as<JsonArray>().size(); if(len > 0){ for(int i = 0;i < len;i++){ img_datas[i] = doc["datas"][i].as<unsigned char>(); } file.close(); display.drawBitmap(112, 0, img_datas, 16, 16, 1); display.display(); } }
4、运行结果
文章来源: https://iotsmart.blog.csdn.net/article/details/123050211
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!