ESP32驱动OLED和天气显示

有时间就接着更新

1.SPI四线驱动OLED

我使用的是U8g2库。

1.1其中一种方法:

#include <Arduino.h>
#include <SPI.h>
#include <U8g2lib.h>

//cs脚只要接地就好,不需要定义
U8G2_SSD1306_128X64_NONAME_1_4W_SW_SPI u8g2(U8G2_R0, /* clock=*/ 36, /* data=*/ 35, /* cs=*/ -1, /* dc=*/ 33, /* reset=*/ 34);

void setup(void) {
    
    
  u8g2.begin();   //选择U8G2模式,或者U8X8模式
}

void loop(void) {
    
    
  u8g2.firstPage();
  do {
    
    
    u8g2.setFont(u8g2_font_ncenB14_tr);
    u8g2.drawStr(0,15,"Hello World!");
  } while ( u8g2.nextPage() );
  delay(1000);
}

1.2也可以用另外的方式

#include <Arduino.h>
#include <SPI.h>
#include <U8g2lib.h>

//cs脚只要接地就好,不需要定义
U8G2_SSD1306_128X64_NONAME_F_4W_SW_SPI u8g2(U8G2_R0, /* clock=*/ 36, /* data=*/ 35, /* cs=*/ -1, /* dc=*/ 33, /* reset=*/ 34);

void setup(void) {
    
    
  u8g2.begin();   //选择U8G2模式,或者U8X8模式
  //下面这个放在loop里面也是可以的
  u8g2.clearBuffer();          // clear the internal memory
  u8g2.setFont(u8g2_font_wqy12_t_gb2312); // choose a suitable font
  u8g2.drawStr(0,8,"Hello World!");  // write something to the internal memory
  u8g2.sendBuffer();          // transfer internal memory to the display
}

void loop(void) {
    
    
  delay(1000);
}

1.3显示多个中文

#include <Arduino.h>
#include <SPI.h>
#include <U8g2lib.h>

//cs脚只要接地就好,不需要定义
U8G2_SSD1306_128X64_NONAME_F_4W_SW_SPI u8g2(U8G2_R0, /* clock=*/ 36, /* data=*/ 35, /* cs=*/ -1, /* dc=*/ 33, /* reset=*/ 34);

//下面是显示多个中文的写法
void setup()
{
    
    
  u8g2.begin();
  u8g2.enableUTF8Print();    // enable UTF8 support for the Arduino print() function
  Serial.begin(115200);
  delay(1500);
}
void loop()
{
    
    
  u8g2.setFont(u8g2_font_wqy12_t_gb2312);     // 像素为8
  u8g2.setFontDirection(0);                   // 设置字体方向
  u8g2.clearBuffer();                         // 清除buffer,清除上一次显示的画面
  Serial.println("oled begin");
  u8g2.setCursor(16, 16);
  u8g2.print("时间:");
  Serial.println("oled end");
  u8g2.sendBuffer();                          // 发送buffer,显示在屏幕上
}

1.4查找字体的官方网站连接:

里面可以直接看到字体的样子,要是看不了的话,就得墙后才可以。
https://github.com/olikraus/u8g2/wiki/fntlistall

https://github.com/olikraus/u8g2/wiki/fntlistall

1.5比较全面的U2g8教程链接:

https://blog.csdn.net/dpjcn1990/article/details/92831760

https://blog.csdn.net/dpjcn1990/article/details/92831760

1.6关于Fontstruct

其实就是可以下载和设计字体

https://vidabytes.com/zh-CN/fontstruct-%E5%88%9B%E5%BB%BA%E4%B8%8B%E8%BD%BD%E5%92%8C%E5%85%B1%E4%BA%AB/

2.ESP32连接网络

#include <Arduino.h>
#include "WiFi.h"
void setup()
{
    
    
  Serial.begin(115200);
  WiFi.mode(WIFI_STA);
  WiFi.begin("AA", "12345678");//WiFi名称和密码
  while (!WiFi.isConnected())
  {
    
    
    delay(500);
    Serial.print(".");
  }
  Serial.println("WIFI连接成功!");
}
void loop()
{
    
    

}

3.ESP32获取气象信息

3.1通过心知天气获取天气数据

