最近在用micropython 开发ESP32s3的应用项目时,总是碰到各种各样的问题,这些问题,在之前的课程中,为了聚焦每个课程的知识内容,我们没有提及,今天我们把之前遇到的一些问题及解决思路跟大家分享一下,希望能帮到碰到类似问题的朋友。
一、MicroPython for ESP32 不同固件之间的差异
要理解这点,我们首先要明白micropython与python的区别:
Python
1、运行于通用操作系统(如 Windows/Linux/macOS),依赖高性能硬件(多核 CPU、GB 级内存),适合桌面、服务器等场景 。
2、作为通用语言,无法直接操作 GPIO、PWM 等硬件外设。
3、拥有完整的标准库(如 os
、sys
)和丰富的第三方库(如 NumPy、TensorFlow),覆盖复杂计算场景
MicroPython
1、专为微控制器(如 ESP32、STM32)设计,支持资源受限设备(KB 级内存、MHz 级处理器),适用于嵌入式系统和物联网开发
2、提供 machine
等模块直接控制硬件(如引脚、传感器),支持实时外设交互(SPI/I2C/UART)
3、仅移植 Python 3.4 的部分标准库,功能简化(如不支持多线程),第三方库需针对嵌入式场景定制
个人以为,以上是两者主要区别,需要知道两者更多区别的朋友请自行搜索整理。
从以上区别,我们比较容易理解,不同微处理器的MicroPython固件,可能支持的功能模块会有所不同,甚至相同微处理器,固件版本不同,也会有差异。
我们现在正在开发的项目,本来开始的时候是打算使用ESP32C3开发的,但随着客户的需求逐渐明确,发现ESP32C3的IO口资源不够用,只能换成ESP32S3,从C3换成s3,开发语言使用的是micropython,按说是非常简单的一件事,但还是遇到问题了,获取天气信息的程序在c3上开发完成后,移植到S3上,说是缺少urequests模块,在开发环境中shell窗口输入help('modules')后,我们发现,s3的固件还真没有urequests模块。知道了原因,处理起来就比较简单,一换支持urequests模块的固件,二自己添加urequests模块。
二、BLE与WIFI共用的问题
这个问题,严格来说其实是第一个问题的具体表现,考虑到ESP32对BLE、WIFI共用的需求比较高,我们单独拿出来讲一讲。
我们开始用BLE来控制WS2812灯珠,功能实现没有问题,但加入WIFI后,总是报“WIFI internal error"之类的错误,在网上搜索原因:
针对以上原因,我们作了一些排除并尝试优化程序,一直没能更好的解决问题,后来在网上搜索到有一条提及:ESP32编译固件时,要想同时支持WIFI及BLE 需要作不同的配置:
我们一时没办法验证,考虑到客户对BLE的需求不是很迫切,于是先放弃BLE部分的功能。确实只使用WIFI功能的话,程序开发比较顺利。但接下来碰到的一些问题,我们明白,我们对自己碰到的BLE与WIFI共用的问题,判断是错误的。
三、电源导致BLE、WIFI工作异常
这个问题出现在项目从c3换成S3之后,换成s3后,刚开始的时候虽然遇到缺少urequests模块的问题,但好呆WIFI工作没出现啥问题,但在我们逐步加入其它功能的时候,突然WIFI不能正常工作了,提示文件系统出问题,于是erase flash, 重刷固件等各种招都试过,还是无法正常工作,于是我们把之前的程序,从头一个功能一个功能添加测试看看可能的原因,当尝试添加BLE 功能时,出问题了,但这段程序是我们早期开发,功能非常简单,而且反复测试过,不可能有问题,于是怀疑开发板是不是坏了,但还是在网上搜索了一下,其中有一条提到可能是电源不稳导致,于是我们接上单独的供电电源,BLE工作正常了。
我们以为问题解决了,很快把代码恢复到正常开发进度,但WIFI还是工作异常。
四、天线导致W、BLE工作异常
反复试验,发现WIFI只要一进入配网,就会报错:
E (1305) wifi_init: Failed to deinit Wi-Fi driver (0x3001)
E (1305) wifi_init: Failed to deinit Wi-Fi (0x3001)
上网找答案:
又是各种折腾,但没有任何意义。
这时我们是真的觉得开发板坏了,联系开发板的卖家,商量能不能换一块, 卖家确实有点水平,给了一个建议:
按卖家建议,我们试了试,还真解决了WIFI工作异常的问题,而且我们加入 BLE功能后,发现BLE与WIFI共用的问题也解决了。
五、中断处理函数注意事项
MicroPython 开发ESP32应用教程 之 Timer、GPIO中断
在这一课,我们提到用Timer、GPIO中断可以提高产品的用户体验,在上一课的实验中,我们也确实能感受到这么做后,按键的反应更灵敏更及时了,体验感确实有提高。
但随着我们在Timer回调函数中加入更多需要处理的功能后,发现体验感反而变得更差了,分析后,应该是我们在Timer回调函数加入了大多运行代码,导致Timer回调函数运行时间太长,从而没办法及时响应GPIO中断及BLE指令等。经过优化后,我们只在Timer回调函数中置上相应的标志,真正处理需求的代码放在主框架中,这样一来,体验感提高。
from machine import I2C,SPI,Pin,Timer
from micropython import const
import time
from esp32_ble import ESP32_BLE
from esp32_wifi import esp32_wifi
from ahtx0 import AHT20,ahtx_interval
from st7735 import ST7735,color
from ws2812 import WS2812
from DateTime import datetime
spi = SPI(2,
baudrate=20000000,
polarity=0,
phase=0,
sck=Pin(4),
mosi=Pin(5),
miso=None)
# 定义控制引脚
dc = Pin(7,Pin.OUT)
cs = Pin(15,Pin.OUT)
rst= Pin(6,Pin.OUT)
#bl = Pin(9, Pin.OUT)
# 初始化显示屏 (128x160)
tft = ST7735(128, 160, spi, dc, cs, rst,None,rotate=0)
i2c = I2C(0,scl=Pin(1),sda=Pin(2),freq=200000)
aht20_sensor = AHT20(i2c)
pin = Pin(48, Pin.OUT) #配置GPIO8为输出端口,控制ws2812灯珠的DIN信号
wsled = WS2812(pin,1,3,1)
MOINTOR_Interval = const(100)
AHT20_Interval = const(60000)
DateTime_Interval = const(1000)
Weather_Interval = const(1000 * 60 * 10)
WS2812_Interval = const(500)
dt_interval = 0
weather_interval = 0
chgWeatherInfoDisplay = False
chgAht20Display = False
chgDateTimeDisplay = False
chgWS2812Status = False
def GetWeatherInfo(location,interval = 0):
if wlan.check_wifi():
weatherinfo = wlan.GetWeather(location,interval)
if weatherinfo != False:
weathertxt = weatherinfo['results'][0]['location']['name']+"天气:" + weatherinfo['results'][0]['now']['text'] + " 温度:" + weatherinfo['results'][0]['now']['temperature'] + " ℃"
# print(weathertxt)
tft.showstring(weathertxt,0,100,color(0,0xff,0))
def monitor(t):
global ahtx_interval,dt_interval,weather_interval
dt_interval += 1
if dt_interval >= (DateTime_Interval / MOINTOR_Interval):
dt_interval = 0
chgDateTimeDisplay = True
if wlan.lasttime_weather is not None:
weather_interval += 1
if weather_interval >= (Weather_Interval / MOINTOR_Interval):
weather_interval = 0
chgWeatherInfoDisplay = True
# GetWeatherInfo("shenzhen",1800)
wsled.ws2812_interval += 1
if wsled.ws2812_interval >= (WS2812_Interval / MOINTOR_Interval):
wsled.ws2812_interval = 0
chgWS2812Status = True
# wsled.ws2812_LED_Cycle()
ahtx_interval += 1
if ahtx_interval >= (AHT20_Interval / MOINTOR_Interval):
ahtx_interval = 0
chgAht20Display = True
# print("实测温湿度:\n温度 : {:>4.1f} ℃\n湿度 : {:>4.1f} %".format(wendu,shidu))
command = ble.get_rec_cmd()
if command == 'LED ON':
wsled.ws2812_Power(1)
# print(ble.ble_msg)
ble.send('LED is ON.')
# ble.ble_msg = ''
# 关闭LED
elif command == 'LED OFF':
wsled.ws2812_Power(0)
# print('LED is OFF.')
ble.send('LED is OFF.')
# ble.ble_msg = ''
def button_handler(pin):
time.sleep_ms(10) #消除抖动
if pin.value() == 0:
wsled.ws2812_Change_Status()
if __name__ == "__main__":
pbootkey = Pin(0, Pin.IN,Pin.PULL_UP) #配置GPIO0为输入端口
pbootkey.irq(trigger = Pin.IRQ_FALLING,handler=button_handler)
ble = ESP32_BLE("913 AI App")
dt = datetime()
tft.clear()
# wendu = aht20_sensor.temperature
# shidu = aht20_sensor.relative_humidity
# tft.showstring("实测温湿度:\n温度 : {:>4.1f} ℃\n湿度 : {:>4.1f} %".format(wendu,shidu),0,42,color(0,0,0xff))
# tft.showstring("日期 " + dt.format_date() + "时间 " + dt.format_time(),0,2,color(0xF8,0,0))
wlan = esp32_wifi()
tim = Timer(3)
tim.init(period = MOINTOR_Interval,mode=Timer.PERIODIC,callback=monitor)
PowerOn = True
# time.sleep(2)
# wlan.configwifi("weald2000","fkepln_730401")
# wlan.save_wificonfig()
while True:
if wlan.check_wifi():
if wlan.lasttime_weather is None:
GetWeatherInfo("shenzhen",1800)
wlan.periodic_time_sync(3600)
if chgDateTimeDisplay or PowerOn:
chgDateTimeDisplay = False
# print ("日期 " + dt.format_date() + "时间 " + dt.format_time())
tft.showstring("日期 " + dt.format_date() + "时间 " + dt.format_time(),0,2,color(0xF8,0,0))
if chgWeatherInfoDisplay:
chgWeatherInfoDisplay = False
GetWeatherInfo("shenzhen",1800)
if chgAht20Display or PowerOn:
chgAht20Display = False
wendu = aht20_sensor.temperature
shidu = aht20_sensor.relative_humidity
tft.showstring("实测温湿度:\n温度 : {:>4.1f} ℃\n湿度 : {:>4.1f} %".format(wendu,shidu),0,42,color(0,0,0xff))
if chgWS2812Status or PowerOn:
wsled.ws2812_LED_Cycle()
PowerOn = False
写这篇博文更多的意义是记录自己开发过程中遇到的一些问题,方便以后再次遇到类似的问题时参考。如果能对碰到类似问题的朋友提供那怕一点点帮助,那就是意外之喜了。