【自制分享】开源mini esp8266 天气时钟

【自制分享】开源mini esp8266 天气时钟

Tkwer Tkwer望远镜 今天

【自制分享】开源mini esp8266 天气时钟

 

                                           作者:Tkwer

公众号:Tkwer望远镜

  前言

    这个是2019年开始做的吧,当时特别多人做这个。自己也在前人的基础上修改,让它变得更加小巧,适合挂在桌子上。

 

原理图

    

 

    CAT6219-----------3.3V稳压芯片500mA

    CH340E------------usb转串口芯片

    ESP-01s-----------esp8266模块

    oled12864--------中景园0.96寸oled

    烧录固件时要先按下SW1按键,然后通电。

  

PCB

 

  尺寸很小,27mm*21.3mm。为了减少焊接困难采用的是0603的阻容元件。

 

 

Code

 

所需头文件,(json相关的库好像是要安装v5版本的)

#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <Ticker.h>
#include <JsonListener.h>
#include <ArduinoOTA.h>
#include <ESP8266mDNS.h>
#include <DNSServer.h>
#include <ESP8266WebServer.h>
#include <Wire.h>
#include <ArduinoJson.h>
#include "SSD1306Wire.h"
#include <OLEDDisplayUi.h>
#include <JsonListener.h>
#include <JsonStreamingParser.h>
#include <WiFiClient.h>
#include <WiFiManager.h>
#include "icons.h"
#include "fonts.h"

 

简单配置一下wifi和通过心知天气获取天气信息,需要用户自己到心知天气官网注册账号获得APIKEY。代码中用到wifimanager这个库,其实也可以一开始通过手机配网的。

/***************************
 * Begin Settings
 **************************/
// WIFI
const char* WIFI_SSID   = "yourssid";
const char* WIFI_PWD    = "yourpassw0rd";
#define HOSTNAME          "ESP8266-OTA-"

//Server
const char* host = "api.seniverse.com";
const char* APIKEY = "**************";        //API KEY
const char* city = "chengdu";//所在城市拼音
const char* language = "en";                    //zh-Hans 简体中文  会显示乱码

const unsigned long BAUD_RATE = 115200;                   // serial connection speed
const unsigned long HTTP_TIMEOUT = 5000;                  // max respone time from server
const size_t MAX_CONTENT_SIZE = 3000;                   // max size of the HTTP response
WiFiClient client;

 

接受天气数据

/**
s* @发送请求指令
*/
bool sendRequest(const char* host, const char* cityid, const char* apiKey) {
  // We now create a URI for the request
  //心知天气
  String GetUrl = "https://api.seniverse.com/v3/weather/now.json?key=";
  GetUrl += apiKey;
  GetUrl += "&location=";
  GetUrl += city;
  GetUrl += "&language=";
  GetUrl += language;
  // This will send the request to the server
  client.print(String("GET ") + GetUrl + " HTTP/1.1\r\n" +
               "Host: " + host + "\r\n" +
               "Connection: close\r\n\r\n");
  Serial.println("create a request:");
  Serial.println(String("GET ") + GetUrl + " HTTP/1.1\r\n" +
               "Host: " + host + "\r\n" +
               "Connection: close\r\n");
  Serial.println();
  Serial.println();
  delay(1000);
  return true;
}

/**
* @Desc 跳过 HTTP 头,使我们在响应正文的开头
*/
bool skipResponseHeaders() {
  // HTTP headers end with an empty line
  bool ok = client.find(endOfHeaders);
  if (!ok) {
    Serial.println("No response or invalid response!");
  }
  return ok;
}

/**
* @Desc 从HTTP服务器响应中读取正文
*/
void readReponseContent(char* content, size_t maxSize) {
  size_t length = client.readBytes(content, maxSize);
  delay(100);
  Serial.println("Get the data from Internet!");
  content[length] = 0;
  Serial.println(content);
  Serial.println("Read data Over!");
  client.flush();//这句代码需要加上  不然会发现每隔一次client.find会失败
}

 

