3022|0

85

帖子

0

TA的资源

一粒金砂(中级)

楼主
 

【零知ESP8266项目篇】1 OLED天气时钟 [复制链接]

引述:
我们一起学了这么久的零知ESP8266的教程,是不是该检验一下自己了呢?在前面的分享中,有小伙伴留言:太简单!那我就顺水推舟,拔高一下,实践搞个小项目——天气时钟。

到现在为止,作为一个基本的开发者,咱们已经对零知ESP8266有了最基本的了解了,可能你早就按耐不住要做项目了吧!那咱今儿个就做个小项目瞧瞧。继续给我们电子世界的轮廓加一个点。

一、硬件准备
电脑,windows系统
零知ESP8266开发板
OLED SSD1306模块
micro-usb线

二、连线

 

 

三、软件库
①打开零知开发工具最新版,选中开发板,如图所示:

 

②点击库,然后安装以下两个库,如图:

安装完成后,就可以啦。

四、打开零知开发软件,新建工程,命名weather—station。然后烧写如下代码(已经做好了中文注释,复制粘贴即可):

  • /*
  • 2019年6月13日13:47:26
  • by 零知实验室
  • */
  • #include <ESPWiFi.h>
  • #include <ESPHTTPClient.h>
  • #include <JsonListener.h>
  • // time
  • #include <time.h>
  • #include <sys/time.h>
  • #include <coredecls.h>
  • #include "SSD1306Wire.h"
  • #include "OLEDDisplayUi.h"
  • #include "Wire.h"
  • #include "OpenWeatherMapCurrent.h"
  • #include "OpenWeatherMapForecast.h"
  • #include "WeatherStationFonts.h"
  • #include "WeatherStationImages.h"
  • /***************************
  • * 开始设置
  • **************************/
  • // 这里填写WiFi凭证信息
  • const char* WIFI_SSID = "WiFi名";
  • const char* WIFI_PWD = "WiFi密码";
  • #define TZ 8 // 通用协调时 东八区 北京时间为准
  • #define DST_MN 60 // 在一些国家依然用夏令时
  • // Setup
  • const int UPDATE_INTERVAL_SECS = 20 * 60; // 更新20分钟
  • // 展示设置
  • const int I2C_DISPLAY_ADDRESS = 0x3c;
  • const int SDA_PIN = D3;
  • const int SDC_PIN = D4;
  • // OpenWeatherMap设置
  • // 在此处注册以获取API密钥
  • // https://docs.thingpulse.com/how-tos/openweathermap-key/
  • //也可以在零知实验室查看原帖获取,或者留言给我呦,免费分享给你
  • String OPEN_WEATHER_MAP_APP_ID = "3213ac05f30cc2f7d8d8da6d2b03f2e8"; //得到密匙 下面会有教程
  • /*
  • 转到https://openweathermap.org/find?q=并搜索位置。
  • 通过结果设置并选择最接近要显示的实际位置的条目数据
  • 它将是一个类似于https://openweathermap.org/city/2657896.的链接最后的数字是你分配给下面常量的数字。
  • */
  • String OPEN_WEATHER_MAP_LOCATION_ID = "1795565"; //city:深圳 数字指的是openweathermap的分配的ID 同样也有教程
  • //从此列表中选择语言代码:
  • //阿拉伯文-ar,保加利亚语-bg,加泰罗尼亚语-ca,捷克语-cz,德语-de,希腊语-el,
  • //英语-en,波斯语(波斯语)-fa,芬兰语-fi,法语-fr,加利西亚语-gl,
  • //克罗地亚语-hr,匈牙利语-hu,意大利语-it,日语-ja,韩语-kr,
  • //拉脱维亚-la,立陶宛语-lt,马其顿语-mk,荷兰语-nl,波兰语-pl,
  • //葡萄牙语-pt,罗马尼亚语-ro,俄语-ru,瑞典语-se,斯洛伐克语-sk,
  • //斯洛文尼亚文-sl,西班牙文-es,土耳其文-tr,乌克兰文-ua,越南文-vi,
  • //简体中文-zh_cn,繁体中文-zh_tw。
  • String OPEN_WEATHER_MAP_LANGUAGE = "zh_cn"; //这里选择中文简体。
  • const uint8_t MAX_FORECASTS = 4;
  • const boolean IS_METRIC = true;
  • // 根据你的需要调整语言
  • 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"}; //12个月
  • /***************************
  • * 结束设置
  • **************************/
  • // 初始化OLED地址
  • // I2C接口:SDA引脚14 SCL引脚12
  • SSD1306Wire display(I2C_DISPLAY_ADDRESS, SDA_PIN, SDC_PIN); //为OLED创建一个实例display
  • OLEDDisplayUi ui( &display ); //创建一个ui实例
  • 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;
  • // 标记每10分钟更改一次。
  • bool readyForWeatherUpdate = false;
  • String lastUpdate = "--";
  • long timeSinceLastWUpdate = 0;
  • //申明原型
  • 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();
  • //添加框架
  • //此数组保留指向所有帧的函数指针
  • //框架是从右向左滑动的单个视图
  • FrameCallback frames[] = { drawDateTime, drawCurrentWeather, drawForecast };
  • int numberOfFrames = 3;
  • OverlayCallback overlays[] = { drawHeaderOverlay };
  • int numberOfOverlays = 1;
  • void setup() {
  • Serial.begin(115200);
  • Serial.println();
  • Serial.println();
  • // 初始化显示
  • 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++;
  • }
  • // 从网络时间服务得到时间
  • configTime(TZ_SEC, DST_SEC, "pool.ntp.org");
  • ui.setTargetFPS(30);
  • ui.setActiveSymbol(activeSymbole);
  • ui.setInactiveSymbol(inactiveSymbole);
  • // 你可以改变它,
  • // 向上(TOP), 向左(LEFT), 向下(BOTTOM), 向右(RIGHT)
  • ui.setIndicatorPosition(BOTTOM);
  • // 定义第一个帧位于中间的位置
  • ui.setIndicatorDirection(LEFT_RIGHT);
  • // 你可以更改幻灯片通过
  • // 向左滑动(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) {
  • //你可以在这里添加一些代码,当然要在下面的remainingTimeBudget(停留时间预算内)
  • //否则会出现闪频状态
  • 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;
  • }

验证完毕,然后再点击“上传”即可。

代码中获取数据的方法:点击这里

完整工程:weather_station1.7z(若有任何问题,欢迎评论留言)

五、结果

 

获取返回结果代码:200表示成功了

如果错误码,可以把地址粘贴到浏览器里看看是什么原因。

效果视频:点我拂尘

此帖出自stm32/stm8论坛
点赞 关注
 

回复
举报
您需要登录后才可以回帖 登录 | 注册

查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/10 下一条
有奖直播:当AI遇见仿真,会有什么样的电子行业革新之路?
首场直播:Simcenter AI 赋能电子行业研发创新
直播时间:04月15日14:00-14:50

查看 »

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

 
机器人开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网 5

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表