3.1.1通过手动输入城市获取天气数据

优质博主写的文章

https://blog.csdn.net/weixin_42487906/article/details/119990731?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522164420210316780366550793%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=164420210316780366550793&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduend~default-1-119990731.first_rank_v2_pc_rank_v29&utm_term=arduino+ESP32%E8%8E%B7%E5%8F%96%E5%A4%A9%E6%B0%94&spm=1018.2226.3001.4187

获取密钥的方法

https://www.seniverse.com/products?iid=1c147258-2934-4f2a-b424-13ee70f6bfa1

其中的API可以有不同的连接方式

https://docs.seniverse.com/api/fct/search.html

修改后的代码(代码来源)
代码中需要修改的地方:

  • 网络名称和密码
  • 心知天气的密钥
  • 城市名称
#include <Arduino.h>
#include <ArduinoJson.h>
#include <WiFi.h>

//使用的时候需要将这里的 网络名称 和 密码 进行更改
const char *ssid = "AA";
const char *password = "12345678";

const char *host = "api.seniverse.com";
const char *privateKey = "****";		//	这里需要你自己去获取密钥,方法上面说过了
const char *city = "guangzhou";		//这里改为你想要查询的城市名称
const char *language = "en";

struct WetherData
{
    
    
   char city[32];
   char weather[64];
   char high[32];
   char low[32];
   char humi[32];
};

void setup()
{
    
    
  
   Serial.begin(115200);

   Serial.print("Connecting to ");
   Serial.println(ssid);

//开始连接网络
   WiFi.begin(ssid, password);

   while (WiFi.status() != WL_CONNECTED)
   {
    
    
       delay(500);
       Serial.print(".");
   }

   Serial.println("");
   Serial.println("WiFi connected");
   Serial.println("IP address: ");
   Serial.println(WiFi.localIP());

   Serial.println("");
   Serial.println("WiFi Conected!");

//开始连接API
   WiFiClient client;

   if (!client.connect(host, 80))
   {
    
    
       Serial.println("Connect host failed!");
       return;
   }
   Serial.println("host Conected!");

   String getUrl = "/v3/weather/daily.json?key=";
   getUrl += privateKey;
   getUrl += "&location=";
   getUrl += city;
   getUrl += "&language=";
   getUrl += language;
   client.print(String("GET ") + getUrl + " HTTP/1.1\r\n" + "Host: " + host + "\r\n" + "Connection: close\r\n\r\n");
   Serial.println("Get send");

   char endOfHeaders[] = "\r\n\r\n";
   bool ok = client.find(endOfHeaders);
   if (!ok)
   {
    
    
       Serial.println("No response or invalid response!");
   }
   Serial.println("Skip headers");

   String line="";

   line += client.readStringUntil('\n'); 

   Serial.println(line);

//下面开始解析得到的json格式的数据

   DynamicJsonDocument doc(1400);

   DeserializationError error = deserializeJson(doc, line);
   if (error)
   {
    
    
       Serial.println("deserialize json failed");
       return;
   }
   Serial.println("deserialize json success");

   struct WetherData weatherdata = {
    
    0};

   strcpy(weatherdata.city, doc["results"][0]["location"]["name"].as<const char*>());
   strcpy(weatherdata.weather, doc["results"][0]["daily"][0]["text_day"].as<const char*>());
   strcpy(weatherdata.high, doc["results"][0]["daily"][0]["high"].as<const char*>());
   strcpy(weatherdata.low, doc["results"][0]["daily"][0]["low"].as<const char*>());
   strcpy(weatherdata.humi, doc["results"][0]["daily"][0]["humidity"].as<const char*>());

   Serial.println("City");
   Serial.println(weatherdata.city);
   Serial.println("textDay");
   Serial.println(weatherdata.weather);
   Serial.println("temp high");
   Serial.println(weatherdata.high);
   Serial.println("temp low");
   Serial.println(weatherdata.low);
   Serial.println("humi");
   Serial.println(weatherdata.humi);

   Serial.println("read json success");
   Serial.println();
   Serial.println("closing connection");
   client.stop();
}

void loop()
{
    
    
   // put your main code here, to run repeatedly:
}

3.1.2通过所连接网络信息直接获取天气数据