显示oled画面,需要安装这个库<OLEDDisplayUi.h>

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(10, 28, 108, 12, percentage);
  display->display();
}

void drawDate(OLEDDisplay *display, int x, int y, int timeZoneIndex) {
  display->setTextAlignment(TEXT_ALIGN_LEFT);
  display->setFont(ArialMT_Plain_16);
  display->drawString(x + 10, y + 10, userData.year);
  display->setFont(ArialMT_Plain_10);
  display->drawString(x + 110, y + 5, userData.weekday);
  if(daysflag == 1){display->drawString(x + 115, y + 20, "+1");}
  display->setFont(Crushed_Plain_20);
  display->drawString(x + 50, y + 15, userData.month);
  display->drawString(x + 90, y + 24, "/");
  display->drawString(x + 100, y + 30, userData.date);
}
void drawTime(OLEDDisplay *display, int x, int y, int timeZoneIndex, String city, const uint8_t* icon) {
  display->setTextAlignment(TEXT_ALIGN_LEFT);
  display->setFont(ArialMT_Plain_10);
  display->drawString(x + 60, y + 5, city);
  display->setFont(Crushed_Plain_36);
  display->drawXbm(x, y, 60, 60, icon);

  long minute_c = atoi(userData.minute)+ (millis()-starttime) / 1000 % 3600 / 60;
  char minute_buffer[4] = ""; 
  if(minute_c/60==1){hoursflag = 1;}else{hoursflag = 0;}
  minute_c = minute_c%60;
  if (minute_c < 10) {
    sprintf(minute_buffer,"%02d",minute_c);
  }
  else{
  itoa(minute_c,minute_buffer,10);
  }
  display->drawString(x + 95, y + 15, minute_buffer);

  uint8_t hour_c = 0;
  if(hoursflag==1){hour_c = atoi(userData.hour)+9;}else{hour_c = atoi(userData.hour)+8;}
  char hour_buffer[4] = ""; 
  if(hour_c/24==1){daysflag = 1;}else{daysflag = 0;}
  hour_c = hour_c%24;
  if(hour_c < 10){
    sprintf(hour_buffer,"%02d",hour_c);
  }
  else{
  itoa(hour_c,hour_buffer,10);
  }
  display->drawString(x + 60, y + 15, hour_buffer);
  display->drawString(x + 90, y + 15, ":");
}
void drawWeather(OLEDDisplay *display, int x, int y, int timeZoneIndex, String city, const uint8_t* icon) {
  display->setTextAlignment(TEXT_ALIGN_LEFT);
  display->setFont(ArialMT_Plain_10);
  display->drawString(x + 100, y + 5, userData.temp);
  display->drawString(x + 112, y + 5, "C");
  display->setFont(Crushed_Plain_20);
  display->drawXbm(x+7, y+7, 50, 50, getIconFromString(userData.weather));
  display->drawString(x + 65, y + 20, userData.weather);
}

void drawFrame1(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) {
  drawDate(display, x, y, 0);
}

void drawFrame2(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) {
  drawTime(display, x, y, 1, userData.city,  chengdu_bits);
}

void drawFrame3(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) {
  drawWeather(display, x, y, 2, "Paris",  paris_bits);
}

void drawFrame4(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) {
  drawTime(display, x, y, 1, userData.city,  chengdu_bits);
}

 

在icons.h中可添加自己城市的图标文件。以成都为例子

