本文演示通過OLED顯示時鐘和天氣情況,主要利用的是openweathermap的免費天氣API。
1、硬件準備
(1)零知ESP8266開發板
(2)OLED SSD1306模塊(3)若干杜邦線
2、電路連接
接線很簡單,I2C接口對應連接即可:
接線圖.jpg (155.75 KB, 下載次數: 107)
下載附件
2019-6-19 10:22 上傳
接好后實物圖如下:
實物圖.jpg (49.76 KB, 下載次數: 106)
下載附件
2019-6-19 10:23 上傳
2、軟件代碼
使用零知開發工具,使用了OLED和WeatherStation相關的軟件庫,因此需要安裝對應的庫:
esp8266-weather-station-1.6.6.rar
(885.92 KB, 下載次數: 190)
2019-6-19 10:24 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
安裝完成后,我們新建工程:
- /*
- 2019年6月13日13:47:26
- by 零知實驗室
- */
-
- #include <ESPWiFi.h>
- #include <ESPHTTPClient.h>
- #include <JsonListener.h>
-
- // time
- #include <time.h> // time() ctime()
- #include <sys/time.h> // struct timeval
- #include <coredecls.h> // settimeofday_cb()
-
- #include "SSD1306Wire.h"
- #include "OLEDDisplayUi.h"
- #include "Wire.h"
- #include "OpenWeatherMapCurrent.h"
- #include "OpenWeatherMapForecast.h"
- #include "WeatherStationFonts.h"
- #include "WeatherStationImages.h"
-
-
- /***************************
- * Begin Settings
- **************************/
-
- // WIFI
- const char* WIFI_SSID = "xx";
- const char* WIFI_PWD = "xx";
-
- #define TZ 8 // (utc+) TZ in hours
- #define DST_MN 60 // use 60mn for summer time in some countries
-
- // Setup
- const int UPDATE_INTERVAL_SECS = 20 * 60; // Update every 20 minutes
-
- // Display Settings
- const int I2C_DISPLAY_ADDRESS = 0x3c;
-
- const int SDA_PIN = D3;
- const int SDC_PIN = D4;
-
- // OpenWeatherMap Settings
- // Sign up here to get an API key:
-
- // Pick a language code from this list:
- // Arabic - ar, Bulgarian - bg, Catalan - ca, Czech - cz, German - de, Greek - el,
- // English - en, Persian (Farsi) - fa, Finnish - fi, French - fr, Galician - gl,
- // Croatian - hr, Hungarian - hu, Italian - it, Japanese - ja, Korean - kr,
- // Latvian - la, Lithuanian - lt, Macedonian - mk, Dutch - nl, Polish - pl,
- // Portuguese - pt, Romanian - ro, Russian - ru, Swedish - se, Slovak - sk,
- // Slovenian - sl, Spanish - es, Turkish - tr, Ukrainian - ua, Vietnamese - vi,
- // Chinese Simplified - zh_cn, Chinese Traditional - zh_tw.
- String OPEN_WEATHER_MAP_LANGUAGE = "zh_cn";
- const uint8_t MAX_FORECASTS = 4;
-
- const boolean IS_METRIC = true;
-
- // Adjust according to your language
- const String WDAY_NAMES[] = {"SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT"};
- const String MONTH_NAMES[] = {"JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"};
-
- /***************************
- * End Settings
- **************************/
- // Initialize the oled display for address 0x3c
- // sda-pin=14 and sdc-pin=12
- SSD1306Wire display(I2C_DISPLAY_ADDRESS, SDA_PIN, SDC_PIN);
- OLEDDisplayUi ui( &display );
-
- OpenWeatherMapCurrentData currentWeather;
- OpenWeatherMapCurrent currentWeatherClient;
-
- OpenWeatherMapForecastData forecasts[MAX_FORECASTS];
- OpenWeatherMapForecast forecastClient;
-
- #define TZ_MN ((TZ)*60)
- #define TZ_SEC ((TZ)*3600)
- #define DST_SEC ((DST_MN)*60)
- time_t now;
-
- // flag changed in the ticker function every 10 minutes
- bool readyForWeatherUpdate = false;
-
- String lastUpdate = "--";
-
- long timeSinceLastWUpdate = 0;
-
- //declaring prototypes
- void drawProgress(OLEDDisplay *display, int percentage, String label);
- void updateData(OLEDDisplay *display);
- void drawDateTime(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y);
- void drawCurrentWeather(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y);
- void drawForecast(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y);
- void drawForecastDetails(OLEDDisplay *display, int x, int y, int dayIndex);
- void drawHeaderOverlay(OLEDDisplay *display, OLEDDisplayUiState* state);
- void setReadyForWeatherUpdate();
-
-
- // Add frames
- // this array keeps function pointers to all frames
- // frames are the single views that slide from right to left
- FrameCallback frames[] = { drawDateTime, drawCurrentWeather, drawForecast };
- int numberOfFrames = 3;
-
- OverlayCallback overlays[] = { drawHeaderOverlay };
- int numberOfOverlays = 1;
-
- void setup() {
- Serial.begin(115200);
- Serial.println();
- Serial.println();
-
- // initialize dispaly
- display.init();
- display.clear();
- display.display();
-
- //display.flipScreenVertically();
- display.setFont(ArialMT_Plain_10);
- display.setTextAlignment(TEXT_ALIGN_CENTER);
- display.setContrast(255);
-
- WiFi.begin(WIFI_SSID, WIFI_PWD);
-
- int counter = 0;
- while (WiFi.status() != WL_CONNECTED) {
- delay(500);
- Serial.print(".");
- display.clear();
- display.drawString(64, 10, "Connecting to WiFi");
- display.drawXbm(46, 30, 8, 8, counter % 3 == 0 ? activeSymbole : inactiveSymbole);
- display.drawXbm(60, 30, 8, 8, counter % 3 == 1 ? activeSymbole : inactiveSymbole);
- display.drawXbm(74, 30, 8, 8, counter % 3 == 2 ? activeSymbole : inactiveSymbole);
- display.display();
-
- counter++;
- }
- // Get time from network time service
- configTime(TZ_SEC, DST_SEC, "pool.ntp.org");
-
- ui.setTargetFPS(30);
-
- ui.setActiveSymbol(activeSymbole);
- ui.setInactiveSymbol(inactiveSymbole);
-
- // You can change this to
- // TOP, LEFT, BOTTOM, RIGHT
- ui.setIndicatorPosition(BOTTOM);
-
- // Defines where the first frame is located in the bar.
- ui.setIndicatorDirection(LEFT_RIGHT);
-
- // You can change the transition that is used
- // SLIDE_LEFT, SLIDE_RIGHT, SLIDE_TOP, SLIDE_DOWN
- ui.setFrameAnimation(SLIDE_LEFT);
-
- ui.setFrames(frames, numberOfFrames);
-
- ui.setOverlays(overlays, numberOfOverlays);
-
- // Inital UI takes care of initalising the display too.
- ui.init();
-
- Serial.println("");
-
- updateData(&display);
-
- }
-
- void loop() {
-
- if (millis() - timeSinceLastWUpdate > (1000L*UPDATE_INTERVAL_SECS)) {
- setReadyForWeatherUpdate();
- timeSinceLastWUpdate = millis();
- }
-
- if (readyForWeatherUpdate && ui.getUiState()->frameState == FIXED) {
- updateData(&display);
- }
-
- int remainingTimeBudget = ui.update();
-
- if (remainingTimeBudget > 0) {
- // You can do some work here
- // Don't do stuff if you are below your
- // time budget.
- delay(remainingTimeBudget);
- }
-
-
- }
-
- void drawProgress(OLEDDisplay *display, int percentage, String label) {
- display->clear();
- display->setTextAlignment(TEXT_ALIGN_CENTER);
- display->setFont(ArialMT_Plain_10);
- display->drawString(64, 10, label);
- display->drawProgressBar(2, 28, 124, 10, percentage);
- display->display();
- }
-
- void updateData(OLEDDisplay *display) {
- drawProgress(display, 10, "Updating time...");
- drawProgress(display, 30, "Updating weather...");
- currentWeatherClient.setMetric(IS_METRIC);
- currentWeatherClient.setLanguage(OPEN_WEATHER_MAP_LANGUAGE);
- currentWeatherClient.updateCurrentById(¤tWeather, OPEN_WEATHER_MAP_APP_ID, OPEN_WEATHER_MAP_LOCATION_ID);
- drawProgress(display, 50, "Updating forecasts...");
- forecastClient.setMetric(IS_METRIC);
- forecastClient.setLanguage(OPEN_WEATHER_MAP_LANGUAGE);
- uint8_t allowedHours[] = {12};
- forecastClient.setAllowedHours(allowedHours, sizeof(allowedHours));
- forecastClient.updateForecastsById(forecasts, OPEN_WEATHER_MAP_APP_ID, OPEN_WEATHER_MAP_LOCATION_ID, MAX_FORECASTS);
-
- readyForWeatherUpdate = false;
- drawProgress(display, 100, "Done...");
- delay(1000);
- }
-
-
-
- void drawDateTime(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) {
- now = time(nullptr);
- struct tm* timeInfo;
- timeInfo = localtime(&now);
- char buff[16];
-
-
- display->setTextAlignment(TEXT_ALIGN_CENTER);
- display->setFont(ArialMT_Plain_10);
- String date = WDAY_NAMES[timeInfo->tm_wday];
-
- sprintf_P(buff, PSTR("%s, %02d/%02d/%04d"), WDAY_NAMES[timeInfo->tm_wday].c_str(), timeInfo->tm_mday, timeInfo->tm_mon+1, timeInfo->tm_year + 1900);
- display->drawString(64 + x, 5 + y, String(buff));
- display->setFont(ArialMT_Plain_24);
-
- sprintf_P(buff, PSTR("%02d:%02d:%02d"), timeInfo->tm_hour, timeInfo->tm_min, timeInfo->tm_sec);
- display->drawString(64 + x, 15 + y, String(buff));
- display->setTextAlignment(TEXT_ALIGN_LEFT);
- }
-
- void drawCurrentWeather(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) {
- display->setFont(ArialMT_Plain_10);
- display->setTextAlignment(TEXT_ALIGN_CENTER);
- display->drawString(64 + x, 38 + y, currentWeather.description);
-
- display->setFont(ArialMT_Plain_24);
- display->setTextAlignment(TEXT_ALIGN_LEFT);
- String temp = String(currentWeather.temp, 1) + (IS_METRIC ? "°C" : "°F");
- display->drawString(60 + x, 5 + y, temp);
-
- display->setFont(Meteocons_Plain_36);
- display->setTextAlignment(TEXT_ALIGN_CENTER);
- display->drawString(32 + x, 0 + y, currentWeather.iconMeteoCon);
- }
-
-
- void drawForecast(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) {
- drawForecastDetails(display, x, y, 0);
- drawForecastDetails(display, x + 44, y, 1);
- drawForecastDetails(display, x + 88, y, 2);
- }
-
- void drawForecastDetails(OLEDDisplay *display, int x, int y, int dayIndex) {
- time_t observationTimestamp = forecasts[dayIndex].observationTime;
- struct tm* timeInfo;
- timeInfo = localtime(&observationTimestamp);
- display->setTextAlignment(TEXT_ALIGN_CENTER);
- display->setFont(ArialMT_Plain_10);
- display->drawString(x + 20, y, WDAY_NAMES[timeInfo->tm_wday]);
-
- display->setFont(Meteocons_Plain_21);
- display->drawString(x + 20, y + 12, forecasts[dayIndex].iconMeteoCon);
- String temp = String(forecasts[dayIndex].temp, 0) + (IS_METRIC ? "°C" : "°F");
- display->setFont(ArialMT_Plain_10);
- display->drawString(x + 20, y + 34, temp);
- display->setTextAlignment(TEXT_ALIGN_LEFT);
- }
-
- void drawHeaderOverlay(OLEDDisplay *display, OLEDDisplayUiState* state) {
- now = time(nullptr);
- struct tm* timeInfo;
- timeInfo = localtime(&now);
- char buff[14];
- sprintf_P(buff, PSTR("%02d:%02d"), timeInfo->tm_hour, timeInfo->tm_min);
-
- display->setColor(WHITE);
- display->setFont(ArialMT_Plain_10);
- display->setTextAlignment(TEXT_ALIGN_LEFT);
- display->drawString(0, 54, String(buff));
- display->setTextAlignment(TEXT_ALIGN_RIGHT);
- String temp = String(currentWeather.temp, 1) + (IS_METRIC ? "°C" : "°F");
- display->drawString(128, 54, temp);
- display->drawHorizontalLine(0, 52, 128);
- }
-
- void setReadyForWeatherUpdate() {
- Serial.println("Setting readyForUpdate to true");
- readyForWeatherUpdate = true;
- }
復制代碼 注意代碼里面填寫自己的APIkey和要查詢的城市名稱,這里填寫的是深圳-shenzhen。
3、驗證測試
將代碼驗證并上傳到零知-ESP8266上面,打開串口調試工具,可以看到如下結果:
調試窗口.jpg (103.19 KB, 下載次數: 93)
下載附件
2019-6-19 10:27 上傳
獲取返回結果代碼為:200,即表示成功了;如果是錯誤碼,可以把地址粘貼到瀏覽器里看看是什么原因。
成功后OLED就會顯示天氣情況:
結果.jpg (145.82 KB, 下載次數: 151)
下載附件
2019-6-19 10:28 上傳
更多詳細資料可到零知實驗室免費獲取。
|