方法:先获取当前所连接网络的IP地址,再去获取天气数据。
代码如下:
代码中需要修改的地方:

  • 网络名称和密码
  • 心知天气的密钥
#include <Arduino.h>
#include "WiFi.h"
#include "HTTPClient.h"
#include "ArduinoJson.h"

String ip_req;
String ip_rsp;
String now_weather_req;
String now_weather_rsp;

const char *ip;                                     //所连接的网络的IP地址
const char *city;                                   //所在的城市
const char *weather;                                //现在的天气
const char *temperature;                            //现在的温度
const char *ssid = "whatk";                         //wifi名
const char *password = "0123456789";                //wifi密码
const char *host = "https://api.seniverse.com";     //心知天气APIhost
const char *apiKey = "*****************";           //API key 私钥

WiFiClient wifi_Client;
HTTPClient http_weather_client;
HTTPClient http_ip_client;

DynamicJsonDocument ip_doc(512);
DynamicJsonDocument now_weather_doc(512);


//Wifi初始化
void Wifi_connect()
{
    
    
 delay(10);
 Serial.println("Connecting WIFI");
 //设置ESP32工作模式为无线终端模式
 WiFi.mode(WIFI_STA);
 WiFi.begin(ssid, password);
 while (WiFi.status() != WL_CONNECTED)
 {
    
    
   delay(500);
   Serial.print(".");
 }
 Serial.println("WiFi connected!");
}

void Http_get_ip()
{
    
    
 short int http_code;
 ip_req = "https://api.live.bilibili.com/client/v1/Ip/getInfoNew";
 Serial.println(ip_req);
 while (1)
 {
    
    
   if (http_ip_client.begin(ip_req))
   {
    
    
     Serial.println("Http_get_ip setUp done!");
   }  
 
   http_code = http_ip_client.GET();
   Serial.println(http_code);
   if (http_code > 0)
   {
    
    
     Serial.printf("HTTP get code: %d\n", http_code);
     if (http_code == HTTP_CODE_OK)
     {
    
    
       ip_rsp = http_ip_client.getString();
       Serial.println(ip_rsp);
       break;
     }
     else
     {
    
    
       Serial.printf("fail to get ip,code:%d\n", http_code);
     }
   }    
 }
}

void Ip_json()
{
    
    
 //解析JSON字符串
 Serial.println("从jsonStr解码成的DynamicJsonDocument对象doc:");
 deserializeJson(ip_doc, ip_rsp);
 serializeJson(ip_doc, Serial);
 Serial.println();
 
 JsonObject data1 = ip_doc["data"];
 Serial.print("data:");
 serializeJson(data1, Serial);
 Serial.println();

 ip = data1["addr"];
 Serial.print("ip:");
 Serial.println(ip);

 city = data1["city"];
 Serial.print("city:");
 Serial.println(city);
 
}
void Http_get_now_weather()
{
    
    
 short int http_code;
//实例:https://api.seniverse.com/v3/weather/now.json?key=SDsx89dbgoOO4RVat&location=beijing&language=zh-Hans&unit=c
 now_weather_req = (String)host + "/v3/weather/now.json?key=";
 now_weather_req += apiKey;
 now_weather_req += "&location=";
 now_weather_req += ip;
 now_weather_req += "&language=zh-Hans&unit=c";
 Serial.println(now_weather_req);

 while(1)
 {
    
    
   if (http_weather_client.begin(now_weather_req))
   {
    
    
     Serial.println("Http_get_now_weather setUp done!");
   }
   
   http_code = http_weather_client.GET();
   Serial.println(http_code);
   if (http_code > 0)
   {
    
    
     Serial.printf("HTTP get code: %d\n", http_code);
     if (http_code == HTTP_CODE_OK)
     {
    
    
       now_weather_rsp = http_weather_client.getString();
       Serial.println(now_weather_rsp);
       break;
     }
     else
     {
    
    
       Serial.printf("fail to get cityWeather,code:%d\n", http_code);
     }
   }  
 } 
}

