1.模块简介
本平台使用了乐鑫公司的ESP32-S2-Mini-1模块。它采用PCB板载天线,模组配置了4MB SPI flash,采用的是 ESP32-S2FN4 芯片。该芯片搭载了Xtensa® 32 位LX7 单核处理器,工作频率高达 240 MHz,同时,它还集成了丰富的外设接口。可用于多种场景。
模块构成:
该模块可以广泛应用于下面的一些领域:
- 通用低功耗 IoT 传感器 Hub
- 通用低功耗 IoT 数据记录器
- USB 设备
- 语音识别
- 图像识别
- Mesh 网络
- 家庭自动化
- 智慧楼宇
- 工业自动化
- 健康/医疗/看护
- Wi-Fi 玩具
- 可穿戴电子产品
- 零售 & 餐饮
- 智能 POS 应用
该模块的性能:
- Core: Xtensa® single-core 32-bit LX7 CPU, frequency up to 240MHz
- Memories:
- 128 KB of ROM
- 320 KB of SRAM
- 16 KB of RTCSRAM
- 4 MB of Flash memory
- Working Voltage: 3 V to 3.6 V
- Up to 37 GPIOs
- 2*12-bit ADC (up to 20 channels)
- Communication interfaces
- 2 I2C interfaces
- 1 I2S interface
- 4 SPI interfaces
- 2 UART interfaces
- 1 USB OTG interface
- Security:
- 4096 bit OTP
- AES, SHA, RSA, ECC, RNG
- Secure Boot, Flash Encryption, Digital signature, HMAC module
- Extended temperature range: -40 to 85 °C
关于该模块更详细的信息,参见ESP32-S2-Mini-1的选型页面
2.项目要求实现
(1).项目要求
利用OLED显示显示当前本地的时间、温度和气象信息。
#include <WiFi.h>
//============WiFi名称和密码================//
const char* ssid = "";
const char* password = "";
display.printf("connecting to %s\n",ssid);//在OLED上打印信息
display.display();
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) //等待连接
{
delay(500);
display.print(".");
display.display();
}
display.println();
display.println("WiFi connected");
display.print("IP: ");
display.println(WiFi.localIP());
display.print("Please wait...");
display.display();
#include <Adafruit_SSD1306.h>
//===============OLED引脚===================//
#define SCREEN_WIDTH 128 // OLED显示宽度,以像素为单位
#define SCREEN_HEIGHT 64 // OLED显示高度,以像素为单位
#define OLED_MOSI 35
#define OLED_CLK 36
#define OLED_DC 33
#define OLED_CS 37
#define OLED_RESET 34
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT,OLED_MOSI, OLED_CLK, OLED_DC, OLED_RESET, OLED_CS);
//检测OLED
if(!display.begin(SSD1306_SWITCHCAPVCC)) {
Serial.println(F("SSD1306 allocation failed"));//SSD1306分配失败
for(;;); // 不要继续,永远循环
}
void GET_Weather()
{
if((millis() - getTime > 5000))//10s
{
getTime = millis();
//Serial.print("connecting to ");
if (!client.connect(host,port))
{
Serial.println("服务器连接失败");
return;
}
//Serial.print("Requesting URL: ");
// 发送请求报文
client.print(String("GET ") + url + " HTTP/1.1\r\n" + //请求行 请求方法 + 请求地址 + 协议版本
"Host: " + host + "\r\n" + //请求头部
"Connection: close\r\n" + //处理完成后断开连接
"\r\n" + //空行
urlDat); //请求数据
delay(100);
while(client.available()) //接收数据
{
String line = client.readStringUntil('\r');
inputString += line;
}
// Serial.println(inputString);
client.stop(); //断开与服务器连接以节约资源
DatFlag = true;
// Serial.println(inputString);
}
}
用ArduinoJson库函数可以将上一步获得的信息提取出来,这一部分比较复杂。但是ArduinoJson库有一个官方支持的网站可以直接得到代码:
https://arduinojson.org/v5/assistant/
但可能根据实际需要更改。
void processMessage()
{
const size_t capacity = JSON_ARRAY_SIZE(1) + JSON_ARRAY_SIZE(3) + JSON_OBJECT_SIZE(1) + JSON_OBJECT_SIZE(3) + JSON_OBJECT_SIZE(6) + 3*JSON_OBJECT_SIZE(13) + 760;
DynamicJsonDocument doc(capacity);
deserializeJson(doc, inputString);
JsonObject results_0 = doc["results"][0];
JsonObject results_0_location = results_0["location"];
const char* results_0_location_name = results_0_location["name"]; // "城市"
JsonArray results_0_daily = results_0["daily"];
JsonObject results_0_daily_0 = results_0_daily[0];
const char* results_0_daily_0_date = results_0_daily_0["date"]; //今天日期
const char* results_0_daily_0_text_day = results_0_daily_0["text_day"]; //白天天气
const char* results_0_daily_0_code_day = results_0_daily_0["code_day"]; //图标编号
const char* results_0_daily_0_text_night = results_0_daily_0["text_night"]; //晚上天气
const char* results_0_daily_0_code_night = results_0_daily_0["code_night"]; //图标编号
const char* results_0_daily_0_high = results_0_daily_0["high"]; //最高气温
const char* results_0_daily_0_low = results_0_daily_0["low"]; //最低气温
const char* results_0_daily_0_wind_direction = results_0_daily_0["wind_direction"]; //风向
const char* results_0_daily_0_wind_direction_degree = results_0_daily_0["wind_direction_degree"]; //度数
const char* results_0_daily_0_wind_speed = results_0_daily_0["wind_speed"]; //速度
const char* results_0_daily_0_wind_scale = results_0_daily_0["wind_scale"]; // 风标
const char* results_0_daily_0_humidity = results_0_daily_0["humidity"]; //湿度
JsonObject results_0_daily_1 = results_0_daily[1];
const char* results_0_daily_1_date = results_0_daily_1["date"];
const char* results_0_daily_1_text_day = results_0_daily_1["text_day"];
const char* results_0_daily_1_code_day = results_0_daily_1["code_day"];
const char* results_0_daily_1_text_night = results_0_daily_1["text_night"];
const char* results_0_daily_1_code_night = results_0_daily_1["code_night"];
const char* results_0_daily_1_high = results_0_daily_1["high"];
const char* results_0_daily_1_low = results_0_daily_1["low"];
const char* results_0_daily_1_precip = results_0_daily_1["precip"];
const char* results_0_daily_1_wind_direction = results_0_daily_1["wind_direction"];
const char* results_0_daily_1_wind_direction_degree = results_0_daily_1["wind_direction_degree"];
const char* results_0_daily_1_wind_speed = results_0_daily_1["wind_speed"];
const char* results_0_daily_1_wind_scale = results_0_daily_1["wind_scale"];
const char* results_0_daily_1_humidity = results_0_daily_1["humidity"];
JsonObject results_0_daily_2 = results_0_daily[2];
const char* results_0_daily_2_date = results_0_daily_2["date"];
const char* results_0_daily_2_text_day = results_0_daily_2["text_day"]; // "小雨"
const char* results_0_daily_2_code_day = results_0_daily_2["code_day"]; // "13"
const char* results_0_daily_2_text_night = results_0_daily_2["text_night"]; // "小雨"
const char* results_0_daily_2_code_night = results_0_daily_2["code_night"]; // "13"
const char* results_0_daily_2_high = results_0_daily_2["high"]; // "12"
const char* results_0_daily_2_low = results_0_daily_2["low"]; // "11"
const char* results_0_daily_2_precip = results_0_daily_2["precip"]; // ""
const char* results_0_daily_2_wind_direction = results_0_daily_2["wind_direction"]; // "东北"
const char* results_0_daily_2_wind_direction_degree = results_0_daily_2["wind_direction_degree"]; // "59"
const char* results_0_daily_2_wind_speed = results_0_daily_2["wind_speed"]; // "34.20"
const char* results_0_daily_2_wind_scale = results_0_daily_2["wind_scale"]; // "5"
const char* results_0_daily_2_humidity = results_0_daily_2["humidity"]; // "86"
const char* results_0_last_update = results_0["last_update"];
String riqi = results_0_last_update; //将日期取出处理
int nian = riqi.lastIndexOf("T");
hTime.Year = (riqi.substring(nian-10, nian-6)).toInt();
hTime.Month = (riqi.substring(nian-5, nian-3)).toInt();
hTime.Day = (riqi.substring(nian-2, nian)).toInt();
OnTime++; //显示标志位 0,1,2显示时间 3显示今天天气 4显示明天天气 5显示后天天气
OnTime%=5;
dTime.Hour = hTime.Hour+8;
dTime.Minute = hTime.Minute;
dTime.Second = hTime.Second;
dTime.Year = hTime.Year;
dTime.Month = hTime.Month;
dTime.Day = hTime.Day;
day1.tianqitubiao = atoi(results_0_daily_0_code_day);//获取今天天气信息
day1.zuigaowendu = atoi(results_0_daily_0_high);
day1.zuidiwendu = atoi(results_0_daily_0_low);
day1.shidu = atoi(results_0_daily_0_humidity);
day2.tianqitubiao = atoi(results_0_daily_1_code_day);
day2.zuigaowendu = atoi(results_0_daily_1_high);
day2.zuidiwendu = atoi(results_0_daily_1_low);
day2.shidu = atoi(results_0_daily_1_humidity);
day3.tianqitubiao = atoi(results_0_daily_2_code_day);
day3.zuigaowendu = atoi(results_0_daily_2_high);
day3.zuidiwendu = atoi(results_0_daily_2_low);
day3.shidu = atoi(results_0_daily_2_humidity);
}
代码前半段是从那个网站上解析到的代码,后半段是取出想要的数据,取出的方法比较暴力,就是一个一个提取,存到设置的结构体中。
(6. 显示时间日期
void DisplayTime()
{
if(OnTime ==0 or OnTime == 1)
{
display.clearDisplay();//清除缓冲区
display.setTextSize(2);//设置字体大小
//display.setCursor(0,0);//设置光标
display.drawBitmap(0,0,liu,16,16,1);
display.drawBitmap(16,0,zhou,16,16,1);
//display.drawBitmap(0,0,liuzhou,16,16,1);//qin
//display.print("LiuZhou");//显示地区
display.setCursor(0,30);//设置光标
display.printf("%d:%d",dTime.Hour,dTime.Minute);//时间
display.setCursor(0,50);//设置光标
display.printf("%d.%d.%d",dTime.Year,dTime.Month,dTime.Day);//日期
display.display();
}
}
(7.显示天气
void display_tq(int dday,int tq,int dw,int gw,int sd)
{
tianqi_dat(dw,gw,sd);
display.clearDisplay();
switch(dday)
{
case 0:display.drawBitmap(64,0,jintian[0],16,16,1);//今
break;
case 1:display.drawBitmap(64,0,jintian[1],16,16,1);//
break;
case 2:display.drawBitmap(64,0,jintian[2],16,16,1);//
break;
}
display.drawBitmap(80,0,jintian[3],16,16,1);//天
switch(tq)
{
case 0:display.drawBitmap(64,16,tianqi[0],16,16,1);//qin
display.drawBitmap(0,0,qintian,60,60,1);//图标
break;
case 4:display.drawBitmap(64,16,tianqi[2],16,16,1);//dy
display.drawBitmap(80,16,tianqi[3],16,16,1);//
display.drawBitmap(0,0,duoyun,60,60,1);//图标
break;
case 9:display.drawBitmap(64,16,tianqi[1],16,16,1);//yin
display.drawBitmap(0,0,yintian,60,60,1);//图标
break;
case 13:display.drawBitmap(64,16,tianqi[4],16,16,1);//x
display.drawBitmap(80,16,tianqi[7],16,16,1);//
display.drawBitmap(0,0,xiaoyu,60,60,1);//图标
break;
case 14:display.drawBitmap(64,16,tianqi[5],16,16,1);//z
display.drawBitmap(80,16,tianqi[7],16,16,1);//
display.drawBitmap(0,0,zhongyu,60,60,1);//图标
break;
case 15:display.drawBitmap(64,16,tianqi[6],16,16,1);//d
display.drawBitmap(80,16,tianqi[7],16,16,1);//
display.drawBitmap(0,0,dayu,60,60,1);//图标
break;
}
display.drawBitmap(64,32,num[Nume.dws],8,16,1);//最低温
display.drawBitmap(72,32,num[Nume.dwg],8,16,1);//最低温
display.drawBitmap(80,32,num[10],8,16,1);//-
display.drawBitmap(88,32,num[Nume.gws],8,16,1);//最g温
display.drawBitmap(96,32,num[Nume.gwg],8,16,1);//最g温
display.drawBitmap(108,32,sheshidu[0],16,16,1);//shehisdu
display.drawBitmap(64,48,shidu[0],16,16,1);//湿
display.drawBitmap(80,48,shidu[1],16,16,1);//度
display.drawBitmap(96,48,num[Nume.sds],8,16,1);//湿度
display.drawBitmap(104,48,num[Nume.sdg],8,16,1);//
display.drawBitmap(112,48,sheshidu[1],16,16,1);//baifenhao
display.display();
}
(8. 结果展示
显示日期时间
显示天气
(9. 已知问题
WIFI连接有时候长时间连不上,只需要按下单片机的复位键即可。
天气图像可能有显示BUG。
3.注意事项
使用该代码时需要更改信息,例如WiFi,心知天气的密钥,地区的字模需要另外制作和替换。