【自制分享】开源mini esp8266 天气时钟
↑ 点击上方,关注“Tkwer望远镜”作者: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

扫码关注最新动态
提供源文件,公众号内回复即可获取:天气时间