void Weather_now_json()
{
    
    
 //解析JSON字符串
 Serial.println("从now_weather_rsp解码成的DynamicJsonDocument对象doc:");
 deserializeJson(now_weather_doc, now_weather_rsp);
 serializeJson(now_weather_doc, Serial);
 Serial.println();
 
 Serial.println("root里有一个子JsonArray对象 results:");
 JsonArray results = now_weather_doc["results"];
 serializeJson(results, Serial);
 Serial.println();
 
 //JsonArray类型的数组results里面只有一个元素: JsonObject对象results[0],
 //该元素有三个子对象 location, now, last_update
 //now
 Serial.println("JsonObject对象 results[0]中的子JsonObject对象now(为了避免和timer中的now重名,把它叫做now1):");
 JsonObject now1 = results[0]["now"];
 serializeJson(now1, Serial);
 Serial.println("从JsonObject对象now1中取出weather");
 weather = now1["text"];
 Serial.println(weather);
 Serial.println("从JsonObject对象now1中取出temperature");
 temperature = now1["temperature"];
 Serial.println(temperature);
 Serial.println();
 
}
void setup()
{
    
    
 Serial.begin(115200);
 delay(1000);
 Wifi_connect();
 Http_get_ip();
 Ip_json();
 Http_get_now_weather();
 Weather_now_json();

}
void loop()
{
    
    

 delay(1000);
}

3.2通过getString方法获取网络时间和气象数据

别人写的文章:

https://blog.csdn.net/weixin_42880082/article/details/120944183?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522164420550316780274197155%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=164420550316780274197155&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_ecpm_v1~rank_v31_ecpm-1-120944183.first_rank_v2_pc_rank_v29&utm_term=%2F**+%E9%80%9A%E8%BF%87getString%E6%96%B9%E6%B3%95%E8%8E%B7%E5%8F%96%E7%BD%91%E7%BB%9C%E6%97%B6%E9%97%B4%E5%92%8C%E6%B0%94%E8%B1%A1%E6%95%B0%E6%8D%AE++*%2F&spm=1018.2226.3001.4187

4.ESP32获取实时时间

4.1最简单直接获取网络时间方法

优质博主写的文章:

https://blog.csdn.net/weixin_42880082/article/details/120947163?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522164420413416780264094419%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=164420413416780264094419&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_ecpm_v1~rank_v31_ecpm-2-120947163.first_rank_v2_pc_rank_v29&utm_term=arduino+esp32+%E8%8E%B7%E5%8F%96%E5%BD%93%E5%89%8D%E6%97%B6%E9%97%B4&spm=1018.2226.3001.4187

修改后的代码:
代码中需要修改的地方:

  • 网络名称和密码
#include <WiFi.h>

#define NTP1  "ntp1.aliyun.com"
#define NTP2  "ntp2.aliyun.com"
#define NTP3  "ntp3.aliyun.com"

//填写WIFI入网信息
const char* ssid     = "AA";    	 // WIFI账户
const char* password = "AA471819";	 // WIFI密码

void setClock() 
{
    
    
  struct tm timeinfo;
  if (!getLocalTime(&timeinfo))
  {
    
    
  	//如果获取失败,就开启联网模式,获取时间
    Serial.println("Failed to obtain time");
    WiFi.disconnect(false);
    WiFi.mode(WIFI_STA);		//开启网络  
    WiFi.begin(ssid, password);
    while (WiFi.status() != WL_CONNECTED)
    {
    
    
      delay(500);
      Serial.print(".");
    }
    configTime(8 * 3600, 0, NTP1, NTP2,NTP3);
    return;
  }
  Serial.println(&timeinfo, "%F %T %A"); // 格式化输出:2021-10-24 23:00:44 Sunday
  Serial.print(asctime(&timeinfo));//默认打印格式:Mon Oct 25 11:13:29 2021
  WiFi.disconnect(true);
}

void setup()
{
    
    
  Serial.begin(115200);
  Serial.println();
  //设置ESP32工作模式为无线终端模式
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED)
  {
    
    
    delay(500);
    Serial.print(".");
  }
  Serial.println("WiFi connected!");
  configTime(8 * 3600, 0, NTP1, NTP2,NTP3);
  setClock();
  // 从网络时间服务器上获取并设置时间
  // 获取成功后芯片会使用RTC时钟保持时间的更新
  
  WiFi.disconnect(true);
  WiFi.mode(WIFI_OFF);//关闭网络
  Serial.println("WiFi disconnected!");
}

