ESP8266+OLED屏实现天气预报+温度显示+NTP时间同步

ESP8266+OLED屏实现天气预报+温度显示+NTP时间同步

利用arduino D1mini板子作为载体开发。本文的源程序代码链接放到最后。
1.OLED屏接口为I2C,4个引脚的,,0.96寸,128*64,
2.温度传感器:DS18b20
3.D1mini
先上图D1mini:
ESP8266+OLED屏实现天气预报+温度显示+NTP时间同步_第1张图片
显示效果一屏:

ESP8266+OLED屏实现天气预报+温度显示+NTP时间同步_第2张图片
第二屏显示效果:
ESP8266+OLED屏实现天气预报+温度显示+NTP时间同步_第3张图片
第三屏显示效果:
ESP8266+OLED屏实现天气预报+温度显示+NTP时间同步_第4张图片


#include 
#include 
#include 
#include 
#include 
#include 
#include 
// time
#include                        // time() ctime()
#include                    // struct timeval
#include                   // settimeofday_cb()


#include "SH1106Wire.h"//or #include "SSD1306Wire.h"
#include "OLEDDisplayUi.h"
#include "Wire.h"
#include "HeFeng.h"

#include "WeatherStationFonts.h"
#include "WeatherStationImages.h"


/***************************
 * Begin Settings
 **************************/

DS18B20 ds(D7); //温度传感器io口。


#define TZ              -8       // (utc+) TZ in hours
#define DST_MN          0      // use 60mn for summer time in some countries

// Setup
const int UPDATE_INTERVAL_SECS = 20 * 60; // Update every 20 minutes  online weather
// Setup
const int UPDATE_CURR_INTERVAL_SECS = 10; // Update every 10 secs DS18B20

// Display Settings
const int I2C_DISPLAY_ADDRESS = 0x3c;
#if defined(ESP8266)
const int SDA_PIN = D2;
const int SDC_PIN = D5;
#endif


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
 SH1106Wire     display(I2C_DISPLAY_ADDRESS, SDA_PIN, SDC_PIN);   // or SSD1306Wire  display(I2C_DISPLAY_ADDRESS, SDA_PIN, SDC_PIN);
 OLEDDisplayUi   ui( &display );

HeFengCurrentData currentWeather;
HeFengForeData foreWeather[3];
 HeFeng HeFengClient;

//OpenWeatherMapForecastData forecasts[MAX_FORECASTS];
//OpenWeatherMapForecast forecastClient;

#define TZ_MN           ((TZ)*60)
#define TZ_SEC          ((TZ)*3600)
#define DST_SEC         ((DST_MN)*60)

const char* HEFENG_KEY="16c945b44ba847589ec6df9f93efd1b6";   //和风天气key
const char* HEFENG_LOCATION="CN101250303"; //城市代码
time_t now;

// flag changed in the ticker function every 10 minutes
bool readyForWeatherUpdate = false;

String lastUpdate = "--";

long timeSinceLastWUpdate = 0;
long timeSinceLastCurrUpdate = 0;

String currTemp="-1.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 };
//drawForecast
int numberOfFrames = 3;

OverlayCallback overlays[] = { drawHeaderOverlay };
int numberOfOverlays = 1;



