You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

树莓派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())

问题原因分析

  1. 客户端连接目标错误:客户端代码中连接的是谷歌DNS服务器(8.8.8.8),而非遥控器AP的IP地址,这是核心问题。
  2. 服务器AP初始化逻辑错误:AP模式下wlan.isconnected()返回的是是否有客户端接入,而非AP接口是否激活,导致初始化判断逻辑失效。
  3. 连接处理逻辑不匹配:服务器每次连接仅处理一次数据交互就关闭连接,客户端循环重连间隔过短,容易触发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默认IP192.168.4.1,确保连接到遥控器服务器。
  • 修正AP初始化逻辑:服务器端判断wlan.active()确认接口激活,而非依赖wlan.isconnected()(仅判断客户端接入状态)。
  • 优化连接模式:改为长连接交互,避免频繁创建/销毁连接引发的AP资源限制;同时延长客户端重连间隔,减少资源占用。
  • 增强异常处理:完善两端的异常捕获和资源释放逻辑,避免连接异常导致的资源泄漏。

内容的提问来源于stack exchange,提问作者Space Cowboy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 19:05:56