网络天气显示
本教程的核心逻辑适用于所有 ESP32 开发板,但所有操作步骤均以 微雪 ESP32-S3-Zero 迷你开发板 为例进行讲解。如果您使用其他型号的开发板,请根据实际情况修改相应设置。
项目介绍
本项目将展示如何利用 ESP32 制作一个网络天气显示器。通过连接 Wi-Fi 网络,ESP32 将定期从 心知天气 API 获取指定城市的实时天气数据(天气现象和温度),并将这些信息显示在微雪 1.5 寸 OLED 屏幕上。
硬件连接
需要使用的器件有:
- 微雪 1.5 寸 OLED 模块 * 1
- 面包板 * 1
- 导线
- ESP32 开发板
按照下面接线图连接电路:
ESP32-S3-Zero 引脚图

以下用 SPI 接口连接 OLED 显示屏,此屏幕也支持 I2C,通过 BS1 和 BS2 控制,如果使用 I2C 模式,请参考 第7节 I2C 通信 中的接线方式。
| ESP32 引脚 | OLED 模块 | 说明 |
|---|---|---|
| GPIO 13 | SCK | SPI 时钟线 |
| GPIO 11 | MOSI | SPI 数据输出 |
| GPIO 10 | CS | 片选信号 |
| GPIO 8 | DC | 数据/命令选择 |
| 3.3V | VCC | 电源正极 |
| GND | GND | 电源负极 |