void loop()
{
    
    
  Serial.println("Waiting 10s before the next round...");
  delay(10000);
  setClock();
}

4.2忘了哪里找来的

#include <Arduino.h>
#include <WiFi.h>
#include <SPI.h>
#include <U8g2lib.h>

//cs脚只要接地就好,不需要定义
U8G2_SSD1306_128X64_NONAME_1_4W_SW_SPI u8g2(U8G2_R0, /* clock=*/ 36, /* data=*/ 35, /* cs=*/ -1, /* dc=*/ 33, /* reset=*/ 34);

#define NTP1 "ntp1.aliyun.com"
#define NTP2 "ntp2.aliyun.com"
#define NTP3 "ntp3.aliyun.com"
//填写WIFI入网信息
const char *ssid = "AA";                                                                                // WIFI账户
const char *password = "12345678";                                                                                 // WIFI密码
const String WDAY_NAMES[] = {
    
    "星期天", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"};                //星期
const String MONTH_NAMES[] = {
    
    "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; //月份

//time_t now; //实例化时间
void setClock()
{
    
    

  struct tm timeInfo; //声明一个结构体
  if (!getLocalTime(&timeInfo))
  {
    
     //一定要加这个条件判断,否则内存溢出
    Serial.println("Failed to obtain time");
    return;
  }
  //Serial.print(asctime(&timeInfo)); //默认打印格式:Mon Oct 25 11:13:29 2021
  String date = WDAY_NAMES[timeInfo.tm_wday];
  Serial.println(date.c_str());
  // sprintf_P(buff1, PSTR("%04d-%02d-%02d %s"), timeInfo.tm_year + 1900, timeInfo.tm_mon + 1, timeInfo.tm_mday, WDAY_NAMES[timeInfo.tm_wday].c_str());
  String shuju = String(timeInfo.tm_year + 1900); //年
  shuju += "-";
  shuju += timeInfo.tm_mon + 1; //月
  shuju += "-";
  shuju += timeInfo.tm_mday; //日
  shuju += " ";
  shuju += timeInfo.tm_hour; //时
  shuju += ":";
  shuju += timeInfo.tm_min;
  shuju += ":";
  shuju += timeInfo.tm_sec;
  shuju += " ";
  shuju += WDAY_NAMES[timeInfo.tm_wday].c_str(); //星期
  
  u8g2.firstPage();
  do {
    
    
    u8g2.setFont(u8g2_font_ncenB14_tr);
    u8g2.drawStr(0,15,timeInfo.tm_mon);
  } while ( u8g2.nextPage() );  
  
  Serial.println(shuju.c_str());
}

void setup()
{
    
    
  u8g2.begin();   //选择U8G2模式,或者U8X8模式

  Serial.begin(115200);
  Serial.println();
  //设置ESP32工作模式为无线终端模式
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED)
  {
    
    
    delay(500);
    Serial.print(".");
  }
  Serial.println("WiFi connected!");
  configTime(8 * 3600, 0, NTP1, NTP2, NTP3);
}

void loop()
{
    
    
  Serial.println("Waiting 10s before the next round...");
  delay(10000);
  setClock();
  // printLocalTime();
}

5.将日期转化为星期几

可以使用蔡勒公式

6.API总结

6.1获取时间

苏宁的

http://quan.suning.com/getSysTime.do

不知道哪来的:

http://api.k780.com:88/?app=life.time&appkey=10003&sign=b59bc3ef6191eb9f747dd4e83c99f2a4&format=json

https://api.m.jd.com/client.actionfunctionId=queryMaterialProducts&client=wh5

https://api.m.jd.com/client.action?functionId=queryMaterialProducts&client=wh5

5.2获取IP地址

bilibili的:

https://api.live.bilibili.com/client/v1/Ip/getInfoNew

6.Json

教程:

https://blog.csdn.net/dpjcn1990/article/details/92831648?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522164464920516781683942710%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=164464920516781683942710&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_ecpm_v1~rank_v31_ecpm-1-92831648.pc_search_result_cache&utm_term=ArduinoJson&spm=1018.2226.3001.4187

猜你喜欢

转载自blog.csdn.net/weixin_52296952/article/details/122805516