尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

ESP32+MicroPython驱动ST7735S:打造低成本WiFi天气显示终端

发布时间:2026/9/28 17:23:03

资讯中心
01
ARTICLE

ESP32+MicroPython驱动ST7735S:打造低成本WiFi天气显示终端

ESP32+MicroPython驱动ST7735S:打造低成本WiFi天气显示终端
1. 为什么选择ESP32加ST7735S这套组合1.1 从需求出发反推硬件选型做一个小型天气显示终端核心需求其实就三条能联网拿数据、能驱动一块彩色屏幕、成本尽量低。ESP32几乎是这个场景下的默认答案——双核240MHz、内置WiFi和蓝牙、GPIO数量够用、MicroPython固件成熟一块开发板二十块钱出头就能拿下。屏幕这边选择就多了ILI9341、ST7789、ST7735S都是常见的SPI TFT驱动芯片我最终选ST7735S的原因很实际1.8寸128x160的分辨率做天气信息展示刚好够用价格便宜而且SPI接口占用的引脚少接线简单对新手友好。ST7735S是一颗单芯片TFT控制器内置了显示RAM支持SPI接口通信最高可以跑到几十MHz的时钟频率。它和ST7789最大的区别在于分辨率——ST7735S通常是128x160或者128x128而ST7789一般是240x320。做天气终端不需要太高分辨率128x160足够显示温度、天气图标、城市名和更新时间了。而且低分辨率意味着刷屏数据量小即使用SPI软件驱动刷新速度也能接受。1.2 MicroPython在这类项目中的真实定位很多人一提到ESP32开发就想到Arduino框架或者ESP-IDF但MicroPython在这个场景下有几个不可替代的优势。第一是开发迭代快改一行代码直接运行不需要编译烧录的等待过程调试UI布局的时候这个优势特别明显。第二是REPL交互环境你可以随时连上去查看变量、测试SPI通信是否正常排查硬件问题的时候非常方便。第三是代码可读性强对于不是专业嵌入式出身的人来说Python的门槛明显低于C语言。当然MicroPython也有代价。运行速度比C慢内存占用更大对于一些需要高实时性的场景不太合适。但天气显示终端这个项目数据更新频率是分钟级别的屏幕刷新也不是高帧率需求MicroPython完全够用。我实测下来ESP32跑MicroPython驱动ST7735S刷一屏全屏内容大概需要80到120毫秒这个速度对于天气终端来说绰绰有余。1.3 整体架构设计思路整个系统的数据流是这样的ESP32通过WiFi连接到网络用HTTP请求从天气API获取JSON格式的天气数据解析出温度、湿度、天气状况等字段然后通过SPI接口把要显示的内容写到ST7735S的显示RAM里。屏幕驱动层我选择用现成的ST7735库但需要根据实际接线修改引脚配置。这里有个设计决策值得说一下为什么不直接在主循环里轮询更新天气而是要考虑定时机制因为天气API通常有调用频率限制免费接口一般限制每小时调用几次到几十次不等。如果每次循环都去请求不仅浪费网络资源还可能被封IP。所以合理的做法是用定时器或者时间戳判断每隔固定时间比如10分钟才去拉一次数据中间的时间屏幕保持显示上一次的数据就行。注意免费天气API通常需要注册获取API Key建议选择支持HTTPS的接口。ESP32的MicroPython固件需要包含ssl模块才能发起HTTPS请求刷固件时要注意选择带ssl的版本。2. 硬件接线与SPI通信核心细节2.1 ST7735S引脚定义与ESP32对应关系ST7735S模块通常引出8个引脚VCC、GND、CS、RESET、DC、SDAMOSI、SCLSCK、BLK背光。不同厂家的模块引脚顺序可能不同拿到手第一件事是看模块背面的丝印或者商品页面提供的引脚图。我用的接线方案如下表所示选择这些GPIO的原因后面会解释ST7735S引脚ESP32 GPIO说明VCC3.3V供电不要接5VGNDGND共地CSGPIO15片选信号RESETGPIO4复位信号DCGPIO2数据/命令选择SDAGPIO13SPI MOSISCLGPIO14SPI SCKBLK3.3V背光常亮这里重点说一下为什么选这几个引脚。ESP32的SPI接口有默认的IO_MUX引脚分配SPI2HSPI的默认SCK是GPIO14MOSI是GPIO13这两个引脚用硬件SPI的时候性能最好。CS我选了GPIO15DC选了GPIO2RESET选了GPIO4这些都是普通的GPIO没有特殊功能冲突。2.2 SPI通信参数配置与原理SPI通信需要配置几个关键参数波特率、极性、相位、位序。ST7735S的数据手册里写得很清楚它支持SPI模式0CPOL0CPHA0和模式3CPOL1CPHA1。MicroPython的SPI构造函数里polarity和phase这两个参数就是用来设置极性和相位的。我一般用模式0配置代码如下from machine import SPI, Pin spi SPI(2, baudrate20000000, polarity0, phase0, sckPin(14), mosiPin(13))波特率设了20MHz这是ST7735S数据手册标称的最高SPI时钟频率。实际使用中如果接线较长或者杜邦线质量不好可能需要降到10MHz甚至更低才能稳定工作。我踩过一次坑用了一根劣质的杜邦线接SCK20MHz下屏幕花屏降到5MHz就正常了。所以如果你遇到花屏问题第一个要排查的就是降速试试。SPI是全双工通信但ST7735S只接收数据不需要回传所以MISO引脚不用接。这也是为什么SPI驱动屏幕比I2C快很多——SPI没有地址帧开销数据可以连续不断地推过去。2.3 硬件片选与软件片选的实际差异SPI协议里片选信号CS的作用是选中总线上特定的从设备。ESP32的硬件SPI控制器支持硬件片选但MicroPython的SPI类默认不管理CS引脚需要自己用Pin对象控制。这意味着实际上我们用的是软件片选——在发送数据前把CS拉低发送完拉高。对于只有一个SPI从设备的场景其实可以把CS直接接地让屏幕一直处于选中状态。但我不建议这么做因为上电瞬间SPI总线上的电平可能不稳定没有CS控制的话屏幕可能收到乱码。而且如果以后要在同一条SPI总线上挂其他设备比如SD卡或者另一个屏幕就必须用CS来区分了。实操心得如果你发现屏幕偶尔出现随机噪点或者局部花屏先检查CS引脚有没有虚焊。我遇到过好几次都是面包板接触不良导致的换成焊接或者换一个孔位就好了。3. 驱动库选型与屏幕初始化流程3.1 为什么选择现成的ST7735驱动库从零写ST7735S的驱动不是不行但没必要。初始化序列有几十条命令涉及伽马校正、电源控制、帧率设置等一堆寄存器自己对着数据手册一条条写很容易出错。GitHub上有几个成熟的MicroPython ST7735驱动库我推荐用st7735.py这个版本代码简洁支持硬件SPI而且初始化参数已经调好了。不过现成库也有坑。不同厂家的ST7735S模块可能用的是不同的偏移量offset。比如有的模块显示区域从(0,0)开始有的从(2,1)或者(0,32)开始。如果你发现屏幕边缘有彩色条纹或者图像偏移了大概率就是offset不对。我手上这块1.8寸128x160的模块offset是(0,0)但之前买过另一块需要设成(2,1)才正常。3.2 屏幕初始化关键步骤拆解初始化流程大致分这么几步硬件复位、软件复位、退出睡眠模式、设置颜色格式、设置显示方向、打开显示。每一步都有对应的命令码驱动库已经封装好了但了解底层原理有助于排查问题。硬件复位就是把RESET引脚拉低至少10微秒再拉高让芯片回到初始状态。软件复位是发送0x01命令。退出睡眠是发送0x11命令然后必须等待至少120毫秒让内部电路稳定。设置颜色格式用0x3A命令参数0x05表示16位RGB565格式这是我们最常用的格式一个像素占两个字节。显示方向通过0x36命令的MADCTL寄存器控制可以设置横屏或竖屏、是否镜像。天气终端我一般用竖屏模式128宽160高上面显示城市名中间显示温度和天气图标下面显示湿度和更新时间。3.3 颜色格式与显存写入方式RGB565格式的意思是红色占5位、绿色占6位、蓝色占5位总共16位。绿色多一位是因为人眼对绿色更敏感。在MicroPython里颜色值通常用color565(r, g, b)函数转换输入0-255的RGB值输出一个16位整数。写显存的时候先发送0x2C命令Memory Write然后连续发送像素数据。驱动库一般提供fill、pixel、text、rect这些方法。全屏填充是最快的操作因为可以连续发送大量数据SPI的吞吐率能跑满。而画单个像素或者小区域反而慢因为每次都要发命令设置地址窗口。注意ST7735S的显存地址窗口设置命令是0x2A列地址和0x2B行地址设置完窗口后再发0x2C开始写数据。如果你自己写驱动这三个命令的顺序不能错。4. 天气数据获取与解析实战4.1 天气API选择与请求构造免费天气API有不少选择国内的和风天气、心知天气都提供免费额度国外的OpenWeatherMap也有免费套餐。我选的是和风天气的免费接口因为它返回的数据字段清晰中文支持好而且免费额度对个人项目来说够用。请求URL的格式大概是这样的https://devapi.qweather.com/v7/weather/now?location101010100key你的API_KEY其中location是城市代码101010100是北京的代码。你需要先调用城市查询接口获取自己城市的代码。返回的JSON数据里now对象包含temp温度、text天气状况文字、humidity湿度、windDir风向等字段。4.2 MicroPython中的HTTPS请求处理ESP32的MicroPython固件需要包含ssl模块才能发HTTPS请求。连接WiFi的代码很标准import network sta network.WLAN(network.STA_IF) sta.active(True) sta.connect(你的WiFi名, 你的WiFi密码) while not sta.isconnected(): pass发HTTPS请求用urequests库import urequests resp urequests.get(url) data resp.json() resp.close()这里有个坑urequests默认不验证SSL证书虽然能跑通但安全性打折扣。对于个人项目来说问题不大但如果你在意安全可以用ssl.wrap_socket手动建立连接。另外记得每次请求完调用close()释放内存ESP32的内存本来就紧张不释放的话跑几次就MemoryError了。4.3 JSON数据解析与异常处理resp.json()返回的是一个字典直接按层级取就行temp data[now][temp] text data[now][text] humidity data[now][humidity]但网络请求随时可能失败——WiFi断了、API限额用完了、服务器返回了非200状态码。所以必须加异常处理try: resp urequests.get(url, timeout10) if resp.status_code 200: data resp.json() # 解析数据 else: # 使用上次缓存的数据 except Exception as e: print(请求失败:, e)我一般会在内存里保留上一次成功获取的数据请求失败的时候就继续显示旧数据同时在屏幕上显示一个小图标提示数据可能不是最新的。5. 界面布局设计与显示优化5.1 128x160屏幕的信息层级规划128x160像素的空间很有限必须精打细算。我的布局方案是这样的顶部20像素显示城市名和日期中间60像素显示大号温度数字和天气图标底部40像素显示湿度和风向最下面留40像素显示更新时间。字体选择上温度用32像素高的字体其他信息用16像素高的字体。字体文件需要提前转换成MicroPython能识别的格式。我一般用PCtoLCD工具生成字模或者直接用驱动库自带的字体。驱动库通常内置了8x8和16x16的ASCII字体中文显示需要自己取模。天气终端其实用英文和数字就够了城市名可以用拼音代替省去中文字库的麻烦。5.2 局部刷新与全屏刷新的取舍全屏刷新就是每次更新都重画整个屏幕优点是代码简单缺点是慢而且屏幕会闪。局部刷新只更新变化的区域速度快、无闪烁但代码复杂一些。我的做法是温度、湿度这些数值用局部刷新只重画数值所在的矩形区域。背景和静态文字只在初始化或者切换页面的时候画一次。具体实现就是先用fill_rect把旧数值区域用背景色覆盖再画新数值。这样每次更新的数据量很小刷一次不到10毫秒肉眼完全看不出闪烁。5.3 天气图标绘制方案天气图标我选择用取模软件生成16x16或者32x32的位图数组直接存在代码里。每个图标对应一个数组绘制的时候遍历数组根据像素值决定画什么颜色。这种方法的好处是不依赖文件系统代码自包含。缺点是图标多了会占内存所以只做常用的几种晴、多云、阴、雨、雪。如果你想要更漂亮的图标可以用SPIFFS文件系统存BMP图片然后读取文件绘制。但ESP32的SPIFFS读写速度一般而且MicroPython的文件操作开销不小对于小尺寸图标来说直接存数组反而更快。6. 常见问题排查与避坑经验6.1 屏幕花屏与颜色异常的排查思路花屏是最常见的问题原因可能有很多。我整理了一个排查顺序先降SPI波特率到5MHz试试如果好了就是信号完整性问题再检查接线是否牢固特别是SCK和MOSI这两根线然后确认offset参数是否正确最后检查供电是否充足ST7735S背光全亮的时候电流能到100mA以上有些开发板的3.3V输出能力不够会导致电压跌落。颜色异常通常是RGB顺序不对。ST7735S支持RGB和BGR两种顺序通过MADCTL寄存器的BGR位控制。如果你发现红色显示成蓝色就是BGR位设反了改一下初始化参数就行。6.2 WiFi连接不稳定导致数据更新失败ESP32的WiFi在MicroPython下偶尔会断连特别是在路由器信号弱或者周围WiFi干扰多的时候。我的解决方案是加一个看门狗机制每次更新数据前检查WiFi状态如果断了就重连重连超过3次就重启ESP32。重启虽然粗暴但有效毕竟这是无人值守的终端设备。另外建议把WiFi连接超时设短一点比如10秒。默认的超时时间太长断网的时候会卡住整个程序。6.3 内存不足与程序崩溃的应对MicroPython在ESP32上可用内存大概100KB左右跑天气终端够用但不宽裕。内存问题通常出现在反复请求HTTPS的时候因为SSL握手会占用大量内存。我的经验是每次请求完手动调用gc.collect()回收内存并且在主循环里定期调用。如果还是不够可以考虑用HTTP代替HTTPS省去SSL的开销。或者把请求频率降低比如改成30分钟更新一次。另外注意不要在循环里创建大对象比如不要每次循环都新建一个字体对象。6.4 常见问题速查表现象可能原因解决方法屏幕全白背光正常但无数据检查CS、DC、RESET接线屏幕全黑背光未供电检查BLK引脚和VCC花屏噪点SPI速率过高降低baudrate到5-10MHz颜色反了BGR位设置错误修改MADCTL参数图像偏移offset参数不对尝试(0,0)、(2,1)、(0,32)请求超时WiFi信号弱检查信号强度加重重试内存报错内存泄漏加gc.collect()减少请求频率7. 完整代码结构与关键实现7.1 项目文件组织方式整个项目我分成三个文件main.py是主程序负责WiFi连接和主循环st7735.py是屏幕驱动库weather.py封装了天气API请求和解析逻辑。这样分的好处是修改UI的时候不用动网络代码调试网络的时候不用管屏幕。main.py的结构大概是import time from machine import SPI, Pin from st7735 import ST7735 import weather # 初始化SPI和屏幕 spi SPI(2, baudrate20000000, polarity0, phase0, sckPin(14), mosiPin(13)) tft ST7735(spi, csPin(15), dcPin(2), rstPin(4)) # 连接WiFi weather.connect_wifi(SSID, PASSWORD) # 主循环 last_update 0 while True: now time.time() if now - last_update 600: # 10分钟更新一次 data weather.get_weather() if data: update_display(tft, data) last_update now time.sleep(1)7.2 屏幕驱动初始化的关键代码驱动库的初始化部分我做了修改主要是调整offset和颜色顺序def __init__(self, spi, cs, dc, rst, width128, height160): self.spi spi self.cs cs self.dc dc self.rst rst self.width width self.height height self.x_offset 0 self.y_offset 0 self.init_display() def init_display(self): self.reset() self.write_cmd(0x01) # 软件复位 time.sleep_ms(150) self.write_cmd(0x11) # 退出睡眠 time.sleep_ms(120) self.write_cmd(0x3A) # 颜色格式 self.write_data(0x05) # RGB565 self.write_cmd(0x36) # 显示方向 self.write_data(0x00) # 竖屏RGB顺序 self.write_cmd(0x29) # 打开显示7.3 天气数据更新与显示刷新逻辑更新显示的时候我先把旧的数据区域用背景色覆盖再画新数据。温度数字变化的时候只重画数字区域天气图标变化的时候只重画图标区域。这样每次刷新的数据量很小屏幕不会闪。def update_display(tft, data): # 清除温度区域 tft.fill_rect(10, 50, 108, 40, BLACK) # 画新温度 tft.text(data[temp] C, 20, 55, WHITE, BLACK, 32) # 清除湿度区域 tft.fill_rect(10, 110, 108, 20, BLACK) # 画新湿度 tft.text(Humidity: data[humidity] %, 10, 112, WHITE, BLACK, 16)8. 外壳制作与最终组装建议8.1 3D打印外壳的设计要点如果你有3D打印机可以给终端做个外壳。设计的时候注意几点屏幕开窗要比可视区域大1-2毫米避免遮挡边缘ESP32的USB接口要留出来方便烧录背面留散热孔ESP32跑WiFi的时候发热不小。我用Fusion 360画了一个简单的方形外壳壁厚2毫米打印材料用PLA就行。没有3D打印机的话用亚克力板切割或者买个现成的仪表盒改造也可以。关键是固定好屏幕和开发板避免杜邦线松动。8.2 供电方案与长期运行稳定性供电可以用USB充电器5V 1A以上的就行。ESP32开发板自带LDO稳压到3.3V但有些板子的LDO输出能力有限屏幕背光全亮的时候可能不够。如果遇到屏幕闪烁或者ESP32重启换一个输出能力更强的充电器试试。长期运行的话建议加一个散热片在ESP32芯片上特别是夏天环境温度高的时候。另外MicroPython长时间运行可能会有内存碎片问题我一般设置每天凌晨自动重启一次保证稳定性。8.3 后续功能扩展方向这个终端目前只显示基本天气信息后续可以扩展的方向不少。比如加一个按钮切换显示未来三天的预报或者加一个蜂鸣器做高温报警再或者用ESP32的蓝牙功能做一个手机端配置界面不用改代码就能换城市。甚至可以用deep sleep模式做电池供电每隔一小时唤醒一次更新数据然后继续休眠一块18650电池能撑好几天。我在实际使用中体会最深的一点是硬件项目最花时间的往往不是写代码而是排查接线和调试硬件。代码逻辑错了可以改但一根线接错了可能让你找半天。所以每次接线完先别急着上电用万用表量一下通断确认没有短路再通电这个习惯能帮你省下不少烧板子的钱。
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

◈

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

◐

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

▲

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。