树莓派Pico搭建RC飞机Web服务器时,如何实现任务与请求监听并行?
问题:树莓派Pico遥控飞机Web服务器阻塞其他任务运行
我用树莓派Pico制作了一架遥控飞机,为实现遥控功能搭建了带控制界面的小型Web服务器,功能正常,但发现飞机指示灯停止闪烁——只有刷新页面或点击按钮时才会闪。原因是微控制器一直在等待Web请求,无法执行其他任务。以下是当前循环代码,plane_duties()包含所有其他任务(比如指示灯闪烁):
while True: plane_duties(.05) try: cl, addr = s.accept() request = cl.recv(1024) request = str(request) tlan_toggle = request.find('tlan=toggle') blan_toggle = request.find('blan=toggle') if tlan_toggle == 8: tlan = not tlan if blan_toggle == 8: blan = not blan print(tlan, blan) tlanState = 'Landing is OFF' if tlan else 'Landing is ON' tlanStateClass = 'off' if tlan else 'on' blanState = 'Cargo is OFF' if blan else 'Cargo is ON' blanStateClass = 'off' if blan else 'on' response = html.replace('{{tlanStateClass}}', tlanStateClass).replace('{{blanStateClass}}', blanStateClass) % ( tlanState, blanState) cl.send('HTTP/1.0 200 OK\r\nContent-type: text/html\r\n\r\n') cl.send(response) cl.close() except OSError as e: cl.close() print('connection closed')
请问有没有办法在等待Web请求的同时运行其他代码?
解决方法:设置非阻塞套接字+轮询
核心问题是s.accept()是阻塞式调用——程序会卡在这一行直到有Web请求进来,完全无法执行plane_duties()。解决思路是把套接字设为非阻塞模式,这样s.accept()不会一直等待,无请求时直接抛出异常,程序就能继续循环执行plane_duties()。
修改步骤:
- 在创建套接字后,添加一行设置非阻塞:
s.setblocking(False)
- 修改主循环逻辑,让
plane_duties()持续执行,同时处理Web请求:
修改后的完整循环代码:
# 先把套接字设为非阻塞(放在创建s的代码后面) s.setblocking(False) while True: plane_duties(.05) # 持续执行飞机的核心任务 try: cl, addr = s.accept() # 处理请求的代码保持不变 request = cl.recv(1024) request = str(request) tlan_toggle = request.find('tlan=toggle') blan_toggle = request.find('blan=toggle') if tlan_toggle == 8: tlan = not tlan if blan_toggle == 8: blan = not blan print(tlan, blan) tlanState = 'Landing is OFF' if tlan else 'Landing is ON' tlanStateClass = 'off' if tlan else 'on' blanState = 'Cargo is OFF' if blan else 'Cargo is ON' blanStateClass = 'off' if blan else 'on' response = html.replace('{{tlanStateClass}}', tlanStateClass).replace('{{blanStateClass}}', blanStateClass) % ( tlanState, blanState) cl.send('HTTP/1.0 200 OK\r\nContent-type: text/html\r\n\r\n') cl.send(response) cl.close() except OSError as e: # 非阻塞模式下,没请求时会抛出EAGAIN/EWOULDBLOCK异常,直接忽略即可 if e.args[0] != 11 and e.args[0] != 110: # 11是Linux下的EAGAIN,110是超时(视Pico系统调整) if 'cl' in locals(): cl.close() print('connection closed')
原理说明:
- 非阻塞模式下,
s.accept()不会卡住,没有请求时立刻抛出特定OSError,程序跳过请求处理逻辑,直接回到循环开头执行plane_duties()。 - 这样
plane_duties()能被高频调用,指示灯闪烁这类任务就能正常运行,同时Web请求来了也能及时处理。
如果需要更复杂的多任务管理,也可以考虑用MicroPython的_thread模块创建线程,把Web服务器放在单独线程里执行,但非阻塞套接字的方案更轻量,适合Pico这类资源有限的微控制器。
内容的提问来源于stack exchange,提问作者benji bon
相关产品推荐
相关产品推荐