bool autoConfig()
{
  WiFi.mode(WIFI_STA);
  WiFi.begin();
  Serial.print("AutoConfig Waiting......");
   int counter = 0;
  for (int i = 0; i < 20; i++)
  {
    if (WiFi.status() == WL_CONNECTED)
    {
      Serial.println("AutoConfig Success");
      Serial.printf("SSID:%s\r\n", WiFi.SSID().c_str());
      Serial.printf("PSW:%s\r\n", WiFi.psk().c_str());
      WiFi.printDiag(Serial);
      return true;
    }
    else
    {
       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++; 
    }
  }
  Serial.println("AutoConfig Faild!" );
  return false;
}
ESP8266WebServer server(80);
String str = "ESP8266网页配网hello,我是fxy,输入wifi信息给wifi时钟配网:  
WiFi名称:
WiFi密码:
"
; void handleRoot() { server.send(200, "text/html", str); } void HandleWifi() { String wifis = server.arg("ssid"); //从JavaScript发送的数据中找ssid的值 String wifip = server.arg("password"); //从JavaScript发送的数据中找password的值 Serial.println("received:"+wifis); server.send(200, "text/html", "连接中.."); WiFi.begin(wifis,wifip); } void handleNotFound() { String message = "File Not Found\n\n"; message += "URI: "; message += server.uri(); message += "\nMethod: "; message += (server.method() == HTTP_GET) ? "GET" : "POST"; message += "\nArguments: "; message += server.args(); message += "\n"; for (uint8_t i = 0; i < server.args(); i++) { message += " " + server.argName(i) + ": " + server.arg(i) + "\n"; } server.send(404, "text/plain", message); } void htmlConfig() { WiFi.mode(WIFI_AP_STA);//设置模式为AP+STA WiFi.softAP("wifi_clock"); IPAddress myIP = WiFi.softAPIP(); if (MDNS.begin("clock")) { Serial.println("MDNS responder started"); } server.on("/", handleRoot); server.on("/HandleWifi", HTTP_GET, HandleWifi); server.onNotFound(handleNotFound);//请求失败回调函数 MDNS.addService("http", "tcp", 80); server.begin();//开启服务器 Serial.println("HTTP server started"); int counter = 0; while(1) { server.handleClient(); MDNS.update(); delay(500); display.clear(); display.drawString(64, 5, "WIFI AP:wifi_clock"); display.drawString(64, 20, "192.168.4.1"); display.drawString(64, 35, "waiting for config wifi."); display.drawXbm(46, 50, 8, 8, counter % 3 == 0 ? activeSymbole : inactiveSymbole); display.drawXbm(60, 50, 8, 8, counter % 3 == 1 ? activeSymbole : inactiveSymbole); display.drawXbm(74, 50, 8, 8, counter % 3 == 2 ? activeSymbole : inactiveSymbole); display.display(); counter++; if (WiFi.status() == WL_CONNECTED) { Serial.println("HtmlConfig Success"); Serial.printf("SSID:%s\r\n", WiFi.SSID().c_str()); Serial.printf("PSW:%s\r\n", WiFi.psk().c_str()); Serial.println("HTML连接成功"); break; } } server.close(); WiFi.mode(WIFI_STA); } 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); bool wifiConfig = autoConfig(); if(wifiConfig == false){ htmlConfig();//HTML配网 } 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.setTimePerFrame(7500); ui.setOverlays(overlays, numberOfOverlays); // Inital UI takes care of initalising the display too. ui.init(); Serial.println(""); configTime(TZ_SEC, DST_SEC, "pool.ntp.org","0.cn.pool.ntp.org","1.cn.pool.ntp.org"); updateData(&display); } void loop() { if (millis() - timeSinceLastWUpdate > (1000L*UPDATE_INTERVAL_SECS)) { setReadyForWeatherUpdate(); timeSinceLastWUpdate = millis(); } if (millis() - timeSinceLastCurrUpdate > (1000L*UPDATE_CURR_INTERVAL_SECS)) { if( ui.getUiState()->frameState == FIXED) { currTemp=String(ds.getTempC(), 1); timeSinceLastCurrUpdate = 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, 30, "Updating weather..."); for(int i=0;i<5;i++){ HeFengClient.doUpdateCurr(&currentWeather, HEFENG_KEY, HEFENG_LOCATION); if(currentWeather.cond_txt!="no network"){ break;} } drawProgress(display, 50, "Updating forecasts..."); for(int i=0;i<5;i++){ HeFengClient.doUpdateFore(foreWeather, HEFENG_KEY, HEFENG_LOCATION); if(foreWeather[0].datestr!="N/A"){ break;} } 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_16); String date = WDAY_NAMES[timeInfo->tm_wday]; sprintf_P(buff, PSTR("%04d-%02d-%02d, %s"), timeInfo->tm_year + 1900, timeInfo->tm_mon+1, timeInfo->tm_mday, WDAY_NAMES[timeInfo->tm_wday].c_str()); 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, 22 + 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.cond_txt+" | Wind: "+currentWeather.wind_sc); display->setFont(ArialMT_Plain_24); display->setTextAlignment(TEXT_ALIGN_LEFT); String temp = currentWeather.tmp + "°C" ; display->drawString(60 + x, 3 + y, temp); display->setFont(ArialMT_Plain_10); display->drawString(70 + x, 26 + y, currentWeather.fl+"°C | "+currentWeather.hum+"%"); 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) { display->setTextAlignment(TEXT_ALIGN_CENTER); display->setFont(ArialMT_Plain_10); display->drawString(x + 20, y, foreWeather[dayIndex].datestr); display->setFont(Meteocons_Plain_21); display->drawString(x + 20, y + 12, foreWeather[dayIndex].iconMeteoCon); String temp=foreWeather[dayIndex].tmp_min+" | "+foreWeather[dayIndex].tmp_max; 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(6, 54, String(buff)); display->setTextAlignment(TEXT_ALIGN_RIGHT); String temp =currTemp +"°C"; display->drawString(128, 54, temp); display->drawHorizontalLine(0, 52, 128); } void setReadyForWeatherUpdate() { Serial.println("Setting readyForUpdate to true"); readyForWeatherUpdate = true; }

百度链接:(如果能对你有帮助,请给个赞,开源代码分享不容易,大家多多支持!)
链接:https://pan.baidu.com/s/1cL8hdTpYwDRFqQuiEcysEQ
提取码:i0jy

你可能感兴趣的:(arduino,esp8266)