MicroPython 开发ESP32应用教程 之 WIFI、BLE共用常见问题处理及中断处理函数注意事项

最近在用micropython 开发ESP32s3的应用项目时,总是碰到各种各样的问题,这些问题,在之前的课程中,为了聚焦每个课程的知识内容,我们没有提及,今天我们把之前遇到的一些问题及解决思路跟大家分享一下,希望能帮到碰到类似问题的朋友。

一、MicroPython for ESP32 不同固件之间的差异

要理解这点,我们首先要明白micropython与python的区别:

Python
1、运行于通用操作系统(如 Windows/Linux/macOS),依赖高性能硬件(多核 CPU、GB 级内存),适合桌面、服务器等场景‌ 。
2、作为通用语言,无法直接操作 GPIO、PWM 等硬件外设‌。
3、拥有完整的标准库(如 ossys)和丰富的第三方库(如 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

写这篇博文更多的意义是记录自己开发过程中遇到的一些问题,方便以后再次遇到类似的问题时参考。如果能对碰到类似问题的朋友提供那怕一点点帮助,那就是意外之喜了。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

永远的元子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值