树莓派Pico W AP模式异步通信中断问题排查求助
问题:Pico W AP模式下客户端仅初始几秒能通信,后续断连
我正在搭建一台配备两块Pico W的机器人,一块作为遥控器(AP模式服务器),另一块部署在机器人本体(STA模式客户端)。计划用异步代码实现遥控器同时发送按键状态、采集按键状态和显示信息的功能。代码在连接路由器时可正常运行,但将遥控器设为AP模式后,客户端仅初始几秒能接收数据,后续无法继续通信。目前两块Pico看似已连接,但没有数据交互的信息显示。
遥控器(AP服务器)原代码
import asyncio import time import network import machine from machine import Pin ssid='NAME' password='PASSWORD' led = Pin("LED", Pin.OUT) async def connect_wlan(): wlan = network.WLAN(network.AP_IF) #changed from STA_IF wlan.config(essid=ssid, password=password) wlan.active(True) while wlan.isconnected() == False: #changed from wlan.isconnected() print('Activating WLAN') await asyncio.sleep(1) print(f'Broadcasting on' , wlan.ifconfig()) async def phoneback(reader: asyncio.StreamReader, writer: asyncio.StreamWriter): addr = writer.get_extra_info('peername') print(f"Conenction from {addr!r}") client_data = await reader.read(1024) print(f"Client data: {client_data}") response = str("response") print(f"sending {response}") writer.write(response.encode()) await writer.drain() writer.close() await writer.wait_closed() async def main(): await connect_wlan() server = await asyncio.start_server(phoneback, '0.0.0.0', 80) async with server: while True: led.toggle() await asyncio.sleep(1) asyncio.run(main())
机器人本体(STA客户端)原代码
import asyncio import time import network from machine import Pin import gc ssid='NAME' password='PASSWORD' async def connect_wlan(): sta_if = network.WLAN(network.STA_IF) sta_if.active(True) sta_if.connect(ssid, password) while sta_if.isconnected() == False: print('Waiting for connection...') await asyncio.sleep(1) return sta_if def log(*args, **kwargs): print(f"{time.time():.1}", *args, **kwargs) async def get_data(): """Periodic network task""" while True: reader, writer = await asyncio.open_connection("8.8.8.8", 80) log(f"Connected!") try: writer.write("Client_Name".encode()) await writer.drain() log(f"Request Sent!") ss = str(await reader.read(1024)) print(f"Received Data: {ss}") print() await asyncio.sleep_ms(200) gc.collect() except: writer.close() await writer.wait_closed() gc.collect() log(f"Disconnected!") await asyncio.sleep(.2) async def main(): sta_if = await connect_wlan() tasks = [] tasks = [ asyncio.create_task(get_data()), ] await asyncio.gather(*tasks) while True: asyncio.run(main())
问题原因分析
- 客户端连接目标错误:客户端代码中连接的是谷歌DNS服务器(
8.8.8.8),而非遥控器AP的IP地址,这是核心问题。 - 服务器AP初始化逻辑错误:AP模式下
wlan.isconnected()返回的是是否有客户端接入,而非AP接口是否激活,导致初始化判断逻辑失效。 - 连接处理逻辑不匹配:服务器每次连接仅处理一次数据交互就关闭连接,客户端循环重连间隔过短,容易触发AP模式下的连接限制。
修复后的代码
遥控器(AP服务器)代码
import asyncio import time import network import machine from machine import Pin ssid='NAME' password='PASSWORD' led = Pin("LED", Pin.OUT) async def connect_wlan(): wlan = network.WLAN(network.AP_IF) wlan.config(essid=ssid, password=password) wlan.active(True) # 修正:判断AP接口是否激活,而非是否有客户端连接 while not wlan.active(): print('Activating WLAN AP') await asyncio.sleep(1) print(f'Broadcasting on' , wlan.ifconfig()) async def phoneback(reader: asyncio.StreamReader, writer: asyncio.StreamWriter): addr = writer.get_extra_info('peername') print(f"Connection from {addr!r}") try: # 改为长连接处理,持续接收客户端数据 while True: client_data = await reader.read(1024) if not client_data: break print(f"Client data: {client_data}") response = "response" print(f"sending {response}") writer.write(response.encode()) await writer.drain() except Exception as e: print(f"Connection error: {e}") finally: writer.close() await writer.wait_closed() print(f"Connection with {addr!r} closed") async def main(): await connect_wlan() server = await asyncio.start_server(phoneback, '0.0.0.0', 80) async with server: while True: led.toggle() await asyncio.sleep(1) asyncio.run(main())
机器人本体(STA客户端)代码
import asyncio import time import network from machine import Pin import gc ssid='NAME' password='PASSWORD' # Pico W AP模式默认IP地址 SERVER_IP = '192.168.4.1' SERVER_PORT = 80 async def connect_wlan(): sta_if = network.WLAN(network.STA_IF) sta_if.active(True) sta_if.connect(ssid, password) while not sta_if.isconnected(): print('Waiting for connection...') await asyncio.sleep(1) print(f"Client connected, IP: {sta_if.ifconfig()}") return sta_if def log(*args, **kwargs): print(f"{time.time():.1f}", *args, **kwargs) async def get_data(): """Periodic network task""" while True: try: reader, writer = await asyncio.open_connection(SERVER_IP, SERVER_PORT) log(f"Connected to server!") # 保持长连接,持续交互 while True: writer.write("Client_Name".encode()) await writer.drain() log(f"Request Sent!") ss = await reader.read(1024) if not ss: log("Server closed connection") break print(f"Received Data: {ss.decode()}") print() await asyncio.sleep_ms(200) gc.collect() except Exception as e: log(f"Connection failed: {e}") if 'writer' in locals(): writer.close() await writer.wait_closed() gc.collect() await asyncio.sleep(1) # 延长重连间隔,避免频繁重试 async def main(): sta_if = await connect_wlan() await get_data() asyncio.run(main())
关键修复点
- 修正连接目标:客户端将连接地址改为Pico W AP默认IP
192.168.4.1,确保连接到遥控器服务器。 - 修正AP初始化逻辑:服务器端判断
wlan.active()确认接口激活,而非依赖wlan.isconnected()(仅判断客户端接入状态)。 - 优化连接模式:改为长连接交互,避免频繁创建/销毁连接引发的AP资源限制;同时延长客户端重连间隔,减少资源占用。
- 增强异常处理:完善两端的异常捕获和资源释放逻辑,避免连接异常导致的资源泄漏。
内容的提问来源于stack exchange,提问作者Space Cowboy
相关产品推荐
相关产品推荐

