用ESP8266制作一個小時鐘,外加天氣情況
首先要準(zhǔn)備一個ESP8266 模塊,和一個OLED,我這里為了好看給他重新設(shè)計(jì)了一個板子,至少個頭會MINI很多,很可愛。代碼已經(jīng)放上來了直接燒錄進(jìn)去,接線就可以使用。
成品圖片
側(cè)顏
部分代碼
#include
#include "SSD1306Wire.h"
//2020.2.19
#include "images.h"
#include
#include
#include
#include
#include "NTP.h"
int json_state;//天氣返回編碼
int json_state2;//溫度返回值
String json_temp;
const char* AP_SSID ="TP-LINK_06"; // 你的WiFi賬號
const char* AP_PSK = "123456789"; // 你的WiFi密碼
const char *host = "ip-api.com"; //欲訪問的域名
// 北京時間時區(qū)
#define STD_TIMEZONE_OFFSET +8 // Standard Time offset (-7 is mountain time)
TimeChangeRule mySTD = {"", First, Sun, Jan, 0, STD_TIMEZONE_OFFSET * 60};
Timezone myTZ(mySTD, mySTD);
WiFiClient client; //創(chuàng)建一個網(wǎng)絡(luò)對象
String key = "SFYwl_WGlDEUncVhp"; //心知天氣的秘鑰,可以自己去注冊也可以用我的
String weizhi = "zhuhai"; //這里寫你的地址
//液晶部分
SSD1306Wire display(0x3c, 5, 4); //SDA SCL
typedef void (*Demo)(void);
/*====================================畫天氣圖標(biāo)函數(shù)===============================*/
void drawzhongyu() {
display.drawXbm(drawposition, 0, WiFi_Logo_width, WiFi_Logo_height, zhongyu);
}
void drawdayu() {
display.drawXbm(drawposition, 0, WiFi_Logo_width, WiFi_Logo_height, dayu);
}
void drawxiaoyu() {
display.drawXbm(drawposition, 0, WiFi_Logo_width, WiFi_Logo_height, xiaoyu);
}
void drawqingtian() {
display.drawXbm(drawposition, 0, WiFi_Logo_width, WiFi_Logo_height, qingtian);
}
void drawduoyun() {
display.drawXbm(drawposition, 0, WiFi_Logo_width, WiFi_Logo_height, duoyun);
}
void drawzhu() {
display.drawXbm(32, 0, 64, 64, WiFi_Logo_bits);
}
void drawseconds_iconclear() {
display.drawXbm(0, 40, 24, 24, icon_clear);
}
Demo demos[] = {drawqingtian, drawduoyun, drawxiaoyu, drawzhongyu, drawdayu, drawzhu, drawseconds_iconclear}; //6
/*========================畫圖部分結(jié)束,接下來是數(shù)據(jù)處理部分=====================*/
void wifi_start_connect() //連接WIFI
{
WiFi.mode(WIFI_STA); //設(shè)置esp8266 工作模式
Serial.println("Connecting to "); //寫幾句提示
Serial.println(AP_SSID);
WiFi.begin(AP_SSID, AP_PSK); //連接wifi
WiFi.setAutoConnect(true);
while (WiFi.status() != WL_CONNECTED) //這個函數(shù)是wifi連接狀態(tài),返回wifi鏈接狀態(tài)
{
delay(500);
Serial.print(".");
}
Serial.println("WiFi connected IP is");
Serial.println(WiFi.localIP());
}
void parseUserData(String content)
{
const size_t capacity = JSON_ARRAY_SIZE(1) + JSON_OBJECT_SIZE(1) + 2 * JSON_OBJECT_SIZE(3) + JSON_OBJECT_SIZE(6) + 210;
DynamicJsonBuffer jsonBuffer(capacity);
JsonObject& root = jsonBuffer.parseObject(content);
JsonObject& results_0 = root["results"][0];
JsonObject& results_0_now = results_0["now"];
//const char* results_0_now_text = results_0_now["text"]; // 天氣情況
int results_0_now_code = results_0_now["code"]; //天氣情況識別碼
const char* results_0_now_temperature = results_0_now["temperature"];//氣溫
display.setTextAlignment(TEXT_ALIGN_LEFT);
display.setFont(ArialMT_Plain_24);
json_temp = results_0_now_temperature;
json_state = results_0_now_code;
}
//調(diào)用api函數(shù)
void apicmd()
{
if (client.connect("api.seniverse.com", 80) == 1) //服務(wù)連接
{
client.print("GET /v3/weather/now.json?key=");
client.print(key);
client.print("&location=");
client.print(weizhi);
client.print("&language=zh-Hans&unit=c HTTP/1.1\r\n");
client.print("Host:api.seniverse.com\r\n");
client.print("Accept-Language:zh-cn\r\n");
client.print("Connection:close\r\n\r\n"); //向心知天氣的服務(wù)器發(fā)送請求。
if (client.find("\r\n\r\n") == 1) //跳過返回的json數(shù)據(jù)頭,
{
String json_from_server = client.readStringUntil('\n'); //讀取返回的JSON數(shù)據(jù)
Serial.println(json_from_server); //打印json數(shù)據(jù)
parseUserData(json_from_server); //調(diào)用josn解析函數(shù),并傳參
}
}
else
{
Serial.println("服務(wù)器連接失敗");
delay(5000);
}
client.stop(); //關(guān)閉HTTP
}
String Middle_minutes;
String Middle_hours;
//時間獲取函數(shù)
void updateDisplay(void) {
TimeChangeRule *tcr; // Pointer to the time change rule
// Read the current UTC time from the NTP provider
time_t utc = now();
// Convert to local time taking DST into consideration
time_t localTime = myTZ.toLocal(utc, &tcr);
// Map time to pixel positions
//int weekdays = weekday(localTime);
String days = (String) day(localTime);
String months = (String) month(localTime);
// String years = (String) year(localTime);
// String seconds = (String) second(localTime);
String minutes = (String) minute(localTime);
String hours = (String) hour(localTime);
/*串口輸出時間
Serial.println("");
Serial.print("Current local time:");
Serial.print(days);
Serial.print("/");
Serial.print(months);
Serial.print("/");
Serial.print(years);
Serial.print(" - ");
Serial.print(hours);
Serial.print(":");
Serial.print(minutes);
Serial.print(":");
Serial.print(seconds);
Serial.print(" - ");
Serial.print(dayStr(weekdays));
Serial.println("");
*/
if (Middle_minutes != minutes)
{
display.clear();
display.setTextAlignment(TEXT_ALIGN_LEFT);
display.setFont(ArialMT_Plain_24);
Serial.println("調(diào)用天氣");
apicmd();
display.drawString(75, 40, json_temp);
display.drawString(100, 40, "°C");
display.drawString(10, 5, hours);
display.drawString(38, 3, ":");
display.drawString(45, 5, minutes);
判斷返回輸出圖標(biāo)
if (json_state == 0)
{
demos[0]();
}
else if (json_state > 0 && json_state < 4)
{
demos[0]();
}
else if (json_state > 3 && json_state < 10)
{
demos[1]();
}
else if (json_state > 9 && json_state < 14)
{
demos[2]();
}
else if (json_state == 14)
{
demos[3]();
}
else if (json_state > 14 && json_state < 19)
{
demos[4]();
}
display.drawString(0, 40, months);
display.drawString(27, 40, "/");
display.drawString(33, 40, days);
Middle_minutes = minutes;
}
display.display();
}
void setup() {
Serial.begin(115200);
display.init();
display.flipScreenVertically();//反向顯示
display.clear();
demos[5]();
display.display();
initNTP(AP_SSID, AP_PSK);
client.setTimeout(5000);//設(shè)置服務(wù)器連接超時時間
}
time_t previousSecond = 0;
void loop() {
if (timeStatus() != timeNotSet) {
if (second() != previousSecond) {
previousSecond = second();
updateDisplay();
}
}
delay(1000);
}