代码实现
此代码示例依赖 ssd1327.py 驱动库。该库基于社区开发者 mcauser 的 micropython-ssd1327 项目。
下载链接:micropython-ssd1327-master.zip
请将该库中的 ssd1327.py 文件上传到开发板的根目录中。
import time
import network
import urequests
import json
from machine import Pin, SPI
import ssd1327
# Wi-Fi 配置
WIFI_SSID = "Maker"
WIFI_PASSWORD = "12345678"
# 心知天气 API 配置 (请替换为你的私钥)
API_KEY = "your_api_key"
LOCATION = "shenzhen" # 你想查询天气的城市
# API URL
API_URL = "https://api.seniverse.com/v3/weather/now.json?key={}&location={}&language=en&unit=c"
# 更新间隔 (秒)
UPDATE_INTERVAL = 1800 # 30 分钟
# SPI 引脚配置
SCK_PIN = 13
MOSI_PIN = 11
CS_PIN = 10
DC_PIN = 8
RST_PIN = 9
# 初始化硬件 SPI,使用 id=1,设置时钟频率为 10 MHz
spi = SPI(1, baudrate=10000000, sck=Pin(SCK_PIN), mosi=Pin(MOSI_PIN))
# 若使用 I2C 接口,取消注释以下代码
# from machine import I2C
# SDA_PIN = 2
# SCL_PIN = 1
# I2C_ADDR = 0x3d
# i2c = I2C(0, scl=Pin(SCL_PIN), sda=Pin(SDA_PIN), freq=400000)
# 初始化显示器
try:
# 使用 SPI 接口
oled = ssd1327.SSD1327_SPI(128, 128, spi, dc=Pin(DC_PIN), res=Pin(RST_PIN), cs=Pin(CS_PIN))
# 使用 I2C 接口
# oled = ssd1327.SSD1327_I2C(128, 128, i2c, I2C_ADDR)
print("OLED display initialized successfully.")
except Exception as e:
print(f"Error initializing display: {e}")
# 如果显示器初始化失败,程序无法继续
while True:
time.sleep(1)
def connect_wifi():
"""连接到 Wi-Fi 网络"""
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
if not wlan.isconnected():
print(f"Connecting to network: {WIFI_SSID}...")
oled.fill(0)
oled.text("Connecting to", 5, 20, 15)
oled.text("WiFi...", 5, 40, 15)
oled.show()
wlan.connect(WIFI_SSID, WIFI_PASSWORD)
# 等待连接成功
timeout = 15 # 15 秒超时
start_time = time.time()
while not wlan.isconnected() and (time.time() - start_time) < timeout:
time.sleep(1)
print(".", end="")
if wlan.isconnected():
print("\nNetwork connected!")
print(f"IP Address: {wlan.ifconfig()[0]}")
oled.fill(0)
oled.text("WiFi Connected!", 5, 20, 15)
oled.text("IP:", 5, 40, 15)
oled.text(wlan.ifconfig()[0], 5, 55, 15)
oled.show()
time.sleep(2)
return True
else:
print("\nFailed to connect to WiFi.")
oled.fill(0)
oled.text("WiFi Failed!", 5, 20, 15)
oled.show()
return False
def get_weather():
"""从心知天气 API 获取天气数据"""
url = API_URL.format(API_KEY, LOCATION)
print(f"Fetching weather from: {url}")
try:
response = urequests.get(url)
if response.status_code == 200:
weather_data = response.json()
print("API Response:", weather_data) # 调试时可以取消注释
# 从 JSON 数据中提取所需信息
result = weather_data['results'][0]
location_name = result['location']['name']
weather_text = result['now']['text']
temperature = result['now']['temperature']
return location_name, weather_text, temperature
else:
print(f"Error getting weather: HTTP Status {response.status_code}")
return None, f"HTTP Err {response.status_code}", ""
except Exception as e:
print(f"Error during API request: {e}")
return None, "Request Error", ""
def display_weather(city, weather, temp):
"""在 OLED 上显示天气信息"""
oled.fill(0) # 清屏
# 城市名称
oled.text(f"City: {city}", 5, 10, 15)
# 天气状况
oled.text(f"Weather:", 5, 40, 15)
oled.text(weather, 5, 55, 15)
# 温度
oled.text(f"Temp: {temp} C", 5, 85, 15)
oled.show() # 更新显示
print(f"Display updated: {city}, {weather}, {temp} C")
#主程序
def main():
# 首先连接 Wi-Fi
if not connect_wifi():
# 如果连接失败,则不再继续
return
while True:
print("\n" + "="*20)
oled.fill(0)
oled.text("Fetching...", 5, 20, 15)
oled.show()
city, weather, temp = get_weather()
if city:
display_weather(city, weather, temp)
else:
# 如果获取失败,显示错误信息
display_weather("Error", weather, temp)
print(f"Waiting for {UPDATE_INTERVAL} seconds before next update...")
time.sleep(UPDATE_INTERVAL)
# 运行主程序
if __name__ == "__main__":
main()
代码解释
-
导入库:
network:用于管理 Wi-Fi 连接。urequests:用于发送 HTTP 请求,从 API 获取数据。json:用于解析 API 返回的 JSON 格式数据。machine:用于控制硬件(SPI 和 GPIO)。ssd1327:用于驱动 1.5 寸 OLED 显示屏。time:用于实现延时和计时。
-
配置参数:程序开头定义了 Wi-Fi 信息、API 密钥、目标城市以及硬件引脚。将这些参数集中管理,方便用户修改配置。
# Wi-Fi 配置
WIFI_SSID = "Maker"
WIFI_PASSWORD = "12345678"
# 心知天气 API 配置
API_KEY = "your_api_key"
LOCATION = "shenzhen" -
硬件初始化:
-
SPI 方式(默认):使用
machine.SPI()初始化 SPI 总线,并使用ssd1327.SSD1327_SPI()初始化 OLED 显示屏。spi = SPI(1, baudrate=10000000, sck=Pin(SCK_PIN), mosi=Pin(MOSI_PIN))
oled = ssd1327.SSD1327_SPI(128, 128, spi, dc=Pin(DC_PIN), res=Pin(RST_PIN), cs=Pin(CS_PIN)) -
I2C 方式:如果使用 I2C 接口的屏幕,可以取消相关代码的注释。使用
machine.I2C()初始化 I2C 总线,并使用ssd1327.SSD1327_I2C()初始化。# I2C 初始化示例
i2c = I2C(0, scl=Pin(SCL_PIN), sda=Pin(SDA_PIN), freq=400000)
oled = ssd1327.SSD1327_I2C(128, 128, i2c, I2C_ADDR)
-
-
网络连接函数
connect_wifi():负责连接 Wi-Fi 网络并在屏幕上显示连接状态。- 使用
network.WLAN(network.STA_IF)创建站点接口。 - 调用
wlan.connect()发起连接。 - 使用
while循环等待连接成功,并设置了 15 秒的超时机制。 - 连接过程中会在 OLED 上显示 "Connecting...",成功后显示 IP 地址。
- 使用
-
获取天气函数
get_weather():从心知天气 API 获取数据。使用心知天气 API 的天气实况接口,获取指定城市的当前天气信息。接口文档:心知天气 API - 天气实况接口-
使用
API_URL.format()构建完整的请求 URL。API_URL = "https://api.seniverse.com/v3/weather/now.json?key={}&location={}&language=en&unit=c"
...
url = API_URL.format(API_KEY, LOCATION) -
使用
urequests.get(url)发送 HTTP GET 请求。 -
检查 HTTP 状态码是否为 200(成功)。
-
使用
response.json()解析返回的数据,并提取城市名、天气现象和温度。# 从 JSON 数据中提取所需信息
result = weather_data['results'][0]
location_name = result['location']['name']
weather_text = result['now']['text']
temperature = result['now']['temperature']
-
-
显示函数
display_weather():将获取到的天气信息显示在 OLED 屏幕上。oled.fill(0):清除屏幕。oled.text():分别在不同位置显示城市、天气和温度。oled.show():刷新屏幕显示。
-
主程序逻辑
main():- 首先调用
connect_wifi()确保网络已连接。 - 进入无限循环
while True:- 显示 "Fetching..." 提示正在获取数据。
- 调用
get_weather()获取最新天气。 - 调用
display_weather()更新屏幕显示。 - 使用
time.sleep(UPDATE_INTERVAL)进入休眠,等待下一次更新(默认 30 分钟)。
- 首先调用