#define chengdu_width 60
#define chengdu_height 60
const uint8_t chengdu_bits[] PROGMEM = {
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  0x00,0x00,0x00,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0x07,0x00,
  0x00,0x00,0x00,0x00,0xf8,0xf1,0x3c,0x00,0x00,0x00,0x00,0x00,0xfe,0x00,
  0xf0,0x00,0x00,0x00,0x00,0x00,0xff,0x82,0xa7,0x03,0x00,0x00,0x00,0xc0,
  0x0f,0xf0,0x1f,0x07,0x00,0x00,0x00,0xe0,0xe3,0xf8,0x3f,0x0f,0x00,0x00,
  0x00,0xf0,0xf9,0xff,0x7f,0x1e,0x00,0x00,0x00,0xf8,0xf9,0xff,0xff,0x3f,
  0x00,0x00,0x00,0xf8,0x7c,0x3c,0xfb,0x7f,0x00,0x00,0x00,0xdc,0x1e,0x60,
  0xf6,0x79,0x00,0x00,0x00,0xc6,0xff,0xc3,0xec,0xf1,0x00,0x00,0x00,0xe6,
  0x0f,0x00,0xc8,0xe7,0x00,0x00,0x00,0xf7,0x03,0x00,0xc8,0xef,0x01,0x00,
  0x00,0xfb,0x19,0x00,0x90,0xee,0x01,0x00,0x80,0xfd,0x0e,0x00,0x80,0xde,
  0x01,0x00,0x80,0xfd,0x03,0x00,0x80,0xde,0x03,0x00,0x80,0xfd,0x01,0x00,
  0x80,0x9c,0x03,0x00,0x80,0xfd,0x00,0x00,0x80,0x1e,0x03,0x00,0x80,0x79,
  0x00,0x00,0x00,0x1e,0x02,0x00,0xc0,0x79,0x02,0x00,0x00,0xce,0x06,0x00,
  0xc0,0x38,0x01,0x00,0x00,0x1a,0x07,0x00,0xc0,0x38,0x01,0x00,0x00,0x39,
  0x06,0x00,0xc0,0xb0,0x01,0x00,0x00,0x3c,0x03,0x00,0xc0,0xb4,0x00,0x00,
  0x00,0x3c,0x03,0x00,0x80,0xb1,0x00,0x00,0x00,0x3e,0x03,0x00,0x80,0xf3,
  0x04,0x00,0x00,0x7b,0x03,0x00,0x80,0xf7,0x04,0x00,0xc0,0x7d,0x03,0x00,
  0x80,0xf7,0x04,0x00,0x60,0x7c,0x03,0x00,0x00,0xf7,0x04,0x00,0x00,0xbf,
  0x01,0x00,0x00,0xf7,0x05,0x00,0x80,0xbf,0x01,0x00,0x00,0xef,0x4d,0x00,
  0xe0,0xdf,0x01,0x00,0x00,0xce,0xcf,0x00,0xb0,0xdf,0x00,0x00,0x00,0x1e,
  0x9f,0x11,0xe0,0xc7,0x00,0x00,0x00,0x3c,0x3f,0xe3,0xff,0x77,0x00,0x00,
  0x00,0xfc,0x7f,0x86,0x7f,0x3e,0x00,0x00,0x00,0xf8,0xff,0x3c,0x3e,0x3e,
  0x00,0x00,0x00,0xf0,0xfc,0xff,0x3f,0x1f,0x00,0x00,0x00,0xe0,0xfc,0x1f,
  0x8f,0x0f,0x00,0x00,0x00,0xc0,0xf0,0x0f,0xe0,0x07,0x00,0x00,0x00,0x00,
  0xe7,0x41,0xff,0x01,0x00,0x00,0x00,0x00,0x1e,0x40,0xff,0x00,0x00,0x00,
  0x00,0x00,0xf8,0xa7,0x3f,0x00,0x00,0x00,0x00,0x00,0xc0,0xff,0x07,0x00,
  0x00,0x00,0x00,0x00,0x00,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  0x00,0x00};

下面给出一些其他城市图标的选择:

可以通过图片取模软件将其转换为数组。(之前用的在线取模网站失效了)

可在http://oleddisplay.squix.ch/#/home 这个网站进行生成各种字体,仅支持英文字符。

代码方面还不是很完善。文后分享PCB和源码,大家喜欢可以自行diy。

END

 

公众号ID:Tkwer望远镜

 

扫码关注最新动态

 

提供源文件,公众号内回复即可获取:天气时间

  • 6
    点赞
  • 43
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值